blob: 384ad207b0ec9697e4890be6b3f551201ce96357 [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"))
739 {
740 strcpy(bw_value,"20MHz");
741 }
742 else if(NULL!=strstr(buf,"40MHz"))
743 {
744 strcpy(bw_value,"40MHz");
745 }
746 else if(NULL!=strstr(buf,"80MHz"))
747 {
748 strcpy(bw_value,"80MHz");
749 }
750 else
751 {
752 return RETURN_ERR;
753 }
754 return RETURN_OK;
755}
756
developer264159b2022-11-02 09:41:35 +0800757// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800758INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
759{
developer5f222492022-09-13 15:21:52 +0800760 struct params params={'\0'};
761 char config_file[MAX_BUF_SIZE] = {0};
762 char buf[MAX_BUF_SIZE] = {'\0'};
763
764 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800765 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800766 if (strlen (beaconRate) >= 5) {
767 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
768 buf[strlen(beaconRate) - 4] = '\0';
769 } else if (strlen(beaconRate) > 0)
770 strcpy(buf, beaconRate);
771 else
772 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800773
774 params.name = "beacon_rate";
775 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
776 if (strncmp(buf, "5.5", 3) == 0) {
777 snprintf(buf, sizeof(buf), "55");
778 params.value = buf;
779 } else {
780 strcat(buf, "0");
781 params.value = buf;
782 }
783
784 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
785 wifi_hostapdWrite(config_file, &params, 1);
786 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
788
789 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800790}
791
792INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
793{
developer1d57d002022-10-12 18:03:15 +0800794 char config_file[128] = {'\0'};
795 char temp_output[128] = {'\0'};
796 char buf[128] = {'\0'};
797 char cmd[128] = {'\0'};
798 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800799 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800800
801 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
802 if (NULL == beaconRate)
803 return RETURN_ERR;
804
805 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
806 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800807 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800808 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
809 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800810 if (strncmp(buf, "55", 2) == 0)
811 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
812 else {
813 rate = strtol(buf, NULL, 10)/10;
814 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
815 }
developer5f222492022-09-13 15:21:52 +0800816 } else {
developer1d57d002022-10-12 18:03:15 +0800817 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800818 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 +0800819 _syscmd(cmd, buf, sizeof(buf));
820 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800821 }
822 strncpy(beaconRate, temp_output, sizeof(temp_output));
823 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
824
825 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800826}
827
828INT wifi_setLED(INT radioIndex, BOOL enable)
829{
830 return 0;
831}
832INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
833{
834 return RETURN_OK;
835}
836/**********************************************************************************
837 *
838 * Wifi Subsystem level function prototypes
839 *
840**********************************************************************************/
841//---------------------------------------------------------------------------------------------------
842//Wifi system api
843//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
844INT wifi_getHalVersion(CHAR *output_string) //RDKB
845{
846 if(!output_string)
847 return RETURN_ERR;
848 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
849
850 return RETURN_OK;
851}
852
853
854/* wifi_factoryReset() function */
855/**
856* @description Clears internal variables to implement a factory reset of the Wi-Fi
857* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
858*
859* @param None
860*
861* @return The status of the operation.
862* @retval RETURN_OK if successful.
863* @retval RETURN_ERR if any error is detected
864*
865* @execution Synchronous
866* @sideeffect None
867*
868* @note This function must not suspend and must not invoke any blocking system
869* calls. It should probably just send a message to a driver event handler task.
870*
871*/
872INT wifi_factoryReset()
873{
874 char cmd[128];
875
876 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800877 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
878 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800879 system(cmd);
880 system("systemctl restart hostapd.service");
881
882 return RETURN_OK;
883}
884
885/* wifi_factoryResetRadios() function */
886/**
887* @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.
888*
889* @param None
890* @return The status of the operation
891* @retval RETURN_OK if successful
892* @retval RETURN_ERR if any error is detected
893*
894* @execution Synchronous
895*
896* @sideeffect None
897*
898* @note This function must not suspend and must not invoke any blocking system
899* calls. It should probably just send a message to a driver event handler task.
900*
901*/
902INT wifi_factoryResetRadios()
903{
developer72ec5572023-01-05 16:27:13 +0800904 int max_radio_num = 0;
905 wifi_getMaxRadioNumber(&max_radio_num);
906 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
907 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800908
developer72ec5572023-01-05 16:27:13 +0800909 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800910}
911
912
913/* wifi_factoryResetRadio() function */
914/**
915* @description Restore selected radio parameters without touching access point parameters
916*
917* @param radioIndex - Index of Wi-Fi Radio channel
918*
919* @return The status of the operation.
920* @retval RETURN_OK if successful.
921* @retval RETURN_ERR if any error is detected
922*
923* @execution Synchronous.
924* @sideeffect None.
925*
926* @note This function must not suspend and must not invoke any blocking system
927* calls. It should probably just send a message to a driver event handler task.
928*
929*/
930INT wifi_factoryResetRadio(int radioIndex) //RDKB
931{
developer72ec5572023-01-05 16:27:13 +0800932 char cmd[128] = {0};
933 char buf[128] = {0};
934 int max_radio_num = 0;
935
936 wifi_getMaxRadioNumber(&max_radio_num);
937 if (radioIndex < 0 || radioIndex > max_radio_num)
938 return RETURN_ERR;
939
940 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
941 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800942
developer06a01d92022-09-07 16:32:39 +0800943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800944 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
945 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800946
developer72ec5572023-01-05 16:27:13 +0800947 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
948 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800949 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
950 return RETURN_OK;
951}
952
953/* wifi_initRadio() function */
954/**
955* Description: This function call initializes the specified radio.
956* Implementation specifics may dictate the functionality since
957* different hardware implementations may have different initilization requirements.
958* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
959*
960* @return The status of the operation.
961* @retval RETURN_OK if successful.
962* @retval RETURN_ERR if any error is detected
963*
964* @execution Synchronous.
965* @sideeffect None.
966*
967* @note This function must not suspend and must not invoke any blocking system
968* calls. It should probably just send a message to a driver event handler task.
969*
970*/
971INT wifi_initRadio(INT radioIndex)
972{
973 //TODO: Initializes the wifi subsystem (for specified radio)
974 return RETURN_OK;
975}
976void macfilter_init()
977{
978 char count[4]={'\0'};
979 char buf[253]={'\0'};
980 char tmp[19]={'\0'};
981 int dev_count,block,mac_entry=0;
982 char res[4]={'\0'};
983 char acl_file_path[64] = {'\0'};
984 FILE *fp = NULL;
985 int index=0;
986 char iface[10]={'\0'};
987 char config_file[MAX_BUF_SIZE] = {0};
988
989
990 sprintf(acl_file_path,"/tmp/mac_filter.sh");
991
992 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800993 if (fp == NULL) {
994 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
995 return RETURN_ERR;
996 }
developer06a01d92022-09-07 16:32:39 +0800997 sprintf(buf,"#!/bin/sh \n");
998 fprintf(fp,"%s\n",buf);
999
1000 system("chmod 0777 /tmp/mac_filter.sh");
1001
1002 for(index=0;index<=1;index++)
1003 {
1004 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1005 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1006 sprintf(buf,"syscfg get %dcountfilter",index);
1007 _syscmd(buf,count,sizeof(count));
1008 mac_entry=atoi(count);
1009
1010 sprintf(buf,"syscfg get %dblockall",index);
1011 _syscmd(buf,res,sizeof(res));
1012 block = atoi(res);
1013
1014 //Allow only those macs mentioned in ACL
1015 if(block==1)
1016 {
1017 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1018 fprintf(fp,"%s\n",buf);
1019 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1020 {
1021 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1022 _syscmd(buf,tmp,sizeof(tmp));
1023 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1024 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1025 fprintf(fp,"%s\n",buf);
1026 }
1027 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1028 fprintf(fp,"%s\n",buf);
1029 }
1030
1031 //Block all the macs mentioned in ACL
1032 else if(block==2)
1033 {
1034 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1035 fprintf(fp,"%s\n",buf);
1036
1037 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1038 {
1039 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1040 _syscmd(buf,tmp,sizeof(tmp));
1041 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1042 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1043 fprintf(fp,"%s\n",buf);
1044 }
1045 }
1046 }
1047 fclose(fp);
1048}
1049
1050// Initializes the wifi subsystem (all radios)
1051INT wifi_init() //RDKB
1052{
1053 char interface[MAX_BUF_SIZE]={'\0'};
1054 char bridge_name[MAX_BUF_SIZE]={'\0'};
1055 INT len=0;
1056
1057 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1058 //Not intitializing macfilter for Turris-Omnia Platform for now
1059 //macfilter_init();
1060
1061 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001062 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001063 sleep(2);//sleep to wait for hostapd to start
1064
1065 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1066
1067 return RETURN_OK;
1068}
1069
1070/* wifi_reset() function */
1071/**
1072* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1073* Implementation specifics may dictate what is actualy reset since
1074* different hardware implementations may have different requirements.
1075* Parameters : None
1076*
1077* @return The status of the operation.
1078* @retval RETURN_OK if successful.
1079* @retval RETURN_ERR if any error is detected
1080*
1081* @execution Synchronous.
1082* @sideeffect None.
1083*
1084* @note This function must not suspend and must not invoke any blocking system
1085* calls. It should probably just send a message to a driver event handler task.
1086*
1087*/
1088INT wifi_reset()
1089{
1090 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001091 system("systemctl stop hostapd.service");
1092 sleep(2);
1093 system("systemctl start hostapd.service");
1094 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001095 return RETURN_OK;
1096}
1097
1098/* wifi_down() function */
1099/**
1100* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1101* Implementation specifics may dictate some functionality since
1102* different hardware implementations may have different requirements.
1103*
1104* @param None
1105*
1106* @return The status of the operation
1107* @retval RETURN_OK if successful
1108* @retval RETURN_ERR if any error is detected
1109*
1110* @execution Synchronous
1111* @sideeffect None
1112*
1113* @note This function must not suspend and must not invoke any blocking system
1114* calls. It should probably just send a message to a driver event handler task.
1115*
1116*/
1117INT wifi_down()
1118{
1119 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001120 int max_num_radios = 0;
1121 wifi_getMaxRadioNumber(&max_num_radios);
1122 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1123 wifi_setRadioEnable(radioIndex, FALSE);
1124
developer06a01d92022-09-07 16:32:39 +08001125 return RETURN_OK;
1126}
1127
1128
1129/* wifi_createInitialConfigFiles() function */
1130/**
1131* @description This function creates wifi configuration files. The format
1132* and content of these files are implementation dependent. This function call is
1133* used to trigger this task if necessary. Some implementations may not need this
1134* function. If an implementation does not need to create config files the function call can
1135* do nothing and return RETURN_OK.
1136*
1137* @param None
1138*
1139* @return The status of the operation
1140* @retval RETURN_OK if successful
1141* @retval RETURN_ERR if any error is detected
1142*
1143* @execution Synchronous
1144* @sideeffect None
1145*
1146* @note This function must not suspend and must not invoke any blocking system
1147* calls. It should probably just send a message to a driver event handler task.
1148*
1149*/
1150INT wifi_createInitialConfigFiles()
1151{
1152 //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)
1153 return RETURN_OK;
1154}
1155
1156// outputs the country code to a max 64 character string
1157INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1158{
developerd946fd62022-12-08 18:03:28 +08001159 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001160 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001161 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001162 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001163
developerac6f1142022-12-20 19:26:35 +08001164 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001165 return RETURN_ERR;
1166 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001167 _syscmd(cmd, buf, sizeof(buf));
1168 if(strlen(buf) > 0)
1169 snprintf(output_string, 64, "%s", buf);
1170 else
1171 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001172
1173 return RETURN_OK;
1174}
1175
1176INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1177{
1178 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001179 char str[MAX_BUF_SIZE]={'\0'};
1180 char cmd[MAX_CMD_SIZE]={'\0'};
1181 struct params params;
1182 char config_file[MAX_BUF_SIZE] = {0};
1183
1184 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1185 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1186 return RETURN_ERR;
1187
developerb86c6f32022-10-07 14:34:58 +08001188 if (strlen(CountryCode) == 0)
1189 strcpy(CountryCode, "US");
1190
developer7543b3b2022-09-13 13:47:17 +08001191 params.name = "country_code";
1192 params.value = CountryCode;
1193 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1194 int ret = wifi_hostapdWrite(config_file, &params, 1);
1195 if (ret) {
1196 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1197 ,__func__, ret);
1198 }
1199
1200 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1201 if (ret) {
1202 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1203 ,__func__, ret);
1204 }
developer7543b3b2022-09-13 13:47:17 +08001205 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1206
developer06a01d92022-09-07 16:32:39 +08001207 return RETURN_OK;
1208}
1209
developera748dcf2022-09-13 15:56:48 +08001210INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1211{
developerd946fd62022-12-08 18:03:28 +08001212 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001213 char channel_util_file[64] = {0};
1214 char cmd[128] = {0};
1215 char buf[128] = {0};
1216 char line[128] = {0};
1217 char *param = NULL, *value = NULL;
1218 int read = 0;
1219 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1220 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1221 size_t len = 0;
1222 FILE *f = NULL;
1223
1224 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1225
developerac6f1142022-12-20 19:26:35 +08001226 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001227 return RETURN_ERR;
1228 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001229 _syscmd(cmd, buf, sizeof(buf));
1230 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1231
1232 memset(cmd, 0, sizeof(cmd));
1233 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001234 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001235 if ((f = popen(cmd, "r")) == NULL) {
1236 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1237 return RETURN_ERR;
1238 }
1239
1240 read = getline(&line, &len, f);
1241 while (read != -1) {
1242 param = strtok(line, ":\t");
1243 value = strtok(NULL, " ");
1244 if(strstr(param, "frequency") != NULL) {
1245 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1246 }
1247 if(strstr(param, "noise") != NULL) {
1248 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1249 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1250 }
1251 if(strstr(param, "channel active time") != NULL) {
1252 ActiveTime = strtol(value, NULL, 10);
1253 }
1254 if(strstr(param, "channel busy time") != NULL) {
1255 BusyTime = strtol(value, NULL, 10);
1256 }
1257 if(strstr(param, "channel transmit time") != NULL) {
1258 TransmitTime = strtol(value, NULL, 10);
1259 }
1260 read = getline(&line, &len, f);
1261 }
1262 pclose(f);
1263
1264 // The file should store the last active, busy and transmit time
1265 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1266 f = fopen(channel_util_file, "r");
1267 if (f != NULL) {
1268 read = getline(&line, &len, f);
1269 preActiveTime = strtol(line, NULL, 10);
1270 read = getline(&line, &len, f);
1271 preBusyTime = strtol(line, NULL, 10);
1272 read = getline(&line, &len, f);
1273 preTransmitTime = strtol(line, NULL, 10);
1274 fclose(f);
1275 }
1276
1277 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1278 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1279
1280 f = fopen(channel_util_file, "w");
1281 if (f != NULL) {
1282 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1283 fclose(f);
1284 }
1285 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1286 return RETURN_OK;
1287}
1288
developer06a01d92022-09-07 16:32:39 +08001289/**********************************************************************************
1290 *
1291 * Wifi radio level function prototypes
1292 *
1293**********************************************************************************/
1294
1295//Get the total number of radios in this wifi subsystem
1296INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1297{
1298 if (NULL == output)
1299 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001300 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001301
1302 return RETURN_OK;
1303}
1304
1305//Get the total number of SSID entries in this wifi subsystem
1306INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1307{
1308 if (NULL == output)
1309 return RETURN_ERR;
1310 *output = MAX_APS;
1311
1312 return RETURN_OK;
1313}
1314
1315//Get the Radio enable config parameter
1316INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1317{
developerd946fd62022-12-08 18:03:28 +08001318 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001319 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001320 int apIndex;
1321 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001322
1323 if (NULL == output_bool)
1324 return RETURN_ERR;
1325
1326 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001327
1328 wifi_getMaxRadioNumber(&max_radio_num);
1329
1330 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001331 return RETURN_ERR;
1332
developera77d84b2023-02-22 16:10:50 +08001333 /* loop all interface in radio, if any is enable, reture true, else return false */
1334 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1335 {
1336 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1337 continue;
1338 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1339 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001340
developera77d84b2023-02-22 16:10:50 +08001341 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1342 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1343 /* return true if any interface is eanble */
1344 *output_bool = TRUE;
1345 break;
1346 }
1347 }
developer06a01d92022-09-07 16:32:39 +08001348 return RETURN_OK;
1349}
1350
1351INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1352{
developerd946fd62022-12-08 18:03:28 +08001353 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001354 char cmd[MAX_CMD_SIZE] = {0};
1355 char buf[MAX_CMD_SIZE] = {0};
1356 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001357 int max_radio_num = 0;
1358 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001359
1360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001361
1362 phyId = radio_index_to_phy(radioIndex);
1363
1364 wifi_getMaxRadioNumber(&max_radio_num);
1365
developer06a01d92022-09-07 16:32:39 +08001366 if(enable==FALSE)
1367 {
developera77d84b2023-02-22 16:10:50 +08001368 /* disable from max apindex to min, to avoid fail in mbss case */
1369 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001370 {
developer1e125222022-12-29 09:35:25 +08001371 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001372 continue;
developer1e125222022-12-29 09:35:25 +08001373
developer06a01d92022-09-07 16:32:39 +08001374 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001375 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001376 _syscmd(cmd, buf, sizeof(buf));
1377 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001378 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001379
developerd946fd62022-12-08 18:03:28 +08001380 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08001381 _syscmd(cmd, buf, sizeof(buf));
1382 }
developer06a01d92022-09-07 16:32:39 +08001383 }
1384 else
1385 {
developer033b37b2022-10-18 11:27:46 +08001386 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001387 {
developer1e125222022-12-29 09:35:25 +08001388 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001389 continue;
developer1e125222022-12-29 09:35:25 +08001390
developerd946fd62022-12-08 18:03:28 +08001391 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001392 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001393 if(*buf == '1') {
1394 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1395 ret = _syscmd(cmd, buf, sizeof(buf));
1396 if ( ret == RETURN_ERR) {
1397 fprintf(stderr, "VAP interface creation failed\n");
1398 continue;
1399 }
1400
developer06a01d92022-09-07 16:32:39 +08001401 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001402 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001403 _syscmd(cmd, buf, sizeof(buf));
1404 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001405 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001406 }
1407 }
1408 }
1409
1410 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1411 return RETURN_OK;
1412}
1413
1414//Get the Radio enable status
1415INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1416{
1417 if (NULL == output_bool)
1418 return RETURN_ERR;
1419
1420 return wifi_getRadioEnable(radioIndex, output_bool);
1421}
1422
1423//Get the Radio Interface name from platform, eg "wlan0"
1424INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1425{
developer804c64f2022-10-19 13:54:40 +08001426 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001427 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001428 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001429}
1430
1431//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1432//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.
1433INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1434{
developerbcc556a2022-09-22 20:02:45 +08001435 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1436 // For max bit rate, we should always choose the best MCS
1437 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001438 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001439 char *tmp = NULL;
1440 UINT mode_map = 0;
1441 UINT num_subcarrier = 0;
1442 UINT code_bits = 0;
1443 float code_rate = 0; // use max code rate
1444 int NSS = 0;
1445 UINT Symbol_duration = 0;
1446 UINT GI_duration = 0;
1447 wifi_band band = band_invalid;
1448 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1449 BOOL enable = FALSE;
1450 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001451
1452 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1453 if (NULL == output_string)
1454 return RETURN_ERR;
1455
developerbcc556a2022-09-22 20:02:45 +08001456 wifi_getRadioEnable(radioIndex, &enable);
1457 if (enable == FALSE) {
1458 snprintf(output_string, 64, "0 Mb/s");
1459 return RETURN_OK;
1460 }
1461
1462 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1463 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1464 return RETURN_ERR;
1465 }
1466
1467 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1468 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1469 return RETURN_ERR;
1470 }
1471
1472 if (gi == wifi_guard_interval_3200)
1473 GI_duration = 32;
1474 else if (gi == wifi_guard_interval_1600)
1475 GI_duration = 16;
1476 else if (gi == wifi_guard_interval_800)
1477 GI_duration = 8;
1478 else // auto, 400
1479 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001480
developerbcc556a2022-09-22 20:02:45 +08001481 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1482 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1483 return RETURN_ERR;
1484 }
1485
1486 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1487 strcpy(channel_bandwidth_str, "160");
1488
1489 if (mode_map & WIFI_MODE_AX) {
1490 if (strstr(channel_bandwidth_str, "160") != NULL)
1491 num_subcarrier = 1960;
1492 else if (strstr(channel_bandwidth_str, "80") != NULL)
1493 num_subcarrier = 980;
1494 else if (strstr(channel_bandwidth_str, "40") != NULL)
1495 num_subcarrier = 468;
1496 else if (strstr(channel_bandwidth_str, "20") != NULL)
1497 num_subcarrier = 234;
1498 code_bits = 10;
1499 code_rate = (float)5/6;
1500 Symbol_duration = 128;
1501 } else if (mode_map & WIFI_MODE_AC) {
1502 if (strstr(channel_bandwidth_str, "160") != NULL)
1503 num_subcarrier = 468;
1504 else if (strstr(channel_bandwidth_str, "80") != NULL)
1505 num_subcarrier = 234;
1506 else if (strstr(channel_bandwidth_str, "40") != NULL)
1507 num_subcarrier = 108;
1508 else if (strstr(channel_bandwidth_str, "20") != NULL)
1509 num_subcarrier = 52;
1510 code_bits = 8;
1511 code_rate = (float)5/6;
1512 Symbol_duration = 32;
1513 } else if (mode_map & WIFI_MODE_N) {
1514 if (strstr(channel_bandwidth_str, "160") != NULL)
1515 num_subcarrier = 468;
1516 else if (strstr(channel_bandwidth_str, "80") != NULL)
1517 num_subcarrier = 234;
1518 else if (strstr(channel_bandwidth_str, "40") != NULL)
1519 num_subcarrier = 108;
1520 else if (strstr(channel_bandwidth_str, "20") != NULL)
1521 num_subcarrier = 52;
1522 code_bits = 6;
1523 code_rate = (float)3/4;
1524 Symbol_duration = 32;
1525 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1526 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1527 snprintf(output_string, 64, "65 Mb/s");
1528 return RETURN_OK;
1529 } else {
1530 snprintf(output_string, 64, "0 Mb/s");
1531 return RETURN_OK;
1532 }
developer06a01d92022-09-07 16:32:39 +08001533
developerbcc556a2022-09-22 20:02:45 +08001534 // Spatial streams
1535 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1536 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1537 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001538 }
developerbcc556a2022-09-22 20:02:45 +08001539
1540 // multiple 10 is to align duration unit (0.1 us)
1541 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1542 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1543
developer06a01d92022-09-07 16:32:39 +08001544 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1545
1546 return RETURN_OK;
1547}
1548#if 0
1549INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1550{
1551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1552 char cmd[64];
1553 char buf[1024];
1554 int apIndex;
1555
1556 if (NULL == output_string)
1557 return RETURN_ERR;
1558
1559 apIndex=(radioIndex==0)?0:1;
1560
developerd946fd62022-12-08 18:03:28 +08001561 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001562 _syscmd(cmd,buf, sizeof(buf));
1563
1564 snprintf(output_string, 64, "%s", buf);
1565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1566 return RETURN_OK;
1567}
1568#endif
1569
1570
1571//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1572//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.
1573INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1574{
developer963da0c2022-09-13 15:58:27 +08001575 wifi_band band = band_invalid;
1576
developer06a01d92022-09-07 16:32:39 +08001577 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1578 if (NULL == output_string)
1579 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001580
1581 band = wifi_index_to_band(radioIndex);
1582
1583 memset(output_string, 0, 10);
1584 if (band == band_2_4)
1585 strcpy(output_string, "2.4GHz");
1586 else if (band == band_5)
1587 strcpy(output_string, "5GHz");
1588 else if (band == band_6)
1589 strcpy(output_string, "6GHz");
1590 else
1591 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1593
1594 return RETURN_OK;
1595#if 0
1596 char buf[MAX_BUF_SIZE]={'\0'};
1597 char str[MAX_BUF_SIZE]={'\0'};
1598 char cmd[MAX_CMD_SIZE]={'\0'};
1599 char *ch=NULL;
1600 char *ch2=NULL;
1601
1602 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1603 if (NULL == output_string)
1604 return RETURN_ERR;
1605
1606
1607 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1608
1609 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1610 {
1611 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1612 return RETURN_ERR;
1613 }
1614 ch=strchr(buf,'\n');
1615 *ch='\0';
1616 ch=strchr(buf,'=');
1617 if(ch==NULL)
1618 return RETURN_ERR;
1619
1620
1621 ch++;
1622
1623 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1624 strcpy(buf,"0");
1625 if(strlen(ch) == 1)
1626 ch=strcat(buf,ch);
1627
1628
1629 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1630
1631 if(_syscmd(cmd,str,64) == RETURN_ERR)
1632 {
1633 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1634 return RETURN_ERR;
1635 }
1636
1637
1638 ch2=strchr(str,'\n');
1639 //replace \n with \0
1640 *ch2='\0';
1641 ch2=strchr(str,'=');
1642 if(ch2==NULL)
1643 {
1644 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1645 return RETURN_ERR;
1646 }
1647 else
1648 wifi_dbg_printf("%s",ch2+1);
1649
1650
1651 ch2++;
1652
1653
1654 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1655
1656 memset(buf,'\0',sizeof(buf));
1657 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1658 {
1659 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1660 return RETURN_ERR;
1661 }
1662 if (strstr(buf,"2.4") != NULL )
1663 strcpy(output_string,"2.4GHz");
1664 else if(strstr(buf,"5.") != NULL )
1665 strcpy(output_string,"5GHz");
1666 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1667
1668 return RETURN_OK;
1669#endif
1670}
1671
1672//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1673//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.
1674INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1675{
developerb7593de2022-10-18 09:51:57 +08001676 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001677 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1678 if (NULL == output_string)
1679 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001680 band = wifi_index_to_band(radioIndex);
1681
1682 if (band == band_2_4)
1683 snprintf(output_string, 64, "2.4GHz");
1684 else if (band == band_5)
1685 snprintf(output_string, 64, "5GHz");
1686 else if (band == band_6)
1687 snprintf(output_string, 64, "6GHz");
1688
developer06a01d92022-09-07 16:32:39 +08001689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1690
1691 return RETURN_OK;
1692#if 0
1693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1694 char buf[MAX_BUF_SIZE]={'\0'};
1695 char str[MAX_BUF_SIZE]={'\0'};
1696 char cmd[MAX_CMD_SIZE]={'\0'};
1697 char *ch=NULL;
1698 char *ch2=NULL;
1699 char ch1[5]="0";
1700
1701 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1702
1703 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1704 {
1705 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1706 return RETURN_ERR;
1707 }
1708
1709 ch=strchr(buf,'\n');
1710 *ch='\0';
1711 ch=strchr(buf,'=');
1712 if(ch==NULL)
1713 return RETURN_ERR;
1714 ch++;
1715
1716 if(strlen(ch)==1)
1717 {
1718 strcat(ch1,ch);
1719
1720 }
1721 else
1722 {
1723 strcpy(ch1,ch);
1724 }
1725
1726
1727
1728 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1729 if(_syscmd(cmd,str,64) == RETURN_ERR)
1730 {
1731 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1732 return RETURN_ERR;
1733 }
1734
1735
1736 ch2=strchr(str,'\n');
1737 //replace \n with \0
1738 *ch2='\0';
1739 ch2=strchr(str,'=');
1740 if(ch2==NULL)
1741 {
1742 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1743 return RETURN_ERR;
1744 }
1745 else
1746 wifi_dbg_printf("%s",ch2+1);
1747 ch2++;
1748
1749
1750 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1751 memset(buf,'\0',sizeof(buf));
1752 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1753 {
1754 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1755 return RETURN_ERR;
1756 }
1757
1758
1759 if(strstr(buf,"2.4")!=NULL)
1760 {
1761 strcpy(output_string,"2.4GHz");
1762 }
1763 if(strstr(buf,"5.")!=NULL)
1764 {
1765 strcpy(output_string,"5GHz");
1766 }
1767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1768 return RETURN_OK;
1769#endif
1770}
1771
1772//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1773//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.
1774INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1775{
developer963da0c2022-09-13 15:58:27 +08001776 char cmd[128]={0};
1777 char buf[128]={0};
1778 char temp_output[128] = {0};
1779 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001780 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001781
1782 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001783 if (NULL == output_string)
1784 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001785
1786 band = wifi_index_to_band(radioIndex);
1787 if (band == band_2_4) {
1788 strcat(temp_output, "b,g,");
1789 } else if (band == band_5) {
1790 strcat(temp_output, "a,");
1791 }
developer033b37b2022-10-18 11:27:46 +08001792 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001793 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001794 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 +08001795 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001796 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001797 strcat(temp_output, "n,");
1798 }
developer06a01d92022-09-07 16:32:39 +08001799
developer963da0c2022-09-13 15:58:27 +08001800 // vht capabilities
1801 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001802 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 +08001803 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001804 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001805 strcat(temp_output, "ac,");
1806 }
1807 }
1808
1809 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001810 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 +08001811 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001812 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001813 strcat(temp_output, "ax,");
1814 }
1815
developer7c4cd202023-03-01 10:56:29 +08001816 // eht capabilities
1817 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);
1818 _syscmd(cmd, buf, sizeof(buf));
1819 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1820 strcat(temp_output, "be,");
1821 }
1822
developer963da0c2022-09-13 15:58:27 +08001823 // Remove the last comma
1824 if (strlen(temp_output) != 0)
1825 temp_output[strlen(temp_output)-1] = '\0';
1826 strncpy(output_string, temp_output, strlen(temp_output));
1827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001828 return RETURN_OK;
1829}
1830
1831//Get the radio operating mode, and pure mode flag. eg: "ac"
1832//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.
1833INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1834{
1835 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1836 if (NULL == output_string)
1837 return RETURN_ERR;
1838
1839 if (radioIndex == 0) {
1840 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1841 *gOnly = FALSE;
1842 *nOnly = TRUE;
1843 *acOnly = FALSE;
1844 } else {
1845 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1846 *gOnly = FALSE;
1847 *nOnly = FALSE;
1848 *acOnly = FALSE;
1849 }
1850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1851
1852 return RETURN_OK;
1853#if 0
1854 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1855 char buf[64] = {0};
1856 char config_file[MAX_BUF_SIZE] = {0};
1857
1858 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1859 return RETURN_ERR;
1860
1861 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1862 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1863
1864 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1865 if (strlen(buf) == 0)
1866 {
1867 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1868 return RETURN_ERR;
1869 }
1870 if(strcmp(buf,"g")==0)
1871 {
1872 wifi_dbg_printf("\nG\n");
1873 *gOnly=TRUE;
1874 *nOnly=FALSE;
1875 *acOnly=FALSE;
1876 }
1877 else if(strcmp(buf,"n")==0)
1878 {
1879 wifi_dbg_printf("\nN\n");
1880 *gOnly=FALSE;
1881 *nOnly=TRUE;
1882 *acOnly=FALSE;
1883 }
1884 else if(strcmp(buf,"ac")==0)
1885 {
1886 wifi_dbg_printf("\nac\n");
1887 *gOnly=FALSE;
1888 *nOnly=FALSE;
1889 *acOnly=TRUE;
1890 }
1891 /* hostapd-5G.conf has "a" as hw_mode */
1892 else if(strcmp(buf,"a")==0)
1893 {
1894 wifi_dbg_printf("\na\n");
1895 *gOnly=FALSE;
1896 *nOnly=FALSE;
1897 *acOnly=FALSE;
1898 }
1899 else
1900 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1901
1902 //for a,n mode
1903 if(radioIndex == 1)
1904 {
1905 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1906 if(strcmp(buf,"1")==0)
1907 {
1908 strncpy(output_string, "n", 1);
1909 *nOnly=FALSE;
1910 }
1911 }
1912
1913 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1914 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1915 return RETURN_OK;
1916#endif
1917}
1918
developerdb744382022-09-13 15:34:54 +08001919INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1920{
1921 char cmd[128] = {0};
1922 char buf[64] = {0};
1923 char config_file[64] = {0};
1924 wifi_band band;
1925
1926 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1927 if(NULL == output_string || NULL == pureMode)
1928 return RETURN_ERR;
1929
1930 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001931 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001932 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 +08001933 _syscmd(cmd, buf, sizeof(buf));
1934
1935 band = wifi_index_to_band(radioIndex);
1936 // puremode is a bit map
1937 *pureMode = 0;
1938 if (band == band_2_4) {
1939 strcat(output_string, "b,g");
1940 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1941 if (strstr(buf, "n") != NULL) {
1942 strcat(output_string, ",n");
1943 *pureMode |= WIFI_MODE_N;
1944 }
1945 if (strstr(buf, "ax") != NULL) {
1946 strcat(output_string, ",ax");
1947 *pureMode |= WIFI_MODE_AX;
1948 }
developer7c4cd202023-03-01 10:56:29 +08001949 if (strstr(buf, "be") != NULL) {
1950 strcat(output_string, ",be");
1951 *pureMode |= WIFI_MODE_BE;
1952 }
developerdb744382022-09-13 15:34:54 +08001953 } else if (band == band_5) {
1954 strcat(output_string, "a");
1955 *pureMode |= WIFI_MODE_A;
1956 if (strstr(buf, "n") != NULL) {
1957 strcat(output_string, ",n");
1958 *pureMode |= WIFI_MODE_N;
1959 }
1960 if (strstr(buf, "ac") != NULL) {
1961 strcat(output_string, ",ac");
1962 *pureMode |= WIFI_MODE_AC;
1963 }
1964 if (strstr(buf, "ax") != NULL) {
1965 strcat(output_string, ",ax");
1966 *pureMode |= WIFI_MODE_AX;
1967 }
developer7c4cd202023-03-01 10:56:29 +08001968 if (strstr(buf, "be") != NULL) {
1969 strcat(output_string, ",be");
1970 *pureMode |= WIFI_MODE_BE;
1971 }
developerdb744382022-09-13 15:34:54 +08001972 } else if (band == band_6) {
1973 if (strstr(buf, "ax") != NULL) {
1974 strcat(output_string, "ax");
1975 *pureMode |= WIFI_MODE_AX;
1976 }
developer7c4cd202023-03-01 10:56:29 +08001977 if (strstr(buf, "be") != NULL) {
1978 strcat(output_string, ",be");
1979 *pureMode |= WIFI_MODE_BE;
1980 }
developerdb744382022-09-13 15:34:54 +08001981 }
1982
1983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1984 return RETURN_OK;
1985}
1986
1987// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001988INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1989{
1990 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1991 if (strcmp (channelMode,"11A") == 0)
1992 {
1993 writeBandWidth(radioIndex,"20MHz");
1994 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1995 printf("\nChannel Mode is 802.11a (5GHz)\n");
1996 }
1997 else if (strcmp (channelMode,"11NAHT20") == 0)
1998 {
1999 writeBandWidth(radioIndex,"20MHz");
2000 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2001 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2002 }
2003 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2004 {
2005 writeBandWidth(radioIndex,"40MHz");
2006 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2007 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2008 }
2009 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2010 {
2011 writeBandWidth(radioIndex,"40MHz");
2012 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2013 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2014 }
2015 else if (strcmp (channelMode,"11ACVHT20") == 0)
2016 {
2017 writeBandWidth(radioIndex,"20MHz");
2018 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2019 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2020 }
2021 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2022 {
2023 writeBandWidth(radioIndex,"40MHz");
2024 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2025 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2026 }
2027 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2028 {
2029 writeBandWidth(radioIndex,"40MHz");
2030 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2031 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2032 }
2033 else if (strcmp (channelMode,"11ACVHT80") == 0)
2034 {
2035 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2036 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2037 }
2038 else if (strcmp (channelMode,"11ACVHT160") == 0)
2039 {
2040 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2041 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2042 }
2043 else if (strcmp (channelMode,"11B") == 0)
2044 {
2045 writeBandWidth(radioIndex,"20MHz");
2046 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2047 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2048 }
2049 else if (strcmp (channelMode,"11G") == 0)
2050 {
2051 writeBandWidth(radioIndex,"20MHz");
2052 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2053 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2054 }
2055 else if (strcmp (channelMode,"11NGHT20") == 0)
2056 {
2057 writeBandWidth(radioIndex,"20MHz");
2058 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2059 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2060 }
2061 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2062 {
2063 writeBandWidth(radioIndex,"40MHz");
2064 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2065 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2066 }
2067 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2068 {
2069 writeBandWidth(radioIndex,"40MHz");
2070 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2071 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2072 }
2073 else
2074 {
2075 return RETURN_ERR;
2076 }
2077 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2078
2079 return RETURN_OK;
2080}
2081
developerdb744382022-09-13 15:34:54 +08002082// Set the radio operating mode, and pure mode flag.
2083INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2084{
developer7c4cd202023-03-01 10:56:29 +08002085 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002086 struct params list[num_hostapd_support_mode];
2087 char config_file[64] = {0};
2088 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002089 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002090 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002091 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002092
2093 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2094 // Set radio mode
2095 list[0].name = "ieee80211n";
2096 list[1].name = "ieee80211ac";
2097 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002098 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002099 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2100
2101 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002102 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002103 list[0].value = "1";
2104 else
2105 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002106 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002107 list[1].value = "1";
2108 else
2109 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002110 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002111 list[2].value = "1";
2112 else
2113 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002114 if (pureMode & WIFI_MODE_BE)
2115 list[3].value = "1";
2116 else
2117 list[3].value = "0";
2118
2119 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2120 if (strstr(supported_mode, "be") != NULL)
2121 eht_support = TRUE;
2122
2123 if (eht_support)
2124 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2125 else
2126 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002127
2128 if (channelMode == NULL || strlen(channelMode) == 0)
2129 return RETURN_OK;
2130 // Set bandwidth
2131 if (strstr(channelMode, "40") != NULL)
2132 strcpy(bandwidth, "40MHz");
2133 else if (strstr(channelMode, "80") != NULL)
2134 strcpy(bandwidth, "80MHz");
2135 else if (strstr(channelMode, "160") != NULL)
2136 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002137 else if (strstr(channelMode, "320") != NULL)
2138 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002139 else // 11A, 11B, 11G....
2140 strcpy(bandwidth, "20MHz");
2141
2142 writeBandWidth(radioIndex, bandwidth);
2143 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2144
2145 wifi_reloadAp(radioIndex);
2146 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2147
2148 return RETURN_OK;
2149}
2150
developer1d12ebf2022-10-04 15:13:38 +08002151INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2152
2153 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002154 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002155 struct params params = {0};
2156 wifi_band band = band_invalid;
2157
2158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2159
2160 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002161
2162 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002163 return RETURN_ERR;
2164 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2165 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002166 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2167 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002168
2169 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2170 params.name = "hw_mode";
2171 params.value = hw_mode;
2172 wifi_hostapdWrite(config_file, &params, 1);
2173 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2174
developeref938762022-10-19 17:21:01 +08002175 if (band == band_2_4) {
2176 if (strncmp(hw_mode, "b", 1) == 0) {
2177 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2178 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2179 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2180 snprintf(buf, sizeof(buf), "%s", "1,2");
2181 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2182 } else {
2183 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2184
2185 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2186 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2187 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2188 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2189 }
2190 }
2191
developer1d12ebf2022-10-04 15:13:38 +08002192 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2193 return RETURN_OK;
2194}
2195
developere8988ba2022-10-18 17:42:30 +08002196INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2197{
2198 char config_file[64] = {0};
2199 struct params params = {0};
2200 wifi_band band = band_invalid;
2201
2202 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2203
2204 band = wifi_index_to_band(radioIndex);
2205
2206 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2207 params.name = "noscan";
2208 params.value = noscan;
2209 wifi_hostapdWrite(config_file, &params, 1);
2210 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2211
2212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2213 return RETURN_OK;
2214}
2215
developer06a01d92022-09-07 16:32:39 +08002216//Get the list of supported channel. eg: "1-11"
2217//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.
2218INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2219{
developer6318ed52022-09-13 15:17:58 +08002220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002221 if (NULL == output_string)
2222 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002223 char cmd[256] = {0};
2224 char buf[128] = {0};
2225 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002226 int phyId = 0;
2227
developer6318ed52022-09-13 15:17:58 +08002228 // Parse possible channel number and separate them with commas.
2229 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002230 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002231 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002232 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002233 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 +08002234 else
developer033b37b2022-10-18 11:27:46 +08002235 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 +08002236
2237 _syscmd(cmd,buf,sizeof(buf));
2238 strncpy(output_string, buf, sizeof(buf));
2239
2240 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2241 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002242}
2243
2244//Get the list for used channel. eg: "1,6,9,11"
2245//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.
2246INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2247{
developerd946fd62022-12-08 18:03:28 +08002248 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002249 char cmd[128] = {0};
2250 char buf[128] = {0};
2251 char config_file[64] = {0};
2252 int channel = 0;
2253 int freq = 0;
2254 int bandwidth = 0;
2255 int center_freq = 0;
2256 int center_channel = 0;
2257 int channel_delta = 0;
2258 wifi_band band = band_invalid;
2259
2260 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2261
developer06a01d92022-09-07 16:32:39 +08002262 if (NULL == output_string)
2263 return RETURN_ERR;
2264
developerac6f1142022-12-20 19:26:35 +08002265 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002266 return RETURN_ERR;
2267 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002268 _syscmd(cmd, buf, sizeof(buf));
2269 if (strlen(buf) == 0) {
2270 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2271 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002272 }
developerf5745ee2022-10-05 16:09:53 +08002273 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2274
2275 if (bandwidth == 20) {
2276 snprintf(output_string, 256, "%d", channel);
2277 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002278 }
developerf5745ee2022-10-05 16:09:53 +08002279
2280 center_channel = ieee80211_frequency_to_channel(center_freq);
2281
2282 band = wifi_index_to_band(radioIndex);
2283 if (band == band_2_4 && bandwidth == 40) {
2284 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2285 memset(buf, 0, sizeof(buf));
2286 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2287
developerf22724d2022-12-22 17:24:14 +08002288 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002289 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002290 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002291 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2292 } else {
2293 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2294 return RETURN_ERR;
2295 }
2296 } else if (band == band_5 || band == band_6){
2297 // 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 +08002298 // 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 +08002299 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002300 memset(output_string, 0, 256);
2301 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2302 // If i is not the last channel, we add a comma.
2303 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2304 strncat(output_string, buf, strlen(buf));
2305 }
developerf5745ee2022-10-05 16:09:53 +08002306 } else
2307 return RETURN_ERR;
2308
2309 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002310 return RETURN_OK;
2311}
2312
2313//Get the running channel number
2314INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2315{
developer5b398df2022-11-17 20:39:48 +08002316 char channel_str[16] = {0};
2317 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002318
developer5b398df2022-11-17 20:39:48 +08002319 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002320 return RETURN_ERR;
2321
developer5b398df2022-11-17 20:39:48 +08002322 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2323 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002324
developer5b398df2022-11-17 20:39:48 +08002325 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002326
developer06a01d92022-09-07 16:32:39 +08002327 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002328}
2329
2330
2331INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2332{
2333 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002334 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002335
2336 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2337 if (NULL == output_ulong)
2338 return RETURN_ERR;
2339
developer06a01d92022-09-07 16:32:39 +08002340 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002341 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2342 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002343 _syscmd(cmd,buf,sizeof(buf));
2344 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2345 if (*output_ulong == 0) {
2346 return RETURN_ERR;
2347 }
2348
2349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2350 return RETURN_OK;
2351}
2352
2353//Storing the previous channel value
2354INT wifi_storeprevchanval(INT radioIndex)
2355{
2356 char buf[256] = {0};
2357 char output[4]={'\0'};
2358 char config_file[MAX_BUF_SIZE] = {0};
2359 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2360 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2361 if(radioIndex == 0)
2362 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2363 else if(radioIndex == 1)
2364 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2365 system(buf);
2366 Radio_flag = FALSE;
2367 return RETURN_OK;
2368}
2369
2370//Set the running channel number
2371INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2372{
developer76989232022-10-04 14:13:19 +08002373 // We only write hostapd config here
2374 char str_channel[8]={0};
2375 char *list_channel;
2376 char config_file[128] = {0};
2377 char possible_channels[256] = {0};
2378 int max_radio_num = 0;
2379 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002380
developer76989232022-10-04 14:13:19 +08002381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002382
developer76989232022-10-04 14:13:19 +08002383 // Check valid
2384 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002385
developer76989232022-10-04 14:13:19 +08002386 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2387 list_channel = strtok(possible_channels, ",");
2388 while(true)
developer06a01d92022-09-07 16:32:39 +08002389 {
developer76989232022-10-04 14:13:19 +08002390 if(list_channel == NULL) { // input not in the list
2391 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2392 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002393 }
developer76989232022-10-04 14:13:19 +08002394 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2395 break;
2396 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002397 }
2398
developer76989232022-10-04 14:13:19 +08002399 list.name = "channel";
2400 list.value = str_channel;
2401 wifi_getMaxRadioNumber(&max_radio_num);
2402 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002403 {
developer76989232022-10-04 14:13:19 +08002404 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2405 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002406 }
2407
developer76989232022-10-04 14:13:19 +08002408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002409 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002410}
developer06a01d92022-09-07 16:32:39 +08002411
2412INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2413{
developer7c4cd202023-03-01 10:56:29 +08002414 struct params list[3];
2415 char str_idx[16] = {0};
2416 char supported_mode[32] = {0};
2417 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002418 int max_num_radios = 0;
2419 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002420 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002421
2422 band = wifi_index_to_band(radioIndex);
2423 if (band == band_2_4)
2424 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002425
developer7c4cd202023-03-01 10:56:29 +08002426 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2427 if (strstr(supported_mode, "be") != NULL)
2428 eht_support = TRUE;
2429
developer30423732022-12-01 16:17:49 +08002430 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002431 list[0].name = "vht_oper_centr_freq_seg0_idx";
2432 list[0].value = str_idx;
2433 list[1].name = "he_oper_centr_freq_seg0_idx";
2434 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002435 list[2].name = "eht_oper_centr_freq_seg0_idx";
2436 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002437
developer76989232022-10-04 14:13:19 +08002438 wifi_getMaxRadioNumber(&max_num_radios);
2439 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002440 {
developer76989232022-10-04 14:13:19 +08002441 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002442 if (eht_support)
2443 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002444 else
2445 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002446 }
2447
2448 return RETURN_OK;
2449}
2450
2451//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2452//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2453INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2454{
2455 //Set to wifi config only. Wait for wifi reset to apply.
2456 char buf[256] = {0};
2457 char str_channel[256] = {0};
2458 int count = 0;
2459 ULONG Value = 0;
2460 FILE *fp = NULL;
2461 if(enable == TRUE)
2462 {
developer06a01d92022-09-07 16:32:39 +08002463 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002464 }
developer5884e982022-10-06 10:52:50 +08002465 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002466}
2467
developer0b246d12022-09-30 15:24:20 +08002468INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2469{
2470 if (output_bool == NULL)
2471 return RETURN_ERR;
2472
2473 *output_bool = TRUE;
2474
2475 return RETURN_OK;
2476}
2477
developer06a01d92022-09-07 16:32:39 +08002478INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2479{
2480 if (NULL == output_bool)
2481 return RETURN_ERR;
2482 *output_bool=FALSE;
2483 return RETURN_OK;
2484}
2485
2486INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2487{
2488 if (NULL == output_bool)
2489 return RETURN_ERR;
2490 *output_bool=FALSE;
2491 return RETURN_OK;
2492}
2493
2494INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2495{
2496 //Set to wifi config only. Wait for wifi reset to apply.
2497 return RETURN_OK;
2498}
2499
2500INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2501{
2502 return RETURN_OK;
2503}
2504
2505INT wifi_factoryResetAP(int apIndex)
2506{
developer838cca92022-10-03 13:19:57 +08002507 char ap_config_file[64] = {0};
2508 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002509 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002510 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002511
developer06a01d92022-09-07 16:32:39 +08002512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002513
2514 wifi_setApEnable(apIndex, FALSE);
2515 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2516 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002517 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002518 wifi_getMaxRadioNumber(&max_radio_num);
2519 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2520 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002521
developer06a01d92022-09-07 16:32:39 +08002522 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002523
developer06a01d92022-09-07 16:32:39 +08002524 return RETURN_OK;
2525}
2526
2527//To set Band Steering AP group
2528//To-do
2529INT wifi_setBandSteeringApGroup(char *ApGroup)
2530{
2531 return RETURN_OK;
2532}
2533
developer1e5aa162022-09-13 16:06:24 +08002534INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2535{
2536 char config_file[128] = {'\0'};
2537 char buf[128] = {'\0'};
2538
2539 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2540 if (dtimInterval == NULL)
2541 return RETURN_ERR;
2542
2543 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2544 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2545
2546 if (strlen(buf) == 0) {
2547 *dtimInterval = 2;
2548 } else {
2549 *dtimInterval = strtoul(buf, NULL, 10);
2550 }
2551
2552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2553 return RETURN_OK;
2554}
2555
developer06a01d92022-09-07 16:32:39 +08002556INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2557{
developer5f222492022-09-13 15:21:52 +08002558 struct params params={0};
2559 char config_file[MAX_BUF_SIZE] = {'\0'};
2560 char buf[MAX_BUF_SIZE] = {'\0'};
2561
2562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2563 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002564 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002565 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002566 }
2567
2568 params.name = "dtim_period";
2569 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2570 params.value = buf;
2571
2572 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2573 wifi_hostapdWrite(config_file, &params, 1);
2574 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2575
2576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2577 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002578}
2579
2580//Check if the driver support the Dfs
2581INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2582{
developer78a15382022-11-02 10:57:40 +08002583 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002584 if (NULL == output_bool)
2585 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002586 *output_bool=FALSE;
2587
2588 band = wifi_index_to_band(radioIndex);
2589 if (band == band_5)
2590 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002591 return RETURN_OK;
2592}
2593
2594//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.
2595//The value of this parameter is a comma seperated list of channel number
2596INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2597{
2598 if (NULL == output_pool)
2599 return RETURN_ERR;
2600 if (radioIndex==1)
2601 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2602 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2603
2604 return RETURN_OK;
2605}
2606
2607INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2608{
2609 //Set to wifi config. And apply instantly.
2610 return RETURN_OK;
2611}
2612
2613INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2614{
2615 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2616 return RETURN_ERR;
2617 *output_interval_seconds=1800;
2618 *output_dwell_milliseconds=40;
2619
2620 return RETURN_OK;
2621}
2622
2623INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2624{
2625 //Set to wifi config. And apply instantly.
2626 return RETURN_OK;
2627}
2628
developerbfc18512022-10-05 17:54:28 +08002629INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2630{
2631 if (output_bool == NULL)
2632 return RETURN_ERR;
2633 *output_bool = true;
2634 return RETURN_OK;
2635}
2636
2637INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2638{
2639 return RETURN_OK;
2640}
2641
developer06a01d92022-09-07 16:32:39 +08002642//Get the Dfs enable status
2643INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2644{
developer9964b5b2022-09-13 15:59:34 +08002645 char buf[16] = {0};
2646 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002647
2648 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2649
developer30423732022-12-01 16:17:49 +08002650 if (output_bool == NULL)
2651 return RETURN_ERR;
2652
developer9964b5b2022-09-13 15:59:34 +08002653 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002654 f = fopen(DFS_ENABLE_FILE, "r");
2655 if (f != NULL) {
2656 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002657 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002658 *output_bool = FALSE;
2659 fclose(f);
2660 }
2661 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002662 return RETURN_OK;
2663}
2664
2665//Set the Dfs enable status
2666INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2667{
developer9964b5b2022-09-13 15:59:34 +08002668 char config_file[128] = {0};
2669 FILE *f = NULL;
2670 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002671
2672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2673
developer9964b5b2022-09-13 15:59:34 +08002674 f = fopen(DFS_ENABLE_FILE, "w");
2675 if (f == NULL)
2676 return RETURN_ERR;
2677 fprintf(f, "%d", enable);
2678 fclose(f);
2679
2680 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002681 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002682 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2683 wifi_hostapdWrite(config_file, &params, 1);
2684 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2685
2686 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2687
developer9964b5b2022-09-13 15:59:34 +08002688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002689 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002690}
2691
2692//Check if the driver support the AutoChannelRefreshPeriod
2693INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2694{
2695 if (NULL == output_bool)
2696 return RETURN_ERR;
2697 *output_bool=FALSE; //not support
2698
2699 return RETURN_OK;
2700}
2701
2702//Get the ACS refresh period in seconds
2703INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2704{
2705 if (NULL == output_ulong)
2706 return RETURN_ERR;
2707 *output_ulong=300;
2708
2709 return RETURN_OK;
2710}
2711
2712//Set the ACS refresh period in seconds
2713INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2714{
2715 return RETURN_ERR;
2716}
2717
developer7c4cd202023-03-01 10:56:29 +08002718INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2719{
2720 int center_channel = 0;
2721 char config_file[32] = {0};
2722 char buf[32] = {0};
2723
2724 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2725 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2726
2727 center_channel = strtoul(buf, NULL, 10);
2728 center_channel += 1; // Add 1 to become muiltiple of 16
2729 if (center_channel % 64 == 32)
2730 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2731 else if (center_channel % 64 == 0)
2732 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2733 else
2734 return RETURN_ERR;
2735 return RETURN_OK;
2736}
2737
developer06a01d92022-09-07 16:32:39 +08002738//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2739//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.
2740INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2741{
developer72ec5572023-01-05 16:27:13 +08002742 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002743 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002744 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002745 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002746 wifi_band band;
developer70490032022-09-13 15:45:20 +08002747
2748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2749
developer06a01d92022-09-07 16:32:39 +08002750 if (NULL == output_string)
2751 return RETURN_ERR;
2752
developer70490032022-09-13 15:45:20 +08002753 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2754 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002755
developer70490032022-09-13 15:45:20 +08002756 if (radio_enable != TRUE)
2757 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002758
developerfa41b1f2023-01-06 10:25:51 +08002759 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002760 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002761 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002762 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2763 snprintf(output_string, 64, "20MHz");
2764 else
2765 snprintf(output_string, 64, "40MHz");
2766
2767 } else {
2768 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2769 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2770 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2771 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2772 if (strncmp(buf, "0", 1) == 0)
2773 snprintf(output_string, 64, "20MHz");
2774 else
2775 snprintf(output_string, 64, "40MHz");
2776
2777 } else if (strncmp(buf, "1", 1) == 0)
2778 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002779 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002780 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002781 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2782 if (strncmp(buf, "9", 1) == 0) {
2783 int BandwidthSet = 0;
2784 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2785 return RETURN_ERR;
2786 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2787 snprintf(output_string, 64, "320-1MHz");
2788 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2789 snprintf(output_string, 64, "320-2MHz");
2790 }
2791 }
developer06a01d92022-09-07 16:32:39 +08002792 }
developer72ec5572023-01-05 16:27:13 +08002793
developer06a01d92022-09-07 16:32:39 +08002794 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002795
2796 return RETURN_OK;
2797}
2798
2799//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002800INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002801{
developerf7a466e2022-09-29 11:55:56 +08002802 char config_file[128];
2803 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002804 char supported_mode[32] = {0};
2805 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002806 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002807 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002808
developer06a01d92022-09-07 16:32:39 +08002809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002810
developerf7a466e2022-09-29 11:55:56 +08002811 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002812 return RETURN_ERR;
2813
developer7c4cd202023-03-01 10:56:29 +08002814 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002815 strcpy(set_value, "2");
2816 else if(strstr(bandwidth,"80") != NULL)
2817 strcpy(set_value, "1");
2818 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2819 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002820 else if (strstr(bandwidth, "Auto") != NULL)
2821 return RETURN_OK;
2822 else {
developerf7a466e2022-09-29 11:55:56 +08002823 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002824 return RETURN_ERR;
2825 }
2826
developer7c4cd202023-03-01 10:56:29 +08002827 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2828 if (strstr(supported_mode, "be") != NULL)
2829 eht_support = TRUE;
2830
developerf7a466e2022-09-29 11:55:56 +08002831 params[0].name = "vht_oper_chwidth";
2832 params[0].value = set_value;
2833 params[1].name = "he_oper_chwidth";
2834 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002835 params[2].name = "eht_oper_chwidth";
2836 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2837 params[2].value = "9";
2838 else
2839 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002840
developerf7a466e2022-09-29 11:55:56 +08002841 wifi_getMaxRadioNumber(&max_radio_num);
2842 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002843 {
developer7c4cd202023-03-01 10:56:29 +08002844 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2845 if (eht_support == TRUE)
2846 wifi_hostapdWrite(config_file, params, 3);
2847 else
2848 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002849 }
2850
2851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2852 return RETURN_OK;
2853}
2854
2855//Getting current radio extension channel
2856INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2857{
2858 CHAR buf[150] = {0};
2859 CHAR cmd[150] = {0};
2860 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2861 _syscmd(cmd, buf, sizeof(buf));
2862 if(NULL != strstr(buf,"HT40+"))
2863 strcpy(Value,"AboveControlChannel");
2864 else if(NULL != strstr(buf,"HT40-"))
2865 strcpy(Value,"BelowControlChannel");
2866 return RETURN_OK;
2867}
2868
2869//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2870//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.
2871INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2872{
developerfa41b1f2023-01-06 10:25:51 +08002873 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002874 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002875
2876 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002877 return RETURN_ERR;
2878
developerfa41b1f2023-01-06 10:25:51 +08002879 band = wifi_index_to_band(radioIndex);
2880 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002881 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002882
2883 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2884
2885 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002886 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002887
2888 return RETURN_OK;
2889}
2890
2891//Set the extension channel.
2892INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002893{
developer06a01d92022-09-07 16:32:39 +08002894 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002895 struct params params={0};
2896 char config_file[64] = {0};
2897 char ext_channel[128]={0};
2898 char buf[128] = {0};
2899 char cmd[128] = {0};
2900 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002901 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002902 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002903 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002904 wifi_band band;
2905
2906 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2907 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2908 _syscmd(cmd, buf, sizeof(buf));
2909 if (strlen(buf) != 0)
2910 stbcEnable = TRUE;
2911 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2912 return RETURN_ERR;
2913 bandwidth = strtol(buf, NULL, 10);
2914 // TDK expected to get error with 20MHz
2915 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2916 return RETURN_ERR;
2917
2918 band = wifi_index_to_band(radioIndex);
2919 if (band == band_invalid)
2920 return RETURN_ERR;
2921
2922 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2923 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002924
developer72ec5572023-01-05 16:27:13 +08002925 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2926 ret = util_get_sec_chan_offset(channel, buf);
2927 if (ret == -EINVAL)
2928 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002929
2930 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002931 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2932 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002933 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002934 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08002935 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
2936 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002937 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002938 } else {
developer033b37b2022-10-18 11:27:46 +08002939 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developerfa41b1f2023-01-06 10:25:51 +08002940 }
developer06a01d92022-09-07 16:32:39 +08002941
2942 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002943
2944 wifi_getMaxRadioNumber(&max_radio_num);
2945 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002946 {
developer033b37b2022-10-18 11:27:46 +08002947 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002948 wifi_hostapdWrite(config_file, &params, 1);
developerfa41b1f2023-01-06 10:25:51 +08002949 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
developer06a01d92022-09-07 16:32:39 +08002950 }
2951
2952 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2953 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2954 return RETURN_OK;
2955}
2956
2957//Get the guard interval value. eg "400nsec" or "800nsec"
2958//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.
2959INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2960{
developer454b9462022-09-13 15:29:16 +08002961 wifi_guard_interval_t GI;
2962
2963 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2964
2965 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002966 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002967
2968 if (GI == wifi_guard_interval_400)
2969 strcpy(output_string, "400nsec");
2970 else if (GI == wifi_guard_interval_800)
2971 strcpy(output_string, "800nsec");
2972 else if (GI == wifi_guard_interval_1600)
2973 strcpy(output_string, "1600nsec");
2974 else if (GI == wifi_guard_interval_3200)
2975 strcpy(output_string, "3200nsec");
2976 else
developer78a15382022-11-02 10:57:40 +08002977 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002978
developer454b9462022-09-13 15:29:16 +08002979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002980 return RETURN_OK;
2981}
2982
2983//Set the guard interval value.
2984INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2985{
developer454b9462022-09-13 15:29:16 +08002986 wifi_guard_interval_t GI;
2987 int ret = 0;
2988
2989 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2990
2991 if (strcmp(string, "400nsec") == 0)
2992 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002993 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002994 GI = wifi_guard_interval_800;
2995 else if (strcmp(string , "1600nsec") == 0)
2996 GI = wifi_guard_interval_1600;
2997 else if (strcmp(string , "3200nsec") == 0)
2998 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002999 else
3000 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003001
3002 ret = wifi_setGuardInterval(radioIndex, GI);
3003
3004 if (ret == RETURN_ERR) {
3005 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3006 return RETURN_ERR;
3007 }
3008
3009 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3010 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003011}
3012
3013//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3014INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3015{
developerf49437e2022-09-29 19:58:21 +08003016 char buf[32]={0};
3017 char mcs_file[64] = {0};
3018 char cmd[64] = {0};
3019 int mode_bitmap = 0;
3020
3021 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3022 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003023 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003024 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3025
3026 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3027 _syscmd(cmd, buf, sizeof(buf));
3028 if (strlen(buf) > 0)
3029 *output_int = strtol(buf, NULL, 10);
3030 else {
3031 // output the max MCS for the current radio mode
3032 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3033 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3034 return RETURN_ERR;
3035 }
3036 if (mode_bitmap & WIFI_MODE_AX) {
3037 *output_int = 11;
3038 } else if (mode_bitmap & WIFI_MODE_AC) {
3039 *output_int = 9;
3040 } else if (mode_bitmap & WIFI_MODE_N) {
3041 *output_int = 7;
3042 }
3043 }
3044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003045
3046 return RETURN_OK;
3047}
3048
3049//Set the Modulation Coding Scheme index
3050INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3051{
developerf49437e2022-09-29 19:58:21 +08003052 // 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).
3053 char config_file[64] = {0};
3054 char set_value[16] = {0};
3055 char mcs_file[32] = {0};
3056 wifi_band band = band_invalid;
3057 struct params set_config = {0};
3058 FILE *f = NULL;
3059
3060 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3061
3062 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3063
developer78a15382022-11-02 10:57:40 +08003064 // -1 means auto
3065 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003066 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3067 return RETURN_ERR;
3068 }
3069
developer78a15382022-11-02 10:57:40 +08003070 if (MCS > 9 || MCS == -1)
3071 strcpy(set_value, "2");
3072 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003073 strcpy(set_value, "1");
3074 else
developer78a15382022-11-02 10:57:40 +08003075 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003076
3077 set_config.name = "he_basic_mcs_nss_set";
3078 set_config.value = set_value;
3079
3080 wifi_hostapdWrite(config_file, &set_config, 1);
3081 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3082
3083 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3084 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3085 f = fopen(mcs_file, "w");
3086 if (f == NULL) {
3087 fprintf(stderr, "%s: fopen failed\n", __func__);
3088 return RETURN_ERR;
3089 }
3090 fprintf(f, "%d", MCS);
3091 fclose(f);
3092
3093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3094 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003095}
3096
3097//Get supported Transmit Power list, eg : "0,25,50,75,100"
3098//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.
3099INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3100{
3101 if (NULL == output_list)
3102 return RETURN_ERR;
3103 snprintf(output_list, 64,"0,25,50,75,100");
3104 return RETURN_OK;
3105}
3106
developera5005b62022-09-13 15:43:35 +08003107//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08003108//The transmite power level is in units of full power for this radio.
3109INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3110{
developerd946fd62022-12-08 18:03:28 +08003111 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003112 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003113 char buf[16]={0};
3114 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003115
developera5005b62022-09-13 15:43:35 +08003116 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003117 return RETURN_ERR;
3118
developerac6f1142022-12-20 19:26:35 +08003119 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003120 return RETURN_ERR;
3121 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003122 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003123
developera5005b62022-09-13 15:43:35 +08003124 *output_ulong = strtol(buf, NULL, 10);
3125
3126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003127 return RETURN_OK;
3128}
3129
3130//Set Transmit Power
3131//The transmite power level is in units of full power for this radio.
3132INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3133{
developerd946fd62022-12-08 18:03:28 +08003134 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003135 char *support;
developer06a01d92022-09-07 16:32:39 +08003136 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003137 char buf[128]={0};
3138 char txpower_str[64] = {0};
3139 int txpower = 0;
3140 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08003141 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003142
3143 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003144
developerac6f1142022-12-20 19:26:35 +08003145 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003146 return RETURN_ERR;
3147 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003148 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003149 maximum_tx = strtol(buf, NULL, 10);
3150
3151 // Get the Tx power supported list and check that is the input in the list
3152 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3153 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3154 support = strtok(buf, ",");
3155 while(true)
3156 {
3157 if(support == NULL) { // input not in the list
3158 wifi_dbg_printf("Input value is invalid.\n");
3159 return RETURN_ERR;
3160 }
3161 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3162 break;
3163 }
3164 support = strtok(NULL, ",");
3165 }
3166 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003167 phyId = radio_index_to_phy(radioIndex);
3168 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003169 _syscmd(cmd, buf, sizeof(buf));
3170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003171
3172 return RETURN_OK;
3173}
3174
3175//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3176INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3177{
3178 if (NULL == Supported)
3179 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003180 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003181
3182 return RETURN_OK;
3183}
3184
3185//Get 80211h feature enable
3186INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3187{
developer3885fec2022-09-13 15:13:47 +08003188 char buf[64]={'\0'};
3189 char config_file[64] = {'\0'};
3190
3191 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3192 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003193 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003194
3195 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3196 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003197
developer3885fec2022-09-13 15:13:47 +08003198 if (strncmp(buf, "1", 1) == 0)
3199 *enable = TRUE;
3200 else
3201 *enable = FALSE;
3202
3203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003204 return RETURN_OK;
3205}
3206
3207//Set 80211h feature enable
3208INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3209{
developer3885fec2022-09-13 15:13:47 +08003210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3211 struct params params={'\0'};
3212 char config_file[MAX_BUF_SIZE] = {0};
3213
3214 params.name = "ieee80211h";
3215
3216 if (enable) {
3217 params.value = "1";
3218 } else {
3219 params.value = "0";
3220 }
3221
3222 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3223 wifi_hostapdWrite(config_file, &params, 1);
3224
3225 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3226 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3227 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003228}
3229
3230//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.
3231INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3232{
3233 if (NULL == output)
3234 return RETURN_ERR;
3235 *output=100;
3236
3237 return RETURN_OK;
3238}
3239
3240//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.
3241INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3242{
3243 if (NULL == output)
3244 return RETURN_ERR;
3245 *output = -99;
3246
3247 return RETURN_OK;
3248}
3249
3250INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3251{
3252 return RETURN_ERR;
3253}
3254
3255
3256//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3257INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3258{
developerd946fd62022-12-08 18:03:28 +08003259 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003260 char cmd[MAX_BUF_SIZE]={'\0'};
3261 char buf[MAX_CMD_SIZE]={'\0'};
3262
3263 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3264 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003265 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003266
developerac6f1142022-12-20 19:26:35 +08003267 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003268 return RETURN_ERR;
3269 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 +08003270 _syscmd(cmd, buf, sizeof(buf));
3271 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003272
developer5f222492022-09-13 15:21:52 +08003273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003274 return RETURN_OK;
3275}
3276
3277INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3278{
developer5f222492022-09-13 15:21:52 +08003279 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3280 struct params params={'\0'};
3281 char buf[MAX_BUF_SIZE] = {'\0'};
3282 char config_file[MAX_BUF_SIZE] = {'\0'};
3283
developer5b398df2022-11-17 20:39:48 +08003284 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3285 return RETURN_ERR;
3286
developer5f222492022-09-13 15:21:52 +08003287 params.name = "beacon_int";
3288 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3289 params.value = buf;
3290
3291 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3292 wifi_hostapdWrite(config_file, &params, 1);
3293
3294 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3296 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003297}
3298
3299//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.
3300INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3301{
developer06a01d92022-09-07 16:32:39 +08003302 //TODO: need to revisit below implementation
3303 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003304 char temp_output[128] = {0};
3305 char temp_TransmitRates[64] = {0};
3306 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003307
3308 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3309 if (NULL == output)
3310 return RETURN_ERR;
3311 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003312 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3313
3314 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3315 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3316 } else {
3317 temp = strtok(temp_TransmitRates," ");
3318 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003319 {
developere9d0abd2022-09-13 15:40:57 +08003320 // Convert 100 kbps to Mbps
3321 temp[strlen(temp)-1]=0;
3322 if((temp[0]=='5') && (temp[1]=='\0'))
3323 {
3324 temp="5.5";
3325 }
3326 strcat(temp_output,temp);
3327 temp = strtok(NULL," ");
3328 if(temp!=NULL)
3329 {
3330 strcat(temp_output,",");
3331 }
developer06a01d92022-09-07 16:32:39 +08003332 }
developere9d0abd2022-09-13 15:40:57 +08003333 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003334 }
developer06a01d92022-09-07 16:32:39 +08003335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003336 return RETURN_OK;
3337}
3338
3339INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3340{
3341 char *temp;
3342 char temp1[128];
3343 char temp_output[128];
3344 char temp_TransmitRates[128];
3345 char set[128];
3346 char sub_set[128];
3347 int set_count=0,subset_count=0;
3348 int set_index=0,subset_index=0;
3349 char *token;
3350 int flag=0, i=0;
3351 struct params params={'\0'};
3352 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003353 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003354
3355 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3356 if(NULL == TransmitRates)
3357 return RETURN_ERR;
3358 strcpy(sub_set,TransmitRates);
3359
3360 //Allow only supported Data transmit rate to be set
3361 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3362 token = strtok(sub_set,",");
3363 while( token != NULL ) /* split the basic rate to be set, by comma */
3364 {
3365 sub_set[subset_count]=atoi(token);
3366 subset_count++;
3367 token=strtok(NULL,",");
3368 }
3369 token=strtok(set,",");
3370 while(token!=NULL) /* split the supported rate by comma */
3371 {
3372 set[set_count]=atoi(token);
3373 set_count++;
3374 token=strtok(NULL,",");
3375 }
3376 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3377 {
3378 for(set_index=0;set_index < set_count;set_index++)
3379 {
3380 flag=0;
3381 if(sub_set[subset_index]==set[set_index])
3382 break;
3383 else
3384 flag=1; /* No match found */
3385 }
3386 if(flag==1)
3387 return RETURN_ERR; //If value not found return Error
3388 }
3389 strcpy(temp_TransmitRates,TransmitRates);
3390
3391 for(i=0;i<strlen(temp_TransmitRates);i++)
3392 {
3393 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003394 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003395 {
3396 continue;
3397 }
3398 else
3399 {
3400 return RETURN_ERR;
3401 }
3402 }
3403 strcpy(temp_output,"");
3404 temp = strtok(temp_TransmitRates,",");
3405 while(temp!=NULL)
3406 {
3407 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003408 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003409 {
developeref938762022-10-19 17:21:01 +08003410 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003411 {
3412 return RETURN_ERR;
3413 }
3414 }
3415
3416 if(strcmp(temp,"5.5")==0)
3417 {
3418 strcpy(temp1,"55");
3419 }
3420 else
3421 {
3422 strcat(temp1,"0");
3423 }
3424 strcat(temp_output,temp1);
3425 temp = strtok(NULL,",");
3426 if(temp!=NULL)
3427 {
3428 strcat(temp_output," ");
3429 }
3430 }
3431 strcpy(TransmitRates,temp_output);
3432
3433 params.name= "basic_rates";
3434 params.value =TransmitRates;
3435
3436 wifi_dbg_printf("\n%s:",__func__);
3437 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3438 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3439 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3440 wifi_hostapdWrite(config_file,&params,1);
3441 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3442 return RETURN_OK;
3443}
3444
3445//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003446INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003447{
3448 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3449 FILE *fp = NULL;
3450 char path[256] = {0}, output_string[256] = {0};
3451 int count = 0;
3452 char *interface = NULL;
3453
3454 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3455 if (fp == NULL)
3456 {
3457 printf("Failed to run command in Function %s\n", __FUNCTION__);
3458 return RETURN_ERR;
3459 }
3460 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3461 {
3462 interface = strchr(path, '=');
3463
3464 if (interface != NULL)
3465 {
3466 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003467 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003468 interface_name[count] = output_string[count];
3469
3470 interface_name[count] = '\0';
3471 }
3472 }
3473 pclose(fp);
3474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3475 return RETURN_OK;
3476}
3477
3478INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3479{
3480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3481 output_struct->radio_BytesSent = 0;
3482 output_struct->radio_BytesReceived = 0;
3483 output_struct->radio_PacketsSent = 0;
3484 output_struct->radio_PacketsReceived = 0;
3485 output_struct->radio_ErrorsSent = 0;
3486 output_struct->radio_ErrorsReceived = 0;
3487 output_struct->radio_DiscardPacketsSent = 0;
3488 output_struct->radio_DiscardPacketsReceived = 0;
3489 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3490 return RETURN_OK;
3491}
3492
3493
3494INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3495{
3496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3497 CHAR buf[MAX_CMD_SIZE] = {0};
3498 CHAR Value[MAX_BUF_SIZE] = {0};
3499 FILE *fp = NULL;
3500
3501 if (ifname == NULL || strlen(ifname) <= 1)
3502 return RETURN_OK;
3503
3504 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3505 system(buf);
3506
3507 fp = fopen("/tmp/Radio_Stats.txt", "r");
3508 if(fp == NULL)
3509 {
3510 printf("/tmp/Radio_Stats.txt not exists \n");
3511 return RETURN_ERR;
3512 }
3513 fclose(fp);
3514
3515 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3516 File_Reading(buf, Value);
3517 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3518
3519 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3520 File_Reading(buf, Value);
3521 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3522
3523 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3524 File_Reading(buf, Value);
3525 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3526
3527 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3528 File_Reading(buf, Value);
3529 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3530
3531 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3532 File_Reading(buf, Value);
3533 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3534
3535 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3536 File_Reading(buf, Value);
3537 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3538
3539 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3540 File_Reading(buf, Value);
3541 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3542
3543 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3544 File_Reading(buf, Value);
3545 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3546
3547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3548 return RETURN_OK;
3549}
3550
3551INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3552{
3553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3554 CHAR buf[MAX_CMD_SIZE] = {0};
3555 FILE *fp = NULL;
3556 INT count = 0;
3557
3558 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3559 {
3560 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3561 File_Reading(buf, status);
3562 }
3563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3564 return RETURN_OK;
3565}
3566
3567//Get detail radio traffic static info
3568INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3569{
3570
3571#if 0
3572 //ifconfig radio_x
3573 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3574 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3575 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3576 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3577
3578 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3579 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3580 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.
3581 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.
3582
3583 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3584 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].
3585 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3586 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.
3587 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
3588 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
3589 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
3590 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
3591 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
3592
3593 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
3594 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
3595 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
3596 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.
3597
3598 return RETURN_OK;
3599#endif
3600
developera91d99f2022-09-29 15:59:10 +08003601 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003602 BOOL iface_status = FALSE;
3603 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003604
3605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3606 if (NULL == output_struct)
3607 return RETURN_ERR;
3608
developerac6f1142022-12-20 19:26:35 +08003609 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08003610 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003611
developera91d99f2022-09-29 15:59:10 +08003612 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003613
developera91d99f2022-09-29 15:59:10 +08003614 if (iface_status == TRUE)
3615 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3616 else
3617 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003618
developera91d99f2022-09-29 15:59:10 +08003619 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3620 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3621 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3622 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3623 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3624 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3625 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3626 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003627
3628 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3629 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].
3630 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3631 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.
3632 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
3633 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
3634 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
3635 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
3636 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
3637
3638 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
3639 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
3640 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
3641 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.
3642
3643 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3644
3645 return RETURN_OK;
3646}
3647
3648//Set radio traffic static Measureing rules
3649INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3650{
3651 //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
3652 // Else, save the MeasuringRate and MeasuringInterval for future usage
3653
3654 return RETURN_OK;
3655}
3656
3657//To start or stop RadioTrafficStats
3658INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3659{
3660 //zqiu: If the RadioTrafficStats process running
3661 // if(enable)
3662 // return RETURN_OK.
3663 // else
3664 // Stop RadioTrafficStats process
3665 // Else
3666 // if(enable)
3667 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3668 // else
3669 // return RETURN_OK.
3670
3671 return RETURN_OK;
3672}
3673
3674//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
3675INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3676{
3677 //zqiu: Please ignor signalIndex.
3678 if (NULL == SignalLevel)
3679 return RETURN_ERR;
3680 *SignalLevel=(radioIndex==0)?-19:-19;
3681
3682 return RETURN_OK;
3683}
3684
3685//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3686INT wifi_applyRadioSettings(INT radioIndex)
3687{
3688 return RETURN_OK;
3689}
3690
3691//Get the radio index assocated with this SSID entry
3692INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3693{
developer5b398df2022-11-17 20:39:48 +08003694 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003695 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003696 int max_radio_num = 0;
3697 wifi_getMaxRadioNumber(&max_radio_num);
3698 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003699 return RETURN_OK;
3700}
3701
3702//Device.WiFi.SSID.{i}.Enable
3703//Get SSID enable configuration parameters (not the SSID enable status)
3704INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3705{
3706 if (NULL == output_bool)
3707 return RETURN_ERR;
3708
developer06a01d92022-09-07 16:32:39 +08003709 return wifi_getApEnable(ssidIndex, output_bool);
3710}
3711
3712//Device.WiFi.SSID.{i}.Enable
3713//Set SSID enable configuration parameters
3714INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3715{
developer06a01d92022-09-07 16:32:39 +08003716 return wifi_setApEnable(ssidIndex, enable);
3717}
3718
3719//Device.WiFi.SSID.{i}.Status
3720//Get the SSID enable status
3721INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3722{
3723 char cmd[MAX_CMD_SIZE]={0};
3724 char buf[MAX_BUF_SIZE]={0};
3725 BOOL output_bool;
3726
3727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3728 if (NULL == output_string)
3729 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003730
developer06a01d92022-09-07 16:32:39 +08003731 wifi_getApEnable(ssidIndex,&output_bool);
3732 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3733
3734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3735 return RETURN_OK;
3736}
3737
3738// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3739INT wifi_getSSIDName(INT apIndex, CHAR *output)
3740{
3741 char config_file[MAX_BUF_SIZE] = {0};
3742
3743 if (NULL == output)
3744 return RETURN_ERR;
3745
3746 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3747 wifi_hostapdRead(config_file,"ssid",output,32);
3748
3749 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3750 return RETURN_OK;
3751}
3752
3753// Set a max 32 byte string and sets an internal variable to the SSID name
3754INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3755{
3756 char str[MAX_BUF_SIZE]={'\0'};
3757 char cmd[MAX_CMD_SIZE]={'\0'};
3758 struct params params;
3759 char config_file[MAX_BUF_SIZE] = {0};
3760
3761 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003762 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003763 return RETURN_ERR;
3764
3765 params.name = "ssid";
3766 params.value = ssid_string;
3767 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3768 wifi_hostapdWrite(config_file, &params, 1);
3769 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3770 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3771
3772 return RETURN_OK;
3773}
3774
3775//Get the BSSID
3776INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3777{
3778 char cmd[MAX_CMD_SIZE]="";
3779
3780 if (NULL == output_string)
3781 return RETURN_ERR;
3782
3783 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3784 {
developer1d57d002022-10-12 18:03:15 +08003785 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 +08003786 _syscmd(cmd, output_string, 64);
3787 return RETURN_OK;
3788 }
3789 strncpy(output_string, "\0", 1);
3790
3791 return RETURN_ERR;
3792}
3793
3794//Get the MAC address associated with this Wifi SSID
3795INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3796{
3797 wifi_getBaseBSSID(ssidIndex,output_string);
3798 return RETURN_OK;
3799}
3800
3801//Get the basic SSID traffic static info
3802//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3803//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3804INT wifi_applySSIDSettings(INT ssidIndex)
3805{
developerd946fd62022-12-08 18:03:28 +08003806 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003807 BOOL status = false;
3808 char cmd[MAX_CMD_SIZE] = {0};
3809 char buf[MAX_CMD_SIZE] = {0};
3810 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003811 int max_radio_num = 0;
3812 int radioIndex = 0;
3813
3814 wifi_getMaxRadioNumber(&max_radio_num);
3815
3816 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003817
3818 wifi_getApEnable(ssidIndex,&status);
3819 // Do not apply when ssid index is disabled
3820 if (status == false)
3821 return RETURN_OK;
3822
3823 /* Doing full remove and add for ssid Index
3824 * Not all hostapd options are supported with reload
3825 * for example macaddr_acl
3826 */
3827 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3828 return RETURN_ERR;
3829
3830 ret = wifi_setApEnable(ssidIndex,true);
3831
3832 /* Workaround for hostapd issue with multiple bss definitions
3833 * when first created interface will be removed
3834 * then all vaps other vaps on same phy are removed
3835 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003836 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003837 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003838 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003839 continue;
developerd946fd62022-12-08 18:03:28 +08003840 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003841 _syscmd(cmd, buf, sizeof(buf));
3842 if(*buf == '1')
3843 wifi_setApEnable(apIndex, true);
3844 }
3845
3846 return ret;
3847}
3848
developera3c68b92022-09-13 15:27:29 +08003849struct channels_noise {
3850 int channel;
3851 int noise;
3852};
3853
3854// Return noise array for each channel
3855int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3856{
developerd946fd62022-12-08 18:03:28 +08003857 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003858 FILE *f = NULL;
3859 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003860 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003861 size_t len = 0;
3862 ssize_t read = 0;
3863 int tmp = 0, arr_index = -1;
3864
developerac6f1142022-12-20 19:26:35 +08003865 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003866 return RETURN_ERR;
3867 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003868
3869 if ((f = popen(cmd, "r")) == NULL) {
3870 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3871 return RETURN_ERR;
3872 }
developer5550e242022-09-30 09:59:32 +08003873
3874 while(fgets(line, sizeof(line), f) != NULL) {
3875 if(arr_index < channels_num){
3876 sscanf(line, "%d", &tmp);
3877 if (tmp > 0) { // channel frequency, the first line must be frequency
3878 arr_index++;
3879 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3880 } else { // noise
3881 channels_noise_arr[arr_index].noise = tmp;
3882 }
3883 }else{
3884 break;
developera3c68b92022-09-13 15:27:29 +08003885 }
3886 }
developera3c68b92022-09-13 15:27:29 +08003887 pclose(f);
3888 return RETURN_OK;
3889}
3890
developer06a01d92022-09-07 16:32:39 +08003891//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3892//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3893INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3894{
developera3c68b92022-09-13 15:27:29 +08003895 int index = -1;
3896 wifi_neighbor_ap2_t *scan_array = NULL;
3897 char cmd[256]={0};
3898 char buf[128]={0};
3899 char file_name[32] = {0};
3900 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003901 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003902 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003903 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003904 int freq=0;
3905 FILE *f = NULL;
3906 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003907 int channels_num = 0;
3908 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003909 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003910 bool filter_enable = false;
3911 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003912 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003913
developer615510b2022-09-27 10:14:35 +08003914 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003915
developerac6f1142022-12-20 19:26:35 +08003916 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003917 return RETURN_ERR;
3918
developera3c68b92022-09-13 15:27:29 +08003919 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3920 f = fopen(file_name, "r");
3921 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08003922 fgets(buf, sizeof(file_name), f);
3923 if ((strncmp(buf, "0", 1)) != 0) {
3924 fgets(filter_SSID, sizeof(file_name), f);
3925 if (strlen(filter_SSID) != 0)
3926 filter_enable = true;
3927 }
developera3c68b92022-09-13 15:27:29 +08003928 fclose(f);
3929 }
3930
developer033b37b2022-10-18 11:27:46 +08003931 phyId = radio_index_to_phy(radioIndex);
3932 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003933 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003934 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003935
developer5550e242022-09-30 09:59:32 +08003936
developer06a01d92022-09-07 16:32:39 +08003937
developerd946fd62022-12-08 18:03:28 +08003938 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3939 // 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 +08003940 fprintf(stderr, "cmd: %s\n", cmd);
3941 if ((f = popen(cmd, "r")) == NULL) {
3942 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3943 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003944 }
developer5550e242022-09-30 09:59:32 +08003945
3946 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3947 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3948
developer615510b2022-09-27 10:14:35 +08003949 ret = fgets(line, sizeof(line), f);
3950 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003951 if(strstr(line, "BSS") != NULL) { // new neighbor info
3952 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3953 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3954 // 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 +08003955
developera3c68b92022-09-13 15:27:29 +08003956 if (!filter_BSS) {
3957 index++;
3958 wifi_neighbor_ap2_t *tmp;
3959 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3960 if (tmp == NULL) { // no more memory to use
3961 index--;
3962 wifi_dbg_printf("%s: realloc failed\n", __func__);
3963 break;
3964 }
3965 scan_array = tmp;
3966 }
3967 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3968
3969 filter_BSS = false;
3970 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3971 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3972 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3973 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3974 } else if (strstr(line, "freq") != NULL) {
3975 sscanf(line," freq: %d", &freq);
3976 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3977
3978 if (freq >= 2412 && freq <= 2484) {
3979 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3980 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3981 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3982 }
3983 else if (freq >= 5160 && freq <= 5805) {
3984 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3985 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3986 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3987 }
3988
3989 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003990 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003991 for (int i = 0; i < channels_num; i++) {
3992 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3993 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3994 break;
3995 }
3996 }
3997 }
3998 } else if (strstr(line, "beacon interval") != NULL) {
3999 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4000 } else if (strstr(line, "signal") != NULL) {
4001 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4002 } else if (strstr(line,"SSID") != NULL) {
4003 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4004 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4005 filter_BSS = true;
4006 }
4007 } else if (strstr(line, "Supported rates") != NULL) {
4008 char SRate[80] = {0}, *tmp = NULL;
4009 memset(buf, 0, sizeof(buf));
4010 strcpy(SRate, line);
4011 tmp = strtok(SRate, ":");
4012 tmp = strtok(NULL, ":");
4013 strcpy(buf, tmp);
4014 memset(SRate, 0, sizeof(SRate));
4015
4016 tmp = strtok(buf, " \n");
4017 while (tmp != NULL) {
4018 strcat(SRate, tmp);
4019 if (SRate[strlen(SRate) - 1] == '*') {
4020 SRate[strlen(SRate) - 1] = '\0';
4021 }
4022 strcat(SRate, ",");
4023
4024 tmp = strtok(NULL, " \n");
4025 }
4026 SRate[strlen(SRate) - 1] = '\0';
4027 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4028 } else if (strstr(line, "DTIM") != NULL) {
4029 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4030 } else if (strstr(line, "VHT capabilities") != NULL) {
4031 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4032 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4033 } else if (strstr(line, "HT capabilities") != NULL) {
4034 strcat(scan_array[index].ap_SupportedStandards, ",n");
4035 strcpy(scan_array[index].ap_OperatingStandards, "n");
4036 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004037 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004038 sscanf(line," * channel width: %d", &vht_channel_width);
4039 if(vht_channel_width == 1) {
4040 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4041 } else {
4042 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4043 }
4044 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4045 continue;
4046 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004047 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004048 sscanf(line," * secondary channel offset: %s", &buf);
4049 if (!strcmp(buf, "above")) {
4050 //40Mhz +
4051 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4052 }
4053 else if (!strcmp(buf, "below")) {
4054 //40Mhz -
4055 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4056 } else {
4057 //20Mhz
4058 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4059 }
4060 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4061 continue;
4062 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004063 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4064 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4065 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004066 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4067 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004068 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004069 else
developer615510b2022-09-27 10:14:35 +08004070 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004071 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004072 if (strstr(line, "HE80/5GHz") != NULL) {
4073 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4074 ret = fgets(line, sizeof(line), f);
4075 } else
4076 continue;
developera3c68b92022-09-13 15:27:29 +08004077 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004078 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004079 }
developer615510b2022-09-27 10:14:35 +08004080 continue;
developera3c68b92022-09-13 15:27:29 +08004081 } else if (strstr(line, "WPA") != NULL) {
4082 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4083 } else if (strstr(line, "RSN") != NULL) {
4084 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4085 } else if (strstr(line, "Group cipher") != NULL) {
4086 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4087 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4088 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4089 }
4090 }
developer615510b2022-09-27 10:14:35 +08004091 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004092 }
4093
4094 if (!filter_BSS) {
4095 *output_array_size = index + 1;
4096 } else {
4097 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4098 *output_array_size = index;
4099 }
4100 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004101 pclose(f);
developer5550e242022-09-30 09:59:32 +08004102 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004103 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004104 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004105}
4106
4107//>> Deprecated: used for old RDKB code.
4108INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4109{
4110 INT status = RETURN_ERR;
4111
4112 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4113 output_struct->wifi_PLCPErrorCount = 0;
4114 output_struct->wifi_FCSErrorCount = 0;
4115 output_struct->wifi_InvalidMACCount = 0;
4116 output_struct->wifi_PacketsOtherReceived = 0;
4117 output_struct->wifi_Noise = 0;
4118 status = RETURN_OK;
4119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4120 return status;
4121}
4122
4123INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4124{
developerd946fd62022-12-08 18:03:28 +08004125 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004126 char cmd[128] = {0};
4127 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004128 char *pos = NULL;
4129
4130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4131 if (NULL == output_struct)
4132 return RETURN_ERR;
4133
developerac6f1142022-12-20 19:26:35 +08004134 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004135 return RETURN_ERR;
4136
developer06a01d92022-09-07 16:32:39 +08004137 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4138
developerd946fd62022-12-08 18:03:28 +08004139 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004140 _syscmd(cmd, buf, sizeof(buf));
4141
4142 pos = buf;
4143 if ((pos = strstr(pos, "RX packets:")) == NULL)
4144 return RETURN_ERR;
4145 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4146
4147 if ((pos = strstr(pos, "TX packets:")) == NULL)
4148 return RETURN_ERR;
4149 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4150
4151 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4152 return RETURN_ERR;
4153 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4154
4155 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4156 return RETURN_ERR;
4157 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4158
developerd946fd62022-12-08 18:03:28 +08004159 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004160 _syscmd(cmd, buf, sizeof(buf));
4161 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4162
4163#if 0
4164 //TODO: need to revisit below implementation
4165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4166 char interface_name[MAX_BUF_SIZE] = {0};
4167 char interface_status[MAX_BUF_SIZE] = {0};
4168 char Value[MAX_BUF_SIZE] = {0};
4169 char buf[MAX_CMD_SIZE] = {0};
4170 char cmd[MAX_CMD_SIZE] = {0};
4171 FILE *fp = NULL;
4172
4173 if (NULL == output_struct) {
4174 return RETURN_ERR;
4175 }
4176
4177 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4178
4179 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4180 {
4181 if(apIndex == 0) //private_wifi for 2.4G
4182 {
developerac6f1142022-12-20 19:26:35 +08004183 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004184 }
4185 else if(apIndex == 1) //private_wifi for 5G
4186 {
developerac6f1142022-12-20 19:26:35 +08004187 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004188 }
4189 else if(apIndex == 4) //public_wifi for 2.4G
4190 {
4191 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4192 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4193 {
4194 return RETURN_ERR;
4195 }
4196 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004197 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004198 else//tenda
developerac6f1142022-12-20 19:26:35 +08004199 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004200 }
4201 else if(apIndex == 5) //public_wifi for 5G
4202 {
developerac6f1142022-12-20 19:26:35 +08004203 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004204 }
4205
4206 GetIfacestatus(interface_name, interface_status);
4207
4208 if(0 != strcmp(interface_status, "1"))
4209 return RETURN_ERR;
4210
4211 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4212 system(cmd);
4213
4214 fp = fopen("/tmp/SSID_Stats.txt", "r");
4215 if(fp == NULL)
4216 {
4217 printf("/tmp/SSID_Stats.txt not exists \n");
4218 return RETURN_ERR;
4219 }
4220 fclose(fp);
4221
4222 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4223 File_Reading(buf, Value);
4224 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4225
4226 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4227 File_Reading(buf, Value);
4228 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4229
4230 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4231 File_Reading(buf, Value);
4232 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4233
4234 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4235 File_Reading(buf, Value);
4236 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4237
4238 /* There is no specific parameter from caller to associate the value wifi_Associations */
4239 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4240 //_syscmd(cmd, buf, sizeof(buf));
4241 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4242 }
4243#endif
4244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4245 return RETURN_OK;
4246}
4247
4248INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4249{
4250 char interface_name[MAX_BUF_SIZE] = {0};
4251 char interface_status[MAX_BUF_SIZE] = {0};
4252 char Value[MAX_BUF_SIZE] = {0};
4253 char buf[MAX_CMD_SIZE] = {0};
4254 char cmd[MAX_CMD_SIZE] = {0};
4255 FILE *fp = NULL;
4256
4257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4258 if (NULL == output_struct)
4259 return RETURN_ERR;
4260
4261 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4262
developerac6f1142022-12-20 19:26:35 +08004263 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004264 return RETURN_ERR;
4265 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004266
developerd946fd62022-12-08 18:03:28 +08004267 if(0 != strcmp(interface_status, "1"))
4268 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004269
developerd946fd62022-12-08 18:03:28 +08004270 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4271 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004272
developerd946fd62022-12-08 18:03:28 +08004273 fp = fopen("/tmp/SSID_Stats.txt", "r");
4274 if(fp == NULL)
4275 {
4276 printf("/tmp/SSID_Stats.txt not exists \n");
4277 return RETURN_ERR;
4278 }
4279 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004280
developerd946fd62022-12-08 18:03:28 +08004281 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4282 File_Reading(buf, Value);
4283 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004284
developerd946fd62022-12-08 18:03:28 +08004285 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4286 File_Reading(buf, Value);
4287 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004288
developerd946fd62022-12-08 18:03:28 +08004289 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4290 File_Reading(buf, Value);
4291 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004292
developerd946fd62022-12-08 18:03:28 +08004293 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4294 File_Reading(buf, Value);
4295 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004296
4297 output_struct->wifi_UnicastPacketsSent = 0;
4298 output_struct->wifi_UnicastPacketsReceived = 0;
4299 output_struct->wifi_MulticastPacketsSent = 0;
4300 output_struct->wifi_MulticastPacketsReceived = 0;
4301 output_struct->wifi_BroadcastPacketsSent = 0;
4302 output_struct->wifi_BroadcastPacketsRecevied = 0;
4303 output_struct->wifi_UnknownPacketsReceived = 0;
4304
4305 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4306 return RETURN_OK;
4307}
4308
4309INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4310{
4311 INT status = RETURN_ERR;
4312
4313 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4314 //Below values should get updated from hal
4315 output_struct->wifi_RetransCount=0;
4316 output_struct->wifi_FailedRetransCount=0;
4317 output_struct->wifi_RetryCount=0;
4318 output_struct->wifi_MultipleRetryCount=0;
4319 output_struct->wifi_ACKFailureCount=0;
4320 output_struct->wifi_AggregatedPacketCount=0;
4321
4322 status = RETURN_OK;
4323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4324
4325 return status;
4326}
4327
4328INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4329{
4330 INT status = RETURN_ERR;
4331 UINT index;
4332 wifi_neighbor_ap_t *pt=NULL;
4333
4334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4335 *output_array_size=2;
4336 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4337 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4338 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4339 strcpy(pt->ap_Radio,"");
4340 strcpy(pt->ap_SSID,"");
4341 strcpy(pt->ap_BSSID,"");
4342 strcpy(pt->ap_Mode,"");
4343 pt->ap_Channel=1;
4344 pt->ap_SignalStrength=0;
4345 strcpy(pt->ap_SecurityModeEnabled,"");
4346 strcpy(pt->ap_EncryptionMode,"");
4347 strcpy(pt->ap_OperatingFrequencyBand,"");
4348 strcpy(pt->ap_SupportedStandards,"");
4349 strcpy(pt->ap_OperatingStandards,"");
4350 strcpy(pt->ap_OperatingChannelBandwidth,"");
4351 pt->ap_BeaconPeriod=1;
4352 pt->ap_Noise=0;
4353 strcpy(pt->ap_BasicDataTransferRates,"");
4354 strcpy(pt->ap_SupportedDataTransferRates,"");
4355 pt->ap_DTIMPeriod=1;
4356 pt->ap_ChannelUtilization = 1;
4357 }
4358
4359 status = RETURN_OK;
4360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4361
4362 return status;
4363}
4364
4365//----------------- AP HAL -------------------------------
4366
4367//>> Deprecated: used for old RDKB code.
4368INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4369{
4370 if (NULL == output_ulong || NULL == output_struct)
4371 return RETURN_ERR;
4372 *output_ulong = 0;
4373 *output_struct = NULL;
4374 return RETURN_OK;
4375}
4376
4377#ifdef HAL_NETLINK_IMPL
4378static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4379 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4380 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4381 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4382 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4383 char mac_addr[20];
4384 static int count=0;
4385 int rate=0;
4386
4387 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4388
4389 nla_parse(tb,
4390 NL80211_ATTR_MAX,
4391 genlmsg_attrdata(gnlh, 0),
4392 genlmsg_attrlen(gnlh, 0),
4393 NULL);
4394
4395 if(!tb[NL80211_ATTR_STA_INFO]) {
4396 fprintf(stderr, "sta stats missing!\n");
4397 return NL_SKIP;
4398 }
4399
4400
4401 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4402 fprintf(stderr, "failed to parse nested attributes!\n");
4403 return NL_SKIP;
4404 }
4405
4406 //devIndex starts from 1
4407 if( ++count == out->wifi_devIndex )
4408 {
4409 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4410 //Getting the mac addrress
4411 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4412
4413 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4414 fprintf(stderr, "failed to parse nested rate attributes!");
4415 return NL_SKIP;
4416 }
4417
4418 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4419 if(rinfo[NL80211_RATE_INFO_BITRATE])
4420 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4421 out->wifi_devTxRate = rate/10;
4422 }
4423
4424 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4425 fprintf(stderr, "failed to parse nested rate attributes!");
4426 return NL_SKIP;
4427 }
4428
4429 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4430 if(rinfo[NL80211_RATE_INFO_BITRATE])
4431 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4432 out->wifi_devRxRate = rate/10;
4433 }
4434 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4435 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4436
4437 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4438 count = 0; //starts the count for next cycle
4439 return NL_STOP;
4440 }
4441
4442 return NL_SKIP;
4443
4444}
4445#endif
4446
4447INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4448{
4449#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004450 Netlink nl = {0};
4451 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004452 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004453
developer30423732022-12-01 16:17:49 +08004454 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004455 info.wifi_devIndex = devIndex;
4456
developerac6f1142022-12-20 19:26:35 +08004457 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004458 return RETURN_ERR;
4459
4460 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004461
4462 nl.id = initSock80211(&nl);
4463
4464 if (nl.id < 0) {
4465 fprintf(stderr, "Error initializing netlink \n");
4466 return -1;
4467 }
4468
4469 struct nl_msg* msg = nlmsg_alloc();
4470
4471 if (!msg) {
4472 fprintf(stderr, "Failed to allocate netlink message.\n");
4473 nlfree(&nl);
4474 return -2;
4475 }
4476
4477 genlmsg_put(msg,
4478 NL_AUTO_PORT,
4479 NL_AUTO_SEQ,
4480 nl.id,
4481 0,
4482 NLM_F_DUMP,
4483 NL80211_CMD_GET_STATION,
4484 0);
4485
4486 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4487 nl_send_auto(nl.socket, msg);
4488 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4489 nl_recvmsgs(nl.socket, nl.cb);
4490 nlmsg_free(msg);
4491 nlfree(&nl);
4492
4493 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4494 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4495 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4496 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4497 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4498 return RETURN_OK;
4499#else
4500 //iw utility to retrieve station information
4501#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4502#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4503#define MACFILE "/tmp/wifi_AssoMac.txt"
4504#define TXRATEFILE "/tmp/wifi_txrate.txt"
4505#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4506 FILE *file = NULL;
4507 char if_name[10] = {'\0'};
4508 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004509 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004510 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004511 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004512
developerac6f1142022-12-20 19:26:35 +08004513 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004514 return RETURN_ERR;
4515
4516 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004517
4518 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4519 file = popen(pipeCmd, "r");
4520
4521 if(file == NULL)
4522 return RETURN_ERR; //popen failed
4523
4524 fgets(line, sizeof line, file);
4525 device = atoi(line);
4526 pclose(file);
4527
4528 if(device == 0)
4529 return RETURN_ERR; //No devices are connected
4530
4531 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4532 system(pipeCmd);
4533
4534 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4535
4536 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4537
4538 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4539
4540 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4541
4542 //devIndex starts from 1, ++count
4543 if((file = fopen(SIGNALFILE, "r")) != NULL )
4544 {
4545 for(count =0;fgets(line, sizeof line, file) != NULL;)
4546 {
4547 if (++count == devIndex)
4548 {
4549 output_struct->wifi_devSignalStrength = atoi(line);
4550 break;
4551 }
4552 }
4553 fclose(file);
4554 }
4555 else
4556 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4557
4558 if((file = fopen(MACFILE, "r")) != NULL )
4559 {
4560 for(count =0;fgets(line, sizeof line, file) != NULL;)
4561 {
4562 if (++count == devIndex)
4563 {
4564 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]);
4565 break;
4566 }
4567 }
4568 fclose(file);
4569 }
4570 else
4571 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4572
4573 if((file = fopen(TXRATEFILE, "r")) != NULL )
4574 {
4575 for(count =0;fgets(line, sizeof line, file) != NULL;)
4576 {
4577 if (++count == devIndex)
4578 {
4579 output_struct->wifi_devTxRate = atoi(line);
4580 break;
4581 }
4582 }
4583 fclose(file);
4584 }
4585 else
4586 fprintf(stderr,"fopen wifi_txrate.txt failed");
4587
4588 if((file = fopen(RXRATEFILE, "r")) != NULL)
4589 {
4590 for(count =0;fgets(line, sizeof line, file) != NULL;)
4591 {
4592 if (++count == devIndex)
4593 {
4594 output_struct->wifi_devRxRate = atoi(line);
4595 break;
4596 }
4597 }
4598 fclose(file);
4599 }
4600 else
4601 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4602
4603 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4604
4605 return RETURN_OK;
4606#endif
4607}
4608
4609INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4610{
4611 if (NULL == device)
4612 return RETURN_ERR;
4613 return RETURN_OK;
4614}
4615//<<
4616
4617
4618//--------------wifi_ap_hal-----------------------------
4619//enables CTS protection for the radio used by this AP
4620INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4621{
4622 //save config and Apply instantly
4623 return RETURN_ERR;
4624}
4625
4626// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4627INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4628{
developer463d39a2022-09-13 15:32:51 +08004629 char config_file[64] = {'\0'};
4630 char buf[64] = {'\0'};
4631 struct params list;
4632
4633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4634 list.name = "ht_coex";
4635 snprintf(buf, sizeof(buf), "%d", enable);
4636 list.value = buf;
4637
4638 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4639 wifi_hostapdWrite(config_file, &list, 1);
4640 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4641
4642 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4643
4644 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004645}
4646
4647//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4648INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4649{
developerea4bcce2022-09-13 15:26:13 +08004650 char config_file[MAX_BUF_SIZE] = {'\0'};
4651 char buf[MAX_BUF_SIZE] = {'\0'};
4652 struct params list;
4653
4654 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4655 if (threshold < 256 || threshold > 2346 )
4656 return RETURN_ERR;
4657 list.name = "fragm_threshold";
4658 snprintf(buf, sizeof(buf), "%d", threshold);
4659 list.value = buf;
4660
4661 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4662 wifi_hostapdWrite(config_file, &list, 1);
4663 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004664
developerea4bcce2022-09-13 15:26:13 +08004665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004666
4667 return RETURN_OK;
4668}
4669
4670// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4671INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4672{
developer51a927d2022-09-13 15:42:22 +08004673 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004674 char cmd[512] = {'\0'};
4675 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004676 char stbc_config[16] = {'\0'};
4677 wifi_band band;
4678 int iterator = 0;
4679 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004680 int ant_count = 0;
4681 int ant_bitmap = 0;
4682 struct params list;
developer51a927d2022-09-13 15:42:22 +08004683
4684 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4685
4686 band = wifi_index_to_band(radioIndex);
4687 if (band == band_invalid)
4688 return RETURN_ERR;
4689
4690 if (band == band_2_4)
4691 iterator = 1;
4692 else if (band == band_5)
4693 iterator = 2;
4694 else
4695 return RETURN_OK;
4696
developer110b8a32022-12-26 15:56:44 +08004697 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4698 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4699 ant_count += ant_bitmap & 1;
4700
4701 if (ant_count == 1 && STBC_Enable == TRUE) {
4702 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4703 return RETURN_OK;
4704 }
4705
developer51a927d2022-09-13 15:42:22 +08004706 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4707
4708 // set ht and vht config
4709 for (int i = 0; i < iterator; i++) {
4710 memset(stbc_config, 0, sizeof(stbc_config));
4711 memset(cmd, 0, sizeof(cmd));
4712 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004713 list.name = (i == 0)?"ht_capab":"vht_capab";
4714 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004715 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4716 _syscmd(cmd, buf, sizeof(buf));
4717 if (strlen(buf) != 0)
4718 current_stbc = TRUE;
4719 if (current_stbc == STBC_Enable)
4720 continue;
4721
4722 if (STBC_Enable == TRUE) {
4723 // Append the STBC flags in capab config
4724 memset(cmd, 0, sizeof(cmd));
4725 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004726 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004727 else
developer6372c2b2022-10-27 17:39:51 +08004728 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 +08004729 _syscmd(cmd, buf, sizeof(buf));
4730 } else if (STBC_Enable == FALSE) {
4731 // Remove the STBC flags and remain other flags in capab
4732 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004733 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004734 _syscmd(cmd, buf, sizeof(buf));
4735 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004736 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004737 _syscmd(cmd, buf, sizeof(buf));
4738 }
developer110b8a32022-12-26 15:56:44 +08004739 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4740 list.value = buf;
4741 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004742 }
4743
4744 wifi_reloadAp(radioIndex);
4745
4746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4747 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004748}
4749
4750// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4751INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4752{
developerfe7aefc2022-12-23 17:13:37 +08004753 char cmd[128] = {0};
4754 char buf[128] = {0};
4755 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004756
4757 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4758
4759 if(output_bool == NULL)
4760 return RETURN_ERR;
4761
developerfe7aefc2022-12-23 17:13:37 +08004762 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4763 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004764
developerfe7aefc2022-12-23 17:13:37 +08004765 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4766 _syscmd(cmd, buf, sizeof(buf));
4767
4768 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004769 *output_bool = TRUE;
4770 else
4771 *output_bool = FALSE;
4772
4773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4774 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004775}
4776
4777// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4778INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4779{
developerfe7aefc2022-12-23 17:13:37 +08004780 char config_file[128] = {0};
4781 struct params list = {0};
4782 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004783
4784 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4785
developerfe7aefc2022-12-23 17:13:37 +08004786 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004787 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004788
developerfe7aefc2022-12-23 17:13:37 +08004789 if (amsduEnable == enable)
4790 return RETURN_OK;
4791
4792 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4793 list.name = "amsdu";
4794 list.value = amsduEnable? "1":"0";
4795 wifi_hostapdWrite(config_file, &list, 1);
4796 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4797 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004798
4799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4800 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004801}
4802
4803//P2 // outputs the number of Tx streams
4804INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4805{
developer2de97692022-09-26 14:00:03 +08004806 char buf[8] = {0};
4807 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004808 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004809
4810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4811
developer033b37b2022-10-18 11:27:46 +08004812 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004813 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004814 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004815
developer110b8a32022-12-26 15:56:44 +08004816 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004817
4818 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4819
4820 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004821}
4822
developer110b8a32022-12-26 15:56:44 +08004823INT fitChainMask(INT radioIndex, int antcount)
4824{
4825 char buf[128] = {0};
4826 char cmd[128] = {0};
4827 char config_file[64] = {0};
4828 wifi_band band;
4829 struct params list[2] = {0};
4830
4831 band = wifi_index_to_band(radioIndex);
4832 if (band == band_invalid)
4833 return RETURN_ERR;
4834
4835 list[0].name = "he_mu_beamformer";
4836 list[1].name = "he_su_beamformer";
4837
4838 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4839 if (antcount == 1) {
4840 // remove config about multiple antennas
4841 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4842 _syscmd(cmd, buf, sizeof(buf));
4843
4844 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4845 _syscmd(cmd, buf, sizeof(buf));
4846
4847 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4848 _syscmd(cmd, buf, sizeof(buf));
4849
4850 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4851 _syscmd(cmd, buf, sizeof(buf));
4852
4853 list[0].value = "0";
4854 list[1].value = "0";
4855 } else {
4856 // 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.
4857 if (band == band_2_4 || band == band_5) {
4858 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4859 _syscmd(cmd, buf, sizeof(buf));
4860 if (strlen(buf) > 0) {
4861 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4862 _syscmd(cmd, buf, sizeof(buf));
4863 }
4864 }
4865 if (band == band_5) {
4866 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4867 _syscmd(cmd, buf, sizeof(buf));
4868 if (strlen(buf) > 0) {
4869 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4870 _syscmd(cmd, buf, sizeof(buf));
4871 }
4872 }
4873
4874 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4875 _syscmd(cmd, buf, sizeof(buf));
4876 if (strlen(buf) == 0) {
4877 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4878 _syscmd(cmd, buf, sizeof(buf));
4879 }
4880
4881 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4882 _syscmd(cmd, buf, sizeof(buf));
4883 if (strlen(buf) == 0) {
4884 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4885 _syscmd(cmd, buf, sizeof(buf));
4886 }
4887
4888 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4889 _syscmd(cmd, buf, sizeof(buf));
4890 if (strlen(buf) == 0) {
4891 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4892 } else {
4893 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4894 }
4895 _syscmd(cmd, buf, sizeof(buf));
4896
4897 list[0].value = "1";
4898 list[1].value = "1";
4899 }
4900 wifi_hostapdWrite(config_file, list, 2);
4901}
4902
developer06a01d92022-09-07 16:32:39 +08004903//P2 // sets the number of Tx streams to an enviornment variable
4904INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4905{
developer2de97692022-09-26 14:00:03 +08004906 char cmd[128] = {0};
4907 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004908 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08004909 int cur_mask = 0;
4910 int antcount = 0;
4911 wifi_band band;
developer2de97692022-09-26 14:00:03 +08004912
4913 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4914
developer110b8a32022-12-26 15:56:44 +08004915 if (numStreams <= 0) {
4916 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08004917 return RETURN_ERR;
4918 }
developer110b8a32022-12-26 15:56:44 +08004919
4920 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4921 if (cur_mask == numStreams)
4922 return RETURN_OK;
4923
developer2de97692022-09-26 14:00:03 +08004924 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004925
4926 phyId = radio_index_to_phy(radioIndex);
4927 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004928 _syscmd(cmd, buf, sizeof(buf));
4929
4930 if (strlen(buf) > 0) {
4931 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4932 return RETURN_ERR;
4933 }
developer2de97692022-09-26 14:00:03 +08004934
developer110b8a32022-12-26 15:56:44 +08004935 // if chain mask changed, we need to make the hostapd config valid.
4936 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
4937 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08004938 }
developer110b8a32022-12-26 15:56:44 +08004939 fitChainMask(radioIndex, antcount);
4940
4941 wifi_setRadioEnable(radioIndex, TRUE);
4942
developer2de97692022-09-26 14:00:03 +08004943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4944 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004945}
4946
4947//P2 // outputs the number of Rx streams
4948INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4949{
developer110b8a32022-12-26 15:56:44 +08004950 char buf[8] = {0};
4951 char cmd[128] = {0};
4952 int phyId = 0;
4953
developer2de97692022-09-26 14:00:03 +08004954 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004955
4956 phyId = radio_index_to_phy(radioIndex);
4957 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
4958 _syscmd(cmd, buf, sizeof(buf));
4959
4960 *output_int = (INT)strtol(buf, NULL, 16);
4961
developer2de97692022-09-26 14:00:03 +08004962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004963
developer06a01d92022-09-07 16:32:39 +08004964 return RETURN_OK;
4965}
4966
4967//P2 // sets the number of Rx streams to an enviornment variable
4968INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4969{
developer2de97692022-09-26 14:00:03 +08004970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4971 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4972 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4973 return RETURN_ERR;
4974 }
4975 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004976 return RETURN_ERR;
4977}
4978
4979//Get radio RDG enable setting
4980INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4981{
4982 if (NULL == output_bool)
4983 return RETURN_ERR;
4984 *output_bool = TRUE;
4985 return RETURN_OK;
4986}
4987
4988//Get radio RDG enable setting
4989INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4990{
4991 if (NULL == output_bool)
4992 return RETURN_ERR;
4993 *output_bool = TRUE;
4994 return RETURN_OK;
4995}
4996
4997//Set radio RDG enable setting
4998INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4999{
5000 return RETURN_ERR;
5001}
5002
5003//Get radio ADDBA enable setting
5004INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5005{
5006 if (NULL == output_bool)
5007 return RETURN_ERR;
5008 *output_bool = TRUE;
5009 return RETURN_OK;
5010}
5011
5012//Set radio ADDBA enable setting
5013INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5014{
5015 return RETURN_ERR;
5016}
5017
5018//Get radio auto block ack enable setting
5019INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5020{
5021 if (NULL == output_bool)
5022 return RETURN_ERR;
5023 *output_bool = TRUE;
5024 return RETURN_OK;
5025}
5026
5027//Set radio auto block ack enable setting
5028INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5029{
5030 return RETURN_ERR;
5031}
5032
5033//Get radio 11n pure mode enable support
5034INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5035{
5036 if (NULL == output_bool)
5037 return RETURN_ERR;
5038 *output_bool = TRUE;
5039 return RETURN_OK;
5040}
5041
5042//Get radio 11n pure mode enable setting
5043INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5044{
5045 if (NULL == output_bool)
5046 return RETURN_ERR;
5047 *output_bool = TRUE;
5048 return RETURN_OK;
5049}
5050
5051//Set radio 11n pure mode enable setting
5052INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5053{
5054 return RETURN_ERR;
5055}
5056
5057//Get radio IGMP snooping enable setting
5058INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5059{
developerd946fd62022-12-08 18:03:28 +08005060 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005061 char cmd[128]={0};
5062 char buf[4]={0};
5063 bool bridge = FALSE, mac80211 = FALSE;
5064 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5065
5066 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005067 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005068
5069 *output_bool = FALSE;
5070
5071 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5072 _syscmd(cmd, buf, sizeof(buf));
5073 if (strncmp(buf, "1", 1) == 0)
5074 bridge = TRUE;
5075
developerac6f1142022-12-20 19:26:35 +08005076 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005077 return RETURN_ERR;
5078 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 +08005079 _syscmd(cmd, buf, sizeof(buf));
5080 if (strncmp(buf, "1", 1) == 0)
5081 mac80211 = TRUE;
5082
5083 if (bridge && mac80211)
5084 *output_bool = TRUE;
5085
5086 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005087 return RETURN_OK;
5088}
5089
5090//Set radio IGMP snooping enable setting
5091INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5092{
developerd946fd62022-12-08 18:03:28 +08005093 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005094 char cmd[128]={0};
5095 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08005096 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08005097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5098
5099 // bridge
5100 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5101 _syscmd(cmd, buf, sizeof(buf));
5102
developer804c64f2022-10-19 13:54:40 +08005103 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005104 // mac80211
developer804c64f2022-10-19 13:54:40 +08005105 for (int i = 0; i < max_num_radios; i++) {
developerac6f1142022-12-20 19:26:35 +08005106 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005107 return RETURN_ERR;
5108 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 +08005109 _syscmd(cmd, buf, sizeof(buf));
5110 }
5111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5112 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005113}
5114
5115//Get the Reset count of radio
5116INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5117{
5118 if (NULL == output_int)
5119 return RETURN_ERR;
5120 *output_int = (radioIndex==0)? 1: 3;
5121
5122 return RETURN_OK;
5123}
5124
5125
5126//---------------------------------------------------------------------------------------------------
5127//
5128// Additional Wifi AP level APIs used for Access Point devices
5129//
5130//---------------------------------------------------------------------------------------------------
5131
5132// creates a new ap and pushes these parameters to the hardware
5133INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5134{
developer7930d352022-12-21 17:55:42 +08005135 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005136 return RETURN_OK;
5137}
5138
5139// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5140INT wifi_deleteAp(INT apIndex)
5141{
developerd946fd62022-12-08 18:03:28 +08005142 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005143 char buf[128] = {0};
5144 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005145
developerac6f1142022-12-20 19:26:35 +08005146 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005147 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005148
developer89df4502023-02-16 20:45:02 +08005149 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5150 return RETURN_ERR;
5151
developer7930d352022-12-21 17:55:42 +08005152 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005153 _syscmd(cmd, buf, sizeof(buf));
5154
5155 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005156 return RETURN_OK;
5157}
5158
5159// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5160INT wifi_getApName(INT apIndex, CHAR *output_string)
5161{
developerd946fd62022-12-08 18:03:28 +08005162 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005163 if(NULL == output_string)
5164 return RETURN_ERR;
5165
developerac6f1142022-12-20 19:26:35 +08005166 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005167 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005168 else
5169 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005170 return RETURN_OK;
5171}
5172
5173// Outputs the index number in that corresponds to the SSID string
5174INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5175{
developerd946fd62022-12-08 18:03:28 +08005176 char cmd [128] = {0};
5177 char buf[32] = {0};
5178 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005179 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005180
developerd946fd62022-12-08 18:03:28 +08005181 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5182 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005183
developerac6f1142022-12-20 19:26:35 +08005184 if (strlen(buf) != 0) {
5185 apIndex_str = strtok(buf, "\n");
5186 *output_int = strtoul(apIndex_str, NULL, 10);
5187 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005188 }
developer67b8ee92022-12-20 10:48:43 +08005189
5190 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5191 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5192 if (apIndex_str) {
5193 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5194 return RETURN_OK;
5195 }
developerd946fd62022-12-08 18:03:28 +08005196 *output_int = -1;
5197 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005198}
5199
5200INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5201{
5202 return wifi_getIndexFromName(inputSsidString, output_int);
5203}
5204
5205// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5206INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5207{
5208 char buf[MAX_BUF_SIZE] = {0};
5209 char cmd[MAX_CMD_SIZE] = {0};
5210 char config_file[MAX_BUF_SIZE] = {0};
5211
5212 if(NULL == output_string)
5213 return RETURN_ERR;
5214
5215 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5216 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5217 if((strcmp(buf,"3")==0))
5218 snprintf(output_string, 32, "WPAand11i");
5219 else if((strcmp(buf,"2")==0))
5220 snprintf(output_string, 32, "11i");
5221 else if((strcmp(buf,"1")==0))
5222 snprintf(output_string, 32, "WPA");
5223 else
5224 snprintf(output_string, 32, "None");
5225
5226 return RETURN_OK;
5227}
5228
5229// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5230INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5231{
5232 char config_file[MAX_BUF_SIZE] = {0};
5233 struct params list;
5234
5235 if (NULL == beaconTypeString)
5236 return RETURN_ERR;
5237 list.name = "wpa";
5238 list.value = "0";
5239
5240 if((strcmp(beaconTypeString,"WPAand11i")==0))
5241 list.value="3";
5242 else if((strcmp(beaconTypeString,"11i")==0))
5243 list.value="2";
5244 else if((strcmp(beaconTypeString,"WPA")==0))
5245 list.value="1";
5246
5247 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5248 wifi_hostapdWrite(config_file, &list, 1);
5249 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5250 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5251 return RETURN_OK;
5252}
5253
5254// sets the beacon interval on the hardware for this AP
5255INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5256{
developer5f222492022-09-13 15:21:52 +08005257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5258 struct params params={'\0'};
5259 char buf[MAX_BUF_SIZE] = {'\0'};
5260 char config_file[MAX_BUF_SIZE] = {'\0'};
5261
5262 params.name = "beacon_int";
5263 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5264 params.value = buf;
5265
5266 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5267 wifi_hostapdWrite(config_file, &params, 1);
5268
5269 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5270 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5271 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005272}
5273
5274INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5275{
developer5b398df2022-11-17 20:39:48 +08005276 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5277 return RETURN_ERR;
5278 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005279}
5280
5281// Get the packet size threshold supported.
5282INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5283{
5284 //save config and apply instantly
5285 if (NULL == output_bool)
5286 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005287 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005288 return RETURN_OK;
5289}
5290
5291// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5292INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5293{
developer514406b2022-12-05 17:20:21 +08005294 char buf[16] = {0};
5295 char config_file[128] = {0};
5296 struct params param = {0};
5297
5298 if (threshold > 65535) {
5299 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5300 return RETURN_ERR;
5301 }
developer06a01d92022-09-07 16:32:39 +08005302
developer23e71282023-01-18 10:25:19 +08005303 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005304 snprintf(buf, sizeof(buf), "%u", threshold);
5305 param.name = "rts_threshold";
5306 param.value = buf;
5307 wifi_hostapdWrite(config_file, &param, 1);
5308 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5309 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005310
5311 return RETURN_OK;
5312}
5313
5314// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5315INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5316{
5317 if (NULL == output_string)
5318 return RETURN_ERR;
5319 snprintf(output_string, 32, "TKIPandAESEncryption");
5320 return RETURN_OK;
5321
5322}
5323
5324// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5325INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5326{
5327 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005328 char *param_name = NULL;
5329 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005330
5331 if(NULL == output_string)
5332 return RETURN_ERR;
5333
5334 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5335 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5336
5337 if(strcmp(buf,"0")==0)
5338 {
5339 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5340 snprintf(output_string, 32, "None");
5341 return RETURN_OK;
5342 }
5343 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5344 param_name = "rsn_pairwise";
5345 else if((strcmp(buf,"1")==0))
5346 param_name = "wpa_pairwise";
5347 else
5348 return RETURN_ERR;
5349 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005350 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005351 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5352 param_name = "wpa_pairwise";
5353 memset(output_string, '\0', 32);
5354 wifi_hostapdRead(config_file, param_name, output_string, 32);
5355 }
developer06a01d92022-09-07 16:32:39 +08005356 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5357
developer72ec5572023-01-05 16:27:13 +08005358 if(strcmp(output_string,"TKIP CCMP") == 0)
5359 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5360 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005361 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5362 else if(strcmp(output_string,"CCMP") == 0)
5363 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005364
5365 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5366 return RETURN_OK;
5367}
5368
5369// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5370INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5371{
5372 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5373 struct params params={'\0'};
5374 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005375 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005376
5377 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005378 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005379
5380 if(strcmp(encMode, "TKIPEncryption") == 0)
5381 params.value = "TKIP";
5382 else if(strcmp(encMode,"AESEncryption") == 0)
5383 params.value = "CCMP";
5384 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5385 params.value = "TKIP CCMP";
5386
5387 if((strcmp(output_string,"WPAand11i")==0))
5388 {
5389 params.name = "wpa_pairwise";
5390 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5391 wifi_hostapdWrite(config_file, &params, 1);
5392 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5393
developer30423732022-12-01 16:17:49 +08005394 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005395 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5396 wifi_hostapdWrite(config_file, &params, 1);
5397 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5398
5399 return RETURN_OK;
5400 }
5401 else if((strcmp(output_string,"11i")==0))
5402 {
5403 params.name = "rsn_pairwise";
5404 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5405 wifi_hostapdWrite(config_file, &params, 1);
5406 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5407 return RETURN_OK;
5408 }
5409 else if((strcmp(output_string,"WPA")==0))
5410 {
5411 params.name = "wpa_pairwise";
5412 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5413 wifi_hostapdWrite(config_file, &params, 1);
5414 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5415 return RETURN_OK;
5416 }
5417
5418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5419 return RETURN_OK;
5420}
5421
5422// deletes internal security varable settings for this ap
5423INT wifi_removeApSecVaribles(INT apIndex)
5424{
5425 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005426 //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 +08005427 //_syscmd(cmd, buf, sizeof(buf));
5428
developerd946fd62022-12-08 18:03:28 +08005429 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005430 //_syscmd(cmd, buf, sizeof(buf));
5431 return RETURN_ERR;
5432}
5433
5434// changes the hardware settings to disable encryption on this ap
5435INT wifi_disableApEncryption(INT apIndex)
5436{
5437 //Apply instantly
5438 return RETURN_ERR;
5439}
5440
5441// set the authorization mode on this ap
5442// mode mapping as: 1: open, 2: shared, 4:auto
5443INT wifi_setApAuthMode(INT apIndex, INT mode)
5444{
developeraf95c502022-09-13 16:18:22 +08005445 struct params params={0};
5446 char config_file[64] = {0};
5447 int ret;
5448
5449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5450
5451 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5452 params.name = "auth_algs";
5453
developer72ec5572023-01-05 16:27:13 +08005454 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005455 params.value = "3";
5456 else if (mode & 2)
5457 params.value = "2";
5458 else if (mode & 1)
5459 params.value = "1";
5460 else
5461 params.value = "0";
5462
5463 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5464 wifi_hostapdWrite(config_file, &params, 1);
5465 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005466 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5468
5469 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005470}
5471
5472// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5473INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5474{
5475 //save to wifi config, and wait for wifi restart to apply
5476 struct params params={'\0'};
5477 char config_file[MAX_BUF_SIZE] = {0};
5478 int ret;
5479
5480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5481 if(authMode == NULL)
5482 return RETURN_ERR;
5483
5484 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5485 params.name = "wpa_key_mgmt";
5486
5487 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5488 params.value = "WPA-PSK";
5489 else if(strcmp(authMode,"EAPAuthentication") == 0)
5490 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005491 else if (strcmp(authMode, "SAEAuthentication") == 0)
5492 params.value = "SAE";
5493 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5494 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005495 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5496 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005497 else if (strcmp(authMode, "Enhanced_Open") == 0)
5498 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005499 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5500 return RETURN_OK; //This is taken careof in beaconType
5501
5502 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5503 ret=wifi_hostapdWrite(config_file,&params,1);
5504 if(!ret)
5505 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5507
5508 return ret;
5509}
5510
5511// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5512INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5513{
5514 //save to wifi config, and wait for wifi restart to apply
5515 char BeaconType[50] = {0};
5516 char config_file[MAX_BUF_SIZE] = {0};
5517
5518 *authMode = 0;
5519 wifi_getApBeaconType(apIndex,BeaconType);
5520 printf("%s____%s \n",__FUNCTION__,BeaconType);
5521
5522 if(strcmp(BeaconType,"None") == 0)
5523 strcpy(authMode,"None");
5524 else
5525 {
5526 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5527 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5528 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5529 if(strcmp(authMode,"WPA-PSK") == 0)
5530 strcpy(authMode,"SharedAuthentication");
5531 else if(strcmp(authMode,"WPA-EAP") == 0)
5532 strcpy(authMode,"EAPAuthentication");
5533 }
5534
5535 return RETURN_OK;
5536}
5537
5538// Outputs the number of stations associated per AP
5539INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5540{
developerd946fd62022-12-08 18:03:28 +08005541 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005542 char cmd[128]={0};
5543 char buf[128]={0};
5544 BOOL status = false;
5545
5546 if(apIndex > MAX_APS)
5547 return RETURN_ERR;
5548
5549 wifi_getApEnable(apIndex,&status);
5550 if (!status)
5551 return RETURN_OK;
5552
developerd946fd62022-12-08 18:03:28 +08005553 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005554 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005555 return RETURN_ERR;
5556 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005557 _syscmd(cmd, buf, sizeof(buf));
5558 sscanf(buf,"%lu", output_ulong);
5559
5560 return RETURN_OK;
5561}
5562
5563// manually removes any active wi-fi association with the device specified on this ap
5564INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5565{
developerd946fd62022-12-08 18:03:28 +08005566 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005567 char buf[126]={'\0'};
5568
developerac6f1142022-12-20 19:26:35 +08005569 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005570 return RETURN_ERR;
5571 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005572 system(buf);
5573
5574 return RETURN_OK;
5575}
5576
5577// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5578INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5579{
5580 if(NULL == output_int)
5581 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005582 int max_radio_num = 0;
5583 wifi_getMaxRadioNumber(&max_radio_num);
5584 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005585 return RETURN_OK;
5586}
5587
5588// sets the radio index for the specific ap
5589INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5590{
5591 //set to config only and wait for wifi reset to apply settings
5592 return RETURN_ERR;
5593}
5594
5595// Get the ACL MAC list per AP
5596INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5597{
developerd946fd62022-12-08 18:03:28 +08005598 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005599 char cmd[MAX_CMD_SIZE]={'\0'};
5600 int ret = 0;
5601
developerac6f1142022-12-20 19:26:35 +08005602 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005603 return RETURN_ERR;
5604 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005605 ret = _syscmd(cmd,macArray,buf_size);
5606 if (ret != 0)
5607 return RETURN_ERR;
5608
5609 return RETURN_OK;
5610}
5611
developere6aafda2022-09-13 14:59:28 +08005612INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5613{
developerd946fd62022-12-08 18:03:28 +08005614 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005615 char cmd[MAX_CMD_SIZE]={'\0'};
5616 int ret = 0;
5617
developerac6f1142022-12-20 19:26:35 +08005618 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005619 return RETURN_ERR;
5620 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005621 ret = _syscmd(cmd,macArray,buf_size);
5622 if (ret != 0)
5623 return RETURN_ERR;
5624
5625 return RETURN_OK;
5626}
5627
developer06a01d92022-09-07 16:32:39 +08005628// Get the list of stations associated per AP
5629INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5630{
developerd946fd62022-12-08 18:03:28 +08005631 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005632 char cmd[128];
5633
5634 if(apIndex > 3) //Currently supporting apIndex upto 3
5635 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005636 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005637 return RETURN_ERR;
5638 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5639 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005640 _syscmd(cmd, macArray, buf_size);
5641
5642 return RETURN_OK;
5643}
5644
developer2f995fb2023-02-24 10:40:44 +08005645INT getAddressControlMode(INT apIndex, INT *mode)
5646{
5647 char buf [16] = {0};
5648 char config_file[64] = {0};
5649
5650 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5651 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5652
5653 *mode = -1;
5654 // 0 use deny file, 1 use accept file
5655 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5656 *mode = (INT)strtol(buf, NULL, 10);
5657
5658 return RETURN_OK;
5659}
5660
developer06a01d92022-09-07 16:32:39 +08005661// adds the mac address to the filter list
5662//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5663INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5664{
5665 char cmd[MAX_CMD_SIZE]={'\0'};
5666 char buf[MAX_BUF_SIZE]={'\0'};
5667
developer2f995fb2023-02-24 10:40:44 +08005668 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005669 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005670
developer06a01d92022-09-07 16:32:39 +08005671 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5672 if(_syscmd(cmd,buf,sizeof(buf)))
5673 return RETURN_ERR;
5674
5675 return RETURN_OK;
5676}
5677
developer2f995fb2023-02-24 10:40:44 +08005678INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5679{
5680 char cmd[MAX_CMD_SIZE]={'\0'};
5681 char buf[MAX_BUF_SIZE]={'\0'};
5682
5683 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5684 return RETURN_ERR;
5685
5686 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5687 if(_syscmd(cmd,buf,sizeof(buf)))
5688 return RETURN_ERR;
5689
5690 return RETURN_OK;
5691}
5692
developer06a01d92022-09-07 16:32:39 +08005693// deletes the mac address from the filter list
5694//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5695INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5696{
5697 char cmd[MAX_CMD_SIZE]={'\0'};
5698 char buf[MAX_BUF_SIZE]={'\0'};
5699
5700#if 0
developerd946fd62022-12-08 18:03:28 +08005701 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005702 if(_syscmd(cmd,buf,sizeof(buf)))
5703 return RETURN_ERR;
5704
5705#endif
developer2f995fb2023-02-24 10:40:44 +08005706 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005707 if(_syscmd(cmd,buf,sizeof(buf)))
5708 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005709 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5710 if(_syscmd(cmd,buf,sizeof(buf)))
5711 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005712
5713 return RETURN_OK;
5714}
5715
5716// outputs the number of devices in the filter list
5717INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5718{
developere6aafda2022-09-13 14:59:28 +08005719 char cmd[MAX_BUF_SIZE]={0};
5720 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005721 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005722
5723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5724 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005725 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005726
developer2f995fb2023-02-24 10:40:44 +08005727 getAddressControlMode(apIndex, &mode);
5728 if (mode == -1)
5729 return RETURN_OK;
5730
5731 if (mode == 0)
5732 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5733 else if (mode == 1)
5734 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005735 _syscmd(cmd, buf, sizeof(buf));
5736
developer2f995fb2023-02-24 10:40:44 +08005737 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005738
5739 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5740 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005741}
5742
5743INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5744{
5745 char cmd[128]={'\0'};
5746 char buf[128]={'\0'};
5747
5748 if(strcmp(action,"DENY")==0)
5749 {
5750 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5751 system(buf);
5752 return RETURN_OK;
5753 }
5754
5755 if(strcmp(action,"ALLOW")==0)
5756 {
5757 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5758 system(buf);
5759 return RETURN_OK;
5760 }
5761
5762 return RETURN_ERR;
5763
5764}
5765
5766// enable kick for devices on acl black list
5767INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5768{
5769 char aclArray[512] = {0}, *acl = NULL;
5770 char assocArray[512] = {0}, *asso = NULL;
5771
developere6aafda2022-09-13 14:59:28 +08005772 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005773 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5774
5775 // if there are no devices connected there is nothing to do
5776 if (strlen(assocArray) < 17)
5777 return RETURN_OK;
5778
5779 if (enable == TRUE)
5780 {
5781 //kick off the MAC which is in ACL array (deny list)
5782 acl = strtok(aclArray, "\r\n");
5783 while (acl != NULL) {
5784 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5785 wifi_kickApAssociatedDevice(apIndex, acl);
5786
5787 acl = strtok(NULL, "\r\n");
5788 }
developere6aafda2022-09-13 14:59:28 +08005789 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005790 }
5791 else
5792 {
developere6aafda2022-09-13 14:59:28 +08005793 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005794 }
5795
5796#if 0
5797 //TODO: need to revisit below implementation
5798 char aclArray[512]={0}, *acl=NULL;
5799 char assocArray[512]={0}, *asso=NULL;
5800 char buf[256]={'\0'};
5801 char action[10]={'\0'};
5802 FILE *fr=NULL;
5803 char interface[10]={'\0'};
5804 char config_file[MAX_BUF_SIZE] = {0};
5805
5806 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5807 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5808 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5809 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5810
5811 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5812 system(buf);
5813 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5814 system(buf);
5815 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5816 system(buf);
5817 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5818 system(buf);
5819 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5820 system(buf);
5821
5822 if ( enable == TRUE )
5823 {
5824 int device_count=0;
5825 strcpy(action,"DENY");
5826 //kick off the MAC which is in ACL array (deny list)
5827 acl = strtok (aclArray,",");
5828 while (acl != NULL) {
5829 if(strlen(acl)>=17)
5830 {
5831 apply_rules(apIndex, acl,action,interface);
5832 device_count++;
5833 //Register mac to be blocked ,in syscfg.db persistent storage
5834 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5835 system(buf);
5836 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5837 system(buf);
5838 system("syscfg commit");
5839
5840 wifi_kickApAssociatedDevice(apIndex, acl);
5841 }
5842 acl = strtok (NULL, ",");
5843 }
5844 }
5845 else
5846 {
5847 int device_count=0;
5848 char cmdmac[20]={'\0'};
5849 strcpy(action,"ALLOW");
5850 //kick off the MAC which is not in ACL array (allow list)
5851 acl = strtok (aclArray,",");
5852 while (acl != NULL) {
5853 if(strlen(acl)>=17)
5854 {
5855 apply_rules(apIndex, acl,action,interface);
5856 device_count++;
5857 //Register mac to be Allowed ,in syscfg.db persistent storage
5858 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5859 system(buf);
5860 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5861 system(buf);
5862 sprintf(cmdmac,"%s",acl);
5863 }
5864 acl = strtok (NULL, ",");
5865 }
5866 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5867 system(buf);
5868
5869 //Disconnect the mac which is not in ACL
5870 asso = strtok (assocArray,",");
5871 while (asso != NULL) {
5872 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5873 wifi_kickApAssociatedDevice(apIndex, asso);
5874 asso = strtok (NULL, ",");
5875 }
5876 }
5877#endif
5878 return RETURN_OK;
5879}
5880
5881INT wifi_setPreferPrivateConnection(BOOL enable)
5882{
developer06a01d92022-09-07 16:32:39 +08005883 return RETURN_OK;
5884}
5885
5886// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5887INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5888{
developerd946fd62022-12-08 18:03:28 +08005889 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005890 int items = 1;
5891 struct params list[2];
5892 char buf[MAX_BUF_SIZE] = {0};
5893 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005894 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005895
5896 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005897
developer10adcc12022-09-13 14:39:17 +08005898 if (filterMode == 0) {
5899 sprintf(buf, "%d", 0);
5900 list[0].value = buf;
5901
developer2f995fb2023-02-24 10:40:44 +08005902 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08005903 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005904 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005905 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
5906 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005907 memset(cmd,0,sizeof(cmd));
5908 // Delete deny_mac_file in hostapd configuration
5909 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08005910 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005911 }
5912 else if (filterMode == 1) {
5913 sprintf(buf, "%d", filterMode);
5914 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005915 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5916 list[1].name = "accept_mac_file";
5917 list[1].value = acl_file;
5918 items = 2;
developer10adcc12022-09-13 14:39:17 +08005919 } else if (filterMode == 2) {
5920 //TODO: deny_mac_file
5921 sprintf(buf, "%d", 0);
5922 list[0].value = buf;
5923 list[1].name = "deny_mac_file";
5924 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5925 list[1].value = deny_file;
5926 items = 2;
5927 } else {
5928 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005929 }
developer10adcc12022-09-13 14:39:17 +08005930
developer06a01d92022-09-07 16:32:39 +08005931 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5932 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08005933 if (multiple_set == FALSE) {
5934 wifi_setApEnable(apIndex, FALSE);
5935 wifi_setApEnable(apIndex, TRUE);
5936 }
developer06a01d92022-09-07 16:32:39 +08005937
5938 return RETURN_OK;
5939
5940#if 0
5941 if(apIndex==0 || apIndex==1)
5942 {
5943 //set the filtermode
5944 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5945 system(buf);
5946 system("syscfg commit");
5947
5948 if(filterMode==0)
5949 {
5950 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5951 system(buf);
5952 return RETURN_OK;
5953 }
5954 }
5955 return RETURN_OK;
5956#endif
5957}
5958
5959// 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.
5960INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5961{
5962 return RETURN_ERR;
5963}
5964
5965// gets the vlan ID for this ap from an internal enviornment variable
5966INT wifi_getApVlanID(INT apIndex, INT *output_int)
5967{
developer30423732022-12-01 16:17:49 +08005968 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005969 {
5970 *output_int=100;
5971 return RETURN_OK;
5972 }
5973
5974 return RETURN_ERR;
5975}
5976
5977// sets the vlan ID for this ap to an internal enviornment variable
5978INT wifi_setApVlanID(INT apIndex, INT vlanId)
5979{
5980 //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)
5981 return RETURN_ERR;
5982}
5983
5984// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5985INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5986{
5987 snprintf(bridgeName, 32, "brlan0");
5988 snprintf(IP, 32, "10.0.0.1");
5989 snprintf(subnet, 32, "255.255.255.0");
5990
5991 return RETURN_OK;
5992}
5993
5994//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5995INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5996{
5997 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5998 return RETURN_ERR;
5999}
6000
6001// reset the vlan configuration for this ap
6002INT wifi_resetApVlanCfg(INT apIndex)
6003{
developerf5fef612022-09-20 19:38:26 +08006004 char original_config_file[64] = {0};
6005 char current_config_file[64] = {0};
6006 char buf[64] = {0};
6007 char cmd[64] = {0};
6008 char vlan_file[64] = {0};
6009 char vlan_tagged_interface[16] = {0};
6010 char vlan_bridge[16] = {0};
6011 char vlan_naming[16] = {0};
6012 struct params list[4] = {0};
6013 wifi_band band;
6014
6015 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6016
6017 band = wifi_index_to_band(apIndex);
6018 if (band == band_2_4)
6019 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006020 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006021 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006022 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006023 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6024
6025 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6026
6027 if (strlen(vlan_file) == 0)
6028 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006029
developerf5fef612022-09-20 19:38:26 +08006030 // The file should exist or this vap would not work.
6031 if (access(vlan_file, F_OK) != 0) {
6032 sprintf(cmd, "touch %s", vlan_file);
6033 _syscmd(cmd, buf, sizeof(buf));
6034 }
6035 list[0].name = "vlan_file";
6036 list[0].value = vlan_file;
6037
6038 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6039 list[1].name = "vlan_tagged_interface";
6040 list[1].value = vlan_tagged_interface;
6041
6042 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6043 list[2].name = "vlan_bridge";
6044 list[2].value = vlan_bridge;
6045
6046 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6047 list[3].name = "vlan_naming";
6048 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006049
developerf5fef612022-09-20 19:38:26 +08006050 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6051 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006052 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006053 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006054
developerf5fef612022-09-20 19:38:26 +08006055 // restart this ap
6056 wifi_setApEnable(apIndex, FALSE);
6057 wifi_setApEnable(apIndex, TRUE);
6058
6059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6060
6061 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006062}
6063
6064// 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.
6065INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6066{
6067 return RETURN_ERR;
6068}
6069
6070// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6071INT wifi_startHostApd()
6072{
6073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6074 system("systemctl start hostapd.service");
6075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6076 return RETURN_OK;
6077 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6078}
6079
6080// stops hostapd
6081INT wifi_stopHostApd()
6082{
6083 char cmd[128] = {0};
6084 char buf[128] = {0};
6085
6086 sprintf(cmd,"systemctl stop hostapd");
6087 _syscmd(cmd, buf, sizeof(buf));
6088
6089 return RETURN_OK;
6090}
6091
6092// restart hostapd dummy function
6093INT wifi_restartHostApd()
6094{
6095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6096 system("systemctl restart hostapd-global");
6097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6098
6099 return RETURN_OK;
6100}
6101
6102static int align_hostapd_config(int index)
6103{
6104 ULONG lval;
6105 wifi_getRadioChannel(index%2, &lval);
6106 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006107 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006108}
6109
6110// sets the AP enable status variable for the specified ap.
6111INT wifi_setApEnable(INT apIndex, BOOL enable)
6112{
developerd946fd62022-12-08 18:03:28 +08006113 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006114 char config_file[MAX_BUF_SIZE] = {0};
6115 char cmd[MAX_CMD_SIZE] = {0};
6116 char buf[MAX_BUF_SIZE] = {0};
6117 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006118 int max_radio_num = 0;
6119 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006120
6121 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006122
6123 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006124 if (enable == status)
6125 return RETURN_OK;
6126
developerac6f1142022-12-20 19:26:35 +08006127 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006128 return RETURN_ERR;
6129
developer06a01d92022-09-07 16:32:39 +08006130 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006131 int radioIndex = apIndex % max_radio_num;
6132 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006133 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6134 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006135 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006136 _syscmd(cmd, buf, sizeof(buf));
developer23e71282023-01-18 10:25:19 +08006137 sprintf(cmd, "iw %s del", interface_name);
6138 _syscmd(cmd, buf, sizeof(buf));
6139 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6140 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08006141 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006142 _syscmd(cmd, buf, sizeof(buf));
6143 }
6144 else {
developerd946fd62022-12-08 18:03:28 +08006145 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006146 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006147 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006148 _syscmd(cmd, buf, sizeof(buf));
6149 }
developera77d84b2023-02-22 16:10:50 +08006150
developer431128d2022-12-16 15:30:41 +08006151 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006152 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006153 _syscmd(cmd, buf, sizeof(buf));
6154 //Wait for wifi up/down to apply
6155 return RETURN_OK;
6156}
6157
6158// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6159INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6160{
developerd946fd62022-12-08 18:03:28 +08006161 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006162 char cmd[MAX_CMD_SIZE] = {'\0'};
6163 char buf[MAX_BUF_SIZE] = {'\0'};
6164
6165 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6166 return RETURN_ERR;
6167
6168 *output_bool = 0;
6169
6170 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6171 {
developerac6f1142022-12-20 19:26:35 +08006172 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006173 *output_bool = FALSE;
6174 return RETURN_OK;
6175 }
6176 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006177 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6178 }
6179
6180 return RETURN_OK;
6181}
6182
6183// Outputs the AP "Enabled" "Disabled" status from driver
6184INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6185{
6186 char cmd[128] = {0};
6187 char buf[128] = {0};
6188 BOOL output_bool;
6189
6190 if ( NULL == output_string)
6191 return RETURN_ERR;
6192 wifi_getApEnable(apIndex,&output_bool);
6193
6194 if(output_bool == 1)
6195 snprintf(output_string, 32, "Up");
6196 else
6197 snprintf(output_string, 32, "Disable");
6198
6199 return RETURN_OK;
6200}
6201
6202//Indicates whether or not beacons include the SSID name.
6203// outputs a 1 if SSID on the AP is enabled, else outputs 0
6204INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6205{
6206 //get the running status
6207 char config_file[MAX_BUF_SIZE] = {0};
6208 char buf[16] = {0};
6209
6210 if (!output)
6211 return RETURN_ERR;
6212
6213 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6214 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006215 // default is enable
6216 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6217 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006218
6219 return RETURN_OK;
6220}
6221
6222// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6223INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6224{
6225 //store the config, apply instantly
6226 char config_file[MAX_BUF_SIZE] = {0};
6227 struct params list;
6228
6229 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6230 list.name = "ignore_broadcast_ssid";
6231 list.value = enable?"0":"1";
6232
6233 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6234 wifi_hostapdWrite(config_file, &list, 1);
6235 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6236 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006237 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006238 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6239
6240 return RETURN_OK;
6241}
6242
6243//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6244INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6245{
6246 //get the running status
6247 if(!output_uint)
6248 return RETURN_ERR;
6249 *output_uint=16;
6250 return RETURN_OK;
6251}
6252
6253INT wifi_setApRetryLimit(INT apIndex, UINT number)
6254{
6255 //apply instantly
6256 return RETURN_ERR;
6257}
6258
6259//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6260INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6261{
6262 if(!output)
6263 return RETURN_ERR;
6264 *output=TRUE;
6265 return RETURN_OK;
6266}
6267
6268//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6269INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6270{
6271 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006272 char cmd[128] = {0};
6273 char buf[128] = {0};
6274 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006275 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006276
developer0b246d12022-09-30 15:24:20 +08006277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006278
developer0b246d12022-09-30 15:24:20 +08006279 wifi_getMaxRadioNumber(&max_radio_num);
6280 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006281 phyId = radio_index_to_phy(radioIndex);
6282 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006283 _syscmd(cmd,buf, sizeof(buf));
6284
6285 if (strlen(buf) > 0)
6286 *output = true;
6287
6288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006289
developer06a01d92022-09-07 16:32:39 +08006290 return RETURN_OK;
6291}
6292
6293//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6294INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6295{
6296 //get the running status from driver
6297 if(!output)
6298 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006299
6300 char config_file[MAX_BUF_SIZE] = {0};
6301 char buf[16] = {0};
6302
6303 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6304 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006305 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006306 *output = TRUE;
6307 else
6308 *output = FALSE;
6309
developer06a01d92022-09-07 16:32:39 +08006310 return RETURN_OK;
6311}
6312
6313// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6314INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6315{
6316 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006317 char config_file[MAX_BUF_SIZE] = {0};
6318 struct params list;
6319
6320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6321 list.name = "wmm_enabled";
6322 list.value = enable?"1":"0";
6323
6324 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6325 wifi_hostapdWrite(config_file, &list, 1);
6326 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6327 wifi_reloadAp(apIndex);
6328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6329
6330 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006331}
6332
6333//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.
6334INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6335{
6336 //get the running status from driver
6337 if(!output)
6338 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006339
6340 char config_file[128] = {0};
6341 char buf[16] = {0};
6342
6343 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6344 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6345 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6346 *output = TRUE;
6347 else
6348 *output = FALSE;
6349
developer06a01d92022-09-07 16:32:39 +08006350 return RETURN_OK;
6351}
6352
6353// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6354INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6355{
6356 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006357 char config_file[MAX_BUF_SIZE] = {0};
6358 struct params list;
6359
6360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6361 list.name = "uapsd_advertisement_enabled";
6362 list.value = enable?"1":"0";
6363
6364 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6365 wifi_hostapdWrite(config_file, &list, 1);
6366 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6367 wifi_reloadAp(apIndex);
6368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6369
6370 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006371}
6372
developer6daeb3f2022-09-30 13:36:39 +08006373// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006374INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6375{
developerd946fd62022-12-08 18:03:28 +08006376 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006377 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6378 char cmd[128] = {0};
6379 char buf[128] = {0};
6380 char ack_filepath[128] = {0};
6381 uint16_t bitmap = 0;
6382 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6383 FILE *f = NULL;
6384
6385 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6386
6387 // Get current setting
6388 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6389 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6390 _syscmd(cmd, buf, sizeof(buf));
6391 if (strlen(buf) > 0)
6392 bitmap = strtoul(buf, NULL, 10);
6393
6394 bitmap = strtoul(buf, NULL, 10);
6395
6396 if (ackPolicy == TRUE) { // True, unset this class
6397 bitmap &= ~class_map[class];
6398 } else { // False, set this class
6399 bitmap |= class_map[class];
6400 }
6401
6402 f = fopen(ack_filepath, "w");
6403 if (f == NULL) {
6404 fprintf(stderr, "%s: fopen failed\n", __func__);
6405 return RETURN_ERR;
6406 }
6407 fprintf(f, "%hu", bitmap);
6408 fclose(f);
6409
developerac6f1142022-12-20 19:26:35 +08006410 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006411 return RETURN_ERR;
6412 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006413 _syscmd(cmd, buf, sizeof(buf));
6414
6415 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6416 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006417}
6418
6419//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.
6420INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6421{
6422 //get the running status from driver
6423 if(!output_uint)
6424 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006425
6426 char output[16]={'\0'};
6427 char config_file[MAX_BUF_SIZE] = {0};
6428
6429 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6430 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6431 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6432 else {
6433 int device_num = atoi(output);
6434 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6435 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6436 return RETURN_ERR;
6437 }
6438 else {
6439 *output_uint = device_num;
6440 }
6441 }
6442
developer06a01d92022-09-07 16:32:39 +08006443 return RETURN_OK;
6444}
6445
6446INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6447{
6448 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006449 char str[MAX_BUF_SIZE]={'\0'};
6450 char cmd[MAX_CMD_SIZE]={'\0'};
6451 struct params params;
6452 char config_file[MAX_BUF_SIZE] = {0};
6453
6454 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006455 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006456 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006457 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006458 }
6459 sprintf(str, "%d", number);
6460 params.name = "max_num_sta";
6461 params.value = str;
6462
6463 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6464 int ret = wifi_hostapdWrite(config_file, &params, 1);
6465 if (ret) {
6466 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6467 ,__func__, ret);
6468 }
6469
6470 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6471 if (ret) {
6472 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6473 ,__func__, ret);
6474 }
6475 wifi_reloadAp(apIndex);
6476 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6477
6478 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006479}
6480
6481//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.
6482INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6483{
6484 //get the current threshold
6485 if(!output_uint)
6486 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006487 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6488 if (*output_uint == 0)
6489 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006490 return RETURN_OK;
6491}
6492
6493INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6494{
6495 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006496 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6497 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006498 return RETURN_ERR;
6499}
6500
6501//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.
6502INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6503{
6504 if(!output_uint)
6505 return RETURN_ERR;
6506 *output_uint = 3;
6507 return RETURN_OK;
6508}
6509
6510//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6511INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6512{
6513 if(!output_uint)
6514 return RETURN_ERR;
6515 *output_uint = 3;
6516 return RETURN_OK;
6517}
6518
6519//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.
6520INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6521{
6522 if(!output_in_seconds)
6523 return RETURN_ERR;
6524 *output_in_seconds = 0;
6525 return RETURN_OK;
6526}
6527
6528//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
6529INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6530{
6531 if(!output || apIndex>=MAX_APS)
6532 return RETURN_ERR;
6533 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006534 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006535 return RETURN_OK;
6536}
6537
6538//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6539INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6540{
developer587c1b62022-09-27 15:58:59 +08006541 char config_file[128] = {0};
6542 char wpa[16] = {0};
6543 char key_mgmt[64] = {0};
6544 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006545 if (!output)
6546 return RETURN_ERR;
6547
6548 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006549 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006550
developer587c1b62022-09-27 15:58:59 +08006551 strcpy(output, "None");//Copying "None" to output string for default case
6552 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006553 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006554 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006555 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006556 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006557 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006558 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006559 snprintf(output, 32, "WPA-WPA2-Personal");
6560
developer72ec5572023-01-05 16:27:13 +08006561 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6562 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006563 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006564 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006565 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006566 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006567 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006568 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006569 snprintf(output, 32, "WPA-WPA2-Enterprise");
6570 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006571 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006572 snprintf(output, 32, "WPA3-Personal");
6573 else
developer4a359672022-10-13 15:30:46 +08006574 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006575 }
developer06a01d92022-09-07 16:32:39 +08006576
6577 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6578 return RETURN_OK;
6579#if 0
6580 //TODO: need to revisit below implementation
6581 char securityType[32], authMode[32];
6582 int enterpriseMode=0;
6583
6584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6585 if(!output)
6586 return RETURN_ERR;
6587
6588 wifi_getApBeaconType(apIndex, securityType);
6589 strcpy(output,"None");//By default, copying "None" to output string
6590 if (strncmp(securityType,"None", strlen("None")) == 0)
6591 return RETURN_OK;
6592
6593 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6594 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6595
6596 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6597 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6598 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6599 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6600 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6601 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6603
6604 return RETURN_OK;
6605#endif
6606}
6607
6608INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6609{
6610 char securityType[32];
6611 char authMode[32];
6612
6613 //store settings and wait for wifi up to apply
6614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6615 if(!encMode)
6616 return RETURN_ERR;
6617
developer06a01d92022-09-07 16:32:39 +08006618 if (strcmp(encMode, "None")==0)
6619 {
6620 strcpy(securityType,"None");
6621 strcpy(authMode,"None");
6622 }
6623 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6624 {
6625 strcpy(securityType,"WPAand11i");
6626 strcpy(authMode,"PSKAuthentication");
6627 }
6628 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6629 {
6630 strcpy(securityType,"WPAand11i");
6631 strcpy(authMode,"EAPAuthentication");
6632 }
6633 else if (strcmp(encMode, "WPA-Personal")==0)
6634 {
6635 strcpy(securityType,"WPA");
6636 strcpy(authMode,"PSKAuthentication");
6637 }
6638 else if (strcmp(encMode, "WPA-Enterprise")==0)
6639 {
6640 strcpy(securityType,"WPA");
6641 strcpy(authMode,"EAPAuthentication");
6642 }
6643 else if (strcmp(encMode, "WPA2-Personal")==0)
6644 {
6645 strcpy(securityType,"11i");
6646 strcpy(authMode,"PSKAuthentication");
6647 }
6648 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6649 {
6650 strcpy(securityType,"11i");
6651 strcpy(authMode,"EAPAuthentication");
6652 }
developer587c1b62022-09-27 15:58:59 +08006653 else if (strcmp(encMode, "WPA3-Personal") == 0)
6654 {
6655 strcpy(securityType,"11i");
6656 strcpy(authMode,"SAEAuthentication");
6657 }
developer4a359672022-10-13 15:30:46 +08006658 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006659 {
6660 strcpy(securityType, "11i");
6661 strcpy(authMode, "PSK-SAEAuthentication");
6662 }
developer587c1b62022-09-27 15:58:59 +08006663 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6664 {
6665 strcpy(securityType,"11i");
6666 strcpy(authMode,"EAP_192-bit_Authentication");
6667 }
developer5c9fee82023-01-13 14:44:16 +08006668 else if (strcmp(encMode, "OWE") == 0)
6669 {
6670 strcpy(securityType,"11i");
6671 strcpy(authMode,"Enhanced_Open");
6672 }
developer06a01d92022-09-07 16:32:39 +08006673 else
6674 {
6675 strcpy(securityType,"None");
6676 strcpy(authMode,"None");
6677 }
6678 wifi_setApBeaconType(apIndex, securityType);
6679 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6681
6682 return RETURN_OK;
6683}
6684
6685
developer4b102122023-02-15 10:53:03 +08006686// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006687//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006688INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6689{
developer30423732022-12-01 16:17:49 +08006690 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006691 char config_file[MAX_BUF_SIZE] = {0};
6692
6693 if(output_string==NULL)
6694 return RETURN_ERR;
6695
6696 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6697 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6698
6699 if(strcmp(buf,"0")==0)
6700 {
6701 printf("wpa_mode is %s ......... \n",buf);
6702 return RETURN_ERR;
6703 }
6704
6705 wifi_dbg_printf("\nFunc=%s\n",__func__);
6706 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006707 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006708 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6709
6710 return RETURN_OK;
6711}
6712
developer4b102122023-02-15 10:53:03 +08006713// Set PreSharedKey associated with a Access Point.
6714// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006715INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6716{
6717 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6718 struct params params={'\0'};
6719 int ret;
6720 char config_file[MAX_BUF_SIZE] = {0};
6721
6722 if(NULL == preSharedKey)
6723 return RETURN_ERR;
6724
developer4b102122023-02-15 10:53:03 +08006725 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006726
developer4b102122023-02-15 10:53:03 +08006727 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006728 {
developer4b102122023-02-15 10:53:03 +08006729 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006730 return RETURN_ERR;
6731 }
6732 params.value = preSharedKey;
6733 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6734 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006735 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006736 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006737 wifi_reloadAp(apIndex);
6738 }
developer06a01d92022-09-07 16:32:39 +08006739 return ret;
6740 //TODO: call hostapd_cli for dynamic_config_control
6741}
6742
6743//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6744// outputs the passphrase, maximum 63 characters
6745INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6746{
6747 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6748
6749 wifi_dbg_printf("\nFunc=%s\n",__func__);
6750 if (NULL == output_string)
6751 return RETURN_ERR;
6752
6753 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6754 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6755 if(strcmp(buf,"0")==0)
6756 {
6757 printf("wpa_mode is %s ......... \n",buf);
6758 return RETURN_ERR;
6759 }
6760
6761 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6762 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6763
6764 return RETURN_OK;
6765}
6766
6767// sets the passphrase enviornment variable, max 63 characters
6768INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6769{
6770 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6771 struct params params={'\0'};
6772 char config_file[MAX_BUF_SIZE] = {0};
6773 int ret;
6774
6775 if(NULL == passPhrase)
6776 return RETURN_ERR;
6777
6778 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6779 {
6780 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6781 return RETURN_ERR;
6782 }
6783 params.name = "wpa_passphrase";
6784 params.value = passPhrase;
6785 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6786 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006787 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006788 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006789 wifi_reloadAp(apIndex);
6790 }
developer06a01d92022-09-07 16:32:39 +08006791
6792 return ret;
6793}
6794
6795//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.
6796INT wifi_setApSecurityReset(INT apIndex)
6797{
developer8d583982022-09-20 11:28:22 +08006798 char original_config_file[64] = {0};
6799 char current_config_file[64] = {0};
6800 char buf[64] = {0};
6801 char cmd[64] = {0};
6802 char wpa[4] = {0};
6803 char wpa_psk[64] = {0};
6804 char wpa_passphrase[64] = {0};
6805 char wpa_psk_file[128] = {0};
6806 char wpa_key_mgmt[64] = {0};
6807 char wpa_pairwise[32] = {0};
6808 wifi_band band;
6809 struct params list[6];
6810
6811 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6812
6813 band = wifi_index_to_band(apIndex);
6814 if (band == band_2_4)
6815 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006816 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006817 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006818 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006819 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6820 else
6821 return RETURN_ERR;
6822
6823 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6824 list[0].name = "wpa";
6825 list[0].value = wpa;
6826
6827 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6828 list[1].name = "wpa_psk";
6829 list[1].value = wpa_psk;
6830
6831 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6832 list[2].name = "wpa_passphrase";
6833 list[2].value = wpa_passphrase;
6834
6835 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6836
6837 if (strlen(wpa_psk_file) == 0)
6838 strcpy(wpa_psk_file, PSK_FILE);
6839
6840 if (access(wpa_psk_file, F_OK) != 0) {
6841 sprintf(cmd, "touch %s", wpa_psk_file);
6842 _syscmd(cmd, buf, sizeof(buf));
6843 }
6844 list[3].name = "wpa_psk_file";
6845 list[3].value = wpa_psk_file;
6846
6847 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6848 list[4].name = "wpa_key_mgmt";
6849 list[4].value = wpa_key_mgmt;
6850
6851 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6852 list[5].name = "wpa_pairwise";
6853 list[5].value = wpa_pairwise;
6854
6855 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6856 wifi_hostapdWrite(current_config_file, list, 6);
6857
6858 wifi_setApEnable(apIndex, FALSE);
6859 wifi_setApEnable(apIndex, TRUE);
6860
6861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6862 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006863}
6864
6865//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).
6866INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6867{
developer8f2ddd52022-09-13 15:39:24 +08006868 char config_file[64] = {0};
6869 char buf[64] = {0};
6870 char cmd[256] = {0};
6871
6872 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6873
developer06a01d92022-09-07 16:32:39 +08006874 if(!IP_output || !Port_output || !RadiusSecret_output)
6875 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006876
developer8f2ddd52022-09-13 15:39:24 +08006877 // Read the first matched config
6878 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6879 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6880 _syscmd(cmd, buf, sizeof(buf));
6881 strncpy(IP_output, buf, 64);
6882
6883 memset(buf, 0, sizeof(buf));
6884 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6885 _syscmd(cmd, buf, sizeof(buf));
6886 *Port_output = atoi(buf);
6887
6888 memset(buf, 0, sizeof(buf));
6889 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6890 _syscmd(cmd, buf, sizeof(buf));
6891 strncpy(RadiusSecret_output, buf, 64);
6892
6893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006894 return RETURN_OK;
6895}
6896
6897INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6898{
developer8f2ddd52022-09-13 15:39:24 +08006899 char config_file[64] = {0};
6900 char port_str[8] = {0};
6901 char cmd[256] = {0};
6902 char buf[128] = {0};
6903
6904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08006905 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
6906 return RETURN_ERR;
6907
6908 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
6909 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006910
6911 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6912
6913 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6914 _syscmd(cmd, buf, sizeof(buf));
6915 memset(cmd, 0, sizeof(cmd));
6916
6917 snprintf(port_str, sizeof(port_str), "%d", port);
6918 if (strlen(buf) == 0)
6919 // Append
6920 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6921 "auth_server_addr=%s\\n"
6922 "auth_server_port=%s\\n"
6923 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6924 else {
6925 // Delete the three lines setting after the "# radius 1" comment
6926 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6927 _syscmd(cmd, buf, sizeof(buf));
6928 memset(cmd, 0, sizeof(cmd));
6929 // Use "# radius 1" comment to find the location to insert the radius setting
6930 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6931 "# radius 1\\n"
6932 "auth_server_addr=%s\\n"
6933 "auth_server_port=%s\\n"
6934 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6935 }
6936 if(_syscmd(cmd, buf, sizeof(buf))) {
6937 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6938 return RETURN_ERR;
6939 }
6940
6941 wifi_reloadAp(apIndex);
6942 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6943 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006944}
6945
6946INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6947{
developer8f2ddd52022-09-13 15:39:24 +08006948 char config_file[64] = {0};
6949 char buf[64] = {0};
6950 char cmd[256] = {0};
6951
6952 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6953
developer06a01d92022-09-07 16:32:39 +08006954 if(!IP_output || !Port_output || !RadiusSecret_output)
6955 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006956
6957 // Read the second matched config
6958 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6959 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6960 _syscmd(cmd, buf, sizeof(buf));
6961 strncpy(IP_output, buf, 64);
6962
6963 memset(buf, 0, sizeof(buf));
6964 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6965 _syscmd(cmd, buf, sizeof(buf));
6966 *Port_output = atoi(buf);
6967
6968 memset(buf, 0, sizeof(buf));
6969 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6970 _syscmd(cmd, buf, sizeof(buf));
6971 strncpy(RadiusSecret_output, buf, 64);
6972
6973 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006974 return RETURN_OK;
6975}
6976
6977INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6978{
developer8f2ddd52022-09-13 15:39:24 +08006979 char config_file[64] = {0};
6980 char port_str[8] = {0};
6981 char cmd[256] = {0};
6982 char buf[128] = {0};
6983
6984 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08006985 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
6986 return RETURN_ERR;
6987
6988 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
6989 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006990
6991 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6992
6993 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6994 _syscmd(cmd, buf, sizeof(buf));
6995 memset(cmd, 0, sizeof(cmd));
6996
6997 snprintf(port_str, sizeof(port_str), "%d", port);
6998 if (strlen(buf) == 0)
6999 // Append
7000 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7001 "auth_server_addr=%s\\n"
7002 "auth_server_port=%s\\n"
7003 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7004 else {
7005 // Delete the three lines setting after the "# radius 2" comment
7006 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7007 _syscmd(cmd, buf, sizeof(buf));
7008 memset(cmd, 0, sizeof(cmd));
7009 // Use "# radius 2" comment to find the location to insert the radius setting
7010 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7011 "# radius 2\\n"
7012 "auth_server_addr=%s\\n"
7013 "auth_server_port=%s\\n"
7014 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7015 }
7016 if(_syscmd(cmd, buf, sizeof(buf))) {
7017 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7018 return RETURN_ERR;
7019 }
7020
7021 wifi_reloadAp(apIndex);
7022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7023 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007024}
7025
7026//RadiusSettings
7027INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7028{
7029 if(!output)
7030 return RETURN_ERR;
7031
7032 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7033 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7034 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7035 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7036 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7037 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.
7038 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7039 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7040 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7041 //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.
7042
7043 return RETURN_OK;
7044}
7045
7046INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7047{
7048 //store the paramters, and apply instantly
7049 return RETURN_ERR;
7050}
7051
7052//Device.WiFi.AccessPoint.{i}.WPS.Enable
7053//Enables or disables WPS functionality for this access point.
7054// outputs the WPS enable state of this ap in output_bool
7055INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7056{
developerd946fd62022-12-08 18:03:28 +08007057 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007058 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08007059 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007060 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007061 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007062 return RETURN_ERR;
7063 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007064 _syscmd(cmd, buf, sizeof(buf));
7065 if(strstr(buf, "configured"))
7066 *output_bool=TRUE;
7067 else
7068 *output_bool=FALSE;
7069
7070 return RETURN_OK;
7071}
7072
7073//Device.WiFi.AccessPoint.{i}.WPS.Enable
7074// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7075INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7076{
7077 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007078 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007079 struct params params;
7080
developer06a01d92022-09-07 16:32:39 +08007081 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7082 //store the paramters, and wait for wifi up to apply
7083 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007084 if (enable == TRUE) {
7085 wifi_getApBeaconType(apIndex, buf);
7086 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7087 params.value = "1";
7088 else // If ap set encryption
7089 params.value = "2";
7090 } else {
7091 params.value = "0";
7092 }
developer06a01d92022-09-07 16:32:39 +08007093
7094 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7095 wifi_hostapdWrite(config_file, &params, 1);
7096 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7097 wifi_reloadAp(apIndex);
7098
7099 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7100 return RETURN_OK;
7101}
7102
7103//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
7104INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7105{
7106 if(!output)
7107 return RETURN_ERR;
7108 snprintf(output, 128, "PushButton,PIN");
7109 return RETURN_OK;
7110}
7111
7112//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7113//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.
7114// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7115INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7116{
7117 if(!output)
7118 return RETURN_ERR;
7119 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7120
7121 return RETURN_OK;
7122}
7123
7124//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7125// 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
7126INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7127{
7128 //apply instantly. No setting need to be stored.
7129 char methods[MAX_BUF_SIZE], *token, *next_token;
7130 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7131 struct params params;
7132
developer5b398df2022-11-17 20:39:48 +08007133 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007134 return RETURN_ERR;
7135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7136 //store the paramters, and wait for wifi up to apply
7137
7138 snprintf(methods, sizeof(methods), "%s", methodString);
7139 for(token=methods; *token; token=next_token)
7140 {
7141 strtok_r(token, ",", &next_token);
7142 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7143 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7144 else if(*token=='E')
7145 {
7146 if(!strcmp(methods, "Ethernet"))
7147 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7148 else if(!strcmp(methods, "ExternalNFCToken"))
7149 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7150 else
7151 printf("%s: Unknown WpsConfigMethod\n", __func__);
7152 }
7153 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7154 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7155 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7156 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7157 else if(*token=='P' )
7158 {
7159 if(!strcmp(token, "PushButton"))
7160 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
7161 else if(!strcmp(token, "PIN"))
7162 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7163 else
7164 printf("%s: Unknown WpsConfigMethod\n", __func__);
7165 }
7166 else
7167 printf("%s: Unknown WpsConfigMethod\n", __func__);
7168 }
7169 params.name = "config_methods";
7170 params.value = config_methods;
7171 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7172 wifi_hostapdWrite(config_file, &params, 1);
7173 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7175
7176 return RETURN_OK;
7177}
7178
7179// outputs the pin value, ulong_pin must be allocated by the caller
7180INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7181{
7182 char buf[MAX_BUF_SIZE] = {0};
7183 char cmd[MAX_CMD_SIZE] = {0};
7184
developer5b398df2022-11-17 20:39:48 +08007185 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007186 return RETURN_ERR;
7187 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7188 _syscmd(cmd, buf, sizeof(buf));
7189 if(strlen(buf) > 0)
7190 *output_ulong=strtoul(buf, NULL, 10);
7191
7192 return RETURN_OK;
7193}
7194
7195// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7196INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7197{
7198 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7199 char ap_pin[16] = {0};
7200 char buf[MAX_BUF_SIZE] = {0};
7201 char config_file[MAX_BUF_SIZE] = {0};
7202 ULONG prev_pin = 0;
7203 struct params params;
7204
developer06a01d92022-09-07 16:32:39 +08007205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7206 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7207 params.name = "ap_pin";
7208 params.value = ap_pin;
7209 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7210 wifi_hostapdWrite(config_file, &params, 1);
7211 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7213
7214 return RETURN_OK;
7215}
7216
7217// Output string is either Not configured or Configured, max 32 characters
7218INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7219{
developerd946fd62022-12-08 18:03:28 +08007220 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007221 char cmd[MAX_CMD_SIZE];
7222 char buf[MAX_BUF_SIZE]={0};
7223
developer5b398df2022-11-17 20:39:48 +08007224 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007225 return RETURN_ERR;
7226 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7227 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007228 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007229 return RETURN_ERR;
7230 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007231 _syscmd(cmd, buf, sizeof(buf));
7232
developer348e3d92022-09-13 14:48:41 +08007233 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007234 snprintf(output_string, 32, "Configured");
7235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7236
7237 return RETURN_OK;
7238}
7239
7240// sets the WPS pin for this AP
7241INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7242{
developerd946fd62022-12-08 18:03:28 +08007243 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007244 char cmd[MAX_CMD_SIZE];
7245 char buf[MAX_BUF_SIZE]={0};
7246 BOOL enable;
7247
developer06a01d92022-09-07 16:32:39 +08007248 wifi_getApEnable(apIndex, &enable);
7249 if (!enable)
7250 return RETURN_ERR;
7251 wifi_getApWpsEnable(apIndex, &enable);
7252 if (!enable)
7253 return RETURN_ERR;
7254
developerac6f1142022-12-20 19:26:35 +08007255 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007256 return RETURN_ERR;
7257 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007258 _syscmd(cmd, buf, sizeof(buf));
7259 if((strstr(buf, "OK"))!=NULL)
7260 return RETURN_OK;
7261
7262 return RETURN_ERR;
7263}
7264
7265// This function is called when the WPS push button has been pressed for this AP
7266INT wifi_setApWpsButtonPush(INT apIndex)
7267{
7268 char cmd[MAX_CMD_SIZE];
7269 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007270 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007271 BOOL enable=FALSE;
7272
developer06a01d92022-09-07 16:32:39 +08007273 wifi_getApEnable(apIndex, &enable);
7274 if (!enable)
7275 return RETURN_ERR;
7276
7277 wifi_getApWpsEnable(apIndex, &enable);
7278 if (!enable)
7279 return RETURN_ERR;
7280
developerac6f1142022-12-20 19:26:35 +08007281 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007282 return RETURN_ERR;
7283
7284 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
developer06a01d92022-09-07 16:32:39 +08007285 _syscmd(cmd, buf, sizeof(buf));
7286
7287 if((strstr(buf, "OK"))!=NULL)
7288 return RETURN_OK;
7289 return RETURN_ERR;
7290}
7291
7292// cancels WPS mode for this AP
7293INT wifi_cancelApWPS(INT apIndex)
7294{
developerd946fd62022-12-08 18:03:28 +08007295 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007296 char cmd[MAX_CMD_SIZE];
7297 char buf[MAX_BUF_SIZE]={0};
7298
developerac6f1142022-12-20 19:26:35 +08007299 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007300 return RETURN_ERR;
7301 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007302 _syscmd(cmd,buf, sizeof(buf));
7303
7304 if((strstr(buf, "OK"))!=NULL)
7305 return RETURN_OK;
7306 return RETURN_ERR;
7307}
7308
7309//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7310//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7311INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7312{
developerd946fd62022-12-08 18:03:28 +08007313 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007314 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007315 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007316 char cmd[256] = {0}, buf[2048] = {0};
7317 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007318 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007319 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007320 wifi_associated_dev_t *dev=NULL;
7321
7322 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7323 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007324 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007325 return RETURN_ERR;
7326 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007327 _syscmd(cmd,buf,sizeof(buf));
7328 *output_array_size = atoi(buf);
7329
7330 if (*output_array_size <= 0)
7331 return RETURN_OK;
7332
7333 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7334 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007335 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007336 _syscmd(cmd,buf,sizeof(buf));
7337 f = fopen("/tmp/connected_devices.txt", "r");
7338 if (f==NULL)
7339 {
7340 *output_array_size=0;
7341 return RETURN_ERR;
7342 }
developer30423732022-12-01 16:17:49 +08007343 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007344 {
7345 param = strtok(line,"=");
7346 value = strtok(NULL,"=");
7347
7348 if( strcmp("flags",param) == 0 )
7349 {
7350 value[strlen(value)-1]='\0';
7351 if(strstr (value,"AUTHORIZED") != NULL )
7352 {
7353 dev[auth_temp].cli_AuthenticationState = 1;
7354 dev[auth_temp].cli_Active = 1;
7355 auth_temp++;
7356 read_flag=1;
7357 }
7358 }
7359 if(read_flag==1)
7360 {
7361 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7362 {
7363 value[strlen(value)-1]='\0';
7364 sscanf(value, "%x:%x:%x:%x:%x:%x",
7365 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7366 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7367 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7368 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7369 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7370 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7371 mac_temp++;
7372 read_flag=0;
7373 }
7374 }
7375 }
7376 *output_array_size = auth_temp;
7377 auth_temp=0;
7378 mac_temp=0;
7379 free(line);
7380 fclose(f);
7381 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7382 return RETURN_OK;
7383}
7384
7385#define MACADDRESS_SIZE 6
7386
7387INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7388{
7389 FILE *fp = NULL;
7390 char str[MAX_BUF_SIZE] = {0};
7391 int wificlientindex = 0 ;
7392 int count = 0;
7393 int signalstrength = 0;
7394 int arr[MACADDRESS_SIZE] = {0};
7395 unsigned char mac[MACADDRESS_SIZE] = {0};
7396 UINT wifi_count = 0;
7397 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7398 char pipeCmd[MAX_CMD_SIZE] = {0};
7399
7400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7401 *output_array_size = 0;
7402 *associated_dev_array = NULL;
7403
7404 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7405 fp = popen(pipeCmd, "r");
7406 if (fp == NULL)
7407 {
7408 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7409 return RETURN_ERR;
7410 }
7411
7412 /* Read the output a line at a time - output it. */
7413 fgets(str, sizeof(str)-1, fp);
7414 wifi_count = (unsigned int) atoi ( str );
7415 *output_array_size = wifi_count;
7416 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7417 pclose(fp);
7418
7419 if(wifi_count == 0)
7420 {
7421 return RETURN_OK;
7422 }
7423 else
7424 {
7425 wifi_associated_dev3_t* temp = NULL;
7426 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7427 if(temp == NULL)
7428 {
7429 printf("Error Statement. Insufficient memory \n");
7430 return RETURN_ERR;
7431 }
7432
7433 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7434 system(pipeCmd);
7435 memset(pipeCmd,0,sizeof(pipeCmd));
7436 if(apIndex == 0)
7437 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7438 else if(apIndex == 1)
7439 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7440 system(pipeCmd);
7441
7442 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7443 if(fp == NULL)
7444 {
7445 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007446 free(temp);
developer06a01d92022-09-07 16:32:39 +08007447 return RETURN_ERR;
7448 }
7449 fclose(fp);
7450
developer30423732022-12-01 16:17:49 +08007451 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007452 fp = popen(pipeCmd, "r");
7453 if(fp)
7454 {
7455 for(count =0 ; count < wifi_count; count++)
7456 {
7457 fgets(str, MAX_BUF_SIZE, fp);
7458 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7459 {
7460 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7461 {
7462 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7463
7464 }
7465 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7466 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]);
7467 }
7468 temp[count].cli_AuthenticationState = 1; //TODO
7469 temp[count].cli_Active = 1; //TODO
7470 }
7471 pclose(fp);
7472 }
7473
developer30423732022-12-01 16:17:49 +08007474 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 +08007475 fp = popen(pipeCmd, "r");
7476 if(fp)
7477 {
7478 pclose(fp);
7479 }
7480 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7481 if(fp)
7482 {
7483 for(count =0 ; count < wifi_count ;count++)
7484 {
7485 fgets(str, MAX_BUF_SIZE, fp);
7486 signalstrength = atoi(str);
7487 temp[count].cli_SignalStrength = signalstrength;
7488 temp[count].cli_RSSI = signalstrength;
7489 temp[count].cli_SNR = signalstrength + 95;
7490 }
7491 pclose(fp);
7492 }
7493
7494
7495 if((apIndex == 0) || (apIndex == 4))
7496 {
7497 for(count =0 ; count < wifi_count ;count++)
7498 {
7499 strcpy(temp[count].cli_OperatingStandard,"g");
7500 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7501 }
7502
7503 //BytesSent
developer30423732022-12-01 16:17:49 +08007504 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 +08007505 fp = popen(pipeCmd, "r");
7506 if(fp)
7507 {
7508 pclose(fp);
7509 }
7510 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7511 if(fp)
7512 {
7513 for (count = 0; count < wifi_count; count++)
7514 {
7515 fgets(str, MAX_BUF_SIZE, fp);
7516 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7517 }
7518 pclose(fp);
7519 }
7520
7521 //BytesReceived
developer30423732022-12-01 16:17:49 +08007522 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 +08007523 fp = popen(pipeCmd, "r");
7524 if (fp)
7525 {
7526 pclose(fp);
7527 }
7528 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7529 if (fp)
7530 {
7531 for (count = 0; count < wifi_count; count++)
7532 {
7533 fgets(str, MAX_BUF_SIZE, fp);
7534 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7535 }
7536 pclose(fp);
7537 }
7538
7539 //PacketsSent
developer30423732022-12-01 16:17:49 +08007540 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 +08007541 fp = popen(pipeCmd, "r");
7542 if (fp)
7543 {
7544 pclose(fp);
7545 }
7546
7547 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7548 if (fp)
7549 {
7550 for (count = 0; count < wifi_count; count++)
7551 {
7552 fgets(str, MAX_BUF_SIZE, fp);
7553 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7554 }
7555 pclose(fp);
7556 }
7557
7558 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007559 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 +08007560 fp = popen(pipeCmd, "r");
7561 if (fp)
7562 {
7563 pclose(fp);
7564 }
7565 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7566 if (fp)
7567 {
7568 for (count = 0; count < wifi_count; count++)
7569 {
7570 fgets(str, MAX_BUF_SIZE, fp);
7571 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7572 }
7573 pclose(fp);
7574 }
7575
7576 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007577 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 +08007578 fp = popen(pipeCmd, "r");
7579 if (fp)
7580 {
7581 pclose(fp);
7582 }
7583 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7584 if (fp)
7585 {
7586 for (count = 0; count < wifi_count; count++)
7587 {
7588 fgets(str, MAX_BUF_SIZE, fp);
7589 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7590 }
7591 pclose(fp);
7592 }
7593
7594 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007595 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 +08007596 fp = popen(pipeCmd, "r");
7597 if (fp)
7598 {
7599 pclose(fp);
7600 }
7601 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7602 if (fp)
7603 {
7604 for (count = 0; count < wifi_count; count++)
7605 {
7606 fgets(str, MAX_BUF_SIZE, fp);
7607 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7608 }
7609 pclose(fp);
7610 }
7611
7612 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007613 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 +08007614 fp = popen(pipeCmd, "r");
7615 if (fp)
7616 {
7617 pclose(fp);
7618 }
7619 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7620 if (fp)
7621 {
7622 for (count = 0; count < wifi_count; count++)
7623 {
7624 fgets(str, MAX_BUF_SIZE, fp);
7625 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7626 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7627 }
7628 pclose(fp);
7629 }
7630
7631 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007632 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 +08007633 fp = popen(pipeCmd, "r");
7634 if (fp)
7635 {
7636 pclose(fp);
7637 }
7638 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7639 if (fp)
7640 {
7641 for (count = 0; count < wifi_count; count++)
7642 {
7643 fgets(str, MAX_BUF_SIZE, fp);
7644 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7645 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7646 }
7647 pclose(fp);
7648 }
7649
7650 }
7651 else if ((apIndex == 1) || (apIndex == 5))
7652 {
7653 for (count = 0; count < wifi_count; count++)
7654 {
7655 strcpy(temp[count].cli_OperatingStandard, "a");
7656 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7657 temp[count].cli_BytesSent = 0;
7658 temp[count].cli_BytesReceived = 0;
7659 temp[count].cli_LastDataUplinkRate = 0;
7660 temp[count].cli_LastDataDownlinkRate = 0;
7661 temp[count].cli_PacketsSent = 0;
7662 temp[count].cli_PacketsReceived = 0;
7663 temp[count].cli_ErrorsSent = 0;
7664 }
7665 }
7666
7667 for (count = 0; count < wifi_count; count++)
7668 {
7669 temp[count].cli_Retransmissions = 0;
7670 temp[count].cli_DataFramesSentAck = 0;
7671 temp[count].cli_DataFramesSentNoAck = 0;
7672 temp[count].cli_MinRSSI = 0;
7673 temp[count].cli_MaxRSSI = 0;
7674 strncpy(temp[count].cli_InterferenceSources, "", 64);
7675 memset(temp[count].cli_IPAddress, 0, 64);
7676 temp[count].cli_RetransCount = 0;
7677 temp[count].cli_FailedRetransCount = 0;
7678 temp[count].cli_RetryCount = 0;
7679 temp[count].cli_MultipleRetryCount = 0;
7680 }
7681 *associated_dev_array = temp;
7682 }
7683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7684 return RETURN_OK;
7685}
7686
7687int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7688{
7689 FILE *fp = NULL;
7690 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7691 char cmd[MAX_CMD_SIZE];
7692 int count = 0;
7693
7694 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7695 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7696 fp = popen(cmd,"r");
7697 if(fp == NULL)
7698 {
7699 printf("Failed to run command in Function %s\n",__FUNCTION__);
7700 return 0;
7701 }
7702 if(fgets(path, sizeof(path)-1, fp) != NULL)
7703 {
7704 for(count=0;path[count]!='\n';count++)
7705 status[count]=path[count];
7706 status[count]='\0';
7707 }
7708 strcpy(wifi_status,status);
7709 pclose(fp);
7710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7711 return RETURN_OK;
7712}
7713
7714/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7715struct hostapd_sta_param {
7716 char key[50];
7717 char value[100];
7718}
7719
7720static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7721 int i = 0;
7722
7723 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7724 if (strncmp(params[i].key,key,50) == 0){
7725 return &params[i].value;
7726 }
7727 i++;
7728 }
7729 return NULL;
7730
7731} */
7732
7733static unsigned int count_occurences(const char *buf, const char *word)
7734{
7735 unsigned int n = 0;
7736 char *ptr = strstr(buf, word);
7737
7738 while (ptr++) {
7739 n++;
7740 ptr = strstr(ptr, word);
7741 }
7742
7743 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7744 return n;
7745}
7746
7747static const char *get_line_from_str_buf(const char *buf, char *line)
7748{
7749 int i;
7750 int n = strlen(buf);
7751
7752 for (i = 0; i < n; i++) {
7753 line[i] = buf[i];
7754 if (buf[i] == '\n') {
7755 line[i] = '\0';
7756 return &buf[i + 1];
7757 }
7758 }
7759
7760 return NULL;
7761}
7762
7763INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7764{
7765 unsigned int assoc_cnt = 0;
7766 char interface_name[50] = {0};
7767 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7768 char cmd[MAX_CMD_SIZE] = {'\0'};
7769 char line[256] = {'\0'};
7770 int i = 0;
7771 int ret = 0;
7772 const char *ptr = NULL;
7773 char *key = NULL;
7774 char *val = NULL;
7775 wifi_associated_dev3_t *temp = NULL;
7776 int rssi;
7777
7778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7779
7780 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7781 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7782 return RETURN_ERR;
7783 }
7784
7785 // Example filtered output of 'iw dev' command:
7786 // Station 0a:69:72:10:d2:fa (on wifi0)
7787 // signal avg:-67 [-71, -71] dBm
7788 // Station 28:c2:1f:25:5f:99 (on wifi0)
7789 // signal avg:-67 [-71, -70] dBm
7790 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7791 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7792 return RETURN_ERR;
7793 }
7794
7795 ret = _syscmd(cmd, buf, sizeof(buf));
7796 if (ret == RETURN_ERR) {
7797 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7798 return RETURN_ERR;
7799 }
7800
7801 *output_array_size = count_occurences(buf, "Station");
7802 if (*output_array_size == 0) return RETURN_OK;
7803
7804 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7805 if (temp == NULL) {
7806 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7807 return RETURN_ERR;
7808 }
7809 *associated_dev_array = temp;
7810
7811 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7812 ptr = get_line_from_str_buf(buf, line);
7813 i = -1;
7814 while (ptr) {
7815 if (strstr(line, "Station")) {
7816 i++;
7817 key = strtok(line, " ");
7818 val = strtok(NULL, " ");
7819 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7820 &temp[i].cli_MACAddress[0],
7821 &temp[i].cli_MACAddress[1],
7822 &temp[i].cli_MACAddress[2],
7823 &temp[i].cli_MACAddress[3],
7824 &temp[i].cli_MACAddress[4],
7825 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7826 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7827 free(*associated_dev_array);
7828 return RETURN_ERR;
7829 }
7830 }
7831 else if (i < 0) {
7832 ptr = get_line_from_str_buf(ptr, line);
7833 continue; // We didn't detect 'station' entry yet
7834 }
7835 else if (strstr(line, "signal avg")) {
7836 key = strtok(line, ":");
7837 val = strtok(NULL, " ");
7838 if (sscanf(val, "%d", &rssi) <= 0 ) {
7839 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7840 free(*associated_dev_array);
7841 return RETURN_ERR;
7842 }
7843 temp[i].cli_RSSI = rssi;
7844 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7845 }
7846 // Here other fields can be parsed if added to filter of 'iw dev' command
7847
7848 ptr = get_line_from_str_buf(ptr, line);
7849 };
7850
7851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7852
7853 return RETURN_OK;
7854}
7855
7856#if 0
7857//To-do
7858INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7859{
7860 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7861
7862 //Using different approach to get required WiFi Parameters from system available commands
7863#if 0
7864 FILE *f;
7865 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7866 char cmd[256], buf[2048];
7867 char *param , *value, *line=NULL;
7868 size_t len = 0;
7869 ssize_t nread;
7870 wifi_associated_dev3_t *dev=NULL;
7871 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007872 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007873 _syscmd(cmd,buf,sizeof(buf));
7874 *output_array_size = atoi(buf);
7875
7876 if (*output_array_size <= 0)
7877 return RETURN_OK;
7878
7879 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7880 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007881 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007882 _syscmd(cmd,buf,sizeof(buf));
7883 f = fopen("/tmp/connected_devices.txt", "r");
7884 if (f==NULL)
7885 {
7886 *output_array_size=0;
7887 return RETURN_ERR;
7888 }
7889 while ((nread = getline(&line, &len, f)) != -1)
7890 {
7891 param = strtok(line,"=");
7892 value = strtok(NULL,"=");
7893
7894 if( strcmp("flags",param) == 0 )
7895 {
7896 value[strlen(value)-1]='\0';
7897 if(strstr (value,"AUTHORIZED") != NULL )
7898 {
7899 dev[auth_temp].cli_AuthenticationState = 1;
7900 dev[auth_temp].cli_Active = 1;
7901 auth_temp++;
7902 read_flag=1;
7903 }
7904 }
7905 if(read_flag==1)
7906 {
7907 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7908 {
7909 value[strlen(value)-1]='\0';
7910 sscanf(value, "%x:%x:%x:%x:%x:%x",
7911 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7912 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7913 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7914 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7915 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7916 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7917
7918 }
7919 else if( strcmp("rx_packets",param) == 0 )
7920 {
7921 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7922 }
7923
7924 else if( strcmp("tx_packets",param) == 0 )
7925 {
7926 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7927 }
7928
7929 else if( strcmp("rx_bytes",param) == 0 )
7930 {
7931 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7932 }
7933
7934 else if( strcmp("tx_bytes",param) == 0 )
7935 {
7936 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7937 mac_temp++;
7938 read_flag=0;
7939 }
7940 }
7941 }
7942
7943 *output_array_size = auth_temp;
7944 auth_temp=0;
7945 mac_temp=0;
7946 free(line);
7947 fclose(f);
7948#endif
7949 char interface_name[MAX_BUF_SIZE] = {0};
7950 char wifi_status[MAX_BUF_SIZE] = {0};
7951 char hostapdconf[MAX_BUF_SIZE] = {0};
7952
7953 wifi_associated_dev3_t *dev_array = NULL;
7954 ULONG wifi_count = 0;
7955
7956 *associated_dev_array = NULL;
7957 *output_array_size = 0;
7958
7959 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7960 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7961 {
7962 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7963
developerac6f1142022-12-20 19:26:35 +08007964 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08007965
7966 if(strlen(interface_name) > 1)
7967 {
7968 wifihal_interfacestatus(wifi_status,interface_name);
7969 if(strcmp(wifi_status,"RUNNING") == 0)
7970 {
7971 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7972
7973 *associated_dev_array = dev_array;
7974 *output_array_size = wifi_count;
7975 }
7976 else
7977 {
7978 *associated_dev_array = NULL;
7979 }
7980 }
7981 }
7982
7983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7984 return RETURN_OK;
7985}
7986#endif
7987
7988/* getIPAddress function */
7989/**
7990* @description Returning IpAddress of the Matched String
7991*
7992* @param
7993* @str Having MacAddress
7994* @ipaddr Having ipaddr
7995* @return The status of the operation
7996* @retval RETURN_OK if successful
7997* @retval RETURN_ERR if any error is detected
7998*
7999*/
8000
8001INT getIPAddress(char *str,char *ipaddr)
8002{
8003 FILE *fp = NULL;
8004 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8005 int LeaseTime = 0,ret = 0;
8006 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8007 {
8008 return RETURN_ERR;
8009 }
8010
8011 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8012 {
8013 /*
8014 Sample:sss
8015 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8016 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8017 */
8018 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008019 &(LeaseTime),
8020 phyAddr,
8021 ipAddr,
8022 hostName
8023 );
developer06a01d92022-09-07 16:32:39 +08008024 if(ret != 4)
8025 continue;
8026 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008027 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008028 }
developerd946fd62022-12-08 18:03:28 +08008029 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008030 return RETURN_OK;
8031}
8032
8033/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8034/**
8035* @description Returning Inactive wireless connected clients informations
8036*
8037* @param
8038* @filename Holding private_wifi 2g/5g content files
8039* @associated_dev_array Having inactiv wireless clients informations
8040* @output_array_size Returning Inactive wireless counts
8041* @return The status of the operation
8042* @retval RETURN_OK if successful
8043* @retval RETURN_ERR if any error is detected
8044*
8045*/
8046
8047INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8048{
8049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8050 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8051 FILE *fp = NULL;
8052 int arr[MACADDRESS_SIZE] = {0};
8053 unsigned char mac[MACADDRESS_SIZE] = {0};
8054 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8055 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8056 fp = popen(buf,"r");
8057 if(fp == NULL)
8058 return RETURN_ERR;
8059 else
8060 {
8061 fgets(path,sizeof(path),fp);
8062 maccount = atoi(path);
8063 }
8064 pclose(fp);
8065 *output_array_size = maccount;
8066 wifi_associated_dev3_t* temp = NULL;
8067 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8068 *associated_dev_array = temp;
8069 if(temp == NULL)
8070 {
8071 printf("Error Statement. Insufficient memory \n");
8072 return RETURN_ERR;
8073 }
8074 memset(buf,0,sizeof(buf));
8075 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8076 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008077 if (fp == NULL) {
8078 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8079 return RETURN_ERR;
8080 }
developer06a01d92022-09-07 16:32:39 +08008081 for(count = 0; count < maccount ; count++)
8082 {
8083 fgets(path,sizeof(path),fp);
8084 for(i = 0; path[i]!='\n';i++)
8085 str[i]=path[i];
8086 str[i]='\0';
8087 getIPAddress(str,ipaddr);
8088 memset(buf,0,sizeof(buf));
8089 if(strlen(ipaddr) > 0)
8090 {
8091 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8092 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8093 {
8094 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8095 {
8096 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8097 {
8098 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8099
8100 }
8101 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8102 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]);
8103 }
8104 temp[count].cli_AuthenticationState = 0; //TODO
8105 temp[count].cli_Active = 0; //TODO
8106 temp[count].cli_SignalStrength = 0;
8107 }
8108 else //Active wireless clients info
8109 {
8110 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8111 {
8112 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8113 {
8114 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8115
8116 }
8117 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8118 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]);
8119 }
8120 temp[count].cli_Active = 1;
8121 }
8122 }
8123 memset(ipaddr,0,sizeof(ipaddr));
8124 }
8125 pclose(fp);
8126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8127 return RETURN_OK;
8128}
8129//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8130//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8131//To get Band Steering Capability
8132INT wifi_getBandSteeringCapability(BOOL *support)
8133{
8134 *support = FALSE;
8135 return RETURN_OK;
8136}
8137
8138
8139//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8140//To get Band Steering enable status
8141INT wifi_getBandSteeringEnable(BOOL *enable)
8142{
8143 *enable = FALSE;
8144 return RETURN_OK;
8145}
8146
8147//To turn on/off Band steering
8148INT wifi_setBandSteeringEnable(BOOL enable)
8149{
8150 return RETURN_OK;
8151}
8152
8153//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8154//To get Band Steering AP group
8155INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8156{
8157 if (NULL == output_ApGroup)
8158 return RETURN_ERR;
8159
8160 strcpy(output_ApGroup, "1,2");
8161 return RETURN_OK;
8162}
8163
8164//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8165//to set and read the band steering BandUtilizationThreshold parameters
8166INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8167{
8168 return RETURN_ERR;
8169}
8170
8171INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8172{
8173 return RETURN_ERR;
8174}
8175
8176//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8177//to set and read the band steering RSSIThreshold parameters
8178INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8179{
8180 return RETURN_ERR;
8181}
8182
8183INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8184{
8185 return RETURN_ERR;
8186}
8187
8188
8189//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8190//to set and read the band steering physical modulation rate threshold parameters
8191INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8192{
8193 //If chip is not support, return -1
8194 return RETURN_ERR;
8195}
8196
8197INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8198{
8199 //If chip is not support, return -1
8200 return RETURN_ERR;
8201}
8202
8203//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8204//to set and read the inactivity time (in seconds) for steering under overload condition
8205INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8206{
8207 return RETURN_ERR;
8208}
8209
8210INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8211{
8212 return RETURN_ERR;
8213}
8214
8215//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8216//to set and read the inactivity time (in seconds) for steering under Idle condition
8217INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8218{
8219 return RETURN_ERR;
8220}
8221
8222INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8223{
8224 return RETURN_ERR;
8225}
8226
8227//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8228//pClientMAC[64]
8229//pSourceSSIDIndex[64]
8230//pDestSSIDIndex[64]
8231//pSteeringReason[256]
8232INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8233{
8234 //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
8235 *pSteeringTime=time(NULL);
8236 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8237 return RETURN_OK;
8238}
8239
8240INT wifi_ifConfigDown(INT apIndex)
8241{
8242 INT status = RETURN_OK;
8243 char cmd[64];
8244
8245 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8246 printf("%s: %s\n", __func__, cmd);
8247 system(cmd);
8248
8249 return status;
8250}
8251
8252INT wifi_ifConfigUp(INT apIndex)
8253{
developerd946fd62022-12-08 18:03:28 +08008254 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008255 char cmd[128];
8256 char buf[1024];
8257
developerac6f1142022-12-20 19:26:35 +08008258 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008259 return RETURN_ERR;
8260 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008261 _syscmd(cmd, buf, sizeof(buf));
8262 return 0;
8263}
8264
8265//>> Deprecated. Replace with wifi_applyRadioSettings
8266INT wifi_pushBridgeInfo(INT apIndex)
8267{
developerd946fd62022-12-08 18:03:28 +08008268 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008269 char ip[32] = {0};
8270 char subnet[32] = {0};
8271 char bridge[32] = {0};
8272 int vlanId = 0;
8273 char cmd[128] = {0};
8274 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008275
8276 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8277 wifi_getApVlanID(apIndex,&vlanId);
8278
developerac6f1142022-12-20 19:26:35 +08008279 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008280 return RETURN_ERR;
8281 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008282 _syscmd(cmd,buf, sizeof(buf));
8283
8284 return 0;
8285}
8286
8287INT wifi_pushChannel(INT radioIndex, UINT channel)
8288{
developerd946fd62022-12-08 18:03:28 +08008289 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008290 char cmd[128];
8291 char buf[1024];
8292 int apIndex;
8293
8294 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008295 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008296 return RETURN_ERR;
8297 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008298 _syscmd(cmd,buf, sizeof(buf));
8299
8300 return 0;
8301}
8302
8303INT wifi_pushChannelMode(INT radioIndex)
8304{
8305 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8306 return RETURN_ERR;
8307}
8308
8309INT wifi_pushDefaultValues(INT radioIndex)
8310{
8311 //Apply Comcast specified default radio settings instantly
8312 //AMPDU=1
8313 //AMPDUFrames=32
8314 //AMPDULim=50000
8315 //txqueuelen=1000
8316
8317 return RETURN_ERR;
8318}
8319
8320INT wifi_pushTxChainMask(INT radioIndex)
8321{
8322 //Apply default TxChainMask instantly
8323 return RETURN_ERR;
8324}
8325
8326INT wifi_pushRxChainMask(INT radioIndex)
8327{
8328 //Apply default RxChainMask instantly
8329 return RETURN_ERR;
8330}
8331
8332INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8333{
8334 INT status;
8335
8336 status = wifi_setSSIDName(apIndex,ssid);
8337 wifi_setApEnable(apIndex,FALSE);
8338 wifi_setApEnable(apIndex,TRUE);
8339
8340 return status;
8341}
8342
8343INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8344{
8345 //Apply default Ssid Advertisement instantly
8346 return RETURN_ERR;
8347}
8348
8349INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8350{
8351 INT status = RETURN_ERR;
8352 *output = 0;
8353 return RETURN_ERR;
8354}
8355
8356INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8357{
8358 return RETURN_OK;
8359}
8360
8361INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8362{
8363 return RETURN_OK;
8364}
8365
8366//To-do
8367INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8368{
developereb199ae2022-09-13 14:04:27 +08008369 char output[16]={'\0'};
8370 char config_file[MAX_BUF_SIZE] = {0};
8371
8372 if (!output_string)
8373 return RETURN_ERR;
8374
8375 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8376 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8377
8378 if (strlen(output) == 0)
8379 snprintf(output_string, 64, "Disabled");
8380 else if (strncmp(output, "0", 1) == 0)
8381 snprintf(output_string, 64, "Disabled");
8382 else if (strncmp(output, "1", 1) == 0)
8383 snprintf(output_string, 64, "Optional");
8384 else if (strncmp(output, "2", 1) == 0)
8385 snprintf(output_string, 64, "Required");
8386 else {
8387 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8388 return RETURN_ERR;
8389 }
8390
8391 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008392 return RETURN_OK;
8393}
8394INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8395{
developereb199ae2022-09-13 14:04:27 +08008396 char str[MAX_BUF_SIZE]={'\0'};
8397 char cmd[MAX_CMD_SIZE]={'\0'};
8398 struct params params;
8399 char config_file[MAX_BUF_SIZE] = {0};
8400
8401 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8402 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8403 return RETURN_ERR;
8404
8405 params.name = "ieee80211w";
8406 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8407 params.value = "0";
8408 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8409 params.value = "1";
8410 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8411 params.value = "2";
8412 else{
8413 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8414 return RETURN_ERR;
8415 }
8416 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8417 wifi_hostapdWrite(config_file, &params, 1);
8418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008419 return RETURN_OK;
8420}
8421INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8422{
8423 char output[16]={'\0'};
8424 char config_file[MAX_BUF_SIZE] = {0};
8425
8426 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8427 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8428 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8429
8430 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8431 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8432
8433 return RETURN_OK;
8434}
8435
8436INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8437{
8438 return RETURN_OK;
8439}
8440
8441INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8442{
8443 return RETURN_OK;
8444}
8445
8446INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8447{
8448 return RETURN_OK;
8449}
8450
8451INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8452{
8453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8454 char config_file[MAX_BUF_SIZE] = {0};
8455
8456 if (NULL == output)
8457 return RETURN_ERR;
8458 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8459 wifi_hostapdRead(config_file,"hw_mode",output,64);
8460
8461 if(strcmp(output,"b")==0)
8462 sprintf(output, "%s", "1,2,5.5,11");
8463 else if (strcmp(output,"a")==0)
8464 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8465 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8466 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8467
8468 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8469 return RETURN_OK;
8470}
8471
8472INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8473{
8474 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8475 char *temp;
8476 char temp_output[128];
8477 char temp_TransmitRates[128];
8478 char config_file[MAX_BUF_SIZE] = {0};
8479
8480 if (NULL == output)
8481 return RETURN_ERR;
8482
8483 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8484 wifi_hostapdRead(config_file,"supported_rates",output,64);
8485
developer5b398df2022-11-17 20:39:48 +08008486 if (strlen(output) == 0) {
8487 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8488 return RETURN_OK;
8489 }
developer06a01d92022-09-07 16:32:39 +08008490 strcpy(temp_TransmitRates,output);
8491 strcpy(temp_output,"");
8492 temp = strtok(temp_TransmitRates," ");
8493 while(temp!=NULL)
8494 {
8495 temp[strlen(temp)-1]=0;
8496 if((temp[0]=='5') && (temp[1]=='\0'))
8497 {
8498 temp="5.5";
8499 }
8500 strcat(temp_output,temp);
8501 temp = strtok(NULL," ");
8502 if(temp!=NULL)
8503 {
8504 strcat(temp_output,",");
8505 }
8506 }
8507 strcpy(output,temp_output);
8508 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8509
8510 return RETURN_OK;
8511}
8512
8513INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8514{
8515 return RETURN_OK;
8516}
8517
8518
8519INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8520{
8521 int i=0;
8522 char *temp;
developeref938762022-10-19 17:21:01 +08008523 char temp1[128] = {0};
8524 char temp_output[128] = {0};
8525 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008526 struct params params={'\0'};
8527 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008528 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008529
8530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8531 if(NULL == output)
8532 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008533 strcpy(temp_TransmitRates,output);
8534
8535 for(i=0;i<strlen(temp_TransmitRates);i++)
8536 {
developeref938762022-10-19 17:21:01 +08008537 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008538 {
8539 continue;
8540 }
8541 else
8542 {
8543 return RETURN_ERR;
8544 }
8545 }
8546 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008547 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008548 while(temp!=NULL)
8549 {
8550 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008551 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008552 {
developeref938762022-10-19 17:21:01 +08008553 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008554 {
8555 return RETURN_ERR;
8556 }
8557 }
8558
8559 if(strcmp(temp,"5.5")==0)
8560 {
8561 strcpy(temp1,"55");
8562 }
8563 else
8564 {
8565 strcat(temp1,"0");
8566 }
8567 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008568 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008569 if(temp!=NULL)
8570 {
8571 strcat(temp_output," ");
8572 }
8573 }
8574 strcpy(output,temp_output);
8575
developer06a01d92022-09-07 16:32:39 +08008576 params.name = "supported_rates";
8577 params.value = output;
8578
8579 wifi_dbg_printf("\n%s:",__func__);
8580 wifi_dbg_printf("params.value=%s\n",params.value);
8581 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8582 wifi_hostapdWrite(config_file,&params,1);
8583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8584
8585 return RETURN_OK;
8586}
8587
8588
8589static char *sncopy(char *dst, int dst_sz, const char *src)
8590{
8591 if (src && dst && dst_sz > 0) {
8592 strncpy(dst, src, dst_sz);
8593 dst[dst_sz - 1] = '\0';
8594 }
8595 return dst;
8596}
8597
8598static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8599{
8600 if (0 == strcmp(ht_mode, "HT40") ||
8601 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008602 0 == strcmp(ht_mode, "HT160") ||
8603 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008604 switch (channel) {
8605 case 1 ... 7:
8606 case 36:
8607 case 44:
8608 case 52:
8609 case 60:
8610 case 100:
8611 case 108:
8612 case 116:
8613 case 124:
8614 case 132:
8615 case 140:
8616 case 149:
8617 case 157:
8618 return 1;
8619 case 8 ... 13:
8620 case 40:
8621 case 48:
8622 case 56:
8623 case 64:
8624 case 104:
8625 case 112:
8626 case 120:
8627 case 128:
8628 case 136:
8629 case 144:
8630 case 153:
8631 case 161:
8632 return -1;
8633 default:
8634 return -EINVAL;
8635 }
8636 }
8637
8638 return -EINVAL;
8639}
8640
developerb7593de2022-10-18 09:51:57 +08008641static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8642{
8643 int idx = channel%8;
8644 if (0 == strcmp(ht_mode, "HT40") ||
8645 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008646 0 == strcmp(ht_mode, "HT160") ||
8647 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008648 switch (idx) {
8649 case 1:
8650 return 1;
8651 case 5:
8652 return -1;
8653 default:
8654 return -EINVAL;
8655 }
8656 }
8657
8658 return -EINVAL;
8659}
developer06a01d92022-09-07 16:32:39 +08008660static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8661{
8662 if (NULL == hw_mode) return;
8663
8664 if (0 == strcmp(hw_mode, "ac"))
8665 sncopy(bw_mode, bw_mode_len, "ht vht");
8666
8667 if (0 == strcmp(hw_mode, "n"))
8668 sncopy(bw_mode, bw_mode_len, "ht");
8669
8670 return;
8671}
8672
8673static int util_chan_to_freq(int chan)
8674{
8675 if (chan == 14)
8676 return 2484;
8677 else if (chan < 14)
8678 return 2407 + chan * 5;
8679 else if (chan >= 182 && chan <= 196)
8680 return 4000 + chan * 5;
8681 else
8682 return 5000 + chan * 5;
8683 return 0;
8684}
8685
developerb7593de2022-10-18 09:51:57 +08008686static int util_6G_chan_to_freq(int chan)
8687{
8688 if (chan)
8689 return 5950 + chan * 5;
8690 else
8691 return 0;
8692
8693}
developer06a01d92022-09-07 16:32:39 +08008694const int *util_unii_5g_chan2list(int chan, int width)
8695{
8696 static const int lists[] = {
8697 // <width>, <chan1>, <chan2>..., 0,
8698 20, 36, 0,
8699 20, 40, 0,
8700 20, 44, 0,
8701 20, 48, 0,
8702 20, 52, 0,
8703 20, 56, 0,
8704 20, 60, 0,
8705 20, 64, 0,
8706 20, 100, 0,
8707 20, 104, 0,
8708 20, 108, 0,
8709 20, 112, 0,
8710 20, 116, 0,
8711 20, 120, 0,
8712 20, 124, 0,
8713 20, 128, 0,
8714 20, 132, 0,
8715 20, 136, 0,
8716 20, 140, 0,
8717 20, 144, 0,
8718 20, 149, 0,
8719 20, 153, 0,
8720 20, 157, 0,
8721 20, 161, 0,
8722 20, 165, 0,
8723 40, 36, 40, 0,
8724 40, 44, 48, 0,
8725 40, 52, 56, 0,
8726 40, 60, 64, 0,
8727 40, 100, 104, 0,
8728 40, 108, 112, 0,
8729 40, 116, 120, 0,
8730 40, 124, 128, 0,
8731 40, 132, 136, 0,
8732 40, 140, 144, 0,
8733 40, 149, 153, 0,
8734 40, 157, 161, 0,
8735 80, 36, 40, 44, 48, 0,
8736 80, 52, 56, 60, 64, 0,
8737 80, 100, 104, 108, 112, 0,
8738 80, 116, 120, 124, 128, 0,
8739 80, 132, 136, 140, 144, 0,
8740 80, 149, 153, 157, 161, 0,
8741 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8742 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8743 -1 // final delimiter
8744 };
8745 const int *start;
8746 const int *p;
8747
8748 for (p = lists; *p != -1; p++) {
8749 if (*p == width) {
8750 for (start = ++p; *p != 0; p++) {
8751 if (*p == chan)
8752 return start;
8753 }
8754 }
8755 // move to the end of channel list of given width
8756 while (*p != 0) {
8757 p++;
8758 }
8759 }
8760
8761 return NULL;
8762}
8763
8764static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8765{
8766 if (NULL == ht_mode)
8767 return 0;
8768
8769 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8770 const int *chans = util_unii_5g_chan2list(channel, width);
8771 int sum = 0;
8772 int cnt = 0;
8773
8774 if (NULL == chans)
8775 return 0;
8776
8777 while (*chans) {
8778 sum += *chans;
8779 cnt++;
8780 chans++;
8781 }
developer30423732022-12-01 16:17:49 +08008782 if (cnt == 0)
8783 return 0;
developer06a01d92022-09-07 16:32:39 +08008784 return sum / cnt;
8785}
8786
developerb7593de2022-10-18 09:51:57 +08008787static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8788{
8789 if (NULL == ht_mode)
8790 return 0;
8791
8792 int width = strtol((ht_mode + 2), NULL, 10);
8793
8794 int idx = 0 ;
8795 int centerchan = 0;
8796 int chan_ofs = 1;
8797
8798 if (width == 40){
8799 idx = ((channel/4) + chan_ofs)%2;
8800 switch (idx) {
8801 case 0:
8802 centerchan = (channel - 2);
8803 break;
8804 case 1:
8805 centerchan = (channel + 2);
8806 break;
8807 default:
8808 return -EINVAL;
8809 }
8810 }else if (width == 80){
8811 idx = ((channel/4) + chan_ofs)%4;
8812 switch (idx) {
8813 case 0:
8814 centerchan = (channel - 6);
8815 break;
8816 case 1:
8817 centerchan = (channel + 6);
8818 break;
8819 case 2:
8820 centerchan = (channel + 2);
8821 break;
8822 case 3:
8823 centerchan = (channel - 2);
8824 break;
8825 default:
8826 return -EINVAL;
8827 }
8828 }else if (width == 160){
8829 switch (channel) {
8830 case 1 ... 29:
8831 centerchan = 15;
8832 break;
8833 case 33 ... 61:
8834 centerchan = 47;
8835 break;
8836 case 65 ... 93:
8837 centerchan = 79;
8838 break;
8839 case 97 ... 125:
8840 centerchan = 111;
8841 break;
8842 case 129 ... 157:
8843 centerchan = 143;
8844 break;
8845 case 161 ... 189:
8846 centerchan = 175;
8847 break;
8848 case 193 ... 221:
8849 centerchan = 207;
8850 break;
8851 default:
8852 return -EINVAL;
8853 }
developer7c4cd202023-03-01 10:56:29 +08008854 }else if (width == 320){
8855 switch (channel) {
8856 case 1 ... 29:
8857 centerchan = 31;
8858 break;
8859 case 33 ... 93:
8860 centerchan = 63;
8861 break;
8862 case 97 ... 157:
8863 centerchan = 127;
8864 break;
8865 case 161 ... 221:
8866 centerchan = 191;
8867 break;
8868 default:
8869 return -EINVAL;
8870 }
developerb7593de2022-10-18 09:51:57 +08008871 }
8872 return centerchan;
8873}
developer06a01d92022-09-07 16:32:39 +08008874static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8875{
8876 BOOL onlyG, onlyN, onlyA;
8877 CHAR tmp[64];
8878 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8879 if (ret == RETURN_OK) {
8880 sncopy(hw_mode, hw_mode_size, tmp);
8881 }
8882 return ret;
8883}
8884
8885INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8886{
8887 // Sample commands:
8888 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8889 // hostapd_cli -i wifi0 chan_switch 30 2437
8890 char cmd[MAX_CMD_SIZE] = {0};
8891 char buf[MAX_BUF_SIZE] = {0};
8892 int freq = 0, ret = 0;
8893 char center_freq1_str[32] = ""; // center_freq1=%d
8894 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8895 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8896 char hw_mode[16] = ""; // n|ac
8897 char bw_mode[16] = ""; // ht|ht vht
8898 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008899 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008900 int sec_chan_offset;
8901 int width;
developer4fb0b922022-09-30 14:29:09 +08008902 char config_file[64] = {0};
8903 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08008904 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08008905 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008906 wifi_band band = band_invalid;
8907 int center_chan = 0;
8908 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008909
developer4fb0b922022-09-30 14:29:09 +08008910 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008911
developerac6f1142022-12-20 19:26:35 +08008912 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008913 return RETURN_ERR;
8914
developer06a01d92022-09-07 16:32:39 +08008915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8916
developerb7593de2022-10-18 09:51:57 +08008917 band = wifi_index_to_band(radioIndex);
8918
developer5884e982022-10-06 10:52:50 +08008919 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008920
8921 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008922 if (channel){
developerb7593de2022-10-18 09:51:57 +08008923 if (band == band_6){
8924 freq = util_6G_chan_to_freq(channel);
8925 }else{
8926 freq = util_chan_to_freq(channel);
8927 }
developer7c4cd202023-03-01 10:56:29 +08008928 if (width == 320) {
8929 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
8930 setEHT320 = TRUE;
8931 }
developer5884e982022-10-06 10:52:50 +08008932 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008933
developer5884e982022-10-06 10:52:50 +08008934 // Provide bandwith if specified
8935 if (channel_width_MHz > 20) {
8936 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8937 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8938 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008939
developer5884e982022-10-06 10:52:50 +08008940 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8941 }else if (channel_width_MHz == 20){
8942 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8943 }
developer06a01d92022-09-07 16:32:39 +08008944
developerb7593de2022-10-18 09:51:57 +08008945
developer5884e982022-10-06 10:52:50 +08008946 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008947 if (band == band_6){
8948 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8949 if(center_chan){
8950 center_freq1 = util_6G_chan_to_freq(center_chan);
8951 }
8952 }else{
8953 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8954 if(center_chan){
8955 center_freq1 = util_chan_to_freq(center_chan);
8956 }
developer5884e982022-10-06 10:52:50 +08008957 }
developerb7593de2022-10-18 09:51:57 +08008958
8959 if (center_freq1)
8960 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8961
8962 }
8963
8964 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8965 if (band == band_6){
8966 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8967 }else{
8968 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008969 }
developerb7593de2022-10-18 09:51:57 +08008970 if (sec_chan_offset != -EINVAL)
8971 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008972
developer5884e982022-10-06 10:52:50 +08008973 // Only the first AP, other are hanging on the same radio
8974 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08008975 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8976 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08008977 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8978 wifi_dbg_printf("execute: '%s'\n", cmd);
8979 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08008980 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08008981
developer5884e982022-10-06 10:52:50 +08008982 ret = wifi_setRadioChannel(radioIndex, channel);
8983 if (ret != RETURN_OK) {
8984 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8985 return RETURN_ERR;
8986 }
8987
8988 if (sec_chan_offset == 1) ext_str = "Above";
8989 else if (sec_chan_offset == -1) ext_str = "Below";
8990
8991 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008992
developer5884e982022-10-06 10:52:50 +08008993 } else {
8994 if (channel_width_MHz > 20)
8995 ext_str = "Above";
8996 }
developer4fb0b922022-09-30 14:29:09 +08008997
developer06a01d92022-09-07 16:32:39 +08008998 wifi_setRadioExtChannel(radioIndex, ext_str);
8999
developer06a01d92022-09-07 16:32:39 +08009000 char mhz_str[16];
9001 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009002 if (setEHT320 == TRUE)
9003 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9004 else
9005 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009006
9007 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9008
9009 return RETURN_OK;
9010}
9011
9012INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9013{
developer615510b2022-09-27 10:14:35 +08009014 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009015 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009016 char cmd[256]={0};
9017 char buf[128]={0};
9018 char file_name[32] = {0};
9019 char filter_SSID[32] = {0};
9020 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009021 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009022 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009023 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009024 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009025 size_t len=0;
9026 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009027 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009028 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009029 bool filter_enable = false;
9030 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009031 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009032
developer615510b2022-09-27 10:14:35 +08009033 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009034
developer615510b2022-09-27 10:14:35 +08009035 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9036 f = fopen(file_name, "r");
9037 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009038 fgets(buf, sizeof(file_name), f);
9039 if ((strncmp(buf, "0", 1)) != 0) {
9040 fgets(filter_SSID, sizeof(file_name), f);
9041 if (strlen(filter_SSID) != 0)
9042 filter_enable = true;
9043 }
developer615510b2022-09-27 10:14:35 +08009044 fclose(f);
9045 }
9046
developerac6f1142022-12-20 19:26:35 +08009047 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009048 return RETURN_ERR;
9049
developer033b37b2022-10-18 11:27:46 +08009050 phyId = radio_index_to_phy(radio_index);
9051
9052 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009053 _syscmd(cmd, buf, sizeof(buf));
9054 channels_num = strtol(buf, NULL, 10);
9055
developerd946fd62022-12-08 18:03:28 +08009056 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9057 // 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 +08009058 fprintf(stderr, "cmd: %s\n", cmd);
9059 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009060 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9061 return RETURN_ERR;
9062 }
developer5550e242022-09-30 09:59:32 +08009063
9064 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9065 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9066
developer615510b2022-09-27 10:14:35 +08009067 ret = fgets(line, sizeof(line), f);
9068 while (ret != NULL) {
9069 if(strstr(line, "BSS") != NULL) { // new neighbor info
9070 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9071 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9072 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9073
9074 if (!filter_BSS) {
9075 index++;
9076 wifi_neighbor_ap2_t *tmp;
9077 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9078 if (tmp == NULL) { // no more memory to use
9079 index--;
9080 wifi_dbg_printf("%s: realloc failed\n", __func__);
9081 break;
9082 }
9083 scan_array = tmp;
9084 }
9085 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009086
developer615510b2022-09-27 10:14:35 +08009087 filter_BSS = false;
9088 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9089 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9090 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9091 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9092 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009093 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009094 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009095
developer615510b2022-09-27 10:14:35 +08009096 if (freq >= 2412 && freq <= 2484) {
9097 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9098 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9099 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9100 }
9101 else if (freq >= 5160 && freq <= 5805) {
9102 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9103 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9104 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9105 }
developer06a01d92022-09-07 16:32:39 +08009106
developer615510b2022-09-27 10:14:35 +08009107 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009108 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009109 for (int i = 0; i < channels_num; i++) {
9110 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9111 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9112 break;
9113 }
9114 }
developer06a01d92022-09-07 16:32:39 +08009115 }
developer615510b2022-09-27 10:14:35 +08009116 } else if (strstr(line, "beacon interval") != NULL) {
9117 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9118 } else if (strstr(line, "signal") != NULL) {
9119 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9120 } else if (strstr(line,"SSID") != NULL) {
9121 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9122 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9123 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009124 }
developer615510b2022-09-27 10:14:35 +08009125 } else if (strstr(line, "Supported rates") != NULL) {
9126 char SRate[80] = {0}, *tmp = NULL;
9127 memset(buf, 0, sizeof(buf));
9128 strcpy(SRate, line);
9129 tmp = strtok(SRate, ":");
9130 tmp = strtok(NULL, ":");
9131 strcpy(buf, tmp);
9132 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009133
developer615510b2022-09-27 10:14:35 +08009134 tmp = strtok(buf, " \n");
9135 while (tmp != NULL) {
9136 strcat(SRate, tmp);
9137 if (SRate[strlen(SRate) - 1] == '*') {
9138 SRate[strlen(SRate) - 1] = '\0';
9139 }
9140 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009141
developer615510b2022-09-27 10:14:35 +08009142 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009143 }
developer615510b2022-09-27 10:14:35 +08009144 SRate[strlen(SRate) - 1] = '\0';
9145 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9146 } else if (strstr(line, "DTIM") != NULL) {
9147 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9148 } else if (strstr(line, "VHT capabilities") != NULL) {
9149 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9150 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9151 } else if (strstr(line, "HT capabilities") != NULL) {
9152 strcat(scan_array[index].ap_SupportedStandards, ",n");
9153 strcpy(scan_array[index].ap_OperatingStandards, "n");
9154 } else if (strstr(line, "VHT operation") != NULL) {
9155 ret = fgets(line, sizeof(line), f);
9156 sscanf(line," * channel width: %d", &vht_channel_width);
9157 if(vht_channel_width == 1) {
9158 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9159 } else {
9160 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9161 }
9162 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9163 continue;
9164 } else if (strstr(line, "HT operation") != NULL) {
9165 ret = fgets(line, sizeof(line), f);
9166 sscanf(line," * secondary channel offset: %s", &buf);
9167 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009168 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009169 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 +08009170 }
developer615510b2022-09-27 10:14:35 +08009171 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009172 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009173 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9174 } else {
9175 //20Mhz
9176 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 +08009177 }
developer615510b2022-09-27 10:14:35 +08009178 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009179 continue;
developer615510b2022-09-27 10:14:35 +08009180 } else if (strstr(line, "HE capabilities") != NULL) {
9181 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9182 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9183 ret = fgets(line, sizeof(line), f);
9184 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9185 if (strstr(line, "HE40/2.4GHz") != NULL)
9186 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9187 else
9188 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9189 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9190 if (strstr(line, "HE80/5GHz") != NULL) {
9191 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9192 ret = fgets(line, sizeof(line), f);
9193 } else
9194 continue;
9195 if (strstr(line, "HE160/5GHz") != NULL)
9196 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009197 }
developer615510b2022-09-27 10:14:35 +08009198 continue;
9199 } else if (strstr(line, "WPA") != NULL) {
9200 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9201 } else if (strstr(line, "RSN") != NULL) {
9202 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9203 } else if (strstr(line, "Group cipher") != NULL) {
9204 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9205 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9206 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009207 }
developer06a01d92022-09-07 16:32:39 +08009208 }
developer615510b2022-09-27 10:14:35 +08009209 ret = fgets(line, sizeof(line), f);
9210 }
9211
9212 if (!filter_BSS) {
9213 *output_array_size = index + 1;
9214 } else {
9215 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9216 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009217 }
developer06a01d92022-09-07 16:32:39 +08009218 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009219 pclose(f);
developer5550e242022-09-30 09:59:32 +08009220 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009221 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009222 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009223}
developer615510b2022-09-27 10:14:35 +08009224
developer06a01d92022-09-07 16:32:39 +08009225INT wifi_getApAssociatedDeviceStats(
9226 INT apIndex,
9227 mac_address_t *clientMacAddress,
9228 wifi_associated_dev_stats_t *associated_dev_stats,
9229 u64 *handle)
9230{
9231 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9232 char interface_name[50] = {0};
9233 char cmd[1024] = {0};
9234 char mac_str[18] = {0};
9235 char *key = NULL;
9236 char *val = NULL;
9237 FILE *f = NULL;
9238 char *line = NULL;
9239 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009240
9241 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9242 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9243 return RETURN_ERR;
9244 }
9245
9246 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9247 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9248 if((f = popen(cmd, "r")) == NULL) {
9249 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9250 return RETURN_ERR;
9251 }
9252
developer30423732022-12-01 16:17:49 +08009253 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009254 key = strtok(line,":");
9255 val = strtok(NULL,":");
9256
9257 if(!strncmp(key,"rx bytes",8))
9258 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9259 if(!strncmp(key,"tx bytes",8))
9260 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9261 if(!strncmp(key,"rx packets",10))
9262 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9263 if(!strncmp(key,"tx packets",10))
9264 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9265 if(!strncmp(key,"tx retries",10))
9266 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9267 if(!strncmp(key,"tx failed",9))
9268 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9269 if(!strncmp(key,"rx drop misc",13))
9270 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9271 if(!strncmp(key,"rx bitrate",10)) {
9272 val = strtok(val, " ");
9273 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9274 }
9275 if(!strncmp(key,"tx bitrate",10)) {
9276 val = strtok(val, " ");
9277 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9278 }
9279 }
9280 free(line);
9281 pclose(f);
9282 return RETURN_OK;
9283}
9284
9285INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9286{
developerd946fd62022-12-08 18:03:28 +08009287 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009288 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9289
9290 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9291 if (NULL == output_string)
9292 return RETURN_ERR;
9293
developerac6f1142022-12-20 19:26:35 +08009294 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009295 return RETURN_ERR;
9296 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 +08009297 _syscmd(cmd, buf, sizeof(buf));
9298
9299 //size of SSID name restricted to value less than 32 bytes
9300 snprintf(output_string, 32, "%s", buf);
9301 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9302
9303 return RETURN_OK;
9304}
9305
9306INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9307{
9308 //char cmd[MAX_CMD_SIZE] = {0};
9309 char config_file[MAX_BUF_SIZE] = {0};
9310 char buf[32] = {0};
9311
9312 if (!output_filterMode)
9313 return RETURN_ERR;
9314
9315 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9316 //_syscmd(cmd, buf, sizeof(buf));
9317 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9318 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009319 if(strlen(buf) == 0) {
9320 *output_filterMode = 0;
9321 }
9322 else {
9323 int macaddr_acl_mode = strtol(buf, NULL, 10);
9324 if (macaddr_acl_mode == 1) {
9325 *output_filterMode = 1;
9326 } else if (macaddr_acl_mode == 0) {
9327 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9328 if (strlen(buf) == 0) {
9329 *output_filterMode = 0;
9330 } else {
9331 *output_filterMode = 2;
9332 }
9333 } else {
9334 return RETURN_ERR;
9335 }
9336 }
developer06a01d92022-09-07 16:32:39 +08009337
9338 return RETURN_OK;
9339}
9340
9341INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9342{
9343 FILE *fp = NULL;
9344 char str[MAX_BUF_SIZE] = {0};
9345 int wificlientindex = 0 ;
9346 int count = 0;
9347 int signalstrength = 0;
9348 int arr[MACADDRESS_SIZE] = {0};
9349 unsigned char mac[MACADDRESS_SIZE] = {0};
9350 UINT wifi_count = 0;
9351 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9352 char pipeCmd[MAX_CMD_SIZE] = {0};
9353
9354 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9355 *output_array_size = 0;
9356 *associated_dev_array = NULL;
9357 char interface_name[50] = {0};
9358
9359 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9360 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9361 return RETURN_ERR;
9362 }
9363
9364 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9365 fp = popen(pipeCmd, "r");
9366 if (fp == NULL)
9367 {
9368 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9369 return RETURN_ERR;
9370 }
9371
9372 /* Read the output a line at a time - output it. */
9373 fgets(str, sizeof(str)-1, fp);
9374 wifi_count = (unsigned int) atoi ( str );
9375 *output_array_size = wifi_count;
9376 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9377 pclose(fp);
9378
9379 if(wifi_count == 0)
9380 {
9381 return RETURN_OK;
9382 }
9383 else
9384 {
9385 wifi_associated_dev2_t* temp = NULL;
9386 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9387 *associated_dev_array = temp;
9388 if(temp == NULL)
9389 {
9390 printf("Error Statement. Insufficient memory \n");
9391 return RETURN_ERR;
9392 }
9393
9394 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9395 system(pipeCmd);
9396
9397 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9398 if(fp == NULL)
9399 {
9400 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9401 return RETURN_ERR;
9402 }
9403 fclose(fp);
9404
developer30423732022-12-01 16:17:49 +08009405 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009406 fp = popen(pipeCmd, "r");
9407 if(fp)
9408 {
9409 for(count =0 ; count < wifi_count; count++)
9410 {
9411 fgets(str, MAX_BUF_SIZE, fp);
9412 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9413 {
9414 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9415 {
9416 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9417
9418 }
9419 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9420 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]);
9421 }
9422 temp[count].cli_AuthenticationState = 1; //TODO
9423 temp[count].cli_Active = 1; //TODO
9424 }
9425 pclose(fp);
9426 }
9427
9428 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009429 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 +08009430 fp = popen(pipeCmd, "r");
9431 if(fp)
9432 {
9433 pclose(fp);
9434 }
9435 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9436 if(fp)
9437 {
9438 for(count =0 ; count < wifi_count ;count++)
9439 {
9440 fgets(str, MAX_BUF_SIZE, fp);
9441 signalstrength = atoi(str);
9442 temp[count].cli_RSSI = signalstrength;
9443 }
9444 pclose(fp);
9445 }
9446
9447
9448 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009449 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 +08009450 fp = popen(pipeCmd, "r");
9451 if (fp)
9452 {
9453 pclose(fp);
9454 }
9455 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9456 if (fp)
9457 {
9458 for (count = 0; count < wifi_count; count++)
9459 {
9460 fgets(str, MAX_BUF_SIZE, fp);
9461 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9462 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9463 }
9464 pclose(fp);
9465 }
9466
9467 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009468 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 +08009469 fp = popen(pipeCmd, "r");
9470 if (fp)
9471 {
9472 pclose(fp);
9473 }
9474 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9475 if (fp)
9476 {
9477 for (count = 0; count < wifi_count; count++)
9478 {
9479 fgets(str, MAX_BUF_SIZE, fp);
9480 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9481 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9482 }
9483 pclose(fp);
9484 }
9485 }
9486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9487 return RETURN_OK;
9488
9489}
9490
9491INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9492{
9493#if 0
9494 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009495 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009496 _syscmd(cmd, buf, sizeof(buf));*/
9497
9498 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9499 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9500 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9501 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9502
9503 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.
9504 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].
9505 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].
9506 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].
9507 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9508 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9509
9510 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9511 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9512 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9513 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.
9514 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.
9515 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.
9516 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.
9517 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.
9518 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.
9519 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.
9520 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9521#endif
9522
9523 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009524 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009525 char pipeCmd[128] = {0};
9526 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009527 wifi_ssidTrafficStats2_t *out = output_struct;
9528
developerce736392022-09-13 15:24:34 +08009529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009530 if (!output_struct)
9531 return RETURN_ERR;
9532
developerce736392022-09-13 15:24:34 +08009533 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009534 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009535 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009536 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009537
developer06a01d92022-09-07 16:32:39 +08009538 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009539 if (fp == NULL) {
9540 fprintf(stderr, "%s: popen failed\n", __func__);
9541 return RETURN_ERR;
9542 }
9543 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009544 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009545
developerce736392022-09-13 15:24:34 +08009546 if (strlen(str) == 0) // interface not exist
9547 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009548
developerce736392022-09-13 15:24:34 +08009549 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9550 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009551
developerce736392022-09-13 15:24:34 +08009552 memset(str, 0, sizeof(str));
9553 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009554 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009555 if (fp == NULL) {
9556 fprintf(stderr, "%s: popen failed\n", __func__);
9557 return RETURN_ERR;
9558 }
9559 fgets(str, sizeof(str), fp);
9560
9561 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9562 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009563 pclose(fp);
developerce736392022-09-13 15:24:34 +08009564
9565 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9566 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9567
9568 // Not supported
9569 output_struct->ssid_RetransCount = 0;
9570 output_struct->ssid_FailedRetransCount = 0;
9571 output_struct->ssid_RetryCount = 0;
9572 output_struct->ssid_MultipleRetryCount = 0;
9573 output_struct->ssid_ACKFailureCount = 0;
9574 output_struct->ssid_AggregatedPacketCount = 0;
9575
developer06a01d92022-09-07 16:32:39 +08009576 return RETURN_OK;
9577}
9578
9579//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).
9580INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9581{
9582 char output_val[16]={'\0'};
9583 char config_file[MAX_BUF_SIZE] = {0};
9584
9585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9586 if (!output)
9587 return RETURN_ERR;
9588 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9589 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9590
9591 if( strcmp(output_val,"1") == 0 )
9592 *output = TRUE;
9593 else
9594 *output = FALSE;
9595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9596
9597 return RETURN_OK;
9598}
9599
9600INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9601{
9602 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9603 char str[MAX_BUF_SIZE]={'\0'};
9604 char string[MAX_BUF_SIZE]={'\0'};
9605 char cmd[MAX_CMD_SIZE]={'\0'};
9606 char *ch;
9607 char config_file[MAX_BUF_SIZE] = {0};
9608 struct params params;
9609
9610 if(enable == TRUE)
9611 strcpy(string,"1");
9612 else
9613 strcpy(string,"0");
9614
9615 params.name = "ap_isolate";
9616 params.value = string;
9617
9618 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9619 wifi_hostapdWrite(config_file,&params,1);
9620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9621
9622 return RETURN_OK;
9623}
9624
9625INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9626{
9627 if (NULL == output_dBm)
9628 return RETURN_ERR;
9629
9630 *output_dBm = 0;
9631 return RETURN_OK;
9632}
9633
9634INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9635{
9636 return RETURN_OK;
9637}
9638INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9639{
9640 return RETURN_OK;
9641}
9642INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9643{
9644 return RETURN_OK;
9645}
9646INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9647{
9648 return RETURN_OK;
9649}
9650INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9651{
9652 return RETURN_OK;
9653}
9654INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9655{
9656 char config_file[MAX_BUF_SIZE] = {0};
9657 struct params list;
9658
9659 list.name = "bss_transition";
9660 list.value = activate?"1":"0";
9661 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9662 wifi_hostapdWrite(config_file, &list, 1);
9663
9664 return RETURN_OK;
9665}
9666wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9667
9668void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9669{
9670 return;
9671}
9672
9673INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9674{
9675 // TODO Implement me!
9676 return RETURN_OK;
9677}
9678
9679INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9680{
developera3c68b92022-09-13 15:27:29 +08009681 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009682 FILE *f = NULL;
9683
developer72ec5572023-01-05 16:27:13 +08009684 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009685
developer72ec5572023-01-05 16:27:13 +08009686 if (essid == NULL)
9687 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009688
developer72ec5572023-01-05 16:27:13 +08009689 if (strlen(essid) == 0 || apIndex == -1) {
9690 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9691 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009692 }
9693
developer72ec5572023-01-05 16:27:13 +08009694 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9695 f = fopen(file_name, "w");
9696 if (f == NULL)
9697 return RETURN_ERR;
9698
9699 // For mode == 0 is to disable filter, just don't write ssid to the file.
9700 fprintf(f, "%d\n%s", mode, mode?essid:"");
9701 fclose(f);
9702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009703 return RETURN_OK;
9704}
9705
9706INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9707{
9708 // TODO Implement me!
9709 //Apply wifi_pushRadioChannel() instantly
9710 return RETURN_ERR;
9711}
9712
9713INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9714{
9715 // TODO Implement me!
9716 return RETURN_OK;
9717}
9718
9719#ifdef HAL_NETLINK_IMPL
9720static int tidStats_callback(struct nl_msg *msg, void *arg) {
9721 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9722 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9723 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9724 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9725 int rem , tid_index = 0;
9726
9727 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9728 wifi_associated_dev_tid_entry_t *stats_entry;
9729
9730 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9731 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9732 };
9733 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9734 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9735 };
9736
9737 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9738 genlmsg_attrlen(gnlh, 0), NULL);
9739
9740
9741 if (!tb[NL80211_ATTR_STA_INFO]) {
9742 fprintf(stderr, "station stats missing!\n");
9743 return NL_SKIP;
9744 }
9745
9746 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9747 tb[NL80211_ATTR_STA_INFO],
9748 stats_policy)) {
9749 fprintf(stderr, "failed to parse nested attributes!\n");
9750 return NL_SKIP;
9751 }
9752
9753 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9754 {
9755 stats_entry = &out->tid_array[tid_index];
9756
9757 stats_entry->tid = tid_index;
9758 stats_entry->ac = _tid_ac_index_get[tid_index];
9759
9760 if(sinfo[NL80211_STA_INFO_TID_STATS])
9761 {
9762 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9763 printf("failed to parse nested stats attributes!");
9764 return NL_SKIP;
9765 }
9766 }
9767 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9768 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9769
9770 if(tid_index < (PS_MAX_TID - 1))
9771 tid_index++;
9772 }
9773 //ToDo: sum_time_ms, ewma_time_ms
9774 return NL_SKIP;
9775}
9776#endif
9777
9778INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9779{
9780#ifdef HAL_NETLINK_IMPL
9781 Netlink nl;
9782 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009783 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009784
developerac6f1142022-12-20 19:26:35 +08009785 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009786 return RETURN_ERR;
9787
9788 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009789
9790 nl.id = initSock80211(&nl);
9791
9792 if (nl.id < 0) {
9793 fprintf(stderr, "Error initializing netlink \n");
9794 return -1;
9795 }
9796
9797 struct nl_msg* msg = nlmsg_alloc();
9798
9799 if (!msg) {
9800 fprintf(stderr, "Failed to allocate netlink message.\n");
9801 nlfree(&nl);
9802 return -2;
9803 }
9804
9805 genlmsg_put(msg,
9806 NL_AUTO_PORT,
9807 NL_AUTO_SEQ,
9808 nl.id,
9809 0,
9810 0,
9811 NL80211_CMD_GET_STATION,
9812 0);
9813
9814 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9815 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9816 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9817 nl_send_auto(nl.socket, msg);
9818 nl_recvmsgs(nl.socket, nl.cb);
9819 nlmsg_free(msg);
9820 nlfree(&nl);
9821 return RETURN_OK;
9822#else
9823//iw implementation
9824#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9825#define TOTAL_MAX_LINES 50
9826
9827 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009828 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009829 FILE *fp=NULL;
9830 char pipeCmd[1024]= {'\0'};
9831 int lines,tid_index=0;
9832 char mac_addr[20] = {'\0'};
9833
developerac6f1142022-12-20 19:26:35 +08009834 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009835 return RETURN_ERR;
9836
developer06a01d92022-09-07 16:32:39 +08009837 wifi_associated_dev_tid_entry_t *stats_entry;
9838
developer06a01d92022-09-07 16:32:39 +08009839 strcpy(mac_addr,clientMacAddress);
9840
9841 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9842 fp= popen(pipeCmd,"r");
9843 if(fp == NULL)
9844 {
9845 perror("popen for station dump failed\n");
9846 return RETURN_ERR;
9847 }
9848 pclose(fp);
9849
9850 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9851 fp=popen(pipeCmd,"r");
9852 if(fp == NULL)
9853 {
9854 perror("popen for grep station failed\n");
9855 return RETURN_ERR;
9856 }
9857 else if(fgets(buf,sizeof(buf),fp) != NULL)
9858 lines=atoi(buf);
9859 else
9860 {
9861 pclose(fp);
9862 fprintf(stderr,"No devices are connected \n");
9863 return RETURN_ERR;
9864 }
9865 pclose(fp);
9866
9867 if(lines == 1)
9868 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9869
9870 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9871 {
9872 stats_entry = &tid_stats->tid_array[tid_index];
9873 stats_entry->tid = tid_index;
9874
9875 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);
9876
9877 fp=popen(pipeCmd,"r");
9878 if(fp ==NULL)
9879 {
9880 perror("Failed to read from tid file \n");
9881 return RETURN_ERR;
9882 }
9883 else if(fgets(buf,sizeof(buf),fp) != NULL)
9884 stats_entry->num_msdus = atol(buf);
9885
9886 pclose(fp);
9887 stats_entry->ac = _tid_ac_index_get[tid_index];
9888// TODO:
9889// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9890// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9891 }
9892 return RETURN_OK;
9893#endif
9894}
9895
9896
9897INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9898{
developerd946fd62022-12-08 18:03:28 +08009899 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009900 char cmd[128]={0};
9901 char buf[128]={0};
9902 int freq = 0;
9903
9904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9905
9906 // full mode is used to scan all channels.
9907 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9908 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9909 ieee80211_channel_to_frequency(chan_list[0], &freq);
9910
developerac6f1142022-12-20 19:26:35 +08009911 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009912 return RETURN_ERR;
9913
developer615510b2022-09-27 10:14:35 +08009914 if (freq)
developerd946fd62022-12-08 18:03:28 +08009915 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009916 else
developerd946fd62022-12-08 18:03:28 +08009917 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009918
9919 _syscmd(cmd, buf, sizeof(buf));
9920 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9921
developer06a01d92022-09-07 16:32:39 +08009922 return RETURN_OK;
9923}
9924
9925
9926INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9927{
9928 // TODO Implement me!
9929 return RETURN_ERR;
9930}
9931
9932INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9933{
9934 // TODO Implement me!
9935 return RETURN_ERR;
9936}
9937
9938INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9939{
9940 // TODO Implement me!
9941 return RETURN_ERR;
9942}
9943
9944INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9945{
9946 // TODO Implement me!
9947 return RETURN_ERR;
9948}
9949
9950INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9951{
9952 // TODO Implement me!
9953 return RETURN_ERR;
9954}
9955
9956INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9957{
9958 // TODO Implement me!
9959 return RETURN_ERR;
9960}
9961
9962INT wifi_steering_eventUnregister(void)
9963{
9964 // TODO Implement me!
9965 return RETURN_ERR;
9966}
9967
9968INT wifi_delApAclDevices(INT apIndex)
9969{
9970#if 0
9971 char cmd[MAX_BUF_SIZE] = {0};
9972 char buf[MAX_BUF_SIZE] = {0};
9973
9974 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +08009975 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +08009976 if(_syscmd(cmd,buf,sizeof(buf)))
9977 return RETURN_ERR;
9978#endif
developere6aafda2022-09-13 14:59:28 +08009979 char cmd[MAX_CMD_SIZE]={0};
9980 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009981
developere6aafda2022-09-13 14:59:28 +08009982 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9983 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9984 if(_syscmd(cmd, buf, sizeof(buf)))
9985 return RETURN_ERR;
9986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009987
9988 return RETURN_OK;
9989}
9990
9991#ifdef HAL_NETLINK_IMPL
9992static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9993 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9994 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9995 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9996 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9997 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9998 char mac_addr[20],dev[20];
9999
10000 nla_parse(tb,
10001 NL80211_ATTR_MAX,
10002 genlmsg_attrdata(gnlh, 0),
10003 genlmsg_attrlen(gnlh, 0),
10004 NULL);
10005
10006 if(!tb[NL80211_ATTR_STA_INFO]) {
10007 fprintf(stderr, "sta stats missing!\n");
10008 return NL_SKIP;
10009 }
10010
10011 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10012 fprintf(stderr, "failed to parse nested attributes!\n");
10013 return NL_SKIP;
10014 }
10015 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10016
10017 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10018
10019 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10020 fprintf(stderr, "failed to parse nested rate attributes!");
10021 return NL_SKIP;
10022 }
10023
10024 if(sinfo[NL80211_STA_INFO_TID_STATS])
10025 {
10026 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10027 printf("failed to parse nested stats attributes!");
10028 return NL_SKIP;
10029 }
10030 }
10031
10032 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10033 {
10034 printf("Type is VHT\n");
10035 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10036 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10037
10038 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10039 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10040 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10041 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10042 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10043 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10044 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10045 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10046 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10047 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10048 }
10049 else
10050 {
10051 printf(" OFDM or CCK \n");
10052 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10053 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10054 }
10055
10056 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10057 if(rinfo[NL80211_RATE_INFO_MCS])
10058 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10059 }
10060 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10061 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10062 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10063 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10064
10065 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10066 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10067
10068 if (sinfo[NL80211_STA_INFO_SIGNAL])
10069 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10070 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10071 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10072 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10073 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10074 //rssi_array need to be filled
10075 return NL_SKIP;
10076}
10077#endif
10078
10079INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10080{
10081#ifdef HAL_NETLINK_IMPL
10082 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010083 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010084 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010085 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010086
10087 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10088
10089 if (*output_array_size <= 0)
10090 return RETURN_OK;
10091
developer06a01d92022-09-07 16:32:39 +080010092 nl.id = initSock80211(&nl);
10093
10094 if (nl.id < 0) {
10095 fprintf(stderr, "Error initializing netlink \n");
10096 return 0;
10097 }
10098
10099 struct nl_msg* msg = nlmsg_alloc();
10100
10101 if (!msg) {
10102 fprintf(stderr, "Failed to allocate netlink message.\n");
10103 nlfree(&nl);
10104 return 0;
10105 }
10106
10107 genlmsg_put(msg,
10108 NL_AUTO_PORT,
10109 NL_AUTO_SEQ,
10110 nl.id,
10111 0,
10112 0,
10113 NL80211_CMD_GET_STATION,
10114 0);
10115
10116 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10117 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10118 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10119 nl_send_auto(nl.socket, msg);
10120 nl_recvmsgs(nl.socket, nl.cb);
10121 nlmsg_free(msg);
10122 nlfree(&nl);
10123 return RETURN_OK;
10124#else
10125 //TODO Implement me
10126 return RETURN_OK;
10127#endif
10128}
10129
10130#ifdef HAL_NETLINK_IMPL
10131static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10132 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10133 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10134 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10135 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10136 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10137 char mac_addr[20],dev[20];
10138
10139 nla_parse(tb,
10140 NL80211_ATTR_MAX,
10141 genlmsg_attrdata(gnlh, 0),
10142 genlmsg_attrlen(gnlh, 0),
10143 NULL);
10144
10145 if(!tb[NL80211_ATTR_STA_INFO]) {
10146 fprintf(stderr, "sta stats missing!\n");
10147 return NL_SKIP;
10148 }
10149
10150 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10151 fprintf(stderr, "failed to parse nested attributes!\n");
10152 return NL_SKIP;
10153 }
10154
10155 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10156
10157 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10158
10159 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10160 fprintf(stderr, "failed to parse nested rate attributes!");
10161 return NL_SKIP;
10162 }
10163
10164 if(sinfo[NL80211_STA_INFO_TID_STATS])
10165 {
10166 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10167 printf("failed to parse nested stats attributes!");
10168 return NL_SKIP;
10169 }
10170 }
10171 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10172 {
10173 printf("Type is VHT\n");
10174 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10175 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10176
10177 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10178 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10179 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10180 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10181 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10182 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10183 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10184 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10185 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10186 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10187 }
10188 else
10189 {
10190 printf(" OFDM or CCK \n");
10191 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10192 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10193 }
10194
10195 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10196 if(rinfo[NL80211_RATE_INFO_MCS])
10197 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10198 }
10199
10200 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10201 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10202 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10203 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10204
10205 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10206 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10207 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10208
10209 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10210 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10211
10212 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10213 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10214
10215 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10216 ((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]);
10217
10218 return NL_SKIP;
10219}
10220#endif
10221
10222INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10223{
10224#ifdef HAL_NETLINK_IMPL
10225 Netlink nl;
10226 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010227 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010228 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010229 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010230
10231 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10232
10233 if (*output_array_size <= 0)
10234 return RETURN_OK;
10235
developerd946fd62022-12-08 18:03:28 +080010236 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010237
10238 nl.id = initSock80211(&nl);
10239
10240 if(nl.id < 0) {
10241 fprintf(stderr, "Error initializing netlink \n");
10242 return 0;
10243 }
10244
10245 struct nl_msg* msg = nlmsg_alloc();
10246
10247 if(!msg) {
10248 fprintf(stderr, "Failed to allocate netlink message.\n");
10249 nlfree(&nl);
10250 return 0;
10251 }
10252
10253 genlmsg_put(msg,
10254 NL_AUTO_PORT,
10255 NL_AUTO_SEQ,
10256 nl.id,
10257 0,
10258 0,
10259 NL80211_CMD_GET_STATION,
10260 0);
10261
10262 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10263 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10264 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10265 nl_send_auto(nl.socket, msg);
10266 nl_recvmsgs(nl.socket, nl.cb);
10267 nlmsg_free(msg);
10268 nlfree(&nl);
10269 return RETURN_OK;
10270#else
10271 //TODO Implement me
10272 return RETURN_OK;
10273#endif
10274}
10275
10276INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10277{
10278 // TODO Implement me!
10279 char buf[MAX_BUF_SIZE] = {0};
10280 char config_file[MAX_BUF_SIZE] = {0};
10281
10282 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10283 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10284 *activate = (strncmp("1",buf,1) == 0);
10285
10286 return RETURN_OK;
10287}
10288
10289INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10290{
10291 char config_file[MAX_BUF_SIZE] = {0};
10292 struct params list;
10293
10294 list.name = "rrm_neighbor_report";
10295 list.value = activate?"1":"0";
10296 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10297 wifi_hostapdWrite(config_file, &list, 1);
10298
10299 return RETURN_OK;
10300}
10301
10302INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10303{
10304 char buf[32] = {0};
10305 char config_file[MAX_BUF_SIZE] = {0};
10306
10307 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10308 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10309 *activate = (strncmp("1",buf,1) == 0);
10310
10311 return RETURN_OK;
10312}
10313#undef HAL_NETLINK_IMPL
10314#ifdef HAL_NETLINK_IMPL
10315static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10316 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10317 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10318 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10319 char dev[20];
10320 int freq =0 ;
10321 static int i=0;
10322
10323 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10324
10325 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10326 };
10327
10328 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10329
10330 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10331
10332 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10333 fprintf(stderr, "survey data missing!\n");
10334 return NL_SKIP;
10335 }
10336
10337 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10338 {
10339 fprintf(stderr, "failed to parse nested attributes!\n");
10340 return NL_SKIP;
10341 }
10342
10343
10344 if(out[0].array_size == 1 )
10345 {
10346 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10347 {
10348 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10349 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10350 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10351
10352 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10353 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10354 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10355 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10356 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10357 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10358 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10359 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10360 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10361 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10362 if (sinfo[NL80211_SURVEY_INFO_TIME])
10363 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10364 return NL_STOP;
10365 }
10366 }
10367 else
10368 {
10369 if ( i <= out[0].array_size )
10370 {
10371 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10372 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10373 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10374
10375 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10376 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10377 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10378 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10379 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10380 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10381 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10382 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10383 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10384 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10385 if (sinfo[NL80211_SURVEY_INFO_TIME])
10386 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10387 }
10388 }
10389
10390 i++;
10391 return NL_SKIP;
10392}
10393#endif
10394
10395static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10396{
10397 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10398 FILE *fp;
10399
10400 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10401 {
10402 printf("Creating Frequency-Channel Map\n");
10403 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10404 }
10405 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10406 if((fp = popen(command, "r")))
10407 {
10408 fgets(output, sizeof(output), fp);
10409 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010410 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010411 }
10412
10413 return 0;
10414}
10415
10416static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10417{
10418 int freqMHz = -1;
10419 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010420 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010421
10422 ieee80211_channel_to_frequency(channel, &freqMHz);
10423 if (freqMHz == -1) {
10424 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10425 return -1;
10426 }
10427
developer7930d352022-12-21 17:55:42 +080010428 wifi_GetInterfaceName(radioIndex, interface_name);
10429 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010430 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10431 radioIndex, freqMHz);
10432 return -1;
10433 }
10434
10435 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10436 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10437 return -1;
10438 }
10439
10440 return 0;
10441}
10442
10443static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10444{
10445 const char *ptr = buf;
10446 char *key = NULL;
10447 char *val = NULL;
10448 char line[256] = { '\0' };
10449
10450 while (ptr = get_line_from_str_buf(ptr, line)) {
10451 if (strstr(line, "Frequency")) continue;
10452
10453 key = strtok(line, ":");
10454 val = strtok(NULL, " ");
10455 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10456
10457 if (!strcmp(key, "noise")) {
10458 sscanf(val, "%d", &stats->ch_noise);
10459 if (stats->ch_noise == 0) {
10460 // Workaround for missing noise information.
10461 // Assume -95 for 2.4G and -103 for 5G
10462 if (radioIndex == 0) stats->ch_noise = -95;
10463 if (radioIndex == 1) stats->ch_noise = -103;
10464 }
10465 }
10466 else if (!strcmp(key, "channel active time")) {
10467 sscanf(val, "%llu", &stats->ch_utilization_total);
10468 }
10469 else if (!strcmp(key, "channel busy time")) {
10470 sscanf(val, "%llu", &stats->ch_utilization_busy);
10471 }
10472 else if (!strcmp(key, "channel receive time")) {
10473 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10474 }
10475 else if (!strcmp(key, "channel transmit time")) {
10476 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10477 }
10478 };
10479
10480 return 0;
10481}
10482
10483INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10484{
10485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10486#ifdef HAL_NETLINK_IMPL
10487 Netlink nl;
10488 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010489 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010490
10491 local[0].array_size = array_size;
10492
developerac6f1142022-12-20 19:26:35 +080010493 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010494 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010495
10496 nl.id = initSock80211(&nl);
10497
10498 if (nl.id < 0) {
10499 fprintf(stderr, "Error initializing netlink \n");
10500 return -1;
10501 }
10502
10503 struct nl_msg* msg = nlmsg_alloc();
10504
10505 if (!msg) {
10506 fprintf(stderr, "Failed to allocate netlink message.\n");
10507 nlfree(&nl);
10508 return -2;
10509 }
10510
10511 genlmsg_put(msg,
10512 NL_AUTO_PORT,
10513 NL_AUTO_SEQ,
10514 nl.id,
10515 0,
10516 NLM_F_DUMP,
10517 NL80211_CMD_GET_SURVEY,
10518 0);
10519
10520 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10521 nl_send_auto(nl.socket, msg);
10522 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10523 nl_recvmsgs(nl.socket, nl.cb);
10524 nlmsg_free(msg);
10525 nlfree(&nl);
10526 //Copying the Values
10527 for(int i=0;i<array_size;i++)
10528 {
10529 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10530 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10531 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10532 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10533 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10534 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10535 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10536 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10537 }
10538#else
10539 ULONG channel = 0;
10540 int i;
10541 int number_of_channels = array_size;
10542 char buf[512];
10543 INT ret;
10544 wifi_channelStats_t tmp_stats;
10545
10546 if (number_of_channels == 0) {
10547 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10548 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10549 return RETURN_ERR;
10550 }
10551 number_of_channels = 1;
10552 input_output_channelStats_array[0].ch_number = channel;
10553 }
10554
10555 for (i = 0; i < number_of_channels; i++) {
10556
10557 input_output_channelStats_array[i].ch_noise = 0;
10558 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10559 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10560 input_output_channelStats_array[i].ch_utilization_busy = 0;
10561 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10562 input_output_channelStats_array[i].ch_utilization_total = 0;
10563
10564 memset(buf, 0, sizeof(buf));
10565 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10566 return RETURN_ERR;
10567 }
10568 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10569 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10570 return RETURN_ERR;
10571 }
10572
10573 // XXX: fake missing 'self' counter which is not available in iw survey output
10574 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10575 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10576
10577 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10578 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10579 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10580 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10581 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10582
10583 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",
10584 __func__,
10585 input_output_channelStats_array[i].ch_number,
10586 input_output_channelStats_array[i].ch_noise,
10587 input_output_channelStats_array[i].ch_utilization_total,
10588 input_output_channelStats_array[i].ch_utilization_busy,
10589 input_output_channelStats_array[i].ch_utilization_busy_rx,
10590 input_output_channelStats_array[i].ch_utilization_busy_tx,
10591 input_output_channelStats_array[i].ch_utilization_busy_self,
10592 input_output_channelStats_array[i].ch_utilization_busy_ext);
10593 }
10594#endif
10595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10596 return RETURN_OK;
10597}
10598#define HAL_NETLINK_IMPL
10599
10600/* Hostapd events */
10601
10602#ifndef container_of
10603#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10604#define container_of(ptr, type, member) \
10605 ((type *)((char *)ptr - offset_of(type, member)))
10606#endif /* container_of */
10607
10608struct ctrl {
10609 char sockpath[128];
10610 char sockdir[128];
10611 char bss[IFNAMSIZ];
10612 char reply[4096];
10613 int ssid_index;
10614 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10615 void (*overrun)(struct ctrl *ctrl);
10616 struct wpa_ctrl *wpa;
10617 unsigned int ovfl;
10618 size_t reply_len;
10619 int initialized;
10620 ev_timer retry;
10621 ev_timer watchdog;
10622 ev_stat stat;
10623 ev_io io;
10624};
10625static wifi_newApAssociatedDevice_callback clients_connect_cb;
10626static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10627static struct ctrl wpa_ctrl[MAX_APS];
10628static int initialized;
10629
10630static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10631{
10632 char cbuf[256] = {};
10633 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10634 struct cmsghdr *cmsg;
10635 unsigned int ovfl = ctrl->ovfl;
10636 unsigned int drop;
10637
10638 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10639 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10640 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10641 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10642
10643 drop = ovfl - ctrl->ovfl;
10644 ctrl->ovfl = ovfl;
10645
10646 return drop;
10647}
10648
10649static void ctrl_close(struct ctrl *ctrl)
10650{
10651 if (ctrl->io.cb)
10652 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10653 if (ctrl->retry.cb)
10654 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10655 if (!ctrl->wpa)
10656 return;
10657
10658 wpa_ctrl_detach(ctrl->wpa);
10659 wpa_ctrl_close(ctrl->wpa);
10660 ctrl->wpa = NULL;
10661 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10662}
10663
10664static void ctrl_process(struct ctrl *ctrl)
10665{
10666 const char *str;
10667 int drops;
10668 int level;
10669 int err;
10670
10671 /* Example events:
10672 *
10673 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10674 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10675 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10676 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10677 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10678 */
10679 if (!(str = index(ctrl->reply, '>')))
10680 return;
10681 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10682 return;
10683
10684 str++;
10685
10686 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10687 if (!(str = index(ctrl->reply, ' ')))
10688 return;
10689 wifi_associated_dev_t sta;
10690 memset(&sta, 0, sizeof(sta));
10691
10692 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10693 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10694 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10695
10696 sta.cli_Active=true;
10697
10698 (clients_connect_cb)(ctrl->ssid_index, &sta);
10699 goto handled;
10700 }
10701
10702 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10703 if (!(str = index(ctrl->reply, ' ')))
10704 return;
10705
10706 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10707 goto handled;
10708 }
10709
10710 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10711 printf("CTRL_WPA: handle TERMINATING event\n");
10712 goto retry;
10713 }
10714
10715 if (strncmp("AP-DISABLED", str, 11) == 0) {
10716 printf("CTRL_WPA: handle AP-DISABLED\n");
10717 goto retry;
10718 }
10719
10720 printf("Event not supported!!\n");
10721
10722handled:
10723
10724 if ((drops = ctrl_get_drops(ctrl))) {
10725 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10726 if (ctrl->overrun)
10727 ctrl->overrun(ctrl);
10728 }
10729
10730 return;
10731
10732retry:
10733 printf("WPA_CTRL: closing\n");
10734 ctrl_close(ctrl);
10735 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10736 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10737}
10738
10739static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10740{
10741 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10742 int err;
10743
10744 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10745 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10746 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10747 ctrl->reply[ctrl->reply_len] = 0;
10748 if (err < 0) {
10749 if (errno == EAGAIN || errno == EWOULDBLOCK)
10750 return;
10751 ctrl_close(ctrl);
10752 ev_timer_again(EV_A_ &ctrl->retry);
10753 return;
10754 }
10755
10756 ctrl_process(ctrl);
10757}
10758
10759static int ctrl_open(struct ctrl *ctrl)
10760{
10761 int fd;
10762
10763 if (ctrl->wpa)
10764 return 0;
10765
10766 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10767 if (!ctrl->wpa)
10768 goto err;
10769
10770 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10771 goto err_close;
10772
10773 fd = wpa_ctrl_get_fd(ctrl->wpa);
10774 if (fd < 0)
10775 goto err_detach;
10776
10777 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10778 goto err_detach;
10779
10780 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10781 ev_io_start(EV_DEFAULT_ &ctrl->io);
10782
10783 return 0;
10784
10785err_detach:
10786 wpa_ctrl_detach(ctrl->wpa);
10787err_close:
10788 wpa_ctrl_close(ctrl->wpa);
10789err:
10790 ctrl->wpa = NULL;
10791 return -1;
10792}
10793
10794static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10795{
10796 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10797
10798 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10799 ctrl_open(ctrl);
10800}
10801
10802static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10803{
10804 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10805
10806 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10807 if (ctrl_open(ctrl) == 0) {
10808 printf("WPA_CTRL: retry successful\n");
10809 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10810 }
10811}
10812
10813int ctrl_enable(struct ctrl *ctrl)
10814{
10815 if (ctrl->wpa)
10816 return 0;
10817
10818 if (!ctrl->stat.cb) {
10819 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10820 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10821 }
10822
10823 if (!ctrl->retry.cb) {
10824 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10825 }
10826
10827 return ctrl_open(ctrl);
10828}
10829
10830static void
10831ctrl_msg_cb(char *buf, size_t len)
10832{
10833 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10834
10835 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10836 ctrl_process(ctrl);
10837}
10838
10839static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10840{
10841 int err;
10842
10843 if (!ctrl->wpa)
10844 return -1;
10845 if (*reply_len < 2)
10846 return -1;
10847
10848 (*reply_len)--;
10849 ctrl->reply_len = sizeof(ctrl->reply);
10850 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10851 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10852 if (err < 0)
10853 return err;
10854
10855 if (ctrl->reply_len > *reply_len)
10856 ctrl->reply_len = *reply_len;
10857
10858 *reply_len = ctrl->reply_len;
10859 memcpy(reply, ctrl->reply, *reply_len);
10860 reply[*reply_len - 1] = 0;
10861 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10862 return 0;
10863}
10864
10865static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10866{
10867 const char *pong = "PONG";
10868 const char *ping = "PING";
10869 char reply[1024];
10870 size_t len = sizeof(reply);
10871 int err;
10872 ULONG s, snum;
10873 INT ret;
10874 BOOL status;
10875
10876 printf("WPA_CTRL: watchdog cb\n");
10877
10878 ret = wifi_getSSIDNumberOfEntries(&snum);
10879 if (ret != RETURN_OK) {
10880 printf("%s: failed to get SSID count", __func__);
10881 return;
10882 }
10883
10884 if (snum > MAX_APS) {
10885 printf("more ssid than supported! %lu\n", snum);
10886 return;
10887 }
10888
10889 for (s = 0; s < snum; s++) {
10890 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010891 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010892 continue;
10893 }
10894 if (status == false) continue;
10895
10896 memset(reply, 0, sizeof(reply));
10897 len = sizeof(reply);
10898 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10899 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10900 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10901 continue;
10902
10903 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10904 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010905 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010906 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10907 }
10908}
10909
10910static int init_wpa()
10911{
10912 int ret = 0, i = 0;
10913 ULONG s, snum;
10914
10915 ret = wifi_getSSIDNumberOfEntries(&snum);
10916 if (ret != RETURN_OK) {
10917 printf("%s: failed to get SSID count", __func__);
10918 return RETURN_ERR;
10919 }
10920
10921 if (snum > MAX_APS) {
10922 printf("more ssid than supported! %lu\n", snum);
10923 return RETURN_ERR;
10924 }
10925
10926 for (s = 0; s < snum; s++) {
10927 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10928 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10929 wpa_ctrl[s].ssid_index = s;
10930 ctrl_enable(&wpa_ctrl[s]);
10931 }
10932
10933 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10934 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10935
10936 initialized = 1;
10937 printf("WPA_CTRL: initialized\n");
10938
10939 return RETURN_OK;
10940}
10941
10942void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10943{
10944 clients_connect_cb = callback_proc;
10945 if (!initialized)
10946 init_wpa();
10947}
10948
10949void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10950{
10951 clients_disconnect_cb = callback_proc;
10952 if (!initialized)
10953 init_wpa();
10954}
10955
10956INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10957{
10958 // TODO Implement me!
10959 return RETURN_ERR;
10960}
10961
10962INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10963{
10964 // TODO Implement me!
10965 return RETURN_ERR;
10966}
10967
10968INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10969{
10970 int i;
developer4b102122023-02-15 10:53:03 +080010971 int phyId = -1;
10972 char cmd[256] = {0};
10973 char channel_numbers_buf[256] = {0};
10974 char dfs_state_buf[256] = {0};
10975 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080010976 const char *ptr;
developer4b102122023-02-15 10:53:03 +080010977 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080010978
developer4b102122023-02-15 10:53:03 +080010979 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080010980
developer4b102122023-02-15 10:53:03 +080010981 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
10982 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080010983
developer4b102122023-02-15 10:53:03 +080010984 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 +080010985
developer4b102122023-02-15 10:53:03 +080010986 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10987 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10988 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010989 }
10990
developer4b102122023-02-15 10:53:03 +080010991 ptr = channel_numbers_buf;
10992 i = 0;
10993 while (ptr = get_line_from_str_buf(ptr, line)) {
10994 if (i >= outputMapSize) {
10995 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10996 return RETURN_ERR;
10997 }
10998 sscanf(line, "%d", &outputMap[i].ch_number);
10999
11000 memset(cmd, 0, sizeof(cmd));
11001 // Below command should fetch string for DFS state (usable, available or unavailable)
11002 // Example line: "DFS state: usable (for 78930 sec)"
11003 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) {
11004 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011005 return RETURN_ERR;
11006 }
11007
developer4b102122023-02-15 10:53:03 +080011008 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11009 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011010 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11011 return RETURN_ERR;
11012 }
11013
developer4b102122023-02-15 10:53:03 +080011014 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011015
developer4b102122023-02-15 10:53:03 +080011016 if (!strcmp(dfs_state_buf, "usable")) {
11017 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11018 } else if (!strcmp(dfs_state_buf, "available")) {
11019 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11020 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11021 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11022 } else {
11023 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011024 }
developer4b102122023-02-15 10:53:03 +080011025 i++;
developer06a01d92022-09-07 16:32:39 +080011026 }
11027
developer4b102122023-02-15 10:53:03 +080011028 return RETURN_OK;
11029
developer06a01d92022-09-07 16:32:39 +080011030 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11031 return RETURN_ERR;
11032}
11033
11034INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11035{
11036 // TODO Implement me!
11037 return RETURN_ERR;
11038}
11039
11040INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11041{
11042 return RETURN_OK;
11043}
11044
11045INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11046{
11047 // TODO Implement me!
11048 return RETURN_ERR;
11049}
11050
11051INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11052{
11053 // TODO API refrence Implementaion is present on RPI hal
11054 return RETURN_ERR;
11055}
11056
11057INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11058{
developerd946fd62022-12-08 18:03:28 +080011059 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080011060 char cmd[128]={'\0'};
11061 char buf[128]={'\0'};
11062 char *support;
11063 int maximum_tx = 0, current_tx = 0;
11064
11065 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11066 if(txpwr_pcntg == NULL)
11067 return RETURN_ERR;
11068
developerac6f1142022-12-20 19:26:35 +080011069 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011070 return RETURN_ERR;
11071
developera5005b62022-09-13 15:43:35 +080011072 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080011073 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080011074 _syscmd(cmd, buf, sizeof(buf));
11075 maximum_tx = strtol(buf, NULL, 10);
11076
11077 // Get the current tx power
11078 memset(cmd, 0, sizeof(cmd));
11079 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080011080 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080011081 _syscmd(cmd, buf, sizeof(buf));
11082 current_tx = strtol(buf, NULL, 10);
11083
11084 // Get the power supported list and find the current power percentage in supported list
11085 memset(buf, 0, sizeof(buf));
11086 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11087 support = strtok(buf, ",");
11088 while(true)
11089 {
11090 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
developer033b37b2022-10-18 11:27:46 +080011091 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080011092 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080011093 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080011094 }
11095 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11096 if (tmp == current_tx) {
11097 *txpwr_pcntg = strtol(support, NULL, 10);
11098 break;
11099 }
11100 support = strtok(NULL, ",");
11101 }
11102 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080011103 return RETURN_OK;
11104}
11105
11106INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11107{
developer58599c22022-09-13 16:40:34 +080011108 // TODO precac feature.
11109 struct params params = {0};
11110 char config_file[128] = {0};
11111
11112 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11113
11114 params.name = "enable_background_radar";
11115 params.value = enable?"1":"0";
11116 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11117 wifi_hostapdWrite(config_file, &params, 1);
11118 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11119
11120 /* TODO precac feature */
11121
11122 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11123 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011124}
11125
11126INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11127{
developer58599c22022-09-13 16:40:34 +080011128 char config_file[128] = {0};
11129 char buf[64] = {0};
11130
11131 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11132 if (NULL == enable || NULL == precac)
11133 return RETURN_ERR;
11134
11135 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11136 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
11137 if (strncmp(enable, "1", 1) == 0)
11138 *enable = true;
11139 else
11140 *enable = false;
11141
11142 /* TODO precac feature */
11143
11144 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11145 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011146}
11147
11148INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11149{
developer58599c22022-09-13 16:40:34 +080011150 *supported = TRUE;
11151 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011152}
11153
developera7149722023-01-11 11:36:21 +080011154bool check_is_hemu_vendor_new_patch() {
11155 char cmd[128] = {0};
11156 char buf[128] = {0};
11157
11158 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11159 _syscmd(cmd, buf, sizeof(buf));
11160
11161 if (strlen(buf) > 0)
11162 return FALSE;
11163 else
11164 return TRUE;
11165}
11166
developer3e6b1692022-09-30 18:04:05 +080011167INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11168{
11169 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11170 struct params params = {0};
11171 char config_file[64] = {0};
11172 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011173 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011174 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011175 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011176 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11177
developera7149722023-01-11 11:36:21 +080011178 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011179
11180 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11181 set_mu_type &= ~0x05; // unset bit 0, 2
11182 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11183 set_mu_type |= 0x01;
11184 set_mu_type &= ~0x04;
11185 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11186 set_mu_type &= ~0x01;
11187 set_mu_type |= 0x04;
11188 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11189 set_mu_type |= 0x05; // set bit 0, 2
11190 }
11191
developera7149722023-01-11 11:36:21 +080011192 new_vendor_patch = check_is_hemu_vendor_new_patch();
11193 if (new_vendor_patch)
11194 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11195 else
11196 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11197
11198 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011199 sprintf(buf, "%u", set_mu_type);
11200 params.value = buf;
11201 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11202 wifi_hostapdWrite(config_file, &params, 1);
11203 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011204 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011205
11206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11207 return RETURN_OK;
11208}
11209
11210INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11211{
11212 struct params params={0};
11213 char config_file[64] = {0};
11214 char buf[64] = {0};
11215 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011216 bool new_vendor_patch = FALSE;
11217 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011218
11219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11220
11221 if (mu_type == NULL)
11222 return RETURN_ERR;
11223
developera7149722023-01-11 11:36:21 +080011224 new_vendor_patch = check_is_hemu_vendor_new_patch();
11225
11226 if (new_vendor_patch)
11227 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11228 else
11229 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11230
developer3e6b1692022-09-30 18:04:05 +080011231 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011232 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011233 get_mu_type = strtol(buf, NULL, 10);
11234
11235 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11236 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11237 else if (get_mu_type & 0x04)
11238 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11239 else if (get_mu_type & 0x01)
11240 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11241 else
11242 *mu_type = WIFI_DL_MU_TYPE_NONE;
11243
11244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11245 return RETURN_OK;
11246}
11247
11248INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11249{
11250 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11251 struct params params={0};
11252 char config_file[64] = {0};
11253 char buf[64] = {0};
11254 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011255 bool new_vendor_patch = FALSE;
11256 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11258
developera7149722023-01-11 11:36:21 +080011259 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011260
11261 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11262 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11263 set_mu_type &= ~0x0a;
11264 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11265 set_mu_type |= 0x02;
11266 set_mu_type &= ~0x08;
11267 }
11268
developera7149722023-01-11 11:36:21 +080011269 new_vendor_patch = check_is_hemu_vendor_new_patch();
11270
11271 if (new_vendor_patch)
11272 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11273 else
11274 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11275
11276 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011277 sprintf(buf, "%u", set_mu_type);
11278 params.value = buf;
11279 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11280 wifi_hostapdWrite(config_file, &params, 1);
11281 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011282 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011283
11284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11285 return RETURN_OK;
11286}
11287
11288INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11289{
11290 struct params params={0};
11291 char config_file[64] = {0};
11292 char buf[64] = {0};
11293 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011294 bool new_vendor_patch = FALSE;
11295 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011296
11297 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11298
developera7149722023-01-11 11:36:21 +080011299 new_vendor_patch = check_is_hemu_vendor_new_patch();
11300
11301 if (new_vendor_patch)
11302 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11303 else
11304 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11305
developer3e6b1692022-09-30 18:04:05 +080011306 if (mu_type == NULL)
11307 return RETURN_ERR;
11308
11309 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011310 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011311
11312 get_mu_type = strtol(buf, NULL, 10);
11313 if (get_mu_type & 0x02)
11314 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11315 else
11316 *mu_type = WIFI_DL_MU_TYPE_NONE;
11317
11318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11319 return RETURN_OK;
11320}
11321
11322
developer454b9462022-09-13 15:29:16 +080011323INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11324{
11325 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011326 char buf[256] = {0};
11327 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011328 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011329 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011330 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011331 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011332
11333 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11334
developer254882b2022-09-30 17:12:31 +080011335 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011336 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11337 return RETURN_ERR;
11338 }
developer454b9462022-09-13 15:29:16 +080011339
developer254882b2022-09-30 17:12:31 +080011340 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011341 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011342
developer254882b2022-09-30 17:12:31 +080011343 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11344 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011345 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011346 _syscmd(cmd, buf, sizeof(buf));
11347 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11348 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11349 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011350 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 +080011351 _syscmd(cmd, buf, sizeof(buf));
11352 }
11353 if (band == band_5) {
11354 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11355 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011356 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 +080011357 _syscmd(cmd, buf, sizeof(buf));
11358 }
11359 }
11360 }
11361 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011362
developer254882b2022-09-30 17:12:31 +080011363 if (guard_interval == wifi_guard_interval_400)
11364 strcpy(GI, "0.4");
11365 else if (guard_interval == wifi_guard_interval_800)
11366 strcpy(GI, "0.8");
11367 else if (guard_interval == wifi_guard_interval_1600)
11368 strcpy(GI, "1.6");
11369 else if (guard_interval == wifi_guard_interval_3200)
11370 strcpy(GI, "3.2");
11371 else if (guard_interval == wifi_guard_interval_auto)
11372 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011373 // Record GI for get GI function
11374 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11375 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011376 if (f == NULL)
11377 return RETURN_ERR;
11378 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011379 fclose(f);
11380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11381 return RETURN_OK;
11382}
11383
11384INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11385{
11386 char buf[32] = {0};
11387 char cmd[64] = {0};
11388
11389 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11390
11391 if (guard_interval == NULL)
11392 return RETURN_ERR;
11393
developer7c4cd202023-03-01 10:56:29 +080011394 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011395 _syscmd(cmd, buf, sizeof(buf));
11396
11397 if (strncmp(buf, "0.4", 3) == 0)
11398 *guard_interval = wifi_guard_interval_400;
11399 else if (strncmp(buf, "0.8", 3) == 0)
11400 *guard_interval = wifi_guard_interval_800;
11401 else if (strncmp(buf, "1.6", 3) == 0)
11402 *guard_interval = wifi_guard_interval_1600;
11403 else if (strncmp(buf, "3.2", 3) == 0)
11404 *guard_interval = wifi_guard_interval_3200;
11405 else
11406 *guard_interval = wifi_guard_interval_auto;
11407
11408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11409 return RETURN_OK;
11410}
11411
developer3cc61d12022-09-13 16:36:05 +080011412INT wifi_setBSSColor(INT radio_index, UCHAR color)
11413{
11414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11415 struct params params = {0};
11416 char config_file[128] = {0};
11417 char bss_color[4] ={0};
11418
11419 params.name = "he_bss_color";
11420 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11421 params.value = bss_color;
11422 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11423 wifi_hostapdWrite(config_file, &params, 1);
11424 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11425
11426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11427 return RETURN_OK;
11428}
11429
11430INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11431{
11432 char config_file[128] = {0};
11433 char buf[64] = {0};
11434 char temp_output[128] = {'\0'};
11435
11436 wifi_dbg_printf("\nFunc=%s\n", __func__);
11437 if (NULL == color)
11438 return RETURN_ERR;
11439
11440 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11441 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11442
11443 if(strlen(buf) > 0) {
11444 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11445 } else {
11446 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11447 }
11448
11449 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11450 wifi_dbg_printf("\noutput_string=%s\n", color);
11451
11452 return RETURN_OK;
11453}
11454
developer06a01d92022-09-07 16:32:39 +080011455/* multi-psk support */
11456INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11457{
11458 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011459 char interface_name[16] = {0};
11460
developerac6f1142022-12-20 19:26:35 +080011461 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011462 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011463
developerd946fd62022-12-08 18:03:28 +080011464 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11465 interface_name,
developer06a01d92022-09-07 16:32:39 +080011466 mac[0],
11467 mac[1],
11468 mac[2],
11469 mac[3],
11470 mac[4],
11471 mac[5]
11472 );
11473 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11474 _syscmd(cmd, key->wifi_keyId, 64);
11475
11476
11477 return RETURN_OK;
11478}
11479
11480INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11481{
developerd946fd62022-12-08 18:03:28 +080011482 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011483 FILE *fd = NULL;
11484 char fname[100];
11485 char cmd[128] = {0};
11486 char out[64] = {0};
11487 wifi_key_multi_psk_t * key = NULL;
11488 if(keysNumber < 0)
11489 return RETURN_ERR;
11490
developer431128d2022-12-16 15:30:41 +080011491 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011492 fd = fopen(fname, "w");
11493 if (!fd) {
11494 return RETURN_ERR;
11495 }
11496 key= (wifi_key_multi_psk_t *) keys;
11497 for(int i=0; i<keysNumber; ++i, key++) {
11498 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11499 }
11500 fclose(fd);
11501
11502 //reload file
developerac6f1142022-12-20 19:26:35 +080011503 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011504 return RETURN_ERR;
11505 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011506 _syscmd(cmd, out, 64);
11507 return RETURN_OK;
11508}
11509
11510INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11511{
11512 FILE *fd = NULL;
11513 char fname[100];
11514 char * line = NULL;
11515 char * pos = NULL;
11516 size_t len = 0;
11517 ssize_t read = 0;
11518 INT ret = RETURN_OK;
11519 wifi_key_multi_psk_t *keys_it = NULL;
11520
11521 if (keysNumber < 1) {
11522 return RETURN_ERR;
11523 }
11524
developer431128d2022-12-16 15:30:41 +080011525 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011526 fd = fopen(fname, "r");
11527 if (!fd) {
11528 return RETURN_ERR;
11529 }
11530
11531 if (keys == NULL) {
11532 ret = RETURN_ERR;
11533 goto close;
11534 }
11535
11536 keys_it = keys;
11537 while ((read = getline(&line, &len, fd)) != -1) {
11538 //Strip trailing new line if present
11539 if (read > 0 && line[read-1] == '\n') {
11540 line[read-1] = '\0';
11541 }
11542
11543 if(strcmp(line,"keyid=")) {
11544 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11545 if (!(pos = index(line, ' '))) {
11546 ret = RETURN_ERR;
11547 goto close;
11548 }
11549 pos++;
11550 //Here should be 00:00:00:00:00:00
11551 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11552 printf("Not supported MAC: %s\n", pos);
11553 }
11554 if (!(pos = index(pos, ' '))) {
11555 ret = RETURN_ERR;
11556 goto close;
11557 }
11558 pos++;
11559
11560 //The rest is PSK
11561 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11562 keys_it++;
11563
11564 if(--keysNumber <= 0)
11565 break;
11566 }
11567 }
11568
11569close:
11570 free(line);
11571 fclose(fd);
11572 return ret;
11573}
11574/* end of multi-psk support */
11575
11576INT wifi_setNeighborReports(UINT apIndex,
11577 UINT numNeighborReports,
11578 wifi_NeighborReport_t *neighborReports)
11579{
11580 char cmd[256] = { 0 };
11581 char hex_bssid[13] = { 0 };
11582 char bssid[18] = { 0 };
11583 char nr[256] = { 0 };
11584 char ssid[256];
11585 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011586 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011587 INT ret;
11588
11589 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011590 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011591 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011592 return RETURN_ERR;
11593 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 +080011594 system(cmd);
11595
11596 for(unsigned int i = 0; i < numNeighborReports; i++)
11597 {
11598 memset(ssid, 0, sizeof(ssid));
11599 ret = wifi_getSSIDName(apIndex, ssid);
11600 if (ret != RETURN_OK)
11601 return RETURN_ERR;
11602
11603 memset(hex_ssid, 0, sizeof(hex_ssid));
11604 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11605 sprintf(hex_ssid + k,"%02x", ssid[j]);
11606
11607 snprintf(hex_bssid, sizeof(hex_bssid),
11608 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11609 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11610 snprintf(bssid, sizeof(bssid),
11611 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11612 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11613
11614 snprintf(nr, sizeof(nr),
11615 "%s" // bssid
11616 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11617 "%02hhx" // operclass
11618 "%02hhx" // channel
11619 "%02hhx", // phy_mode
11620 hex_bssid,
11621 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11622 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11623 neighborReports[i].opClass,
11624 neighborReports[i].channel,
11625 neighborReports[i].phyTable);
11626
11627 snprintf(cmd, sizeof(cmd),
11628 "hostapd_cli set_neighbor "
11629 "%s " // bssid
11630 "ssid=%s " // ssid
11631 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011632 "-i %s",
11633 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011634
11635 if (WEXITSTATUS(system(cmd)) != 0)
11636 {
11637 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11638 }
11639 }
11640
11641 return RETURN_OK;
11642}
11643
11644INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11645{
11646 return RETURN_OK;
11647}
11648
11649#ifdef _WIFI_HAL_TEST_
11650int main(int argc,char **argv)
11651{
11652 int index;
11653 INT ret=0;
11654 char buf[1024]="";
11655
11656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11657 if(argc<3)
11658 {
11659 if(argc==2)
11660 {
11661 if(!strcmp(argv[1], "init"))
11662 return wifi_init();
11663 if(!strcmp(argv[1], "reset"))
11664 return wifi_reset();
11665 if(!strcmp(argv[1], "wifi_getHalVersion"))
11666 {
11667 char buffer[64];
11668 if(wifi_getHalVersion(buffer)==RETURN_OK)
11669 printf("Version: %s\n", buffer);
11670 else
11671 printf("Error in wifi_getHalVersion\n");
11672 return RETURN_OK;
11673 }
11674 }
11675 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11676 exit(-1);
11677 }
11678
11679 index = atoi(argv[2]);
11680 if(strstr(argv[1], "wifi_getApName")!=NULL)
11681 {
11682 wifi_getApName(index,buf);
11683 printf("Ap name is %s \n",buf);
11684 return 0;
11685 }
11686 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11687 {
11688 BOOL b = FALSE;
11689 BOOL *output_bool = &b;
11690 wifi_getRadioAutoChannelEnable(index,output_bool);
11691 printf("Channel enabled = %d \n",b);
11692 return 0;
11693 }
11694 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11695 {
11696 wifi_getApWpaEncryptionMode(index,buf);
11697 printf("encryption enabled = %s\n",buf);
11698 return 0;
11699 }
11700 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11701 {
11702 BOOL b = FALSE;
11703 BOOL *output_bool = &b;
11704 wifi_getApSsidAdvertisementEnable(index,output_bool);
11705 printf("advertisment enabled = %d\n",b);
11706 return 0;
11707 }
11708 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11709 {
11710 if(argc <= 3 )
11711 {
11712 printf("Insufficient arguments \n");
11713 exit(-1);
11714 }
11715
11716 char sta[20] = {'\0'};
11717 ULLONG handle= 0;
11718 strcpy(sta,argv[3]);
11719 mac_address_t st;
11720 mac_addr_aton(st,sta);
11721
11722 wifi_associated_dev_tid_stats_t tid_stats;
11723 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11724 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11725 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);
11726 }
11727
11728 if(strstr(argv[1], "getApEnable")!=NULL) {
11729 BOOL enable;
11730 ret=wifi_getApEnable(index, &enable);
11731 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11732 }
11733 else if(strstr(argv[1], "setApEnable")!=NULL) {
11734 BOOL enable = atoi(argv[3]);
11735 ret=wifi_setApEnable(index, enable);
11736 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11737 }
11738 else if(strstr(argv[1], "getApStatus")!=NULL) {
11739 char status[64];
11740 ret=wifi_getApStatus(index, status);
11741 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11742 }
11743 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11744 {
11745 wifi_getSSIDNameStatus(index,buf);
11746 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11747 return 0;
11748 }
11749 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11750 wifi_ssidTrafficStats2_t stats={0};
11751 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11752 printf("%s %d: returns %d\n", argv[1], index, ret);
11753 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11754 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11755 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11756 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11757 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11758 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11759 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11760 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11761 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11762 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11763 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11764 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11765 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11766 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11767 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11768 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11769 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11770 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11771 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11772 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11773 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11774 }
11775 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11776 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11777 UINT array_size=0;
11778 UINT i=0;
11779 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11780 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11781 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11782 printf(" neighbor %d:\n", i);
11783 printf(" ap_SSID =%s\n", pt->ap_SSID);
11784 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11785 printf(" ap_Mode =%s\n", pt->ap_Mode);
11786 printf(" ap_Channel =%d\n", pt->ap_Channel);
11787 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11788 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11789 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11790 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11791 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11792 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11793 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11794 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11795 printf(" ap_Noise =%d\n", pt->ap_Noise);
11796 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11797 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11798 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11799 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11800 }
11801 if(neighbor_ap_array)
11802 free(neighbor_ap_array); //make sure to free the list
11803 }
11804 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11805 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11806 UINT array_size=0;
11807 UINT i=0;
11808 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11809 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11810 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11811 printf(" associated_dev %d:\n", i);
11812 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11813 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11814 printf(" cli_SNR =%d\n", pt->cli_SNR);
11815 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11816 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11817 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11818 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11819 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11820 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11821 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11822 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11823 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11824 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11825 }
11826 if(associated_dev_array)
11827 free(associated_dev_array); //make sure to free the list
11828 }
11829
11830 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11831 {
11832#define MAX_ARRAY_SIZE 64
11833 int i, array_size;
11834 char *p, *ch_str;
11835 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11836
11837 if(argc != 5)
11838 {
11839 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11840 exit(-1);
11841 }
11842 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11843
11844 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11845 {
11846 strtok_r(ch_str, ",", &p);
11847 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11848 }
11849 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11850 if(!array_size)
11851 array_size=1;//Need to print current channel statistics
11852 for(i=0; i<array_size; i++)
11853 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11854 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11855 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11856 input_output_channelStats_array[i].ch_number,\
11857 input_output_channelStats_array[i].ch_noise,\
11858 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11859 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11860 input_output_channelStats_array[i].ch_utilization_busy,\
11861 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11862 input_output_channelStats_array[i].ch_utilization_total);
11863 }
11864
11865 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11866 {
11867 if(argc <= 3 )
11868 {
11869 printf("Insufficient arguments \n");
11870 exit(-1);
11871 }
11872 char mac_addr[20] = {'\0'};
11873 wifi_device_t output_struct;
11874 int dev_index = atoi(argv[3]);
11875
11876 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11877 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11878 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);
11879 }
11880
11881 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11882 {
11883 if (argc <= 3)
11884 {
11885 printf("Insufficient arguments\n");
11886 exit(-1);
11887 }
11888 char args[256];
11889 wifi_NeighborReport_t *neighborReports;
11890
11891 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11892 if (!neighborReports)
11893 {
11894 printf("Failed to allocate memory");
11895 exit(-1);
11896 }
11897
11898 for (int i = 3; i < argc; ++i)
11899 {
11900 char *val;
11901 int j = 0;
11902 memset(args, 0, sizeof(args));
11903 strncpy(args, argv[i], sizeof(args));
11904 val = strtok(args, ";");
11905 while (val != NULL)
11906 {
11907 if (j == 0)
11908 {
11909 mac_addr_aton(neighborReports[i - 3].bssid, val);
11910 } else if (j == 1)
11911 {
11912 neighborReports[i - 3].info = strtol(val, NULL, 16);
11913 } else if (j == 2)
11914 {
11915 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11916 } else if (j == 3)
11917 {
11918 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11919 } else if (j == 4)
11920 {
11921 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11922 } else {
11923 printf("Insufficient arguments]n\n");
11924 exit(-1);
11925 }
11926 val = strtok(NULL, ";");
11927 j++;
11928 }
11929 }
11930
11931 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11932 if (ret != RETURN_OK)
11933 {
11934 printf("wifi_setNeighborReports ret = %d", ret);
11935 exit(-1);
11936 }
11937 }
11938 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11939 {
11940 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11941 printf("%s.\n", buf);
11942 else
11943 printf("Error returned\n");
11944 }
11945 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11946 {
11947 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11948 printf("%s.\n", buf);
11949 else
11950 printf("Error returned\n");
11951 }
11952 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11953 {
11954 if (argc <= 2)
11955 {
11956 printf("Insufficient arguments\n");
11957 exit(-1);
11958 }
11959 char buf[64]= {'\0'};
11960 wifi_getRadioOperatingChannelBandwidth(index,buf);
11961 printf("Current bandwidth is %s \n",buf);
11962 return 0;
11963 }
11964 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11965 {
11966 if (argc <= 5)
11967 {
11968 printf("Insufficient arguments\n");
11969 exit(-1);
11970 }
11971 UINT channel = atoi(argv[3]);
11972 UINT width = atoi(argv[4]);
11973 UINT beacon = atoi(argv[5]);
11974 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11975 printf("Result = %d", ret);
11976 }
11977
11978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11979 return 0;
11980}
11981
11982#endif
11983
11984#ifdef WIFI_HAL_VERSION_3
11985
developer1e5aa162022-09-13 16:06:24 +080011986INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11987{
11988 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11989 if (bitMap & WIFI_BITRATE_1MBPS)
11990 strcat(BasicRate, "1,");
11991 if (bitMap & WIFI_BITRATE_2MBPS)
11992 strcat(BasicRate, "2,");
11993 if (bitMap & WIFI_BITRATE_5_5MBPS)
11994 strcat(BasicRate, "5.5,");
11995 if (bitMap & WIFI_BITRATE_6MBPS)
11996 strcat(BasicRate, "6,");
11997 if (bitMap & WIFI_BITRATE_9MBPS)
11998 strcat(BasicRate, "9,");
11999 if (bitMap & WIFI_BITRATE_11MBPS)
12000 strcat(BasicRate, "11,");
12001 if (bitMap & WIFI_BITRATE_12MBPS)
12002 strcat(BasicRate, "12,");
12003 if (bitMap & WIFI_BITRATE_18MBPS)
12004 strcat(BasicRate, "18,");
12005 if (bitMap & WIFI_BITRATE_24MBPS)
12006 strcat(BasicRate, "24,");
12007 if (bitMap & WIFI_BITRATE_36MBPS)
12008 strcat(BasicRate, "36,");
12009 if (bitMap & WIFI_BITRATE_48MBPS)
12010 strcat(BasicRate, "48,");
12011 if (bitMap & WIFI_BITRATE_54MBPS)
12012 strcat(BasicRate, "54,");
12013 if (strlen(BasicRate) != 0) // remove last comma
12014 BasicRate[strlen(BasicRate) - 1] = '\0';
12015 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12016 return RETURN_OK;
12017}
12018
12019INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12020{
12021 UINT BitMap = 0;
12022 char *rate;
12023
12024 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12025 rate = strtok(BasicRatesList, ",");
12026 while(rate != NULL)
12027 {
12028 if (strcmp(rate, "1") == 0)
12029 BitMap |= WIFI_BITRATE_1MBPS;
12030 else if (strcmp(rate, "2") == 0)
12031 BitMap |= WIFI_BITRATE_2MBPS;
12032 else if (strcmp(rate, "5.5") == 0)
12033 BitMap |= WIFI_BITRATE_5_5MBPS;
12034 else if (strcmp(rate, "6") == 0)
12035 BitMap |= WIFI_BITRATE_6MBPS;
12036 else if (strcmp(rate, "9") == 0)
12037 BitMap |= WIFI_BITRATE_9MBPS;
12038 else if (strcmp(rate, "11") == 0)
12039 BitMap |= WIFI_BITRATE_11MBPS;
12040 else if (strcmp(rate, "12") == 0)
12041 BitMap |= WIFI_BITRATE_12MBPS;
12042 else if (strcmp(rate, "18") == 0)
12043 BitMap |= WIFI_BITRATE_18MBPS;
12044 else if (strcmp(rate, "24") == 0)
12045 BitMap |= WIFI_BITRATE_24MBPS;
12046 else if (strcmp(rate, "36") == 0)
12047 BitMap |= WIFI_BITRATE_36MBPS;
12048 else if (strcmp(rate, "48") == 0)
12049 BitMap |= WIFI_BITRATE_48MBPS;
12050 else if (strcmp(rate, "54") == 0)
12051 BitMap |= WIFI_BITRATE_54MBPS;
12052 rate = strtok(NULL, ",");
12053 }
12054 *basicRateBitMap = BitMap;
12055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12056 return RETURN_OK;
12057}
12058
developer7c4cd202023-03-01 10:56:29 +080012059INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12060{
12061 int center_channel = 0;
12062 char central_channel_str[16] = {0};
12063 char config_file[32] = {0};
12064 struct params param = {0};
12065
12066 center_channel = util_unii_6g_centerfreq("HT320", channel);
12067 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12068 if (channel >= 193)
12069 return RETURN_ERR;
12070 if (channel >= 33) {
12071 if (channel > center_channel)
12072 center_channel += 32;
12073 else
12074 center_channel -= 32;
12075 }
12076 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12077 if (channel <= 29)
12078 return RETURN_ERR;
12079 }
12080 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12081 param.name = "eht_oper_centr_freq_seg0_idx";
12082 param.value = central_channel_str;
12083 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12084 wifi_hostapdWrite(config_file, &param, 1);
12085
12086 return RETURN_OK;
12087}
12088
12089INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12090{
12091 int op_class = 0;
12092 char config_file[32] = {0};
12093 char op_class_str[8] = {0};
12094 struct params param = {0};
12095
12096 if (bandwidth == 20)
12097 op_class = 131;
12098 else if (bandwidth == 40)
12099 op_class = 132;
12100 else if (bandwidth == 80)
12101 op_class = 133;
12102 else if (bandwidth == 160)
12103 op_class = 134;
12104 else if (bandwidth == 320)
12105 op_class = 137;
12106 else
12107 return RETURN_ERR;
12108 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12109 param.name = "op_class";
12110 param.value = op_class_str;
12111 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12112 wifi_hostapdWrite(config_file, &param, 1);
12113 return RETURN_OK;
12114}
12115
12116INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12117{
12118 char config_file[32] = {0};
12119 char buf [16] = {0};
12120
12121 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12122 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12123 return RETURN_ERR; // 6g band should set op_class
12124 *class = (UINT)strtoul(buf, NULL, 10);
12125
12126 return RETURN_OK;
12127}
12128
developer1e5aa162022-09-13 16:06:24 +080012129// 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 +080012130INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12131{
developer1e5aa162022-09-13 16:06:24 +080012132 char buf[128] = {0};
12133 char cmd[128] = {0};
12134 char config_file[64] = {0};
12135 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012136 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012137 wifi_radio_operationParam_t current_param;
12138
12139 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12140
12141 multiple_set = TRUE;
12142 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12143 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12144 return RETURN_ERR;
12145 }
12146 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12147 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12148 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12149 return RETURN_ERR;
12150 }
12151 }
developer5884e982022-10-06 10:52:50 +080012152
12153 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12154 bandwidth = 20;
12155 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12156 bandwidth = 40;
12157 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12158 bandwidth = 80;
12159 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12160 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012161 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12162 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012163 if (operationParam->autoChannelEnabled){
12164 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12165 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12166 return RETURN_ERR;
12167 }
12168 }else{
developer1e5aa162022-09-13 16:06:24 +080012169 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12170 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12171 return RETURN_ERR;
12172 }
12173 }
developer5884e982022-10-06 10:52:50 +080012174
developer7c4cd202023-03-01 10:56:29 +080012175 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12176 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12177 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12178 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12179 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12180 return RETURN_ERR;
12181 }
12182 }
12183
12184 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12185 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12186 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12187 return RETURN_ERR;
12188 }
12189 }
12190
developer1e5aa162022-09-13 16:06:24 +080012191 if (current_param.variant != operationParam->variant) {
12192 // Two different definition bit map, so need to check every bit.
12193 if (operationParam->variant & WIFI_80211_VARIANT_A)
12194 set_mode |= WIFI_MODE_A;
12195 if (operationParam->variant & WIFI_80211_VARIANT_B)
12196 set_mode |= WIFI_MODE_B;
12197 if (operationParam->variant & WIFI_80211_VARIANT_G)
12198 set_mode |= WIFI_MODE_G;
12199 if (operationParam->variant & WIFI_80211_VARIANT_N)
12200 set_mode |= WIFI_MODE_N;
12201 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12202 set_mode |= WIFI_MODE_AC;
12203 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12204 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012205 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12206 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012207 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12208 memset(buf, 0, sizeof(buf));
12209 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12210 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12211 return RETURN_ERR;
12212 }
12213 }
12214 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12215 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12216 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12217 return RETURN_ERR;
12218 }
12219 }
12220 if (current_param.beaconInterval != operationParam->beaconInterval) {
12221 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12222 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12223 return RETURN_ERR;
12224 }
12225 }
12226 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12227 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12228 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12229 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12230 return RETURN_ERR;
12231 }
12232 }
12233 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12234 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12235 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12236 return RETURN_ERR;
12237 }
12238 }
12239 if (current_param.guardInterval != operationParam->guardInterval) {
12240 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12241 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12242 return RETURN_ERR;
12243 }
12244 }
12245 if (current_param.transmitPower != operationParam->transmitPower) {
12246 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12247 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12248 return RETURN_ERR;
12249 }
12250 }
12251 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12252 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12253 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12254 return RETURN_ERR;
12255 }
12256 }
12257 if (current_param.obssCoex != operationParam->obssCoex) {
12258 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12259 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12260 return RETURN_ERR;
12261 }
12262 }
12263 if (current_param.stbcEnable != operationParam->stbcEnable) {
12264 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12265 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12266 return RETURN_ERR;
12267 }
12268 }
12269 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12270 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12271 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12272 return RETURN_ERR;
12273 }
12274 }
12275
12276 // if enable is true, then restart the radio
12277 wifi_setRadioEnable(index, FALSE);
12278 if (operationParam->enable == TRUE)
12279 wifi_setRadioEnable(index, TRUE);
12280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12281
developer06a01d92022-09-07 16:32:39 +080012282 return RETURN_OK;
12283}
12284
12285INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12286{
developer1e5aa162022-09-13 16:06:24 +080012287 char band[64] = {0};
12288 char buf[256] = {0};
12289 char config_file[64] = {0};
12290 char cmd[128] = {0};
12291 int ret = RETURN_ERR;
12292 int mode = 0;
12293 ULONG channel = 0;
12294 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012295
12296 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12297 printf("Entering %s index = %d\n", __func__, (int)index);
12298
developer1e5aa162022-09-13 16:06:24 +080012299 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12300 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12301 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012302 {
developer1e5aa162022-09-13 16:06:24 +080012303 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012304 return RETURN_ERR;
12305 }
12306 operationParam->enable = enabled;
12307
12308 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012309 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012310 {
developer1e5aa162022-09-13 16:06:24 +080012311 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012312 return RETURN_ERR;
12313 }
12314
12315 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012316 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012317 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012318 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012319 else if (!strcmp(band, "6GHz"))
12320 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012321 else
12322 {
developer1e5aa162022-09-13 16:06:24 +080012323 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012324 band);
12325 }
12326
developer1e5aa162022-09-13 16:06:24 +080012327 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12328 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12329 operationParam->channel = 0;
12330 operationParam->autoChannelEnabled = TRUE;
12331 } else {
12332 operationParam->channel = strtol(buf, NULL, 10);
12333 operationParam->autoChannelEnabled = FALSE;
12334 }
12335
developer06a01d92022-09-07 16:32:39 +080012336 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012337 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12338 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12339 return RETURN_ERR;
12340 }
developer06a01d92022-09-07 16:32:39 +080012341 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12342 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12343 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012344 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012345 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12346 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012347 else
12348 {
developer1e5aa162022-09-13 16:06:24 +080012349 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12350 return false;
developer06a01d92022-09-07 16:32:39 +080012351 }
12352
developer7c4cd202023-03-01 10:56:29 +080012353 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12354 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12355 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12356 return RETURN_ERR;
12357 }
12358 }
12359
developer1e5aa162022-09-13 16:06:24 +080012360 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12361 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12362 return RETURN_ERR;
12363 }
12364 // Two different definition bit map, so need to check every bit.
12365 if (mode & WIFI_MODE_A)
12366 operationParam->variant |= WIFI_80211_VARIANT_A;
12367 if (mode & WIFI_MODE_B)
12368 operationParam->variant |= WIFI_80211_VARIANT_B;
12369 if (mode & WIFI_MODE_G)
12370 operationParam->variant |= WIFI_80211_VARIANT_G;
12371 if (mode & WIFI_MODE_N)
12372 operationParam->variant |= WIFI_80211_VARIANT_N;
12373 if (mode & WIFI_MODE_AC)
12374 operationParam->variant |= WIFI_80211_VARIANT_AC;
12375 if (mode & WIFI_MODE_AX)
12376 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012377 if (mode & WIFI_MODE_BE)
12378 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012379 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12380 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12381 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012382 }
developer1e5aa162022-09-13 16:06:24 +080012383 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12384 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12385 return RETURN_ERR;
12386 }
12387 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12388 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12389 return RETURN_ERR;
12390 }
developer06a01d92022-09-07 16:32:39 +080012391
developer1e5aa162022-09-13 16:06:24 +080012392 memset(buf, 0, sizeof(buf));
12393 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12394 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12395 return RETURN_ERR;
12396 }
12397 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12398
12399 memset(buf, 0, sizeof(buf));
12400 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12401 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12402 return RETURN_ERR;
12403 }
12404 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12405
12406 memset(buf, 0, sizeof(buf));
12407 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12408 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12409
12410 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12411 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12412 return RETURN_ERR;
12413 }
12414 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12415 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12416 return RETURN_ERR;
12417 }
12418
12419 memset(buf, 0, sizeof(buf));
12420 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12421 if (strcmp(buf, "-1") == 0) {
12422 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12423 operationParam->ctsProtection = FALSE;
12424 } else {
12425 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12426 operationParam->ctsProtection = TRUE;
12427 }
12428
12429 memset(buf, 0, sizeof(buf));
12430 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12431 if (strcmp(buf, "0") == 0)
12432 operationParam->obssCoex = FALSE;
12433 else
12434 operationParam->obssCoex = TRUE;
12435
12436 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12437 _syscmd(cmd, buf, sizeof(buf));
12438 if (strlen(buf) != 0)
12439 operationParam->stbcEnable = TRUE;
12440 else
12441 operationParam->stbcEnable = FALSE;
12442
12443 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12444 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12445 return RETURN_ERR;
12446 }
12447
12448 // Below value is hardcoded
12449
12450 operationParam->numSecondaryChannels = 0;
12451 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12452 operationParam->channelSecondary[i] = 0;
12453 }
12454 operationParam->csa_beacon_count = 15;
12455 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012456
12457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12458 return RETURN_OK;
12459}
12460
12461static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12462{
developerc086fb72022-10-04 10:18:22 +080012463 int max_radio_num = 0;
12464
12465 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012466 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012467 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12468 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012469 }
12470
developerc086fb72022-10-04 10:18:22 +080012471 return (arrayIndex * max_radio_num) + radioIndex;
12472}
developer06a01d92022-09-07 16:32:39 +080012473
developerc086fb72022-10-04 10:18:22 +080012474wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12475 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12476 return WIFI_BITRATE_1MBPS;
12477 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12478 return WIFI_BITRATE_2MBPS;
12479 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12480 return WIFI_BITRATE_5_5MBPS;
12481 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12482 return WIFI_BITRATE_6MBPS;
12483 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12484 return WIFI_BITRATE_9MBPS;
12485 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12486 return WIFI_BITRATE_11MBPS;
12487 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12488 return WIFI_BITRATE_12MBPS;
12489 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12490 return WIFI_BITRATE_18MBPS;
12491 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12492 return WIFI_BITRATE_24MBPS;
12493 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12494 return WIFI_BITRATE_36MBPS;
12495 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12496 return WIFI_BITRATE_48MBPS;
12497 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12498 return WIFI_BITRATE_54MBPS;
12499 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012500}
12501
developer1d57d002022-10-12 18:03:15 +080012502INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12503{
12504 if (beacon == WIFI_BITRATE_1MBPS)
12505 strcpy(beacon_str, "1Mbps");
12506 else if (beacon == WIFI_BITRATE_2MBPS)
12507 strcpy(beacon_str, "2Mbps");
12508 else if (beacon == WIFI_BITRATE_5_5MBPS)
12509 strcpy(beacon_str, "5.5Mbps");
12510 else if (beacon == WIFI_BITRATE_6MBPS)
12511 strcpy(beacon_str, "6Mbps");
12512 else if (beacon == WIFI_BITRATE_9MBPS)
12513 strcpy(beacon_str, "9Mbps");
12514 else if (beacon == WIFI_BITRATE_11MBPS)
12515 strcpy(beacon_str, "11Mbps");
12516 else if (beacon == WIFI_BITRATE_12MBPS)
12517 strcpy(beacon_str, "12Mbps");
12518 else if (beacon == WIFI_BITRATE_18MBPS)
12519 strcpy(beacon_str, "18Mbps");
12520 else if (beacon == WIFI_BITRATE_24MBPS)
12521 strcpy(beacon_str, "24Mbps");
12522 else if (beacon == WIFI_BITRATE_36MBPS)
12523 strcpy(beacon_str, "36Mbps");
12524 else if (beacon == WIFI_BITRATE_48MBPS)
12525 strcpy(beacon_str, "48Mbps");
12526 else if (beacon == WIFI_BITRATE_54MBPS)
12527 strcpy(beacon_str, "54Mbps");
12528 return RETURN_OK;
12529}
12530
developer06a01d92022-09-07 16:32:39 +080012531INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12532{
developerc086fb72022-10-04 10:18:22 +080012533 INT mode = 0;
12534 INT ret = -1;
12535 INT output = 0;
12536 int i = 0;
12537 int vap_index = 0;
12538 BOOL enabled = FALSE;
12539 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012540 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012541
developer06a01d92022-09-07 16:32:39 +080012542
12543 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12544 printf("Entering %s index = %d\n", __func__, (int)index);
12545
developera77d84b2023-02-22 16:10:50 +080012546 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012547 {
developerc086fb72022-10-04 10:18:22 +080012548 map->vap_array[i].radio_index = index;
12549
developer06a01d92022-09-07 16:32:39 +080012550 vap_index = array_index_to_vap_index(index, i);
12551 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012552 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012553
developerc086fb72022-10-04 10:18:22 +080012554 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012555
12556 map->vap_array[i].vap_index = vap_index;
12557
12558 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012559 ret = wifi_getApName(vap_index, buf);
12560 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012561 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12562
developerc086fb72022-10-04 10:18:22 +080012563 return RETURN_ERR;
12564 }
12565 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12566
12567 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012568 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012569 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012570 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012571 return RETURN_ERR;
12572 }
12573 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 +080012574
12575 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012576 if (ret != RETURN_OK) {
12577 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012578 return RETURN_ERR;
12579 }
12580 map->vap_array[i].u.bss_info.enabled = enabled;
12581
developerc086fb72022-10-04 10:18:22 +080012582 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12583 if (ret != RETURN_OK) {
12584 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12585 return RETURN_ERR;
12586 }
developer06a01d92022-09-07 16:32:39 +080012587 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012588
12589 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12590 if (ret != RETURN_OK) {
12591 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12592 return RETURN_ERR;
12593 }
12594 map->vap_array[i].u.bss_info.isolation = enabled;
12595
12596 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12597 if (ret != RETURN_OK) {
12598 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12599 return RETURN_ERR;
12600 }
12601 map->vap_array[i].u.bss_info.bssMaxSta = output;
12602
12603 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12604 if (ret != RETURN_OK) {
12605 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12606 return RETURN_ERR;
12607 }
12608 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012609
developerc086fb72022-10-04 10:18:22 +080012610 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12611 if (ret != RETURN_OK) {
12612 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12613 return RETURN_ERR;
12614 }
12615 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012616
developerc086fb72022-10-04 10:18:22 +080012617 ret = wifi_getApSecurity(vap_index, &security);
12618 if (ret != RETURN_OK) {
12619 printf("%s: wifi_getApSecurity return error\n", __func__);
12620 return RETURN_ERR;
12621 }
12622 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012623
developerc086fb72022-10-04 10:18:22 +080012624 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12625 if (ret != RETURN_OK) {
12626 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12627 return RETURN_ERR;
12628 }
12629 if (mode == 0)
12630 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12631 else
12632 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12633 if (mode == 1)
12634 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12635 else if (mode == 2)
12636 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012637
developerc086fb72022-10-04 10:18:22 +080012638 ret = wifi_getApWmmEnable(vap_index, &enabled);
12639 if (ret != RETURN_OK) {
12640 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12641 return RETURN_ERR;
12642 }
12643 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012644
developerc086fb72022-10-04 10:18:22 +080012645 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12646 if (ret != RETURN_OK) {
12647 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012648 return RETURN_ERR;
12649 }
developerc086fb72022-10-04 10:18:22 +080012650 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012651
12652 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012653 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012654 if (ret != RETURN_OK) {
12655 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12656 return RETURN_ERR;
12657 }
12658 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012659
developerc086fb72022-10-04 10:18:22 +080012660 memset(buf, 0, sizeof(buf));
12661 ret = wifi_getBaseBSSID(vap_index, buf);
12662 if (ret != RETURN_OK) {
12663 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12664 return RETURN_ERR;
12665 }
12666 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12667 &map->vap_array[i].u.bss_info.bssid[0],
12668 &map->vap_array[i].u.bss_info.bssid[1],
12669 &map->vap_array[i].u.bss_info.bssid[2],
12670 &map->vap_array[i].u.bss_info.bssid[3],
12671 &map->vap_array[i].u.bss_info.bssid[4],
12672 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012673 // 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]);
12674
12675 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12676 if (ret != RETURN_OK) {
12677 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12678 return RETURN_ERR;
12679 }
12680 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developera77d84b2023-02-22 16:10:50 +080012681 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012682 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012683 }
12684 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12685 return RETURN_OK;
12686}
12687
developer431128d2022-12-16 15:30:41 +080012688void checkVapStatus(int apIndex, bool *enable)
12689{
12690 char if_name[16] = {0};
12691 char cmd[128] = {0};
12692 char buf[128] = {0};
12693
12694 *enable = FALSE;
developerac6f1142022-12-20 19:26:35 +080012695 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
developer431128d2022-12-16 15:30:41 +080012696 return;
12697
12698 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12699 _syscmd(cmd, buf, sizeof(buf));
12700 if (strlen(buf) > 0)
12701 *enable = TRUE;
12702 return;
12703}
12704
developerd946fd62022-12-08 18:03:28 +080012705static int prepareInterface(UINT apIndex, char *new_interface)
12706{
12707 char cur_interface[16] = {0};
12708 char config_file[128] = {0};
12709 char cmd[128] = {0};
12710 char buf[16] = {0};
12711 int max_radio_num = 0;
12712 int radioIndex = -1;
12713 int phyIndex = -1;
12714
12715 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12716 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12717
12718 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12719 wifi_getMaxRadioNumber(&max_radio_num);
12720 radioIndex = apIndex % max_radio_num;
12721 phyIndex = radio_index_to_phy(radioIndex);
12722 // disable and del old interface, then add new interface
12723 wifi_setApEnable(apIndex, FALSE);
developer431128d2022-12-16 15:30:41 +080012724 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
developerd946fd62022-12-08 18:03:28 +080012725 _syscmd(cmd, buf, sizeof(buf));
12726 }
developer431128d2022-12-16 15:30:41 +080012727 // update the vap status file
12728 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12729 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012730 return RETURN_OK;
12731}
12732
developer06a01d92022-09-07 16:32:39 +080012733INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12734{
developerd946fd62022-12-08 18:03:28 +080012735 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012736 unsigned int i;
12737 wifi_vap_info_t *vap_info = NULL;
12738 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012739 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012740 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012741 char buf[256] = {0};
12742 char cmd[128] = {0};
12743 char config_file[64] = {0};
12744 char bssid[32] = {0};
12745 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012746 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012747
12748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12749 printf("Entering %s index = %d\n", __func__, (int)index);
12750 for (i = 0; i < map->num_vaps; i++)
12751 {
developer1d57d002022-10-12 18:03:15 +080012752 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012753 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012754
12755 // Check vap status file to enable multiple ap if the system boot.
12756 checkVapStatus(vap_info->vap_index, &enable);
12757 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012758 continue;
developer06a01d92022-09-07 16:32:39 +080012759
developer1d57d002022-10-12 18:03:15 +080012760 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12761
developer431128d2022-12-16 15:30:41 +080012762 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12763 enable = FALSE;
12764
12765 // multi-ap first up need to copy current radio config
12766 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012767 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12768 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012769 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12770 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12771 } else {
12772 // Check whether the interface name is valid or this ap change it.
12773 int apIndex = -1;
12774 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12775 if (apIndex != -1 && apIndex != vap_info->vap_index)
12776 continue;
12777 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012778 }
developer06a01d92022-09-07 16:32:39 +080012779
developer1d57d002022-10-12 18:03:15 +080012780 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012781 params[0].name = "interface";
12782 params[0].value = vap_info->vap_name;
12783 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12784 params[1].name = "bssid";
12785 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012786 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012787 params[2].name = "wpa_psk_file";
12788 params[2].value = psk_file;
12789
12790 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12791 wifi_hostapdWrite(config_file, params, 3);
12792
12793 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12794 _syscmd(cmd, buf, sizeof(buf));
12795
12796 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12797 if (ret != RETURN_OK) {
12798 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12799 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012800 }
developer1d57d002022-10-12 18:03:15 +080012801
12802 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12803 if (ret != RETURN_OK) {
12804 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12805 return RETURN_ERR;
12806 }
12807
12808 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12809 if (ret != RETURN_OK) {
12810 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12811 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012812 }
12813
developer1d57d002022-10-12 18:03:15 +080012814 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12815 if (ret != RETURN_OK) {
12816 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12817 return RETURN_ERR;
12818 }
developer06a01d92022-09-07 16:32:39 +080012819
developer1d57d002022-10-12 18:03:15 +080012820 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12821 if (ret != RETURN_OK) {
12822 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12823 return RETURN_ERR;
12824 }
developer06a01d92022-09-07 16:32:39 +080012825
developer1d57d002022-10-12 18:03:15 +080012826 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12827 if (ret != RETURN_OK) {
12828 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12829 return RETURN_ERR;
12830 }
12831
developer804c64f2022-10-19 13:54:40 +080012832 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012833 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012834 }else {
12835 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012836 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012837 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12838 _syscmd(cmd, buf, sizeof(buf));
12839 }else{
developer1d57d002022-10-12 18:03:15 +080012840 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012841 }
developer1d57d002022-10-12 18:03:15 +080012842 }
12843
12844 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12845 if (ret != RETURN_OK) {
12846 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12847 return RETURN_ERR;
12848 }
12849
12850 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12851 if (ret != RETURN_OK) {
12852 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12853 return RETURN_ERR;
12854 }
12855
12856 memset(buf, 0, sizeof(buf));
12857 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12858 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12859 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12860 if (ret != RETURN_OK) {
12861 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12862 return RETURN_ERR;
12863 }
12864
12865 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12866 if (ret != RETURN_OK) {
12867 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12868 return RETURN_ERR;
12869 }
12870
developer1d57d002022-10-12 18:03:15 +080012871 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12872 if (ret != RETURN_OK) {
12873 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12874 return RETURN_ERR;
12875 }
12876
12877 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12878 if (ret != RETURN_OK) {
12879 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12880 return RETURN_ERR;
12881 }
developer06a01d92022-09-07 16:32:39 +080012882
developer2f995fb2023-02-24 10:40:44 +080012883 wifi_setApEnable(vap_info->vap_index, FALSE);
12884 wifi_setApEnable(vap_info->vap_index, TRUE);
12885 multiple_set = FALSE;
12886
12887 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12888
developer1d57d002022-10-12 18:03:15 +080012889 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012890 }
12891 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12892 return RETURN_OK;
12893}
12894
12895int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12896{
12897 char *token, *next;
12898 const char s[2] = ",";
12899 int count =0;
12900
12901 /* get the first token */
12902 token = strtok_r(pchannels, s, &next);
12903
12904 /* walk through other tokens */
12905 while( token != NULL && count < MAX_CHANNELS) {
12906 chlistptr->channels_list[count++] = atoi(token);
12907 token = strtok_r(NULL, s, &next);
12908 }
12909
12910 return count;
12911}
12912
12913static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12914{
12915 INT status;
12916 wifi_channels_list_t *chlistp;
12917 CHAR output_string[64];
12918 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080012919 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080012920 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080012921
12922 if(rcap == NULL)
12923 {
12924 return RETURN_ERR;
12925 }
12926
12927 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012928 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012929
developer1e5aa162022-09-13 16:06:24 +080012930 if (band == band_2_4)
12931 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12932 else if (band == band_5)
12933 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12934 else if (band == band_6)
12935 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012936
12937 chlistp = &(rcap->channel_list[0]);
12938 memset(pchannels, 0, sizeof(pchannels));
12939
12940 /* possible number of radio channels */
12941 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12942 {
12943 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12944 }
12945 /* Number of channels and list*/
12946 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12947
12948 /* autoChannelSupported */
12949 /* always ON with wifi_getRadioAutoChannelSupported */
12950 rcap->autoChannelSupported = TRUE;
12951
12952 /* DCSSupported */
12953 /* always ON with wifi_getRadioDCSSupported */
12954 rcap->DCSSupported = TRUE;
12955
12956 /* zeroDFSSupported - TBD */
12957 rcap->zeroDFSSupported = FALSE;
12958
12959 /* Supported Country List*/
12960 memset(output_string, 0, sizeof(output_string));
12961 status = wifi_getRadioCountryCode(radioIndex, output_string);
12962 if( status != 0 ) {
12963 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12964 return RETURN_ERR;
12965 } else {
12966 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12967 }
12968 if(!strcmp(output_string,"US")){
12969 rcap->countrySupported[0] = wifi_countrycode_US;
12970 rcap->countrySupported[1] = wifi_countrycode_CA;
12971 } else if (!strcmp(output_string,"CA")) {
12972 rcap->countrySupported[0] = wifi_countrycode_CA;
12973 rcap->countrySupported[1] = wifi_countrycode_US;
12974 } else {
12975 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12976 }
12977
12978 rcap->numcountrySupported = 2;
12979
12980 /* csi */
12981 rcap->csi.maxDevices = 8;
12982 rcap->csi.soudingFrameSupported = TRUE;
12983
developer7930d352022-12-21 17:55:42 +080012984 wifi_GetInterfaceName(radioIndex, interface_name);
12985 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080012986
12987 /* channelWidth - all supported bandwidths */
12988 int i=0;
12989 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080012990
12991 /* mode - all supported variants */
12992 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12993 wifi_getRadioSupportedStandards(radioIndex, output_string);
12994
developer06a01d92022-09-07 16:32:39 +080012995 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12996 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12997 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080012998 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080012999
developer7c4cd202023-03-01 10:56:29 +080013000 if (strstr(output_string, "n") != NULL)
13001 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13002 if (strstr(output_string, "ax") != NULL)
13003 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13004 if (strstr(output_string, "be") != NULL)
13005 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13006 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013007 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13008 WIFI_CHANNELBANDWIDTH_40MHZ |
13009 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013010 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013011
developer7c4cd202023-03-01 10:56:29 +080013012 if (strstr(output_string, "n") != NULL)
13013 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13014 if (strstr(output_string, "ac") != NULL)
13015 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13016 if (strstr(output_string, "ax") != NULL)
13017 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13018 if (strstr(output_string, "be") != NULL)
13019 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13020 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13021 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13022 WIFI_CHANNELBANDWIDTH_40MHZ |
13023 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013024 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013025
13026 if (strstr(output_string, "be") != NULL) {
13027 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13028 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13029 }
developer06a01d92022-09-07 16:32:39 +080013030 }
developer7c4cd202023-03-01 10:56:29 +080013031
developer06a01d92022-09-07 16:32:39 +080013032 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13033 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13034
13035 /* supportedBitRate - all supported bitrates */
13036 rcap->supportedBitRate[i] = 0;
13037 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13038 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13039 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13040 }
developer1e5aa162022-09-13 16:06:24 +080013041 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013042 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13043 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13044 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13045 }
13046
13047
13048 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13049 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13050 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13051 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13052 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13053 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13054 rcap->cipherSupported = 0;
13055 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13056 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13057
13058 return RETURN_OK;
13059}
13060
13061INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13062{
developer30423732022-12-01 16:17:49 +080013063 INT status = 0, radioIndex = 0;
13064 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013065 int iter = 0;
developer30423732022-12-01 16:17:49 +080013066 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013067 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013068 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013069
13070 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13071
13072 memset(cap, 0, sizeof(wifi_hal_capability_t));
13073
13074 /* version */
13075 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13076 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13077
13078 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013079 wifi_getMaxRadioNumber(&max_num_radios);
13080 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013081
13082 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13083 {
13084 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13085 if (status != 0) {
13086 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13087 return RETURN_ERR;
13088 }
13089
13090 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13091 {
developer804c64f2022-10-19 13:54:40 +080013092 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013093 {
13094 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13095 return RETURN_ERR;
13096 }
13097 iface_info = &cap->wifi_prop.interface_map[iter];
13098 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13099 iface_info->rdk_radio_index = radioIndex;
13100 memset(output, 0, sizeof(output));
13101 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13102 {
13103 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13104 }
13105 // TODO: bridge name
13106 // TODO: vlan id
13107 // TODO: primary
13108 iface_info->index = array_index_to_vap_index(radioIndex, j);
13109 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013110 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013111 {
13112 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13113 }
13114 iter++;
13115 }
13116 }
13117
13118 cap->BandSteeringSupported = FALSE;
13119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13120 return RETURN_OK;
13121}
13122
developer9df4e652022-10-11 11:27:38 +080013123INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13124{
13125 struct params h_config={0};
13126 char config_file[64] = {0};
13127
13128 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13129
13130 h_config.name = "okc";
13131 h_config.value = okc_enable?"1":"0";
13132
13133 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13134 wifi_hostapdWrite(config_file, &h_config, 1);
13135 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13136
13137 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13138 return RETURN_OK;
13139}
13140
13141INT wifi_setSAEMFP(int ap_index, BOOL enable)
13142{
13143 struct params h_config={0};
13144 char config_file[64] = {0};
13145 char buf[128] = {0};
13146
13147 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13148
13149 h_config.name = "sae_require_mfp";
13150 h_config.value = enable?"1":"0";
13151
13152 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13153 wifi_hostapdWrite(config_file, &h_config, 1);
13154 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13155
13156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13157 return RETURN_OK;
13158}
13159
13160INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13161{
13162 struct params h_config={0};
13163 char config_file[64] = {0};
13164 char buf[128] = {0};
13165
13166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13167
13168 h_config.name = "sae_pwe";
13169 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13170 h_config.value = buf;
13171
13172 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13173 wifi_hostapdWrite(config_file, &h_config, 1);
13174 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13175
13176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13177 return RETURN_OK;
13178}
13179
13180INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13181{
13182 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13183 struct params h_config={0};
13184 char config_file[64] = {0};
13185
13186 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13187
13188 h_config.name = "wpa_disable_eapol_key_retries";
13189 h_config.value = disable_EAPOL_retries?"1":"0";
13190
13191 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13192 wifi_hostapdWrite(config_file, &h_config, 1);
13193 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13194
13195 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13196 return RETURN_OK;
13197}
13198
developer06a01d92022-09-07 16:32:39 +080013199INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13200{
developer587c1b62022-09-27 15:58:59 +080013201 char buf[128] = {0};
13202 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013203 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013204 char password[64] = {0};
13205 char mfp[32] = {0};
13206 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013207 BOOL okc_enable = FALSE;
13208 BOOL sae_MFP = FALSE;
13209 BOOL disable_EAPOL_retries = TRUE;
13210 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013211 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013212 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013213
13214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13215
13216 multiple_set = TRUE;
13217 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13218 if (security->mode == wifi_security_mode_none) {
13219 strcpy(wpa_mode, "None");
13220 } else if (security->mode == wifi_security_mode_wpa_personal)
13221 strcpy(wpa_mode, "WPA-Personal");
13222 else if (security->mode == wifi_security_mode_wpa2_personal)
13223 strcpy(wpa_mode, "WPA2-Personal");
13224 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13225 strcpy(wpa_mode, "WPA-WPA2-Personal");
13226 else if (security->mode == wifi_security_mode_wpa_enterprise)
13227 strcpy(wpa_mode, "WPA-Enterprise");
13228 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13229 strcpy(wpa_mode, "WPA2-Enterprise");
13230 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13231 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013232 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013233 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013234 okc_enable = TRUE;
13235 sae_MFP = TRUE;
13236 sae_pwe = 2;
13237 disable_EAPOL_retries = FALSE;
13238 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013239 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013240 okc_enable = TRUE;
13241 sae_MFP = TRUE;
13242 sae_pwe = 2;
13243 disable_EAPOL_retries = FALSE;
13244 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013245 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013246 sae_MFP = TRUE;
13247 sae_pwe = 2;
13248 disable_EAPOL_retries = FALSE;
developer5c9fee82023-01-13 14:44:16 +080013249 } else if (security->mode == wifi_security_mode_owe) {
13250 strcpy(wpa_mode, "OWE");
13251 sae_MFP = TRUE;
13252 sae_pwe = 2;
13253 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013254 }
13255
13256 band = wifi_index_to_band(ap_index);
13257 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13258 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13259 return RETURN_ERR;
13260 }
developer587c1b62022-09-27 15:58:59 +080013261
13262 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013263 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013264 wifi_setSAEMFP(ap_index, sae_MFP);
13265 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013266 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013267
developer23e71282023-01-18 10:25:19 +080013268 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_owe) {
developer4b102122023-02-15 10:53:03 +080013269 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) {
13270 int key_len = strlen(security->u.key.key);
13271 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13272 if (key_len == 64) { // set wpa_psk
13273 strncpy(password, security->u.key.key, 64); // 64 characters
13274 password[64] = '\0';
13275 wifi_setApSecurityPreSharedKey(ap_index, password);
13276 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13277 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13278 strncpy(password, security->u.key.key, 63);
13279 password[63] = '\0';
13280 wifi_setApSecurityKeyPassphrase(ap_index, password);
13281 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13282 } else
13283 return RETURN_ERR;
13284 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013285 }
13286 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13287 params.name = "sae_password";
13288 params.value = security->u.key.key;
13289 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013290 } else { // remove sae_password
13291 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13292 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013293 }
13294 }
developer587c1b62022-09-27 15:58:59 +080013295
13296 if (security->mode != wifi_security_mode_none) {
13297 memset(&params, 0, sizeof(params));
13298 params.name = "wpa_pairwise";
13299 if (security->encr == wifi_encryption_tkip)
13300 params.value = "TKIP";
13301 else if (security->encr == wifi_encryption_aes)
13302 params.value = "CCMP";
13303 else if (security->encr == wifi_encryption_aes_tkip)
13304 params.value = "TKIP CCMP";
13305 wifi_hostapdWrite(config_file, &params, 1);
13306 }
13307
13308 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013309 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013310 else if (security->mfp == wifi_mfp_cfg_optional)
13311 strcpy(mfp, "Optional");
13312 else if (security->mfp == wifi_mfp_cfg_required)
13313 strcpy(mfp, "Required");
13314 wifi_setApSecurityMFPConfig(ap_index, mfp);
13315
13316 memset(&params, 0, sizeof(params));
13317 params.name = "transition_disable";
13318 if (security->wpa3_transition_disable == TRUE)
13319 params.value = "0x01";
13320 else
13321 params.value = "0x00";
13322 wifi_hostapdWrite(config_file, &params, 1);
13323
13324 memset(&params, 0, sizeof(params));
13325 params.name = "wpa_group_rekey";
13326 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13327 params.value = buf;
13328 wifi_hostapdWrite(config_file, &params, 1);
13329
13330 memset(&params, 0, sizeof(params));
13331 params.name = "wpa_strict_rekey";
13332 params.value = security->strict_rekey?"1":"0";
13333 wifi_hostapdWrite(config_file, &params, 1);
13334
13335 memset(&params, 0, sizeof(params));
13336 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013337 if (security->eapol_key_retries == 0)
13338 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013339 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13340 params.value = buf;
13341 wifi_hostapdWrite(config_file, &params, 1);
13342
13343 memset(&params, 0, sizeof(params));
13344 params.name = "disable_pmksa_caching";
13345 params.value = security->disable_pmksa_caching?"1":"0";
13346 wifi_hostapdWrite(config_file, &params, 1);
13347
developer23e71282023-01-18 10:25:19 +080013348 if (multiple_set == FALSE) {
13349 wifi_setApEnable(ap_index, FALSE);
13350 wifi_setApEnable(ap_index, TRUE);
13351 }
developer587c1b62022-09-27 15:58:59 +080013352
13353 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13354
developer06a01d92022-09-07 16:32:39 +080013355 return RETURN_OK;
13356}
13357
13358INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13359{
developer9df4e652022-10-11 11:27:38 +080013360 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013361 char config_file[128] = {0};
13362 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013363 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013364
13365 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13366 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13367 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13368 security->mode = wifi_security_mode_none;
13369 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013370 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013371 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013372 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013373 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013374 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013375 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013376 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013377 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013378 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013379 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013380 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013381 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013382 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013383 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013384 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013385 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013386 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013387 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013388 else if (!strcmp(buf, "OWE"))
13389 security->mode = wifi_security_mode_owe;
developer587c1b62022-09-27 15:58:59 +080013390 }
13391
13392 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13393 if (security->mode == wifi_security_mode_none)
13394 security->encr = wifi_encryption_none;
13395 else {
13396 if (strcmp(buf, "TKIP") == 0)
13397 security->encr = wifi_encryption_tkip;
13398 else if (strcmp(buf, "CCMP") == 0)
13399 security->encr = wifi_encryption_aes;
13400 else
13401 security->encr = wifi_encryption_aes_tkip;
13402 }
13403
developer9df4e652022-10-11 11:27:38 +080013404 if (security->mode != wifi_encryption_none) {
13405 memset(buf, 0, sizeof(buf));
13406 // wpa3 can use one or both configs as password, so we check sae_password first.
13407 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013408 if (strlen(buf) != 0) {
13409 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13410 security->u.key.type = wifi_security_key_type_sae;
13411 set_sae = TRUE;
13412 strncpy(security->u.key.key, buf, sizeof(buf));
13413 }
13414 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13415 if (strlen(buf) != 0){
13416 if (set_sae == TRUE)
13417 security->u.key.type = wifi_security_key_type_psk_sae;
13418 else if (strlen(buf) == 64)
13419 security->u.key.type = wifi_security_key_type_psk;
13420 else
13421 security->u.key.type = wifi_security_key_type_pass;
13422 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013423 }
developer9df4e652022-10-11 11:27:38 +080013424 security->u.key.key[255] = '\0';
13425 }
13426
developer587c1b62022-09-27 15:58:59 +080013427 memset(buf, 0, sizeof(buf));
13428 wifi_getApSecurityMFPConfig(ap_index, buf);
13429 if (strcmp(buf, "Disabled") == 0)
13430 security->mfp = wifi_mfp_cfg_disabled;
13431 else if (strcmp(buf, "Optional") == 0)
13432 security->mfp = wifi_mfp_cfg_optional;
13433 else if (strcmp(buf, "Required") == 0)
13434 security->mfp = wifi_mfp_cfg_required;
13435
13436 memset(buf, 0, sizeof(buf));
13437 security->wpa3_transition_disable = FALSE;
13438 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13439 disable = strtol(buf, NULL, 16);
13440 if (disable != 0)
13441 security->wpa3_transition_disable = TRUE;
13442
13443 memset(buf, 0, sizeof(buf));
13444 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13445 if (strlen(buf) == 0)
13446 security->rekey_interval = 86400;
13447 else
13448 security->rekey_interval = strtol(buf, NULL, 10);
13449
13450 memset(buf, 0, sizeof(buf));
13451 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13452 if (strlen(buf) == 0)
13453 security->strict_rekey = 1;
13454 else
13455 security->strict_rekey = strtol(buf, NULL, 10);
13456
13457 memset(buf, 0, sizeof(buf));
13458 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13459 if (strlen(buf) == 0)
13460 security->eapol_key_retries = 4;
13461 else
13462 security->eapol_key_retries = strtol(buf, NULL, 10);
13463
13464 memset(buf, 0, sizeof(buf));
13465 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13466 if (strlen(buf) == 0)
13467 security->disable_pmksa_caching = FALSE;
13468 else
13469 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13470
13471 /* TODO
13472 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13473 */
13474 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13475 security->eap_identity_req_timeout = 0;
13476 security->eap_identity_req_retries = 0;
13477 security->eap_req_timeout = 0;
13478 security->eap_req_retries = 0;
13479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013480 return RETURN_OK;
13481}
13482
13483#endif /* WIFI_HAL_VERSION_3 */
13484
13485#ifdef WIFI_HAL_VERSION_3_PHASE2
13486INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13487{
developerd946fd62022-12-08 18:03:28 +080013488 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013489 char cmd[128] = {0};
13490 char buf[128] = {0};
13491 char *mac_addr = NULL;
13492 BOOL status = FALSE;
13493 size_t len = 0;
13494
13495 if(ap_index > MAX_APS)
13496 return RETURN_ERR;
13497
13498 *output_numDevices = 0;
13499 wifi_getApEnable(ap_index, &status);
13500 if (status == FALSE)
13501 return RETURN_OK;
13502
developerac6f1142022-12-20 19:26:35 +080013503 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013504 return RETURN_ERR;
13505 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013506 _syscmd(cmd, buf, sizeof(buf));
13507
13508 mac_addr = strtok(buf, "\n");
13509 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13510 *output_numDevices = i + 1;
13511 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13512 addr_ptr = output_deviceMacAddressArray[i];
13513 mac_addr_aton(addr_ptr, mac_addr);
13514 mac_addr = strtok(NULL, "\n");
13515 }
13516
13517 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013518}
13519#else
13520INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13521{
developerd946fd62022-12-08 18:03:28 +080013522 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013523 char cmd[128];
13524 BOOL status = false;
13525
13526 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13527 return RETURN_ERR;
13528
13529 output_buf[0] = '\0';
13530
13531 wifi_getApEnable(ap_index,&status);
13532 if (!status)
13533 return RETURN_OK;
13534
developerac6f1142022-12-20 19:26:35 +080013535 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013536 return RETURN_ERR;
13537 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013538 _syscmd(cmd, output_buf, output_buf_size);
13539
13540 return RETURN_OK;
13541}
13542#endif
developer2f513ab2022-09-13 14:26:06 +080013543
13544INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13545{
13546 char output[16]={'\0'};
13547 char config_file[MAX_BUF_SIZE] = {0};
13548
13549 if (!enable)
13550 return RETURN_ERR;
13551
13552 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13553 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13554
13555 if (strlen(output) == 0)
13556 *enable = FALSE;
13557 else if (strncmp(output, "1", 1) == 0)
13558 *enable = TRUE;
13559 else
13560 *enable = FALSE;
13561
13562 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13563 return RETURN_OK;
13564}
developer2d9c30f2022-09-13 15:06:14 +080013565
13566INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13567{
developer804c64f2022-10-19 13:54:40 +080013568 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013569 return RETURN_ERR;
13570 *output_enable=TRUE;
13571 return RETURN_OK;
13572}
developerfd7d2892022-09-13 16:44:53 +080013573
13574INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13575{
13576 char cmd[128] = {0};
13577 char buf[128] = {0};
13578 char line[128] = {0};
13579 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013580 FILE *f = NULL;
13581 int index = 0;
13582 int exp = 0;
13583 int mantissa = 0;
13584 int duration = 0;
13585 int radio_index = 0;
13586 int max_radio_num = 0;
13587 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013588 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013589 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13590
13591 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013592
developerfd7d2892022-09-13 16:44:53 +080013593 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013594
13595 phyId = radio_index_to_phy(radio_index);
13596 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013597 _syscmd(cmd, buf, sizeof(buf));
13598 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13599 if (*numSessionReturned > maxNumberSessions)
13600 *numSessionReturned = maxNumberSessions;
13601 else if (*numSessionReturned < 1) {
13602 *numSessionReturned = 0;
13603 return RETURN_OK;
13604 }
13605
developer033b37b2022-10-18 11:27:46 +080013606 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 +080013607 if ((f = popen(cmd, "r")) == NULL) {
13608 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13609 return RETURN_ERR;
13610 }
13611
13612 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013613 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013614 char *tmp = NULL;
13615 strcpy(buf, line);
13616 tmp = strtok(buf, " ");
13617 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13618 tmp = strtok(NULL, " ");
13619 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13620 tmp = strtok(NULL, " ");
13621 if (strstr(tmp, "t")) {
13622 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13623 }
13624 if (strstr(tmp, "a")) {
13625 twtSessions[index].twtParameters.operation.announced = TRUE;
13626 }
13627 tmp = strtok(NULL, " ");
13628 exp = strtol(tmp, NULL, 10);
13629 tmp = strtok(NULL, " ");
13630 mantissa = strtol(tmp, NULL, 10);
13631 tmp = strtok(NULL, " ");
13632 duration = strtol(tmp, NULL, 10);
13633
13634 // only implicit supported
13635 twtSessions[index].twtParameters.operation.implicit = TRUE;
13636 // only individual agreement supported
13637 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13638
13639 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13640 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013641 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013642 // Overflow handling
13643 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13644 } else {
13645 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13646 }
13647 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13648 index++;
13649 }
13650
13651 pclose(f);
13652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13653 return RETURN_OK;
13654}