blob: ff1a4f830ed35d0f6bfc95c9b5b05151a7feeb85 [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
66#define MAX_BUF_SIZE 128
67#define MAX_CMD_SIZE 1024
68#define MAX_POSSIBLE_CHANNEL_STRING_BUF 512
69#define IF_NAME_SIZE 50
70#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080071#define ACL_PREFIX "/nvram/hostapd-acl"
72#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080073//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080075#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080076#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080077#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080081#define PSK_FILE "/nvram/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
developer06a01d92022-09-07 16:32:39 +0800100
developer033b37b2022-10-18 11:27:46 +0800101
developer804c64f2022-10-19 13:54:40 +0800102#define MAX_APS MAX_NUM_RADIOS*5
developer06a01d92022-09-07 16:32:39 +0800103#ifndef AP_PREFIX
104#define AP_PREFIX "wifi"
105#endif
106
107#ifndef RADIO_PREFIX
108#define RADIO_PREFIX "wlan"
109#endif
110
111#define MAX_BUF_SIZE 128
112#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800113#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800114
115//Uncomment to enable debug logs
116//#define WIFI_DEBUG
117
118#ifdef WIFI_DEBUG
119#define wifi_dbg_printf printf
120#define WIFI_ENTRY_EXIT_DEBUG printf
121#else
122#define wifi_dbg_printf(format, args...) printf("")
123#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
124#endif
125
126#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
127#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
128#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
129#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
130#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
131#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
132#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
133#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
134#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
135#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
136
developer4fb0b922022-09-30 14:29:09 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800138
139#define BW_FNAME "/nvram/bw_file.txt"
140
141#define PS_MAX_TID 16
142
143static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
145 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
148 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
150 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
153 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
156 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
158 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
160};
161
162typedef unsigned long long u64;
163
164/* Enum to define WiFi Bands */
165typedef enum
166{
167 band_invalid = -1,
168 band_2_4 = 0,
169 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800170 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800171} wifi_band;
172
developerdb744382022-09-13 15:34:54 +0800173typedef enum {
174 WIFI_MODE_A = 0x01,
175 WIFI_MODE_B = 0x02,
176 WIFI_MODE_G = 0x04,
177 WIFI_MODE_N = 0x08,
178 WIFI_MODE_AC = 0x10,
179 WIFI_MODE_AX = 0x20,
180} wifi_ieee80211_Mode;
181
developer06a01d92022-09-07 16:32:39 +0800182#ifdef WIFI_HAL_VERSION_3
183
184// Return number of elements in array
185#ifndef ARRAY_SIZE
186#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187#endif /* ARRAY_SIZE */
188
189#ifndef ARRAY_AND_SIZE
190#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
191#endif /* ARRAY_AND_SIZE */
192
193#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
194
195typedef struct {
196 int32_t value;
197 int32_t param;
198 intptr_t key;
199 intptr_t data;
200} wifi_secur_list;
201
202wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
203wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
204char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800205static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800206
207static wifi_secur_list map_security[] =
208{
209 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800219 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800220 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800221};
222
223wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
224{
225 wifi_secur_list *item;
226 int i;
227
228 for (item = list,i = 0;i < list_sz; item++, i++) {
229 if ((int)(item->key) == key) {
230 return item;
231 }
232 }
233
234 return NULL;
235}
236
237char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
238{
239 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
240
241 if (!item) {
242 return "";
243 }
244
245 return (char *)(item->data);
246}
247
248wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
249{
250 wifi_secur_list *item;
251 int i;
252
253 for (item = list,i = 0;i < list_sz; item++, i++) {
254 if (strcmp((char *)(item->data), str) == 0) {
255 return item;
256 }
257 }
258
259 return NULL;
260}
261#endif /* WIFI_HAL_VERSION_3 */
262
263#ifdef HAL_NETLINK_IMPL
264typedef struct {
265 int id;
266 struct nl_sock* socket;
267 struct nl_cb* cb;
268} Netlink;
269
270static int mac_addr_aton(unsigned char *mac_addr, char *arg)
271{
272 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800273 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 +0800274 mac_addr[0] = mac_addr_int[0];
275 mac_addr[1] = mac_addr_int[1];
276 mac_addr[2] = mac_addr_int[2];
277 mac_addr[3] = mac_addr_int[3];
278 mac_addr[4] = mac_addr_int[4];
279 mac_addr[5] = mac_addr_int[5];
280 return 0;
281}
282
283static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
284{
285 unsigned int mac_addr_int[6]={};
286 mac_addr_int[0] = arg[0];
287 mac_addr_int[1] = arg[1];
288 mac_addr_int[2] = arg[2];
289 mac_addr_int[3] = arg[3];
290 mac_addr_int[4] = arg[4];
291 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800292 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 +0800293 return;
294}
295
296static int ieee80211_frequency_to_channel(int freq)
297{
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800299 if (freq == 2484)
300 return 14;
developerf5745ee2022-10-05 16:09:53 +0800301 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
302 else if (freq == 5935)
303 return 2;
developer06a01d92022-09-07 16:32:39 +0800304 else if (freq < 2484)
305 return (freq - 2407) / 5;
306 else if (freq >= 4910 && freq <= 4980)
307 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800308 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800309 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800310 else if (freq <= 45000) /* DMG band lower limit */
311 /* see 802.11ax D6.1 27.3.23.2 */
312 return (freq - 5950) / 5;
313 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800314 return (freq - 56160) / 2160;
315 else
316 return 0;
317}
318
319static int initSock80211(Netlink* nl) {
320 nl->socket = nl_socket_alloc();
321 if (!nl->socket) {
322 fprintf(stderr, "Failing to allocate the sock\n");
323 return -ENOMEM;
324 }
325
326 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
327
328 if (genl_connect(nl->socket)) {
329 fprintf(stderr, "Failed to connect\n");
330 nl_close(nl->socket);
331 nl_socket_free(nl->socket);
332 return -ENOLINK;
333 }
334
335 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
336 if (nl->id< 0) {
337 fprintf(stderr, "interface not found.\n");
338 nl_close(nl->socket);
339 nl_socket_free(nl->socket);
340 return -ENOENT;
341 }
342
343 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
344 if ((!nl->cb)) {
345 fprintf(stderr, "Failed to allocate netlink callback.\n");
346 nl_close(nl->socket);
347 nl_socket_free(nl->socket);
348 return ENOMEM;
349 }
350
351 return nl->id;
352}
353
354static int nlfree(Netlink *nl)
355{
356 nl_cb_put(nl->cb);
357 nl_close(nl->socket);
358 nl_socket_free(nl->socket);
359 return 0;
360}
361
362static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
363 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
364 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
365 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
366};
367
368static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
369};
370
371static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
372};
373
374typedef struct _wifi_channelStats_loc {
375 INT array_size;
376 INT ch_number;
377 BOOL ch_in_pool;
378 INT ch_noise;
379 BOOL ch_radar_noise;
380 INT ch_max_80211_rssi;
381 INT ch_non_80211_noise;
382 INT ch_utilization;
383 ULLONG ch_utilization_total;
384 ULLONG ch_utilization_busy;
385 ULLONG ch_utilization_busy_tx;
386 ULLONG ch_utilization_busy_rx;
387 ULLONG ch_utilization_busy_self;
388 ULLONG ch_utilization_busy_ext;
389} wifi_channelStats_t_loc;
390
391typedef struct wifi_device_info {
392 INT wifi_devIndex;
393 UCHAR wifi_devMacAddress[6];
394 CHAR wifi_devIPAddress[64];
395 BOOL wifi_devAssociatedDeviceAuthentiationState;
396 INT wifi_devSignalStrength;
397 INT wifi_devTxRate;
398 INT wifi_devRxRate;
399} wifi_device_info_t;
400
401#endif
402
403//For 5g Alias Interfaces
404static BOOL priv_flag = TRUE;
405static BOOL pub_flag = TRUE;
406static BOOL Radio_flag = TRUE;
407//wifi_setApBeaconRate(1, beaconRate);
408
developer1e5aa162022-09-13 16:06:24 +0800409BOOL multiple_set = FALSE;
410
developer06a01d92022-09-07 16:32:39 +0800411struct params
412{
413 char * name;
414 char * value;
415};
416
417static int _syscmd(char *cmd, char *retBuf, int retBufSize)
418{
419 FILE *f;
420 char *ptr = retBuf;
421 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
422
423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
424 if((f = popen(cmd, "r")) == NULL) {
425 fprintf(stderr,"\npopen %s error\n", cmd);
426 return RETURN_ERR;
427 }
428
429 while(!feof(f))
430 {
431 *ptr = 0;
432 if(bufSize>=128) {
433 bufbytes=128;
434 } else {
435 bufbytes=bufSize-1;
436 }
437
438 fgets(ptr,bufbytes,f);
439 readbytes=strlen(ptr);
440
441 if(!readbytes)
442 break;
443
444 bufSize-=readbytes;
445 ptr += readbytes;
446 }
447 cmd_ret = pclose(f);
448 retBuf[retBufSize-1]=0;
449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
450
451 return cmd_ret >> 8;
452}
453
developer033b37b2022-10-18 11:27:46 +0800454INT radio_index_to_phy(int radioIndex)
455{
456 char cmd[128] = {0};
457 char buf[64] = {0};
458 int phyIndex = 0;
459 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
460 _syscmd(cmd, buf, sizeof(buf));
461
462 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800463 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800464 return RETURN_ERR;
465 }
466 sscanf(buf, "phy%d", &phyIndex);
467
468 return phyIndex;
469}
developer026ac9e2022-11-07 13:46:24 +0800470
developer431128d2022-12-16 15:30:41 +0800471INT wifi_getMaxRadioNumber(INT *max_radio_num)
472{
473 char cmd[64] = {0};
474 char buf[4] = {0};
475
476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
477
478 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
479 _syscmd(cmd, buf, sizeof(buf));
480 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
481
482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
483
484 return RETURN_OK;
485}
486
487wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800488{
489 char cmd[128] = {0};
490 char buf[64] = {0};
developer026ac9e2022-11-07 13:46:24 +0800491 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800492 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800493 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800494 int radioIndex = 0;
495 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800496 wifi_band band = band_invalid;
497
498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800499
developer431128d2022-12-16 15:30:41 +0800500 wifi_getMaxRadioNumber(&max_radio_num);
501 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800502 phyIndex = radio_index_to_phy(radioIndex);
developer5884e982022-10-06 10:52:50 +0800503 while(i < 10){
developer026ac9e2022-11-07 13:46:24 +0800504 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800505 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800506 nl80211_band = strtol(buf, NULL, 10);
507 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800508 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800509 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800510 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800511 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800512 band = band_6;
513
514 if(band != band_invalid)
515 break;
516
517 i++;
518 sleep(1);
519 }
developerc707e972022-09-13 15:38:02 +0800520
521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
522 return band;
523}
524
developer06a01d92022-09-07 16:32:39 +0800525static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
526{
527 char cmd[MAX_CMD_SIZE]={'\0'};
528 char buf[MAX_BUF_SIZE]={'\0'};
529 int ret = 0;
530
developerd946fd62022-12-08 18:03:28 +0800531 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
developer06a01d92022-09-07 16:32:39 +0800532 ret = _syscmd(cmd, buf, sizeof(buf));
533 if ((ret != 0) && (strlen(buf) == 0))
534 return -1;
535 snprintf(output, output_size, "%s", buf);
536
537 return 0;
538}
539
540static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
541{
542 char cmd[MAX_CMD_SIZE]={'\0'};
543 char buf[MAX_BUF_SIZE]={'\0'};
544
545 for(int i=0;i<item_count;i++)
546 {
547 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
548 if (strlen(buf) == 0) //Insert
549 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
550 else //Update
551 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developer5884e982022-10-06 10:52:50 +0800552
developer06a01d92022-09-07 16:32:39 +0800553 if(_syscmd(cmd, buf, sizeof(buf)))
554 return -1;
555 }
556
557 return 0;
558}
559
developerd946fd62022-12-08 18:03:28 +0800560//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800561static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800562{
563 char config_file[128] = {0};
564
565 if (interface_name == NULL)
566 return RETURN_ERR;
567
568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
569
570 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
571 wifi_hostapdRead(config_file, "interface", interface_name, 16);
572 if (strlen(interface_name) == 0)
573 return RETURN_ERR;
574
575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
576 return RETURN_OK;
577}
578
developerac6f1142022-12-20 19:26:35 +0800579// wifi agent will call this function, do not change the parameter
580void GetInterfaceName(char *interface_name, char *conf_file)
581{
582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
583 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
584 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
585}
586
developer06a01d92022-09-07 16:32:39 +0800587static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
588{
developerd946fd62022-12-08 18:03:28 +0800589 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800590 if (multiple_set == TRUE)
591 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800592 char cmd[MAX_CMD_SIZE]="", output[32]="";
593 FILE *fp;
594 int i;
595 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800596 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800597 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800598 for(i=0; i<item_count; i++, list++)
599 {
developerd946fd62022-12-08 18:03:28 +0800600 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800601 if((fp = popen(cmd, "r"))==NULL)
602 {
603 perror("popen failed");
604 return -1;
605 }
606 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
607 {
608 pclose(fp);
609 perror("fgets failed");
610 return -1;
611 }
612 pclose(fp);
613 }
614 return 0;
615}
616
617static int wifi_reloadAp(int apIndex)
618{
developerd946fd62022-12-08 18:03:28 +0800619 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800620 if (multiple_set == TRUE)
621 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800622 char cmd[MAX_CMD_SIZE]="";
623 char buf[MAX_BUF_SIZE]="";
624
developerac6f1142022-12-20 19:26:35 +0800625 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800626 return RETURN_ERR;
627 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800628 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
629 return RETURN_ERR;
630
developerd946fd62022-12-08 18:03:28 +0800631 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800632 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
633 return RETURN_ERR;
634
developerd946fd62022-12-08 18:03:28 +0800635 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800636 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
637 return RETURN_ERR;
638
639 return RETURN_OK;
640}
641
developer06a01d92022-09-07 16:32:39 +0800642INT File_Reading(CHAR *file, char *Value)
643{
644 FILE *fp = NULL;
645 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
646 int count = 0;
647
648 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
649 fp = popen(file,"r");
650 if(fp == NULL)
651 return RETURN_ERR;
652
653 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
654 {
655 for(count=0;buf[count]!='\n';count++)
656 copy_buf[count]=buf[count];
657 copy_buf[count]='\0';
658 }
659 strcpy(Value,copy_buf);
660 pclose(fp);
661 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
662
663 return RETURN_OK;
664}
665
666void wifi_RestartHostapd_2G()
667{
668 int Public2GApIndex = 4;
669
670 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
671 wifi_setApEnable(Public2GApIndex, FALSE);
672 wifi_setApEnable(Public2GApIndex, TRUE);
673 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
674}
675
676void wifi_RestartHostapd_5G()
677{
678 int Public5GApIndex = 5;
679
680 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
681 wifi_setApEnable(Public5GApIndex, FALSE);
682 wifi_setApEnable(Public5GApIndex, TRUE);
683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
684}
685
686void wifi_RestartPrivateWifi_2G()
687{
688 int PrivateApIndex = 0;
689
690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
691 wifi_setApEnable(PrivateApIndex, FALSE);
692 wifi_setApEnable(PrivateApIndex, TRUE);
693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
694}
695
696void wifi_RestartPrivateWifi_5G()
697{
698 int Private5GApIndex = 1;
699
700 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
701 wifi_setApEnable(Private5GApIndex, FALSE);
702 wifi_setApEnable(Private5GApIndex, TRUE);
703 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
704}
705
706static int writeBandWidth(int radioIndex,char *bw_value)
707{
708 char buf[MAX_BUF_SIZE];
709 char cmd[MAX_CMD_SIZE];
710
711 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
712 if(_syscmd(cmd, buf, sizeof(buf)))
713 {
714 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
715 _syscmd(cmd, buf, sizeof(buf));
716 return RETURN_OK;
717 }
718
719 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
720 _syscmd(cmd,buf,sizeof(buf));
721 return RETURN_OK;
722}
723
724static int readBandWidth(int radioIndex,char *bw_value)
725{
developer30423732022-12-01 16:17:49 +0800726 char buf[MAX_BUF_SIZE] = {0};
727 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800728 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
729 _syscmd(cmd,buf,sizeof(buf));
730 if(NULL!=strstr(buf,"20MHz"))
731 {
732 strcpy(bw_value,"20MHz");
733 }
734 else if(NULL!=strstr(buf,"40MHz"))
735 {
736 strcpy(bw_value,"40MHz");
737 }
738 else if(NULL!=strstr(buf,"80MHz"))
739 {
740 strcpy(bw_value,"80MHz");
741 }
742 else
743 {
744 return RETURN_ERR;
745 }
746 return RETURN_OK;
747}
748
developer264159b2022-11-02 09:41:35 +0800749// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800750INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
751{
developer5f222492022-09-13 15:21:52 +0800752 struct params params={'\0'};
753 char config_file[MAX_BUF_SIZE] = {0};
754 char buf[MAX_BUF_SIZE] = {'\0'};
755
756 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800757 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800758 if (strlen (beaconRate) >= 5) {
759 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
760 buf[strlen(beaconRate) - 4] = '\0';
761 } else if (strlen(beaconRate) > 0)
762 strcpy(buf, beaconRate);
763 else
764 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800765
766 params.name = "beacon_rate";
767 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
768 if (strncmp(buf, "5.5", 3) == 0) {
769 snprintf(buf, sizeof(buf), "55");
770 params.value = buf;
771 } else {
772 strcat(buf, "0");
773 params.value = buf;
774 }
775
776 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
777 wifi_hostapdWrite(config_file, &params, 1);
778 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
779 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
780
781 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800782}
783
784INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
785{
developer1d57d002022-10-12 18:03:15 +0800786 char config_file[128] = {'\0'};
787 char temp_output[128] = {'\0'};
788 char buf[128] = {'\0'};
789 char cmd[128] = {'\0'};
790 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800791 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800792
793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
794 if (NULL == beaconRate)
795 return RETURN_ERR;
796
797 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
798 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800799 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800800 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
801 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800802 if (strncmp(buf, "55", 2) == 0)
803 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
804 else {
805 rate = strtol(buf, NULL, 10)/10;
806 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
807 }
developer5f222492022-09-13 15:21:52 +0800808 } else {
developer1d57d002022-10-12 18:03:15 +0800809 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800810 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 +0800811 _syscmd(cmd, buf, sizeof(buf));
812 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800813 }
814 strncpy(beaconRate, temp_output, sizeof(temp_output));
815 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
816
817 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800818}
819
820INT wifi_setLED(INT radioIndex, BOOL enable)
821{
822 return 0;
823}
824INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
825{
826 return RETURN_OK;
827}
828/**********************************************************************************
829 *
830 * Wifi Subsystem level function prototypes
831 *
832**********************************************************************************/
833//---------------------------------------------------------------------------------------------------
834//Wifi system api
835//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
836INT wifi_getHalVersion(CHAR *output_string) //RDKB
837{
838 if(!output_string)
839 return RETURN_ERR;
840 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
841
842 return RETURN_OK;
843}
844
845
846/* wifi_factoryReset() function */
847/**
848* @description Clears internal variables to implement a factory reset of the Wi-Fi
849* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
850*
851* @param None
852*
853* @return The status of the operation.
854* @retval RETURN_OK if successful.
855* @retval RETURN_ERR if any error is detected
856*
857* @execution Synchronous
858* @sideeffect None
859*
860* @note This function must not suspend and must not invoke any blocking system
861* calls. It should probably just send a message to a driver event handler task.
862*
863*/
864INT wifi_factoryReset()
865{
866 char cmd[128];
867
868 /*delete running hostapd conf files*/
869 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
870 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
871 system(cmd);
872 system("systemctl restart hostapd.service");
873
874 return RETURN_OK;
875}
876
877/* wifi_factoryResetRadios() function */
878/**
879* @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.
880*
881* @param None
882* @return The status of the operation
883* @retval RETURN_OK if successful
884* @retval RETURN_ERR if any error is detected
885*
886* @execution Synchronous
887*
888* @sideeffect None
889*
890* @note This function must not suspend and must not invoke any blocking system
891* calls. It should probably just send a message to a driver event handler task.
892*
893*/
894INT wifi_factoryResetRadios()
895{
896 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
897 return RETURN_OK;
898
899 return RETURN_ERR;
900}
901
902
903/* wifi_factoryResetRadio() function */
904/**
905* @description Restore selected radio parameters without touching access point parameters
906*
907* @param radioIndex - Index of Wi-Fi Radio channel
908*
909* @return The status of the operation.
910* @retval RETURN_OK if successful.
911* @retval RETURN_ERR if any error is detected
912*
913* @execution Synchronous.
914* @sideeffect None.
915*
916* @note This function must not suspend and must not invoke any blocking system
917* calls. It should probably just send a message to a driver event handler task.
918*
919*/
920INT wifi_factoryResetRadio(int radioIndex) //RDKB
921{
developer5ff7f5f2022-09-13 15:12:16 +0800922 system("systemctl stop hostapd.service");
923
developer06a01d92022-09-07 16:32:39 +0800924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
925 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800926 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800927 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800928 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800929 else
930 return RETURN_ERR;
931
developer5ff7f5f2022-09-13 15:12:16 +0800932 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800933 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
934 return RETURN_OK;
935}
936
937/* wifi_initRadio() function */
938/**
939* Description: This function call initializes the specified radio.
940* Implementation specifics may dictate the functionality since
941* different hardware implementations may have different initilization requirements.
942* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
943*
944* @return The status of the operation.
945* @retval RETURN_OK if successful.
946* @retval RETURN_ERR if any error is detected
947*
948* @execution Synchronous.
949* @sideeffect None.
950*
951* @note This function must not suspend and must not invoke any blocking system
952* calls. It should probably just send a message to a driver event handler task.
953*
954*/
955INT wifi_initRadio(INT radioIndex)
956{
957 //TODO: Initializes the wifi subsystem (for specified radio)
958 return RETURN_OK;
959}
960void macfilter_init()
961{
962 char count[4]={'\0'};
963 char buf[253]={'\0'};
964 char tmp[19]={'\0'};
965 int dev_count,block,mac_entry=0;
966 char res[4]={'\0'};
967 char acl_file_path[64] = {'\0'};
968 FILE *fp = NULL;
969 int index=0;
970 char iface[10]={'\0'};
971 char config_file[MAX_BUF_SIZE] = {0};
972
973
974 sprintf(acl_file_path,"/tmp/mac_filter.sh");
975
976 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800977 if (fp == NULL) {
978 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
979 return RETURN_ERR;
980 }
developer06a01d92022-09-07 16:32:39 +0800981 sprintf(buf,"#!/bin/sh \n");
982 fprintf(fp,"%s\n",buf);
983
984 system("chmod 0777 /tmp/mac_filter.sh");
985
986 for(index=0;index<=1;index++)
987 {
988 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
989 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
990 sprintf(buf,"syscfg get %dcountfilter",index);
991 _syscmd(buf,count,sizeof(count));
992 mac_entry=atoi(count);
993
994 sprintf(buf,"syscfg get %dblockall",index);
995 _syscmd(buf,res,sizeof(res));
996 block = atoi(res);
997
998 //Allow only those macs mentioned in ACL
999 if(block==1)
1000 {
1001 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1002 fprintf(fp,"%s\n",buf);
1003 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1004 {
1005 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1006 _syscmd(buf,tmp,sizeof(tmp));
1007 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1008 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1009 fprintf(fp,"%s\n",buf);
1010 }
1011 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1012 fprintf(fp,"%s\n",buf);
1013 }
1014
1015 //Block all the macs mentioned in ACL
1016 else if(block==2)
1017 {
1018 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1019 fprintf(fp,"%s\n",buf);
1020
1021 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1022 {
1023 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1024 _syscmd(buf,tmp,sizeof(tmp));
1025 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1026 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1027 fprintf(fp,"%s\n",buf);
1028 }
1029 }
1030 }
1031 fclose(fp);
1032}
1033
1034// Initializes the wifi subsystem (all radios)
1035INT wifi_init() //RDKB
1036{
1037 char interface[MAX_BUF_SIZE]={'\0'};
1038 char bridge_name[MAX_BUF_SIZE]={'\0'};
1039 INT len=0;
1040
1041 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1042 //Not intitializing macfilter for Turris-Omnia Platform for now
1043 //macfilter_init();
1044
1045 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001046 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001047 sleep(2);//sleep to wait for hostapd to start
1048
1049 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1050
1051 return RETURN_OK;
1052}
1053
1054/* wifi_reset() function */
1055/**
1056* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1057* Implementation specifics may dictate what is actualy reset since
1058* different hardware implementations may have different requirements.
1059* Parameters : None
1060*
1061* @return The status of the operation.
1062* @retval RETURN_OK if successful.
1063* @retval RETURN_ERR if any error is detected
1064*
1065* @execution Synchronous.
1066* @sideeffect None.
1067*
1068* @note This function must not suspend and must not invoke any blocking system
1069* calls. It should probably just send a message to a driver event handler task.
1070*
1071*/
1072INT wifi_reset()
1073{
1074 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001075 system("systemctl stop hostapd.service");
1076 sleep(2);
1077 system("systemctl start hostapd.service");
1078 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001079 return RETURN_OK;
1080}
1081
1082/* wifi_down() function */
1083/**
1084* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1085* Implementation specifics may dictate some functionality since
1086* different hardware implementations may have different requirements.
1087*
1088* @param None
1089*
1090* @return The status of the operation
1091* @retval RETURN_OK if successful
1092* @retval RETURN_ERR if any error is detected
1093*
1094* @execution Synchronous
1095* @sideeffect None
1096*
1097* @note This function must not suspend and must not invoke any blocking system
1098* calls. It should probably just send a message to a driver event handler task.
1099*
1100*/
1101INT wifi_down()
1102{
1103 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001104 system("systemctl stop hostapd.service");
1105 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001106 return RETURN_OK;
1107}
1108
1109
1110/* wifi_createInitialConfigFiles() function */
1111/**
1112* @description This function creates wifi configuration files. The format
1113* and content of these files are implementation dependent. This function call is
1114* used to trigger this task if necessary. Some implementations may not need this
1115* function. If an implementation does not need to create config files the function call can
1116* do nothing and return RETURN_OK.
1117*
1118* @param None
1119*
1120* @return The status of the operation
1121* @retval RETURN_OK if successful
1122* @retval RETURN_ERR if any error is detected
1123*
1124* @execution Synchronous
1125* @sideeffect None
1126*
1127* @note This function must not suspend and must not invoke any blocking system
1128* calls. It should probably just send a message to a driver event handler task.
1129*
1130*/
1131INT wifi_createInitialConfigFiles()
1132{
1133 //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)
1134 return RETURN_OK;
1135}
1136
1137// outputs the country code to a max 64 character string
1138INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1139{
developerd946fd62022-12-08 18:03:28 +08001140 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001141 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001142 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001143 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001144
developerac6f1142022-12-20 19:26:35 +08001145 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001146 return RETURN_ERR;
1147 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001148 _syscmd(cmd, buf, sizeof(buf));
1149 if(strlen(buf) > 0)
1150 snprintf(output_string, 64, "%s", buf);
1151 else
1152 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001153
1154 return RETURN_OK;
1155}
1156
1157INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1158{
1159 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001160 char str[MAX_BUF_SIZE]={'\0'};
1161 char cmd[MAX_CMD_SIZE]={'\0'};
1162 struct params params;
1163 char config_file[MAX_BUF_SIZE] = {0};
1164
1165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1166 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1167 return RETURN_ERR;
1168
developerb86c6f32022-10-07 14:34:58 +08001169 if (strlen(CountryCode) == 0)
1170 strcpy(CountryCode, "US");
1171
developer7543b3b2022-09-13 13:47:17 +08001172 params.name = "country_code";
1173 params.value = CountryCode;
1174 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1175 int ret = wifi_hostapdWrite(config_file, &params, 1);
1176 if (ret) {
1177 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1178 ,__func__, ret);
1179 }
1180
1181 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1182 if (ret) {
1183 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1184 ,__func__, ret);
1185 }
developer7543b3b2022-09-13 13:47:17 +08001186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1187
developer06a01d92022-09-07 16:32:39 +08001188 return RETURN_OK;
1189}
1190
developera748dcf2022-09-13 15:56:48 +08001191INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1192{
developerd946fd62022-12-08 18:03:28 +08001193 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001194 char channel_util_file[64] = {0};
1195 char cmd[128] = {0};
1196 char buf[128] = {0};
1197 char line[128] = {0};
1198 char *param = NULL, *value = NULL;
1199 int read = 0;
1200 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1201 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1202 size_t len = 0;
1203 FILE *f = NULL;
1204
1205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1206
developerac6f1142022-12-20 19:26:35 +08001207 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001208 return RETURN_ERR;
1209 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001210 _syscmd(cmd, buf, sizeof(buf));
1211 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1212
1213 memset(cmd, 0, sizeof(cmd));
1214 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001215 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001216 if ((f = popen(cmd, "r")) == NULL) {
1217 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1218 return RETURN_ERR;
1219 }
1220
1221 read = getline(&line, &len, f);
1222 while (read != -1) {
1223 param = strtok(line, ":\t");
1224 value = strtok(NULL, " ");
1225 if(strstr(param, "frequency") != NULL) {
1226 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1227 }
1228 if(strstr(param, "noise") != NULL) {
1229 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1230 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1231 }
1232 if(strstr(param, "channel active time") != NULL) {
1233 ActiveTime = strtol(value, NULL, 10);
1234 }
1235 if(strstr(param, "channel busy time") != NULL) {
1236 BusyTime = strtol(value, NULL, 10);
1237 }
1238 if(strstr(param, "channel transmit time") != NULL) {
1239 TransmitTime = strtol(value, NULL, 10);
1240 }
1241 read = getline(&line, &len, f);
1242 }
1243 pclose(f);
1244
1245 // The file should store the last active, busy and transmit time
1246 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1247 f = fopen(channel_util_file, "r");
1248 if (f != NULL) {
1249 read = getline(&line, &len, f);
1250 preActiveTime = strtol(line, NULL, 10);
1251 read = getline(&line, &len, f);
1252 preBusyTime = strtol(line, NULL, 10);
1253 read = getline(&line, &len, f);
1254 preTransmitTime = strtol(line, NULL, 10);
1255 fclose(f);
1256 }
1257
1258 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1259 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1260
1261 f = fopen(channel_util_file, "w");
1262 if (f != NULL) {
1263 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1264 fclose(f);
1265 }
1266 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1267 return RETURN_OK;
1268}
1269
developer06a01d92022-09-07 16:32:39 +08001270/**********************************************************************************
1271 *
1272 * Wifi radio level function prototypes
1273 *
1274**********************************************************************************/
1275
1276//Get the total number of radios in this wifi subsystem
1277INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1278{
1279 if (NULL == output)
1280 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001281 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001282
1283 return RETURN_OK;
1284}
1285
1286//Get the total number of SSID entries in this wifi subsystem
1287INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1288{
1289 if (NULL == output)
1290 return RETURN_ERR;
1291 *output = MAX_APS;
1292
1293 return RETURN_OK;
1294}
1295
1296//Get the Radio enable config parameter
1297INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1298{
developerd946fd62022-12-08 18:03:28 +08001299 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001300 char interface_path[MAX_CMD_SIZE] = {0};
1301 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001302 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001303
1304 if (NULL == output_bool)
1305 return RETURN_ERR;
1306
1307 *output_bool = FALSE;
developer804c64f2022-10-19 13:54:40 +08001308 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001309 return RETURN_ERR;
1310
developer033b37b2022-10-18 11:27:46 +08001311 phyId = radio_index_to_phy(radioIndex);
1312
1313 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001314 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001315 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001316 {
developercf48e482022-09-13 14:49:50 +08001317 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001318 }
developerd946fd62022-12-08 18:03:28 +08001319 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001320 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001321 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
developerac6f1142022-12-20 19:26:35 +08001322 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001323 return RETURN_ERR;
1324 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
developercf48e482022-09-13 14:49:50 +08001325 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001326
developercf48e482022-09-13 14:49:50 +08001327 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1328 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08001329 return RETURN_OK;
1330}
1331
1332INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1333{
developerd946fd62022-12-08 18:03:28 +08001334 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001335 char cmd[MAX_CMD_SIZE] = {0};
1336 char buf[MAX_CMD_SIZE] = {0};
1337 int apIndex, ret;
1338 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001339 int max_radio_num = 0;
1340 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001341
1342 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001343
1344 phyId = radio_index_to_phy(radioIndex);
1345
1346 wifi_getMaxRadioNumber(&max_radio_num);
1347
developerac6f1142022-12-20 19:26:35 +08001348 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001349 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001350 if(enable==FALSE)
1351 {
developer033b37b2022-10-18 11:27:46 +08001352 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001353 {
1354 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001355 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001356 _syscmd(cmd, buf, sizeof(buf));
1357 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001358 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1359 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08001360 _syscmd(cmd, buf, sizeof(buf));
1361 }
developer033b37b2022-10-18 11:27:46 +08001362 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001363 _syscmd(cmd, buf, sizeof(buf));
1364 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001365 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001366 }
1367 else
1368 {
developer033b37b2022-10-18 11:27:46 +08001369 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001370 _syscmd(cmd, buf, sizeof(buf));
1371 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001372 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001373 sleep(1);
developer033b37b2022-10-18 11:27:46 +08001374
1375 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001376 {
developer431128d2022-12-16 15:30:41 +08001377 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
developer06a01d92022-09-07 16:32:39 +08001378 ret = _syscmd(cmd, buf, sizeof(buf));
1379 if ( ret == RETURN_ERR)
1380 {
1381 fprintf(stderr, "VAP interface creation failed\n");
1382 continue;
1383 }
developerd946fd62022-12-08 18:03:28 +08001384 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001385 _syscmd(cmd, buf, sizeof(buf));
1386 if(*buf == '1')
1387 {
1388 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001389 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001390 _syscmd(cmd, buf, sizeof(buf));
1391 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001392 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001393 }
1394 }
1395 }
1396
1397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1398 return RETURN_OK;
1399}
1400
1401//Get the Radio enable status
1402INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1403{
1404 if (NULL == output_bool)
1405 return RETURN_ERR;
1406
1407 return wifi_getRadioEnable(radioIndex, output_bool);
1408}
1409
1410//Get the Radio Interface name from platform, eg "wlan0"
1411INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1412{
developer033b37b2022-10-18 11:27:46 +08001413 int phyId = 0;
developer804c64f2022-10-19 13:54:40 +08001414 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001415 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08001416 phyId = radio_index_to_phy(radioIndex);
1417 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001418
1419 return RETURN_OK;
1420}
1421
1422//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1423//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.
1424INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1425{
developerbcc556a2022-09-22 20:02:45 +08001426 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1427 // For max bit rate, we should always choose the best MCS
1428 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001429 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001430 char *tmp = NULL;
1431 UINT mode_map = 0;
1432 UINT num_subcarrier = 0;
1433 UINT code_bits = 0;
1434 float code_rate = 0; // use max code rate
1435 int NSS = 0;
1436 UINT Symbol_duration = 0;
1437 UINT GI_duration = 0;
1438 wifi_band band = band_invalid;
1439 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1440 BOOL enable = FALSE;
1441 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001442
1443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1444 if (NULL == output_string)
1445 return RETURN_ERR;
1446
developerbcc556a2022-09-22 20:02:45 +08001447 wifi_getRadioEnable(radioIndex, &enable);
1448 if (enable == FALSE) {
1449 snprintf(output_string, 64, "0 Mb/s");
1450 return RETURN_OK;
1451 }
1452
1453 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1454 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1455 return RETURN_ERR;
1456 }
1457
1458 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1459 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1460 return RETURN_ERR;
1461 }
1462
1463 if (gi == wifi_guard_interval_3200)
1464 GI_duration = 32;
1465 else if (gi == wifi_guard_interval_1600)
1466 GI_duration = 16;
1467 else if (gi == wifi_guard_interval_800)
1468 GI_duration = 8;
1469 else // auto, 400
1470 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001471
developerbcc556a2022-09-22 20:02:45 +08001472 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1473 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1474 return RETURN_ERR;
1475 }
1476
1477 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1478 strcpy(channel_bandwidth_str, "160");
1479
1480 if (mode_map & WIFI_MODE_AX) {
1481 if (strstr(channel_bandwidth_str, "160") != NULL)
1482 num_subcarrier = 1960;
1483 else if (strstr(channel_bandwidth_str, "80") != NULL)
1484 num_subcarrier = 980;
1485 else if (strstr(channel_bandwidth_str, "40") != NULL)
1486 num_subcarrier = 468;
1487 else if (strstr(channel_bandwidth_str, "20") != NULL)
1488 num_subcarrier = 234;
1489 code_bits = 10;
1490 code_rate = (float)5/6;
1491 Symbol_duration = 128;
1492 } else if (mode_map & WIFI_MODE_AC) {
1493 if (strstr(channel_bandwidth_str, "160") != NULL)
1494 num_subcarrier = 468;
1495 else if (strstr(channel_bandwidth_str, "80") != NULL)
1496 num_subcarrier = 234;
1497 else if (strstr(channel_bandwidth_str, "40") != NULL)
1498 num_subcarrier = 108;
1499 else if (strstr(channel_bandwidth_str, "20") != NULL)
1500 num_subcarrier = 52;
1501 code_bits = 8;
1502 code_rate = (float)5/6;
1503 Symbol_duration = 32;
1504 } else if (mode_map & WIFI_MODE_N) {
1505 if (strstr(channel_bandwidth_str, "160") != NULL)
1506 num_subcarrier = 468;
1507 else if (strstr(channel_bandwidth_str, "80") != NULL)
1508 num_subcarrier = 234;
1509 else if (strstr(channel_bandwidth_str, "40") != NULL)
1510 num_subcarrier = 108;
1511 else if (strstr(channel_bandwidth_str, "20") != NULL)
1512 num_subcarrier = 52;
1513 code_bits = 6;
1514 code_rate = (float)3/4;
1515 Symbol_duration = 32;
1516 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1517 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1518 snprintf(output_string, 64, "65 Mb/s");
1519 return RETURN_OK;
1520 } else {
1521 snprintf(output_string, 64, "0 Mb/s");
1522 return RETURN_OK;
1523 }
developer06a01d92022-09-07 16:32:39 +08001524
developerbcc556a2022-09-22 20:02:45 +08001525 // Spatial streams
1526 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1527 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1528 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001529 }
developerbcc556a2022-09-22 20:02:45 +08001530
1531 // multiple 10 is to align duration unit (0.1 us)
1532 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1533 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1534
developer06a01d92022-09-07 16:32:39 +08001535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1536
1537 return RETURN_OK;
1538}
1539#if 0
1540INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1541{
1542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1543 char cmd[64];
1544 char buf[1024];
1545 int apIndex;
1546
1547 if (NULL == output_string)
1548 return RETURN_ERR;
1549
1550 apIndex=(radioIndex==0)?0:1;
1551
developerd946fd62022-12-08 18:03:28 +08001552 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001553 _syscmd(cmd,buf, sizeof(buf));
1554
1555 snprintf(output_string, 64, "%s", buf);
1556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1557 return RETURN_OK;
1558}
1559#endif
1560
1561
1562//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1563//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.
1564INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1565{
developer963da0c2022-09-13 15:58:27 +08001566 wifi_band band = band_invalid;
1567
developer06a01d92022-09-07 16:32:39 +08001568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1569 if (NULL == output_string)
1570 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001571
1572 band = wifi_index_to_band(radioIndex);
1573
1574 memset(output_string, 0, 10);
1575 if (band == band_2_4)
1576 strcpy(output_string, "2.4GHz");
1577 else if (band == band_5)
1578 strcpy(output_string, "5GHz");
1579 else if (band == band_6)
1580 strcpy(output_string, "6GHz");
1581 else
1582 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1584
1585 return RETURN_OK;
1586#if 0
1587 char buf[MAX_BUF_SIZE]={'\0'};
1588 char str[MAX_BUF_SIZE]={'\0'};
1589 char cmd[MAX_CMD_SIZE]={'\0'};
1590 char *ch=NULL;
1591 char *ch2=NULL;
1592
1593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1594 if (NULL == output_string)
1595 return RETURN_ERR;
1596
1597
1598 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1599
1600 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1601 {
1602 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1603 return RETURN_ERR;
1604 }
1605 ch=strchr(buf,'\n');
1606 *ch='\0';
1607 ch=strchr(buf,'=');
1608 if(ch==NULL)
1609 return RETURN_ERR;
1610
1611
1612 ch++;
1613
1614 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1615 strcpy(buf,"0");
1616 if(strlen(ch) == 1)
1617 ch=strcat(buf,ch);
1618
1619
1620 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1621
1622 if(_syscmd(cmd,str,64) == RETURN_ERR)
1623 {
1624 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1625 return RETURN_ERR;
1626 }
1627
1628
1629 ch2=strchr(str,'\n');
1630 //replace \n with \0
1631 *ch2='\0';
1632 ch2=strchr(str,'=');
1633 if(ch2==NULL)
1634 {
1635 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1636 return RETURN_ERR;
1637 }
1638 else
1639 wifi_dbg_printf("%s",ch2+1);
1640
1641
1642 ch2++;
1643
1644
1645 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1646
1647 memset(buf,'\0',sizeof(buf));
1648 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1649 {
1650 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1651 return RETURN_ERR;
1652 }
1653 if (strstr(buf,"2.4") != NULL )
1654 strcpy(output_string,"2.4GHz");
1655 else if(strstr(buf,"5.") != NULL )
1656 strcpy(output_string,"5GHz");
1657 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1658
1659 return RETURN_OK;
1660#endif
1661}
1662
1663//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1664//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.
1665INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1666{
developerb7593de2022-10-18 09:51:57 +08001667 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1669 if (NULL == output_string)
1670 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001671 band = wifi_index_to_band(radioIndex);
1672
1673 if (band == band_2_4)
1674 snprintf(output_string, 64, "2.4GHz");
1675 else if (band == band_5)
1676 snprintf(output_string, 64, "5GHz");
1677 else if (band == band_6)
1678 snprintf(output_string, 64, "6GHz");
1679
developer06a01d92022-09-07 16:32:39 +08001680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1681
1682 return RETURN_OK;
1683#if 0
1684 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1685 char buf[MAX_BUF_SIZE]={'\0'};
1686 char str[MAX_BUF_SIZE]={'\0'};
1687 char cmd[MAX_CMD_SIZE]={'\0'};
1688 char *ch=NULL;
1689 char *ch2=NULL;
1690 char ch1[5]="0";
1691
1692 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1693
1694 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1695 {
1696 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1697 return RETURN_ERR;
1698 }
1699
1700 ch=strchr(buf,'\n');
1701 *ch='\0';
1702 ch=strchr(buf,'=');
1703 if(ch==NULL)
1704 return RETURN_ERR;
1705 ch++;
1706
1707 if(strlen(ch)==1)
1708 {
1709 strcat(ch1,ch);
1710
1711 }
1712 else
1713 {
1714 strcpy(ch1,ch);
1715 }
1716
1717
1718
1719 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1720 if(_syscmd(cmd,str,64) == RETURN_ERR)
1721 {
1722 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1723 return RETURN_ERR;
1724 }
1725
1726
1727 ch2=strchr(str,'\n');
1728 //replace \n with \0
1729 *ch2='\0';
1730 ch2=strchr(str,'=');
1731 if(ch2==NULL)
1732 {
1733 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1734 return RETURN_ERR;
1735 }
1736 else
1737 wifi_dbg_printf("%s",ch2+1);
1738 ch2++;
1739
1740
1741 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1742 memset(buf,'\0',sizeof(buf));
1743 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1744 {
1745 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1746 return RETURN_ERR;
1747 }
1748
1749
1750 if(strstr(buf,"2.4")!=NULL)
1751 {
1752 strcpy(output_string,"2.4GHz");
1753 }
1754 if(strstr(buf,"5.")!=NULL)
1755 {
1756 strcpy(output_string,"5GHz");
1757 }
1758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1759 return RETURN_OK;
1760#endif
1761}
1762
1763//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1764//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.
1765INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1766{
developer963da0c2022-09-13 15:58:27 +08001767 char cmd[128]={0};
1768 char buf[128]={0};
1769 char temp_output[128] = {0};
1770 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001771 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001772
1773 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001774 if (NULL == output_string)
1775 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001776
1777 band = wifi_index_to_band(radioIndex);
1778 if (band == band_2_4) {
1779 strcat(temp_output, "b,g,");
1780 } else if (band == band_5) {
1781 strcat(temp_output, "a,");
1782 }
developer033b37b2022-10-18 11:27:46 +08001783 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001784 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001785 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 +08001786 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001787 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001788 strcat(temp_output, "n,");
1789 }
developer06a01d92022-09-07 16:32:39 +08001790
developer963da0c2022-09-13 15:58:27 +08001791 // vht capabilities
1792 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001793 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 +08001794 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001795 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001796 strcat(temp_output, "ac,");
1797 }
1798 }
1799
1800 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001801 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 +08001802 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001803 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001804 strcat(temp_output, "ax,");
1805 }
1806
1807 // Remove the last comma
1808 if (strlen(temp_output) != 0)
1809 temp_output[strlen(temp_output)-1] = '\0';
1810 strncpy(output_string, temp_output, strlen(temp_output));
1811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001812 return RETURN_OK;
1813}
1814
1815//Get the radio operating mode, and pure mode flag. eg: "ac"
1816//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.
1817INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1818{
1819 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1820 if (NULL == output_string)
1821 return RETURN_ERR;
1822
1823 if (radioIndex == 0) {
1824 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1825 *gOnly = FALSE;
1826 *nOnly = TRUE;
1827 *acOnly = FALSE;
1828 } else {
1829 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1830 *gOnly = FALSE;
1831 *nOnly = FALSE;
1832 *acOnly = FALSE;
1833 }
1834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1835
1836 return RETURN_OK;
1837#if 0
1838 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1839 char buf[64] = {0};
1840 char config_file[MAX_BUF_SIZE] = {0};
1841
1842 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1843 return RETURN_ERR;
1844
1845 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1846 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1847
1848 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1849 if (strlen(buf) == 0)
1850 {
1851 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1852 return RETURN_ERR;
1853 }
1854 if(strcmp(buf,"g")==0)
1855 {
1856 wifi_dbg_printf("\nG\n");
1857 *gOnly=TRUE;
1858 *nOnly=FALSE;
1859 *acOnly=FALSE;
1860 }
1861 else if(strcmp(buf,"n")==0)
1862 {
1863 wifi_dbg_printf("\nN\n");
1864 *gOnly=FALSE;
1865 *nOnly=TRUE;
1866 *acOnly=FALSE;
1867 }
1868 else if(strcmp(buf,"ac")==0)
1869 {
1870 wifi_dbg_printf("\nac\n");
1871 *gOnly=FALSE;
1872 *nOnly=FALSE;
1873 *acOnly=TRUE;
1874 }
1875 /* hostapd-5G.conf has "a" as hw_mode */
1876 else if(strcmp(buf,"a")==0)
1877 {
1878 wifi_dbg_printf("\na\n");
1879 *gOnly=FALSE;
1880 *nOnly=FALSE;
1881 *acOnly=FALSE;
1882 }
1883 else
1884 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1885
1886 //for a,n mode
1887 if(radioIndex == 1)
1888 {
1889 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1890 if(strcmp(buf,"1")==0)
1891 {
1892 strncpy(output_string, "n", 1);
1893 *nOnly=FALSE;
1894 }
1895 }
1896
1897 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1898 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1899 return RETURN_OK;
1900#endif
1901}
1902
developerdb744382022-09-13 15:34:54 +08001903INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1904{
1905 char cmd[128] = {0};
1906 char buf[64] = {0};
1907 char config_file[64] = {0};
1908 wifi_band band;
1909
1910 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1911 if(NULL == output_string || NULL == pureMode)
1912 return RETURN_ERR;
1913
1914 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001915 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerdb744382022-09-13 15:34:54 +08001916 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1917 _syscmd(cmd, buf, sizeof(buf));
1918
1919 band = wifi_index_to_band(radioIndex);
1920 // puremode is a bit map
1921 *pureMode = 0;
1922 if (band == band_2_4) {
1923 strcat(output_string, "b,g");
1924 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1925 if (strstr(buf, "n") != NULL) {
1926 strcat(output_string, ",n");
1927 *pureMode |= WIFI_MODE_N;
1928 }
1929 if (strstr(buf, "ax") != NULL) {
1930 strcat(output_string, ",ax");
1931 *pureMode |= WIFI_MODE_AX;
1932 }
1933 } else if (band == band_5) {
1934 strcat(output_string, "a");
1935 *pureMode |= WIFI_MODE_A;
1936 if (strstr(buf, "n") != NULL) {
1937 strcat(output_string, ",n");
1938 *pureMode |= WIFI_MODE_N;
1939 }
1940 if (strstr(buf, "ac") != NULL) {
1941 strcat(output_string, ",ac");
1942 *pureMode |= WIFI_MODE_AC;
1943 }
1944 if (strstr(buf, "ax") != NULL) {
1945 strcat(output_string, ",ax");
1946 *pureMode |= WIFI_MODE_AX;
1947 }
1948 } else if (band == band_6) {
1949 if (strstr(buf, "ax") != NULL) {
1950 strcat(output_string, "ax");
1951 *pureMode |= WIFI_MODE_AX;
1952 }
1953 }
1954
1955 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1956 return RETURN_OK;
1957}
1958
1959// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001960INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1961{
1962 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1963 if (strcmp (channelMode,"11A") == 0)
1964 {
1965 writeBandWidth(radioIndex,"20MHz");
1966 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1967 printf("\nChannel Mode is 802.11a (5GHz)\n");
1968 }
1969 else if (strcmp (channelMode,"11NAHT20") == 0)
1970 {
1971 writeBandWidth(radioIndex,"20MHz");
1972 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1973 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1974 }
1975 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1976 {
1977 writeBandWidth(radioIndex,"40MHz");
1978 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1979 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1980 }
1981 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1982 {
1983 writeBandWidth(radioIndex,"40MHz");
1984 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1985 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1986 }
1987 else if (strcmp (channelMode,"11ACVHT20") == 0)
1988 {
1989 writeBandWidth(radioIndex,"20MHz");
1990 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1991 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1992 }
1993 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1994 {
1995 writeBandWidth(radioIndex,"40MHz");
1996 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1997 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1998 }
1999 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2000 {
2001 writeBandWidth(radioIndex,"40MHz");
2002 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2003 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2004 }
2005 else if (strcmp (channelMode,"11ACVHT80") == 0)
2006 {
2007 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2008 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2009 }
2010 else if (strcmp (channelMode,"11ACVHT160") == 0)
2011 {
2012 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2013 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2014 }
2015 else if (strcmp (channelMode,"11B") == 0)
2016 {
2017 writeBandWidth(radioIndex,"20MHz");
2018 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2019 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2020 }
2021 else if (strcmp (channelMode,"11G") == 0)
2022 {
2023 writeBandWidth(radioIndex,"20MHz");
2024 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2025 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2026 }
2027 else if (strcmp (channelMode,"11NGHT20") == 0)
2028 {
2029 writeBandWidth(radioIndex,"20MHz");
2030 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2031 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2032 }
2033 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2034 {
2035 writeBandWidth(radioIndex,"40MHz");
2036 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2037 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2038 }
2039 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2040 {
2041 writeBandWidth(radioIndex,"40MHz");
2042 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2043 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2044 }
2045 else
2046 {
2047 return RETURN_ERR;
2048 }
2049 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2050
2051 return RETURN_OK;
2052}
2053
developerdb744382022-09-13 15:34:54 +08002054// Set the radio operating mode, and pure mode flag.
2055INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2056{
2057 int num_hostapd_support_mode = 3; // n, ac, ax
2058 struct params list[num_hostapd_support_mode];
2059 char config_file[64] = {0};
2060 char bandwidth[16] = {0};
2061 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002062
developerdb744382022-09-13 15:34:54 +08002063
2064 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2065 // Set radio mode
2066 list[0].name = "ieee80211n";
2067 list[1].name = "ieee80211ac";
2068 list[2].name = "ieee80211ax";
2069 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2070
2071 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002072 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002073 list[0].value = "1";
2074 else
2075 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002076 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002077 list[1].value = "1";
2078 else
2079 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002080 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002081 list[2].value = "1";
2082 else
2083 list[2].value = "0";
2084 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2085
2086 if (channelMode == NULL || strlen(channelMode) == 0)
2087 return RETURN_OK;
2088 // Set bandwidth
2089 if (strstr(channelMode, "40") != NULL)
2090 strcpy(bandwidth, "40MHz");
2091 else if (strstr(channelMode, "80") != NULL)
2092 strcpy(bandwidth, "80MHz");
2093 else if (strstr(channelMode, "160") != NULL)
2094 strcpy(bandwidth, "160MHz");
2095 else // 11A, 11B, 11G....
2096 strcpy(bandwidth, "20MHz");
2097
2098 writeBandWidth(radioIndex, bandwidth);
2099 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2100
2101 wifi_reloadAp(radioIndex);
2102 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2103
2104 return RETURN_OK;
2105}
2106
developer1d12ebf2022-10-04 15:13:38 +08002107INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2108
2109 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002110 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002111 struct params params = {0};
2112 wifi_band band = band_invalid;
2113
2114 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2115
2116 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002117
2118 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002119 return RETURN_ERR;
2120 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2121 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002122 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2123 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002124
2125 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2126 params.name = "hw_mode";
2127 params.value = hw_mode;
2128 wifi_hostapdWrite(config_file, &params, 1);
2129 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2130
developeref938762022-10-19 17:21:01 +08002131 if (band == band_2_4) {
2132 if (strncmp(hw_mode, "b", 1) == 0) {
2133 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2134 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2135 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2136 snprintf(buf, sizeof(buf), "%s", "1,2");
2137 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2138 } else {
2139 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2140
2141 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2142 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2143 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2144 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2145 }
2146 }
2147
developer1d12ebf2022-10-04 15:13:38 +08002148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2149 return RETURN_OK;
2150}
2151
developere8988ba2022-10-18 17:42:30 +08002152INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2153{
2154 char config_file[64] = {0};
2155 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);
developer30423732022-12-01 16:17:49 +08002161 if (band != band_2_4)
2162 return RETURN_OK;
developere8988ba2022-10-18 17:42:30 +08002163
2164 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2165 params.name = "noscan";
2166 params.value = noscan;
2167 wifi_hostapdWrite(config_file, &params, 1);
2168 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2169
2170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2171 return RETURN_OK;
2172}
2173
developer06a01d92022-09-07 16:32:39 +08002174//Get the list of supported channel. eg: "1-11"
2175//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.
2176INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2177{
developer6318ed52022-09-13 15:17:58 +08002178 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002179 if (NULL == output_string)
2180 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002181 char cmd[256] = {0};
2182 char buf[128] = {0};
2183 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002184 int phyId = 0;
2185
developer6318ed52022-09-13 15:17:58 +08002186 // Parse possible channel number and separate them with commas.
2187 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002188 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002189 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002190 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002191 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 +08002192 else
developer033b37b2022-10-18 11:27:46 +08002193 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 +08002194
2195 _syscmd(cmd,buf,sizeof(buf));
2196 strncpy(output_string, buf, sizeof(buf));
2197
2198 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2199 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002200}
2201
2202//Get the list for used channel. eg: "1,6,9,11"
2203//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.
2204INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2205{
developerd946fd62022-12-08 18:03:28 +08002206 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002207 char cmd[128] = {0};
2208 char buf[128] = {0};
2209 char config_file[64] = {0};
2210 int channel = 0;
2211 int freq = 0;
2212 int bandwidth = 0;
2213 int center_freq = 0;
2214 int center_channel = 0;
2215 int channel_delta = 0;
2216 wifi_band band = band_invalid;
2217
2218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2219
developer06a01d92022-09-07 16:32:39 +08002220 if (NULL == output_string)
2221 return RETURN_ERR;
2222
developerac6f1142022-12-20 19:26:35 +08002223 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002224 return RETURN_ERR;
2225 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002226 _syscmd(cmd, buf, sizeof(buf));
2227 if (strlen(buf) == 0) {
2228 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2229 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002230 }
developerf5745ee2022-10-05 16:09:53 +08002231 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2232
2233 if (bandwidth == 20) {
2234 snprintf(output_string, 256, "%d", channel);
2235 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002236 }
developerf5745ee2022-10-05 16:09:53 +08002237
2238 center_channel = ieee80211_frequency_to_channel(center_freq);
2239
2240 band = wifi_index_to_band(radioIndex);
2241 if (band == band_2_4 && bandwidth == 40) {
2242 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2243 memset(buf, 0, sizeof(buf));
2244 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2245
developerf22724d2022-12-22 17:24:14 +08002246 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002247 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002248 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002249 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2250 } else {
2251 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2252 return RETURN_ERR;
2253 }
2254 } else if (band == band_5 || band == band_6){
2255 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2256 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2257 channel_delta = (bandwidth-20)/10;
2258 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2259 } else
2260 return RETURN_ERR;
2261
2262 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002263 return RETURN_OK;
2264}
2265
2266//Get the running channel number
2267INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2268{
developer5b398df2022-11-17 20:39:48 +08002269 char channel_str[16] = {0};
2270 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002271
developer5b398df2022-11-17 20:39:48 +08002272 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002273 return RETURN_ERR;
2274
developer5b398df2022-11-17 20:39:48 +08002275 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2276 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002277
developer5b398df2022-11-17 20:39:48 +08002278 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002279
developer06a01d92022-09-07 16:32:39 +08002280 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002281}
2282
2283
2284INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2285{
2286 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002287 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002288
2289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2290 if (NULL == output_ulong)
2291 return RETURN_ERR;
2292
developer06a01d92022-09-07 16:32:39 +08002293 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002294 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2295 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002296 _syscmd(cmd,buf,sizeof(buf));
2297 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2298 if (*output_ulong == 0) {
2299 return RETURN_ERR;
2300 }
2301
2302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2303 return RETURN_OK;
2304}
2305
2306//Storing the previous channel value
2307INT wifi_storeprevchanval(INT radioIndex)
2308{
2309 char buf[256] = {0};
2310 char output[4]={'\0'};
2311 char config_file[MAX_BUF_SIZE] = {0};
2312 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2313 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2314 if(radioIndex == 0)
2315 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2316 else if(radioIndex == 1)
2317 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2318 system(buf);
2319 Radio_flag = FALSE;
2320 return RETURN_OK;
2321}
2322
2323//Set the running channel number
2324INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2325{
developer76989232022-10-04 14:13:19 +08002326 // We only write hostapd config here
2327 char str_channel[8]={0};
2328 char *list_channel;
2329 char config_file[128] = {0};
2330 char possible_channels[256] = {0};
2331 int max_radio_num = 0;
2332 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002333
developer76989232022-10-04 14:13:19 +08002334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002335
developer76989232022-10-04 14:13:19 +08002336 // Check valid
2337 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002338
developer76989232022-10-04 14:13:19 +08002339 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2340 list_channel = strtok(possible_channels, ",");
2341 while(true)
developer06a01d92022-09-07 16:32:39 +08002342 {
developer76989232022-10-04 14:13:19 +08002343 if(list_channel == NULL) { // input not in the list
2344 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2345 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002346 }
developer76989232022-10-04 14:13:19 +08002347 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2348 break;
2349 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002350 }
2351
developer76989232022-10-04 14:13:19 +08002352 list.name = "channel";
2353 list.value = str_channel;
2354 wifi_getMaxRadioNumber(&max_radio_num);
2355 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002356 {
developer76989232022-10-04 14:13:19 +08002357 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2358 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002359 }
2360
developer76989232022-10-04 14:13:19 +08002361 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002362 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002363}
developer06a01d92022-09-07 16:32:39 +08002364
2365INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2366{
developer76989232022-10-04 14:13:19 +08002367 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002368 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002369 char config_file[64];
2370 int max_num_radios = 0;
2371 wifi_band band = band_invalid;
2372
2373 band = wifi_index_to_band(radioIndex);
2374 if (band == band_2_4)
2375 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002376
developer30423732022-12-01 16:17:49 +08002377 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002378 list[0].name = "vht_oper_centr_freq_seg0_idx";
2379 list[0].value = str_idx;
2380 list[1].name = "he_oper_centr_freq_seg0_idx";
2381 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002382
developer76989232022-10-04 14:13:19 +08002383 wifi_getMaxRadioNumber(&max_num_radios);
2384 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002385 {
developer76989232022-10-04 14:13:19 +08002386 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2387 if (band == band_6)
2388 wifi_hostapdWrite(config_file, &list[1], 1);
2389 else
2390 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002391 }
2392
2393 return RETURN_OK;
2394}
2395
2396//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2397//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2398INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2399{
2400 //Set to wifi config only. Wait for wifi reset to apply.
2401 char buf[256] = {0};
2402 char str_channel[256] = {0};
2403 int count = 0;
2404 ULONG Value = 0;
2405 FILE *fp = NULL;
2406 if(enable == TRUE)
2407 {
developer06a01d92022-09-07 16:32:39 +08002408 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002409 }
developer5884e982022-10-06 10:52:50 +08002410 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002411}
2412
developer0b246d12022-09-30 15:24:20 +08002413INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2414{
2415 if (output_bool == NULL)
2416 return RETURN_ERR;
2417
2418 *output_bool = TRUE;
2419
2420 return RETURN_OK;
2421}
2422
developer06a01d92022-09-07 16:32:39 +08002423INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2424{
2425 if (NULL == output_bool)
2426 return RETURN_ERR;
2427 *output_bool=FALSE;
2428 return RETURN_OK;
2429}
2430
2431INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2432{
2433 if (NULL == output_bool)
2434 return RETURN_ERR;
2435 *output_bool=FALSE;
2436 return RETURN_OK;
2437}
2438
2439INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2440{
2441 //Set to wifi config only. Wait for wifi reset to apply.
2442 return RETURN_OK;
2443}
2444
2445INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2446{
2447 return RETURN_OK;
2448}
2449
2450INT wifi_factoryResetAP(int apIndex)
2451{
developer838cca92022-10-03 13:19:57 +08002452 char ap_config_file[64] = {0};
2453 char cmd[128] = {0};
2454
developer06a01d92022-09-07 16:32:39 +08002455 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002456
2457 wifi_setApEnable(apIndex, FALSE);
2458 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2459 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2460 wifi_setApEnable(apIndex, TRUE);
2461
developer06a01d92022-09-07 16:32:39 +08002462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002463
developer06a01d92022-09-07 16:32:39 +08002464 return RETURN_OK;
2465}
2466
2467//To set Band Steering AP group
2468//To-do
2469INT wifi_setBandSteeringApGroup(char *ApGroup)
2470{
2471 return RETURN_OK;
2472}
2473
developer1e5aa162022-09-13 16:06:24 +08002474INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2475{
2476 char config_file[128] = {'\0'};
2477 char buf[128] = {'\0'};
2478
2479 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2480 if (dtimInterval == NULL)
2481 return RETURN_ERR;
2482
2483 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2484 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2485
2486 if (strlen(buf) == 0) {
2487 *dtimInterval = 2;
2488 } else {
2489 *dtimInterval = strtoul(buf, NULL, 10);
2490 }
2491
2492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2493 return RETURN_OK;
2494}
2495
developer06a01d92022-09-07 16:32:39 +08002496INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2497{
developer5f222492022-09-13 15:21:52 +08002498 struct params params={0};
2499 char config_file[MAX_BUF_SIZE] = {'\0'};
2500 char buf[MAX_BUF_SIZE] = {'\0'};
2501
2502 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2503 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002504 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002505 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002506 }
2507
2508 params.name = "dtim_period";
2509 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2510 params.value = buf;
2511
2512 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2513 wifi_hostapdWrite(config_file, &params, 1);
2514 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2515
2516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2517 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002518}
2519
2520//Check if the driver support the Dfs
2521INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2522{
developer78a15382022-11-02 10:57:40 +08002523 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002524 if (NULL == output_bool)
2525 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002526 *output_bool=FALSE;
2527
2528 band = wifi_index_to_band(radioIndex);
2529 if (band == band_5)
2530 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002531 return RETURN_OK;
2532}
2533
2534//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.
2535//The value of this parameter is a comma seperated list of channel number
2536INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2537{
2538 if (NULL == output_pool)
2539 return RETURN_ERR;
2540 if (radioIndex==1)
2541 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2542 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2543
2544 return RETURN_OK;
2545}
2546
2547INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2548{
2549 //Set to wifi config. And apply instantly.
2550 return RETURN_OK;
2551}
2552
2553INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2554{
2555 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2556 return RETURN_ERR;
2557 *output_interval_seconds=1800;
2558 *output_dwell_milliseconds=40;
2559
2560 return RETURN_OK;
2561}
2562
2563INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2564{
2565 //Set to wifi config. And apply instantly.
2566 return RETURN_OK;
2567}
2568
developerbfc18512022-10-05 17:54:28 +08002569INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2570{
2571 if (output_bool == NULL)
2572 return RETURN_ERR;
2573 *output_bool = true;
2574 return RETURN_OK;
2575}
2576
2577INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2578{
2579 return RETURN_OK;
2580}
2581
developer06a01d92022-09-07 16:32:39 +08002582//Get the Dfs enable status
2583INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2584{
developer9964b5b2022-09-13 15:59:34 +08002585 char buf[16] = {0};
2586 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002587
2588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2589
developer30423732022-12-01 16:17:49 +08002590 if (output_bool == NULL)
2591 return RETURN_ERR;
2592
developer9964b5b2022-09-13 15:59:34 +08002593 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002594 f = fopen(DFS_ENABLE_FILE, "r");
2595 if (f != NULL) {
2596 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002597 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002598 *output_bool = FALSE;
2599 fclose(f);
2600 }
2601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002602 return RETURN_OK;
2603}
2604
2605//Set the Dfs enable status
2606INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2607{
developer9964b5b2022-09-13 15:59:34 +08002608 char config_file[128] = {0};
2609 FILE *f = NULL;
2610 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002611
2612 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2613
developer9964b5b2022-09-13 15:59:34 +08002614 f = fopen(DFS_ENABLE_FILE, "w");
2615 if (f == NULL)
2616 return RETURN_ERR;
2617 fprintf(f, "%d", enable);
2618 fclose(f);
2619
2620 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002621 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002622 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2623 wifi_hostapdWrite(config_file, &params, 1);
2624 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2625
2626 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2627
developer9964b5b2022-09-13 15:59:34 +08002628 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002629 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002630}
2631
2632//Check if the driver support the AutoChannelRefreshPeriod
2633INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2634{
2635 if (NULL == output_bool)
2636 return RETURN_ERR;
2637 *output_bool=FALSE; //not support
2638
2639 return RETURN_OK;
2640}
2641
2642//Get the ACS refresh period in seconds
2643INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2644{
2645 if (NULL == output_ulong)
2646 return RETURN_ERR;
2647 *output_ulong=300;
2648
2649 return RETURN_OK;
2650}
2651
2652//Set the ACS refresh period in seconds
2653INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2654{
2655 return RETURN_ERR;
2656}
2657
2658//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2659//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.
2660INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2661{
developer70490032022-09-13 15:45:20 +08002662 char cmd[128] = {0}, buf[64] = {0};
2663 char interface_name[64] = {0};
2664 int ret = 0, len=0;
2665 BOOL radio_enable = FALSE;
2666
2667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2668
developer06a01d92022-09-07 16:32:39 +08002669 if (NULL == output_string)
2670 return RETURN_ERR;
2671
developer70490032022-09-13 15:45:20 +08002672 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2673 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002674
developer70490032022-09-13 15:45:20 +08002675 if (radio_enable != TRUE)
2676 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002677
developerac6f1142022-12-20 19:26:35 +08002678 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002679 return RETURN_ERR;
2680 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6", interface_name);
developer06a01d92022-09-07 16:32:39 +08002681 ret = _syscmd(cmd, buf, sizeof(buf));
2682 len = strlen(buf);
2683 if((ret != 0) || (len == 0))
2684 {
2685 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2686 return RETURN_ERR;
2687 }
2688
2689 buf[len-1] = '\0';
2690 snprintf(output_string, 64, "%sMHz", buf);
2691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2692
2693#if 0
2694 //TODO: revisit below implementation
2695 char output_buf[8]={0};
2696 char bw_value[10];
2697 char config_file[MAX_BUF_SIZE] = {0};
2698
2699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2700 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2701 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2702 readBandWidth(radioIndex,bw_value);
2703
2704 if(strstr (output_buf,"0") != NULL )
2705 {
2706 strcpy(output_string,bw_value);
2707 }
2708 else if (strstr (output_buf,"1") != NULL)
2709 {
2710 strcpy(output_string,"80MHz");
2711 }
2712 else if (strstr (output_buf,"2") != NULL)
2713 {
2714 strcpy(output_string,"160MHz");
2715 }
2716 else if (strstr (output_buf,"3") != NULL)
2717 {
2718 strcpy(output_string,"80+80");
2719 }
2720 else
2721 {
2722 strcpy(output_string,"Auto");
2723 }
2724 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2725#endif
2726
2727 return RETURN_OK;
2728}
2729
2730//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002731INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002732{
developerf7a466e2022-09-29 11:55:56 +08002733 char config_file[128];
2734 char set_value[16];
2735 struct params params[2];
2736 int max_radio_num = 0;
2737
developer06a01d92022-09-07 16:32:39 +08002738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002739
developerf7a466e2022-09-29 11:55:56 +08002740 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002741 return RETURN_ERR;
2742
developerf7a466e2022-09-29 11:55:56 +08002743 if(strstr(bandwidth,"80+80") != NULL)
2744 strcpy(set_value, "3");
2745 else if(strstr(bandwidth,"160") != NULL)
2746 strcpy(set_value, "2");
2747 else if(strstr(bandwidth,"80") != NULL)
2748 strcpy(set_value, "1");
2749 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2750 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002751 else
2752 {
developerf7a466e2022-09-29 11:55:56 +08002753 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002754 return RETURN_ERR;
2755 }
2756
developerf7a466e2022-09-29 11:55:56 +08002757 params[0].name = "vht_oper_chwidth";
2758 params[0].value = set_value;
2759 params[1].name = "he_oper_chwidth";
2760 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002761
developerf7a466e2022-09-29 11:55:56 +08002762 wifi_getMaxRadioNumber(&max_radio_num);
2763 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002764 {
developerf7a466e2022-09-29 11:55:56 +08002765 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2766 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002767 }
2768
2769 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2770 return RETURN_OK;
2771}
2772
2773//Getting current radio extension channel
2774INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2775{
2776 CHAR buf[150] = {0};
2777 CHAR cmd[150] = {0};
2778 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2779 _syscmd(cmd, buf, sizeof(buf));
2780 if(NULL != strstr(buf,"HT40+"))
2781 strcpy(Value,"AboveControlChannel");
2782 else if(NULL != strstr(buf,"HT40-"))
2783 strcpy(Value,"BelowControlChannel");
2784 return RETURN_OK;
2785}
2786
2787//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2788//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.
2789INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2790{
2791 if (NULL == output_string)
2792 return RETURN_ERR;
2793
2794 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2795#if 0
2796 CHAR Value[100] = {0};
2797 if (NULL == output_string)
2798 return RETURN_ERR;
2799 if(radioIndex == 0)
2800 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2801 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2802 {
2803 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2804 if(strcmp(Value,"40MHz") == 0)
2805 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2806 else
2807 strcpy(Value,"Auto");
2808 }
2809 strcpy(output_string,Value);
2810#endif
2811
2812 return RETURN_OK;
2813}
2814
2815//Set the extension channel.
2816INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2817{
2818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2819 struct params params={'\0'};
2820 char config_file[MAX_BUF_SIZE] = {0};
2821 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002822 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002823 params.name = "ht_capab";
2824
developer033b37b2022-10-18 11:27:46 +08002825 if(NULL!= strstr(string,"Above"))
2826 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2827 else if(NULL!= strstr(string,"Below"))
2828 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2829 else
2830 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2831
developer06a01d92022-09-07 16:32:39 +08002832
2833 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002834
2835 wifi_getMaxRadioNumber(&max_radio_num);
2836 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002837 {
developer033b37b2022-10-18 11:27:46 +08002838 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002839 wifi_hostapdWrite(config_file, &params, 1);
2840 }
2841
2842 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2844 return RETURN_OK;
2845}
2846
2847//Get the guard interval value. eg "400nsec" or "800nsec"
2848//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.
2849INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2850{
developer454b9462022-09-13 15:29:16 +08002851 wifi_guard_interval_t GI;
2852
2853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2854
2855 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002856 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002857
2858 if (GI == wifi_guard_interval_400)
2859 strcpy(output_string, "400nsec");
2860 else if (GI == wifi_guard_interval_800)
2861 strcpy(output_string, "800nsec");
2862 else if (GI == wifi_guard_interval_1600)
2863 strcpy(output_string, "1600nsec");
2864 else if (GI == wifi_guard_interval_3200)
2865 strcpy(output_string, "3200nsec");
2866 else
developer78a15382022-11-02 10:57:40 +08002867 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002868
developer454b9462022-09-13 15:29:16 +08002869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002870 return RETURN_OK;
2871}
2872
2873//Set the guard interval value.
2874INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2875{
developer454b9462022-09-13 15:29:16 +08002876 wifi_guard_interval_t GI;
2877 int ret = 0;
2878
2879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2880
2881 if (strcmp(string, "400nsec") == 0)
2882 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002883 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002884 GI = wifi_guard_interval_800;
2885 else if (strcmp(string , "1600nsec") == 0)
2886 GI = wifi_guard_interval_1600;
2887 else if (strcmp(string , "3200nsec") == 0)
2888 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002889 else
2890 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002891
2892 ret = wifi_setGuardInterval(radioIndex, GI);
2893
2894 if (ret == RETURN_ERR) {
2895 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2896 return RETURN_ERR;
2897 }
2898
2899 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2900 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002901}
2902
2903//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2904INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2905{
developerf49437e2022-09-29 19:58:21 +08002906 char buf[32]={0};
2907 char mcs_file[64] = {0};
2908 char cmd[64] = {0};
2909 int mode_bitmap = 0;
2910
2911 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2912 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002913 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002914 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2915
2916 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2917 _syscmd(cmd, buf, sizeof(buf));
2918 if (strlen(buf) > 0)
2919 *output_int = strtol(buf, NULL, 10);
2920 else {
2921 // output the max MCS for the current radio mode
2922 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2923 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2924 return RETURN_ERR;
2925 }
2926 if (mode_bitmap & WIFI_MODE_AX) {
2927 *output_int = 11;
2928 } else if (mode_bitmap & WIFI_MODE_AC) {
2929 *output_int = 9;
2930 } else if (mode_bitmap & WIFI_MODE_N) {
2931 *output_int = 7;
2932 }
2933 }
2934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002935
2936 return RETURN_OK;
2937}
2938
2939//Set the Modulation Coding Scheme index
2940INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2941{
developerf49437e2022-09-29 19:58:21 +08002942 // 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).
2943 char config_file[64] = {0};
2944 char set_value[16] = {0};
2945 char mcs_file[32] = {0};
2946 wifi_band band = band_invalid;
2947 struct params set_config = {0};
2948 FILE *f = NULL;
2949
2950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2951
2952 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2953
developer78a15382022-11-02 10:57:40 +08002954 // -1 means auto
2955 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08002956 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2957 return RETURN_ERR;
2958 }
2959
developer78a15382022-11-02 10:57:40 +08002960 if (MCS > 9 || MCS == -1)
2961 strcpy(set_value, "2");
2962 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08002963 strcpy(set_value, "1");
2964 else
developer78a15382022-11-02 10:57:40 +08002965 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08002966
2967 set_config.name = "he_basic_mcs_nss_set";
2968 set_config.value = set_value;
2969
2970 wifi_hostapdWrite(config_file, &set_config, 1);
2971 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2972
2973 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2974 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2975 f = fopen(mcs_file, "w");
2976 if (f == NULL) {
2977 fprintf(stderr, "%s: fopen failed\n", __func__);
2978 return RETURN_ERR;
2979 }
2980 fprintf(f, "%d", MCS);
2981 fclose(f);
2982
2983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2984 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002985}
2986
2987//Get supported Transmit Power list, eg : "0,25,50,75,100"
2988//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.
2989INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2990{
2991 if (NULL == output_list)
2992 return RETURN_ERR;
2993 snprintf(output_list, 64,"0,25,50,75,100");
2994 return RETURN_OK;
2995}
2996
developera5005b62022-09-13 15:43:35 +08002997//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002998//The transmite power level is in units of full power for this radio.
2999INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3000{
developerd946fd62022-12-08 18:03:28 +08003001 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003002 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003003 char buf[16]={0};
3004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003005
developera5005b62022-09-13 15:43:35 +08003006 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003007 return RETURN_ERR;
3008
developerac6f1142022-12-20 19:26:35 +08003009 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003010 return RETURN_ERR;
3011 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 +08003012 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003013
developera5005b62022-09-13 15:43:35 +08003014 *output_ulong = strtol(buf, NULL, 10);
3015
3016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003017 return RETURN_OK;
3018}
3019
3020//Set Transmit Power
3021//The transmite power level is in units of full power for this radio.
3022INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3023{
developerd946fd62022-12-08 18:03:28 +08003024 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003025 char *support;
developer06a01d92022-09-07 16:32:39 +08003026 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003027 char buf[128]={0};
3028 char txpower_str[64] = {0};
3029 int txpower = 0;
3030 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08003031 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003032
3033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003034
developerac6f1142022-12-20 19:26:35 +08003035 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003036 return RETURN_ERR;
3037 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 +08003038 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003039 maximum_tx = strtol(buf, NULL, 10);
3040
3041 // Get the Tx power supported list and check that is the input in the list
3042 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3043 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3044 support = strtok(buf, ",");
3045 while(true)
3046 {
3047 if(support == NULL) { // input not in the list
3048 wifi_dbg_printf("Input value is invalid.\n");
3049 return RETURN_ERR;
3050 }
3051 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3052 break;
3053 }
3054 support = strtok(NULL, ",");
3055 }
3056 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003057 phyId = radio_index_to_phy(radioIndex);
3058 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003059 _syscmd(cmd, buf, sizeof(buf));
3060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003061
3062 return RETURN_OK;
3063}
3064
3065//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3066INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3067{
3068 if (NULL == Supported)
3069 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003070 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003071
3072 return RETURN_OK;
3073}
3074
3075//Get 80211h feature enable
3076INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3077{
developer3885fec2022-09-13 15:13:47 +08003078 char buf[64]={'\0'};
3079 char config_file[64] = {'\0'};
3080
3081 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3082 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003083 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003084
3085 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3086 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003087
developer3885fec2022-09-13 15:13:47 +08003088 if (strncmp(buf, "1", 1) == 0)
3089 *enable = TRUE;
3090 else
3091 *enable = FALSE;
3092
3093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003094 return RETURN_OK;
3095}
3096
3097//Set 80211h feature enable
3098INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3099{
developer3885fec2022-09-13 15:13:47 +08003100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3101 struct params params={'\0'};
3102 char config_file[MAX_BUF_SIZE] = {0};
3103
3104 params.name = "ieee80211h";
3105
3106 if (enable) {
3107 params.value = "1";
3108 } else {
3109 params.value = "0";
3110 }
3111
3112 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3113 wifi_hostapdWrite(config_file, &params, 1);
3114
3115 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3116 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3117 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003118}
3119
3120//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.
3121INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3122{
3123 if (NULL == output)
3124 return RETURN_ERR;
3125 *output=100;
3126
3127 return RETURN_OK;
3128}
3129
3130//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.
3131INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3132{
3133 if (NULL == output)
3134 return RETURN_ERR;
3135 *output = -99;
3136
3137 return RETURN_OK;
3138}
3139
3140INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3141{
3142 return RETURN_ERR;
3143}
3144
3145
3146//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3147INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3148{
developerd946fd62022-12-08 18:03:28 +08003149 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003150 char cmd[MAX_BUF_SIZE]={'\0'};
3151 char buf[MAX_CMD_SIZE]={'\0'};
3152
3153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3154 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003155 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003156
developerac6f1142022-12-20 19:26:35 +08003157 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003158 return RETURN_ERR;
3159 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 +08003160 _syscmd(cmd, buf, sizeof(buf));
3161 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003162
developer5f222492022-09-13 15:21:52 +08003163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003164 return RETURN_OK;
3165}
3166
3167INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3168{
developer5f222492022-09-13 15:21:52 +08003169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3170 struct params params={'\0'};
3171 char buf[MAX_BUF_SIZE] = {'\0'};
3172 char config_file[MAX_BUF_SIZE] = {'\0'};
3173
developer5b398df2022-11-17 20:39:48 +08003174 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3175 return RETURN_ERR;
3176
developer5f222492022-09-13 15:21:52 +08003177 params.name = "beacon_int";
3178 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3179 params.value = buf;
3180
3181 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3182 wifi_hostapdWrite(config_file, &params, 1);
3183
3184 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3185 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3186 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003187}
3188
3189//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.
3190INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3191{
developer06a01d92022-09-07 16:32:39 +08003192 //TODO: need to revisit below implementation
3193 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003194 char temp_output[128] = {0};
3195 char temp_TransmitRates[64] = {0};
3196 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003197
3198 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3199 if (NULL == output)
3200 return RETURN_ERR;
3201 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003202 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3203
3204 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3205 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3206 } else {
3207 temp = strtok(temp_TransmitRates," ");
3208 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003209 {
developere9d0abd2022-09-13 15:40:57 +08003210 // Convert 100 kbps to Mbps
3211 temp[strlen(temp)-1]=0;
3212 if((temp[0]=='5') && (temp[1]=='\0'))
3213 {
3214 temp="5.5";
3215 }
3216 strcat(temp_output,temp);
3217 temp = strtok(NULL," ");
3218 if(temp!=NULL)
3219 {
3220 strcat(temp_output,",");
3221 }
developer06a01d92022-09-07 16:32:39 +08003222 }
developere9d0abd2022-09-13 15:40:57 +08003223 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003224 }
developer06a01d92022-09-07 16:32:39 +08003225 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003226 return RETURN_OK;
3227}
3228
3229INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3230{
3231 char *temp;
3232 char temp1[128];
3233 char temp_output[128];
3234 char temp_TransmitRates[128];
3235 char set[128];
3236 char sub_set[128];
3237 int set_count=0,subset_count=0;
3238 int set_index=0,subset_index=0;
3239 char *token;
3240 int flag=0, i=0;
3241 struct params params={'\0'};
3242 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003243 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003244
3245 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3246 if(NULL == TransmitRates)
3247 return RETURN_ERR;
3248 strcpy(sub_set,TransmitRates);
3249
3250 //Allow only supported Data transmit rate to be set
3251 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3252 token = strtok(sub_set,",");
3253 while( token != NULL ) /* split the basic rate to be set, by comma */
3254 {
3255 sub_set[subset_count]=atoi(token);
3256 subset_count++;
3257 token=strtok(NULL,",");
3258 }
3259 token=strtok(set,",");
3260 while(token!=NULL) /* split the supported rate by comma */
3261 {
3262 set[set_count]=atoi(token);
3263 set_count++;
3264 token=strtok(NULL,",");
3265 }
3266 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3267 {
3268 for(set_index=0;set_index < set_count;set_index++)
3269 {
3270 flag=0;
3271 if(sub_set[subset_index]==set[set_index])
3272 break;
3273 else
3274 flag=1; /* No match found */
3275 }
3276 if(flag==1)
3277 return RETURN_ERR; //If value not found return Error
3278 }
3279 strcpy(temp_TransmitRates,TransmitRates);
3280
3281 for(i=0;i<strlen(temp_TransmitRates);i++)
3282 {
3283 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003284 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003285 {
3286 continue;
3287 }
3288 else
3289 {
3290 return RETURN_ERR;
3291 }
3292 }
3293 strcpy(temp_output,"");
3294 temp = strtok(temp_TransmitRates,",");
3295 while(temp!=NULL)
3296 {
3297 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003298 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003299 {
developeref938762022-10-19 17:21:01 +08003300 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003301 {
3302 return RETURN_ERR;
3303 }
3304 }
3305
3306 if(strcmp(temp,"5.5")==0)
3307 {
3308 strcpy(temp1,"55");
3309 }
3310 else
3311 {
3312 strcat(temp1,"0");
3313 }
3314 strcat(temp_output,temp1);
3315 temp = strtok(NULL,",");
3316 if(temp!=NULL)
3317 {
3318 strcat(temp_output," ");
3319 }
3320 }
3321 strcpy(TransmitRates,temp_output);
3322
3323 params.name= "basic_rates";
3324 params.value =TransmitRates;
3325
3326 wifi_dbg_printf("\n%s:",__func__);
3327 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3328 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3329 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3330 wifi_hostapdWrite(config_file,&params,1);
3331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3332 return RETURN_OK;
3333}
3334
3335//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003336INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003337{
3338 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3339 FILE *fp = NULL;
3340 char path[256] = {0}, output_string[256] = {0};
3341 int count = 0;
3342 char *interface = NULL;
3343
3344 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3345 if (fp == NULL)
3346 {
3347 printf("Failed to run command in Function %s\n", __FUNCTION__);
3348 return RETURN_ERR;
3349 }
3350 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3351 {
3352 interface = strchr(path, '=');
3353
3354 if (interface != NULL)
3355 {
3356 strcpy(output_string, interface + 1);
3357 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3358 interface_name[count] = output_string[count];
3359
3360 interface_name[count] = '\0';
3361 }
3362 }
3363 pclose(fp);
3364 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3365 return RETURN_OK;
3366}
3367
3368INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3369{
3370 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3371 output_struct->radio_BytesSent = 0;
3372 output_struct->radio_BytesReceived = 0;
3373 output_struct->radio_PacketsSent = 0;
3374 output_struct->radio_PacketsReceived = 0;
3375 output_struct->radio_ErrorsSent = 0;
3376 output_struct->radio_ErrorsReceived = 0;
3377 output_struct->radio_DiscardPacketsSent = 0;
3378 output_struct->radio_DiscardPacketsReceived = 0;
3379 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3380 return RETURN_OK;
3381}
3382
3383
3384INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3385{
3386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3387 CHAR buf[MAX_CMD_SIZE] = {0};
3388 CHAR Value[MAX_BUF_SIZE] = {0};
3389 FILE *fp = NULL;
3390
3391 if (ifname == NULL || strlen(ifname) <= 1)
3392 return RETURN_OK;
3393
3394 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3395 system(buf);
3396
3397 fp = fopen("/tmp/Radio_Stats.txt", "r");
3398 if(fp == NULL)
3399 {
3400 printf("/tmp/Radio_Stats.txt not exists \n");
3401 return RETURN_ERR;
3402 }
3403 fclose(fp);
3404
3405 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3406 File_Reading(buf, Value);
3407 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3408
3409 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3410 File_Reading(buf, Value);
3411 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3412
3413 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3414 File_Reading(buf, Value);
3415 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3416
3417 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3418 File_Reading(buf, Value);
3419 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3420
3421 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3422 File_Reading(buf, Value);
3423 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3424
3425 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3426 File_Reading(buf, Value);
3427 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3428
3429 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3430 File_Reading(buf, Value);
3431 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3432
3433 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3434 File_Reading(buf, Value);
3435 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3436
3437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3438 return RETURN_OK;
3439}
3440
3441INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3442{
3443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3444 CHAR buf[MAX_CMD_SIZE] = {0};
3445 FILE *fp = NULL;
3446 INT count = 0;
3447
3448 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3449 {
3450 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3451 File_Reading(buf, status);
3452 }
3453 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3454 return RETURN_OK;
3455}
3456
3457//Get detail radio traffic static info
3458INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3459{
3460
3461#if 0
3462 //ifconfig radio_x
3463 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3464 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3465 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3466 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3467
3468 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3469 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3470 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.
3471 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.
3472
3473 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3474 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].
3475 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3476 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.
3477 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
3478 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
3479 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
3480 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
3481 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
3482
3483 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
3484 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
3485 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
3486 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.
3487
3488 return RETURN_OK;
3489#endif
3490
developera91d99f2022-09-29 15:59:10 +08003491 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003492 BOOL iface_status = FALSE;
3493 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003494
3495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3496 if (NULL == output_struct)
3497 return RETURN_ERR;
3498
developerac6f1142022-12-20 19:26:35 +08003499 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08003500 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003501
developera91d99f2022-09-29 15:59:10 +08003502 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003503
developera91d99f2022-09-29 15:59:10 +08003504 if (iface_status == TRUE)
3505 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3506 else
3507 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003508
developera91d99f2022-09-29 15:59:10 +08003509 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3510 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3511 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3512 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3513 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3514 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3515 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3516 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003517
3518 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3519 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].
3520 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3521 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.
3522 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
3523 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
3524 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
3525 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
3526 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
3527
3528 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
3529 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
3530 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
3531 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.
3532
3533 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3534
3535 return RETURN_OK;
3536}
3537
3538//Set radio traffic static Measureing rules
3539INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3540{
3541 //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
3542 // Else, save the MeasuringRate and MeasuringInterval for future usage
3543
3544 return RETURN_OK;
3545}
3546
3547//To start or stop RadioTrafficStats
3548INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3549{
3550 //zqiu: If the RadioTrafficStats process running
3551 // if(enable)
3552 // return RETURN_OK.
3553 // else
3554 // Stop RadioTrafficStats process
3555 // Else
3556 // if(enable)
3557 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3558 // else
3559 // return RETURN_OK.
3560
3561 return RETURN_OK;
3562}
3563
3564//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
3565INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3566{
3567 //zqiu: Please ignor signalIndex.
3568 if (NULL == SignalLevel)
3569 return RETURN_ERR;
3570 *SignalLevel=(radioIndex==0)?-19:-19;
3571
3572 return RETURN_OK;
3573}
3574
3575//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3576INT wifi_applyRadioSettings(INT radioIndex)
3577{
3578 return RETURN_OK;
3579}
3580
3581//Get the radio index assocated with this SSID entry
3582INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3583{
developer5b398df2022-11-17 20:39:48 +08003584 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003585 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003586 int max_radio_num = 0;
3587 wifi_getMaxRadioNumber(&max_radio_num);
3588 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003589 return RETURN_OK;
3590}
3591
3592//Device.WiFi.SSID.{i}.Enable
3593//Get SSID enable configuration parameters (not the SSID enable status)
3594INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3595{
3596 if (NULL == output_bool)
3597 return RETURN_ERR;
3598
developer06a01d92022-09-07 16:32:39 +08003599 return wifi_getApEnable(ssidIndex, output_bool);
3600}
3601
3602//Device.WiFi.SSID.{i}.Enable
3603//Set SSID enable configuration parameters
3604INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3605{
developer06a01d92022-09-07 16:32:39 +08003606 return wifi_setApEnable(ssidIndex, enable);
3607}
3608
3609//Device.WiFi.SSID.{i}.Status
3610//Get the SSID enable status
3611INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3612{
3613 char cmd[MAX_CMD_SIZE]={0};
3614 char buf[MAX_BUF_SIZE]={0};
3615 BOOL output_bool;
3616
3617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3618 if (NULL == output_string)
3619 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003620
developer06a01d92022-09-07 16:32:39 +08003621 wifi_getApEnable(ssidIndex,&output_bool);
3622 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3623
3624 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3625 return RETURN_OK;
3626}
3627
3628// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3629INT wifi_getSSIDName(INT apIndex, CHAR *output)
3630{
3631 char config_file[MAX_BUF_SIZE] = {0};
3632
3633 if (NULL == output)
3634 return RETURN_ERR;
3635
3636 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3637 wifi_hostapdRead(config_file,"ssid",output,32);
3638
3639 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3640 return RETURN_OK;
3641}
3642
3643// Set a max 32 byte string and sets an internal variable to the SSID name
3644INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3645{
3646 char str[MAX_BUF_SIZE]={'\0'};
3647 char cmd[MAX_CMD_SIZE]={'\0'};
3648 struct params params;
3649 char config_file[MAX_BUF_SIZE] = {0};
3650
3651 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3652 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3653 return RETURN_ERR;
3654
3655 params.name = "ssid";
3656 params.value = ssid_string;
3657 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3658 wifi_hostapdWrite(config_file, &params, 1);
3659 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3661
3662 return RETURN_OK;
3663}
3664
3665//Get the BSSID
3666INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3667{
3668 char cmd[MAX_CMD_SIZE]="";
3669
3670 if (NULL == output_string)
3671 return RETURN_ERR;
3672
3673 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3674 {
developer1d57d002022-10-12 18:03:15 +08003675 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 +08003676 _syscmd(cmd, output_string, 64);
3677 return RETURN_OK;
3678 }
3679 strncpy(output_string, "\0", 1);
3680
3681 return RETURN_ERR;
3682}
3683
3684//Get the MAC address associated with this Wifi SSID
3685INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3686{
3687 wifi_getBaseBSSID(ssidIndex,output_string);
3688 return RETURN_OK;
3689}
3690
3691//Get the basic SSID traffic static info
3692//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3693//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3694INT wifi_applySSIDSettings(INT ssidIndex)
3695{
developerd946fd62022-12-08 18:03:28 +08003696 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003697 BOOL status = false;
3698 char cmd[MAX_CMD_SIZE] = {0};
3699 char buf[MAX_CMD_SIZE] = {0};
3700 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003701 int max_radio_num = 0;
3702 int radioIndex = 0;
3703
3704 wifi_getMaxRadioNumber(&max_radio_num);
3705
3706 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003707
3708 wifi_getApEnable(ssidIndex,&status);
3709 // Do not apply when ssid index is disabled
3710 if (status == false)
3711 return RETURN_OK;
3712
3713 /* Doing full remove and add for ssid Index
3714 * Not all hostapd options are supported with reload
3715 * for example macaddr_acl
3716 */
3717 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3718 return RETURN_ERR;
3719
3720 ret = wifi_setApEnable(ssidIndex,true);
3721
3722 /* Workaround for hostapd issue with multiple bss definitions
3723 * when first created interface will be removed
3724 * then all vaps other vaps on same phy are removed
3725 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003726 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003727 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003728 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003729 return RETURN_ERR;
3730 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003731 _syscmd(cmd, buf, sizeof(buf));
3732 if(*buf == '1')
3733 wifi_setApEnable(apIndex, true);
3734 }
3735
3736 return ret;
3737}
3738
developera3c68b92022-09-13 15:27:29 +08003739struct channels_noise {
3740 int channel;
3741 int noise;
3742};
3743
3744// Return noise array for each channel
3745int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3746{
developerd946fd62022-12-08 18:03:28 +08003747 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003748 FILE *f = NULL;
3749 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003750 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003751 size_t len = 0;
3752 ssize_t read = 0;
3753 int tmp = 0, arr_index = -1;
3754
developerac6f1142022-12-20 19:26:35 +08003755 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003756 return RETURN_ERR;
3757 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003758
3759 if ((f = popen(cmd, "r")) == NULL) {
3760 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3761 return RETURN_ERR;
3762 }
developer5550e242022-09-30 09:59:32 +08003763
3764 while(fgets(line, sizeof(line), f) != NULL) {
3765 if(arr_index < channels_num){
3766 sscanf(line, "%d", &tmp);
3767 if (tmp > 0) { // channel frequency, the first line must be frequency
3768 arr_index++;
3769 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3770 } else { // noise
3771 channels_noise_arr[arr_index].noise = tmp;
3772 }
3773 }else{
3774 break;
developera3c68b92022-09-13 15:27:29 +08003775 }
3776 }
developera3c68b92022-09-13 15:27:29 +08003777 pclose(f);
3778 return RETURN_OK;
3779}
3780
developer06a01d92022-09-07 16:32:39 +08003781//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3782//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3783INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3784{
developera3c68b92022-09-13 15:27:29 +08003785 int index = -1;
3786 wifi_neighbor_ap2_t *scan_array = NULL;
3787 char cmd[256]={0};
3788 char buf[128]={0};
3789 char file_name[32] = {0};
3790 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003791 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003792 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003793 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003794 int freq=0;
3795 FILE *f = NULL;
3796 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003797 int channels_num = 0;
3798 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003799 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003800 bool filter_enable = false;
3801 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003802 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003803
developer615510b2022-09-27 10:14:35 +08003804 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003805
developerac6f1142022-12-20 19:26:35 +08003806 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003807 return RETURN_ERR;
3808
developera3c68b92022-09-13 15:27:29 +08003809 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3810 f = fopen(file_name, "r");
3811 if (f != NULL) {
3812 fgets(filter_SSID, sizeof(file_name), f);
3813 if (strlen(filter_SSID) != 0)
3814 filter_enable = true;
3815 fclose(f);
3816 }
3817
developer033b37b2022-10-18 11:27:46 +08003818 phyId = radio_index_to_phy(radioIndex);
3819 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003820 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003821 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003822
developer5550e242022-09-30 09:59:32 +08003823
developer06a01d92022-09-07 16:32:39 +08003824
developerd946fd62022-12-08 18:03:28 +08003825 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3826 // 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 +08003827 fprintf(stderr, "cmd: %s\n", cmd);
3828 if ((f = popen(cmd, "r")) == NULL) {
3829 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3830 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003831 }
developer5550e242022-09-30 09:59:32 +08003832
3833 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3834 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3835
developer615510b2022-09-27 10:14:35 +08003836 ret = fgets(line, sizeof(line), f);
3837 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003838 if(strstr(line, "BSS") != NULL) { // new neighbor info
3839 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3840 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3841 // 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 +08003842
developera3c68b92022-09-13 15:27:29 +08003843 if (!filter_BSS) {
3844 index++;
3845 wifi_neighbor_ap2_t *tmp;
3846 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3847 if (tmp == NULL) { // no more memory to use
3848 index--;
3849 wifi_dbg_printf("%s: realloc failed\n", __func__);
3850 break;
3851 }
3852 scan_array = tmp;
3853 }
3854 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3855
3856 filter_BSS = false;
3857 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3858 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3859 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3860 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3861 } else if (strstr(line, "freq") != NULL) {
3862 sscanf(line," freq: %d", &freq);
3863 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3864
3865 if (freq >= 2412 && freq <= 2484) {
3866 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3867 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3868 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3869 }
3870 else if (freq >= 5160 && freq <= 5805) {
3871 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3872 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3873 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3874 }
3875
3876 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003877 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003878 for (int i = 0; i < channels_num; i++) {
3879 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3880 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3881 break;
3882 }
3883 }
3884 }
3885 } else if (strstr(line, "beacon interval") != NULL) {
3886 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3887 } else if (strstr(line, "signal") != NULL) {
3888 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3889 } else if (strstr(line,"SSID") != NULL) {
3890 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3891 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3892 filter_BSS = true;
3893 }
3894 } else if (strstr(line, "Supported rates") != NULL) {
3895 char SRate[80] = {0}, *tmp = NULL;
3896 memset(buf, 0, sizeof(buf));
3897 strcpy(SRate, line);
3898 tmp = strtok(SRate, ":");
3899 tmp = strtok(NULL, ":");
3900 strcpy(buf, tmp);
3901 memset(SRate, 0, sizeof(SRate));
3902
3903 tmp = strtok(buf, " \n");
3904 while (tmp != NULL) {
3905 strcat(SRate, tmp);
3906 if (SRate[strlen(SRate) - 1] == '*') {
3907 SRate[strlen(SRate) - 1] = '\0';
3908 }
3909 strcat(SRate, ",");
3910
3911 tmp = strtok(NULL, " \n");
3912 }
3913 SRate[strlen(SRate) - 1] = '\0';
3914 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3915 } else if (strstr(line, "DTIM") != NULL) {
3916 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3917 } else if (strstr(line, "VHT capabilities") != NULL) {
3918 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3919 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3920 } else if (strstr(line, "HT capabilities") != NULL) {
3921 strcat(scan_array[index].ap_SupportedStandards, ",n");
3922 strcpy(scan_array[index].ap_OperatingStandards, "n");
3923 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003924 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003925 sscanf(line," * channel width: %d", &vht_channel_width);
3926 if(vht_channel_width == 1) {
3927 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3928 } else {
3929 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3930 }
3931 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3932 continue;
3933 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003934 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003935 sscanf(line," * secondary channel offset: %s", &buf);
3936 if (!strcmp(buf, "above")) {
3937 //40Mhz +
3938 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3939 }
3940 else if (!strcmp(buf, "below")) {
3941 //40Mhz -
3942 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3943 } else {
3944 //20Mhz
3945 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3946 }
3947 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3948 continue;
3949 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003950 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3951 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3952 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003953 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3954 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003955 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003956 else
developer615510b2022-09-27 10:14:35 +08003957 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003958 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003959 if (strstr(line, "HE80/5GHz") != NULL) {
3960 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3961 ret = fgets(line, sizeof(line), f);
3962 } else
3963 continue;
developera3c68b92022-09-13 15:27:29 +08003964 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003965 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003966 }
developer615510b2022-09-27 10:14:35 +08003967 continue;
developera3c68b92022-09-13 15:27:29 +08003968 } else if (strstr(line, "WPA") != NULL) {
3969 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3970 } else if (strstr(line, "RSN") != NULL) {
3971 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3972 } else if (strstr(line, "Group cipher") != NULL) {
3973 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3974 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3975 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3976 }
3977 }
developer615510b2022-09-27 10:14:35 +08003978 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003979 }
3980
3981 if (!filter_BSS) {
3982 *output_array_size = index + 1;
3983 } else {
3984 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3985 *output_array_size = index;
3986 }
3987 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003988 pclose(f);
developer5550e242022-09-30 09:59:32 +08003989 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003991 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003992}
3993
3994//>> Deprecated: used for old RDKB code.
3995INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3996{
3997 INT status = RETURN_ERR;
3998
3999 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4000 output_struct->wifi_PLCPErrorCount = 0;
4001 output_struct->wifi_FCSErrorCount = 0;
4002 output_struct->wifi_InvalidMACCount = 0;
4003 output_struct->wifi_PacketsOtherReceived = 0;
4004 output_struct->wifi_Noise = 0;
4005 status = RETURN_OK;
4006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4007 return status;
4008}
4009
4010INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4011{
developerd946fd62022-12-08 18:03:28 +08004012 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004013 char cmd[128] = {0};
4014 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004015 char *pos = NULL;
4016
4017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4018 if (NULL == output_struct)
4019 return RETURN_ERR;
4020
developerac6f1142022-12-20 19:26:35 +08004021 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004022 return RETURN_ERR;
4023
developer06a01d92022-09-07 16:32:39 +08004024 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4025
developerd946fd62022-12-08 18:03:28 +08004026 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004027 _syscmd(cmd, buf, sizeof(buf));
4028
4029 pos = buf;
4030 if ((pos = strstr(pos, "RX packets:")) == NULL)
4031 return RETURN_ERR;
4032 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4033
4034 if ((pos = strstr(pos, "TX packets:")) == NULL)
4035 return RETURN_ERR;
4036 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4037
4038 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4039 return RETURN_ERR;
4040 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4041
4042 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4043 return RETURN_ERR;
4044 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4045
developerd946fd62022-12-08 18:03:28 +08004046 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004047 _syscmd(cmd, buf, sizeof(buf));
4048 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4049
4050#if 0
4051 //TODO: need to revisit below implementation
4052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4053 char interface_name[MAX_BUF_SIZE] = {0};
4054 char interface_status[MAX_BUF_SIZE] = {0};
4055 char Value[MAX_BUF_SIZE] = {0};
4056 char buf[MAX_CMD_SIZE] = {0};
4057 char cmd[MAX_CMD_SIZE] = {0};
4058 FILE *fp = NULL;
4059
4060 if (NULL == output_struct) {
4061 return RETURN_ERR;
4062 }
4063
4064 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4065
4066 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4067 {
4068 if(apIndex == 0) //private_wifi for 2.4G
4069 {
developerac6f1142022-12-20 19:26:35 +08004070 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004071 }
4072 else if(apIndex == 1) //private_wifi for 5G
4073 {
developerac6f1142022-12-20 19:26:35 +08004074 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004075 }
4076 else if(apIndex == 4) //public_wifi for 2.4G
4077 {
4078 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4079 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4080 {
4081 return RETURN_ERR;
4082 }
4083 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004084 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004085 else//tenda
developerac6f1142022-12-20 19:26:35 +08004086 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004087 }
4088 else if(apIndex == 5) //public_wifi for 5G
4089 {
developerac6f1142022-12-20 19:26:35 +08004090 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004091 }
4092
4093 GetIfacestatus(interface_name, interface_status);
4094
4095 if(0 != strcmp(interface_status, "1"))
4096 return RETURN_ERR;
4097
4098 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4099 system(cmd);
4100
4101 fp = fopen("/tmp/SSID_Stats.txt", "r");
4102 if(fp == NULL)
4103 {
4104 printf("/tmp/SSID_Stats.txt not exists \n");
4105 return RETURN_ERR;
4106 }
4107 fclose(fp);
4108
4109 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4110 File_Reading(buf, Value);
4111 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4112
4113 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4114 File_Reading(buf, Value);
4115 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4116
4117 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4118 File_Reading(buf, Value);
4119 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4120
4121 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4122 File_Reading(buf, Value);
4123 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4124
4125 /* There is no specific parameter from caller to associate the value wifi_Associations */
4126 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4127 //_syscmd(cmd, buf, sizeof(buf));
4128 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4129 }
4130#endif
4131 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4132 return RETURN_OK;
4133}
4134
4135INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4136{
4137 char interface_name[MAX_BUF_SIZE] = {0};
4138 char interface_status[MAX_BUF_SIZE] = {0};
4139 char Value[MAX_BUF_SIZE] = {0};
4140 char buf[MAX_CMD_SIZE] = {0};
4141 char cmd[MAX_CMD_SIZE] = {0};
4142 FILE *fp = NULL;
4143
4144 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4145 if (NULL == output_struct)
4146 return RETURN_ERR;
4147
4148 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4149
developerac6f1142022-12-20 19:26:35 +08004150 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004151 return RETURN_ERR;
4152 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004153
developerd946fd62022-12-08 18:03:28 +08004154 if(0 != strcmp(interface_status, "1"))
4155 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004156
developerd946fd62022-12-08 18:03:28 +08004157 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4158 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004159
developerd946fd62022-12-08 18:03:28 +08004160 fp = fopen("/tmp/SSID_Stats.txt", "r");
4161 if(fp == NULL)
4162 {
4163 printf("/tmp/SSID_Stats.txt not exists \n");
4164 return RETURN_ERR;
4165 }
4166 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004167
developerd946fd62022-12-08 18:03:28 +08004168 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4169 File_Reading(buf, Value);
4170 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004171
developerd946fd62022-12-08 18:03:28 +08004172 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4173 File_Reading(buf, Value);
4174 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004175
developerd946fd62022-12-08 18:03:28 +08004176 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4177 File_Reading(buf, Value);
4178 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004179
developerd946fd62022-12-08 18:03:28 +08004180 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4181 File_Reading(buf, Value);
4182 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004183
4184 output_struct->wifi_UnicastPacketsSent = 0;
4185 output_struct->wifi_UnicastPacketsReceived = 0;
4186 output_struct->wifi_MulticastPacketsSent = 0;
4187 output_struct->wifi_MulticastPacketsReceived = 0;
4188 output_struct->wifi_BroadcastPacketsSent = 0;
4189 output_struct->wifi_BroadcastPacketsRecevied = 0;
4190 output_struct->wifi_UnknownPacketsReceived = 0;
4191
4192 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4193 return RETURN_OK;
4194}
4195
4196INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4197{
4198 INT status = RETURN_ERR;
4199
4200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4201 //Below values should get updated from hal
4202 output_struct->wifi_RetransCount=0;
4203 output_struct->wifi_FailedRetransCount=0;
4204 output_struct->wifi_RetryCount=0;
4205 output_struct->wifi_MultipleRetryCount=0;
4206 output_struct->wifi_ACKFailureCount=0;
4207 output_struct->wifi_AggregatedPacketCount=0;
4208
4209 status = RETURN_OK;
4210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4211
4212 return status;
4213}
4214
4215INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4216{
4217 INT status = RETURN_ERR;
4218 UINT index;
4219 wifi_neighbor_ap_t *pt=NULL;
4220
4221 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4222 *output_array_size=2;
4223 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4224 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4225 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4226 strcpy(pt->ap_Radio,"");
4227 strcpy(pt->ap_SSID,"");
4228 strcpy(pt->ap_BSSID,"");
4229 strcpy(pt->ap_Mode,"");
4230 pt->ap_Channel=1;
4231 pt->ap_SignalStrength=0;
4232 strcpy(pt->ap_SecurityModeEnabled,"");
4233 strcpy(pt->ap_EncryptionMode,"");
4234 strcpy(pt->ap_OperatingFrequencyBand,"");
4235 strcpy(pt->ap_SupportedStandards,"");
4236 strcpy(pt->ap_OperatingStandards,"");
4237 strcpy(pt->ap_OperatingChannelBandwidth,"");
4238 pt->ap_BeaconPeriod=1;
4239 pt->ap_Noise=0;
4240 strcpy(pt->ap_BasicDataTransferRates,"");
4241 strcpy(pt->ap_SupportedDataTransferRates,"");
4242 pt->ap_DTIMPeriod=1;
4243 pt->ap_ChannelUtilization = 1;
4244 }
4245
4246 status = RETURN_OK;
4247 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4248
4249 return status;
4250}
4251
4252//----------------- AP HAL -------------------------------
4253
4254//>> Deprecated: used for old RDKB code.
4255INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4256{
4257 if (NULL == output_ulong || NULL == output_struct)
4258 return RETURN_ERR;
4259 *output_ulong = 0;
4260 *output_struct = NULL;
4261 return RETURN_OK;
4262}
4263
4264#ifdef HAL_NETLINK_IMPL
4265static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4266 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4267 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4268 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4269 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4270 char mac_addr[20];
4271 static int count=0;
4272 int rate=0;
4273
4274 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4275
4276 nla_parse(tb,
4277 NL80211_ATTR_MAX,
4278 genlmsg_attrdata(gnlh, 0),
4279 genlmsg_attrlen(gnlh, 0),
4280 NULL);
4281
4282 if(!tb[NL80211_ATTR_STA_INFO]) {
4283 fprintf(stderr, "sta stats missing!\n");
4284 return NL_SKIP;
4285 }
4286
4287
4288 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4289 fprintf(stderr, "failed to parse nested attributes!\n");
4290 return NL_SKIP;
4291 }
4292
4293 //devIndex starts from 1
4294 if( ++count == out->wifi_devIndex )
4295 {
4296 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4297 //Getting the mac addrress
4298 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4299
4300 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4301 fprintf(stderr, "failed to parse nested rate attributes!");
4302 return NL_SKIP;
4303 }
4304
4305 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4306 if(rinfo[NL80211_RATE_INFO_BITRATE])
4307 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4308 out->wifi_devTxRate = rate/10;
4309 }
4310
4311 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4312 fprintf(stderr, "failed to parse nested rate attributes!");
4313 return NL_SKIP;
4314 }
4315
4316 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4317 if(rinfo[NL80211_RATE_INFO_BITRATE])
4318 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4319 out->wifi_devRxRate = rate/10;
4320 }
4321 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4322 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4323
4324 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4325 count = 0; //starts the count for next cycle
4326 return NL_STOP;
4327 }
4328
4329 return NL_SKIP;
4330
4331}
4332#endif
4333
4334INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4335{
4336#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004337 Netlink nl = {0};
4338 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004339 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004340
developer30423732022-12-01 16:17:49 +08004341 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004342 info.wifi_devIndex = devIndex;
4343
developerac6f1142022-12-20 19:26:35 +08004344 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004345 return RETURN_ERR;
4346
4347 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004348
4349 nl.id = initSock80211(&nl);
4350
4351 if (nl.id < 0) {
4352 fprintf(stderr, "Error initializing netlink \n");
4353 return -1;
4354 }
4355
4356 struct nl_msg* msg = nlmsg_alloc();
4357
4358 if (!msg) {
4359 fprintf(stderr, "Failed to allocate netlink message.\n");
4360 nlfree(&nl);
4361 return -2;
4362 }
4363
4364 genlmsg_put(msg,
4365 NL_AUTO_PORT,
4366 NL_AUTO_SEQ,
4367 nl.id,
4368 0,
4369 NLM_F_DUMP,
4370 NL80211_CMD_GET_STATION,
4371 0);
4372
4373 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4374 nl_send_auto(nl.socket, msg);
4375 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4376 nl_recvmsgs(nl.socket, nl.cb);
4377 nlmsg_free(msg);
4378 nlfree(&nl);
4379
4380 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4381 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4382 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4383 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4384 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4385 return RETURN_OK;
4386#else
4387 //iw utility to retrieve station information
4388#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4389#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4390#define MACFILE "/tmp/wifi_AssoMac.txt"
4391#define TXRATEFILE "/tmp/wifi_txrate.txt"
4392#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4393 FILE *file = NULL;
4394 char if_name[10] = {'\0'};
4395 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004396 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004397 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004398 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004399
developerac6f1142022-12-20 19:26:35 +08004400 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004401 return RETURN_ERR;
4402
4403 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004404
4405 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4406 file = popen(pipeCmd, "r");
4407
4408 if(file == NULL)
4409 return RETURN_ERR; //popen failed
4410
4411 fgets(line, sizeof line, file);
4412 device = atoi(line);
4413 pclose(file);
4414
4415 if(device == 0)
4416 return RETURN_ERR; //No devices are connected
4417
4418 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4419 system(pipeCmd);
4420
4421 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4422
4423 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4424
4425 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4426
4427 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4428
4429 //devIndex starts from 1, ++count
4430 if((file = fopen(SIGNALFILE, "r")) != NULL )
4431 {
4432 for(count =0;fgets(line, sizeof line, file) != NULL;)
4433 {
4434 if (++count == devIndex)
4435 {
4436 output_struct->wifi_devSignalStrength = atoi(line);
4437 break;
4438 }
4439 }
4440 fclose(file);
4441 }
4442 else
4443 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4444
4445 if((file = fopen(MACFILE, "r")) != NULL )
4446 {
4447 for(count =0;fgets(line, sizeof line, file) != NULL;)
4448 {
4449 if (++count == devIndex)
4450 {
4451 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]);
4452 break;
4453 }
4454 }
4455 fclose(file);
4456 }
4457 else
4458 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4459
4460 if((file = fopen(TXRATEFILE, "r")) != NULL )
4461 {
4462 for(count =0;fgets(line, sizeof line, file) != NULL;)
4463 {
4464 if (++count == devIndex)
4465 {
4466 output_struct->wifi_devTxRate = atoi(line);
4467 break;
4468 }
4469 }
4470 fclose(file);
4471 }
4472 else
4473 fprintf(stderr,"fopen wifi_txrate.txt failed");
4474
4475 if((file = fopen(RXRATEFILE, "r")) != NULL)
4476 {
4477 for(count =0;fgets(line, sizeof line, file) != NULL;)
4478 {
4479 if (++count == devIndex)
4480 {
4481 output_struct->wifi_devRxRate = atoi(line);
4482 break;
4483 }
4484 }
4485 fclose(file);
4486 }
4487 else
4488 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4489
4490 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4491
4492 return RETURN_OK;
4493#endif
4494}
4495
4496INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4497{
4498 if (NULL == device)
4499 return RETURN_ERR;
4500 return RETURN_OK;
4501}
4502//<<
4503
4504
4505//--------------wifi_ap_hal-----------------------------
4506//enables CTS protection for the radio used by this AP
4507INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4508{
4509 //save config and Apply instantly
4510 return RETURN_ERR;
4511}
4512
4513// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4514INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4515{
developer463d39a2022-09-13 15:32:51 +08004516 char config_file[64] = {'\0'};
4517 char buf[64] = {'\0'};
4518 struct params list;
4519
4520 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4521 list.name = "ht_coex";
4522 snprintf(buf, sizeof(buf), "%d", enable);
4523 list.value = buf;
4524
4525 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4526 wifi_hostapdWrite(config_file, &list, 1);
4527 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4528
4529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4530
4531 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004532}
4533
4534//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4535INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4536{
developerea4bcce2022-09-13 15:26:13 +08004537 char config_file[MAX_BUF_SIZE] = {'\0'};
4538 char buf[MAX_BUF_SIZE] = {'\0'};
4539 struct params list;
4540
4541 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4542 if (threshold < 256 || threshold > 2346 )
4543 return RETURN_ERR;
4544 list.name = "fragm_threshold";
4545 snprintf(buf, sizeof(buf), "%d", threshold);
4546 list.value = buf;
4547
4548 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4549 wifi_hostapdWrite(config_file, &list, 1);
4550 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004551
developerea4bcce2022-09-13 15:26:13 +08004552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004553
4554 return RETURN_OK;
4555}
4556
4557// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4558INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4559{
developer51a927d2022-09-13 15:42:22 +08004560 char config_file[64] = {'\0'};
4561 char cmd[128] = {'\0'};
4562 char buf[64] = {'\0'};
4563 char stbc_config[16] = {'\0'};
4564 wifi_band band;
4565 int iterator = 0;
4566 BOOL current_stbc = FALSE;
4567
4568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4569
4570 band = wifi_index_to_band(radioIndex);
4571 if (band == band_invalid)
4572 return RETURN_ERR;
4573
4574 if (band == band_2_4)
4575 iterator = 1;
4576 else if (band == band_5)
4577 iterator = 2;
4578 else
4579 return RETURN_OK;
4580
4581 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4582
4583 // set ht and vht config
4584 for (int i = 0; i < iterator; i++) {
4585 memset(stbc_config, 0, sizeof(stbc_config));
4586 memset(cmd, 0, sizeof(cmd));
4587 memset(buf, 0, sizeof(buf));
4588 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4589 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4590 _syscmd(cmd, buf, sizeof(buf));
4591 if (strlen(buf) != 0)
4592 current_stbc = TRUE;
4593 if (current_stbc == STBC_Enable)
4594 continue;
4595
4596 if (STBC_Enable == TRUE) {
4597 // Append the STBC flags in capab config
4598 memset(cmd, 0, sizeof(cmd));
4599 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004600 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004601 else
developer6372c2b2022-10-27 17:39:51 +08004602 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 +08004603 _syscmd(cmd, buf, sizeof(buf));
4604 } else if (STBC_Enable == FALSE) {
4605 // Remove the STBC flags and remain other flags in capab
4606 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004607 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004608 _syscmd(cmd, buf, sizeof(buf));
4609 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004610 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004611 _syscmd(cmd, buf, sizeof(buf));
4612 }
4613 }
4614
4615 wifi_reloadAp(radioIndex);
4616
4617 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4618 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004619}
4620
4621// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4622INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4623{
developer54e6b9f2022-09-28 14:41:20 +08004624 char AMSDU_file_path[64] = {0};
4625
4626 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4627
4628 if(output_bool == NULL)
4629 return RETURN_ERR;
4630
4631 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4632
4633 if (access(AMSDU_file_path, F_OK) == 0)
4634 *output_bool = TRUE;
4635 else
4636 *output_bool = FALSE;
4637
4638 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4639 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004640}
4641
4642// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4643INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4644{
developerd946fd62022-12-08 18:03:28 +08004645 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004646 char cmd[64]={0};
4647 char buf[64]={0};
4648 char AMSDU_file_path[64] = {0};
4649
4650 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4651
developerac6f1142022-12-20 19:26:35 +08004652 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004653 return RETURN_ERR;
4654 sprintf(cmd, "mt76-vendor %s set ap_wireless amsdu=%d", interface_name, amsduEnable);
developer54e6b9f2022-09-28 14:41:20 +08004655 _syscmd(cmd, buf, sizeof(buf));
4656
4657 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4658 memset(cmd, 0, sizeof(cmd));
4659 if (amsduEnable == TRUE)
4660 sprintf(cmd, "touch %s", AMSDU_file_path);
4661 else
4662 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4663 _syscmd(cmd, buf, sizeof(buf));
4664
4665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4666 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004667}
4668
4669//P2 // outputs the number of Tx streams
4670INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4671{
developer2de97692022-09-26 14:00:03 +08004672 char buf[8] = {0};
4673 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004674 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004675
4676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4677
4678 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4679 _syscmd(cmd, buf, sizeof(buf));
4680
developer033b37b2022-10-18 11:27:46 +08004681 phyId = radio_index_to_phy(radioIndex);
developer2de97692022-09-26 14:00:03 +08004682 // if there is no record, output the max number of spatial streams
4683 if (strlen(buf) == 0) {
developer033b37b2022-10-18 11:27:46 +08004684 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", phyId);
developer2de97692022-09-26 14:00:03 +08004685 _syscmd(cmd, buf, sizeof(buf));
4686 }
4687
4688 *output_int = (INT)strtol(buf, NULL, 10);
4689
4690 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4691
4692 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004693}
4694
4695//P2 // sets the number of Tx streams to an enviornment variable
4696INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4697{
developer2de97692022-09-26 14:00:03 +08004698 char cmd[128] = {0};
4699 char buf[128] = {0};
4700 char chain_mask_file[128] = {0};
4701 FILE *f = NULL;
developer033b37b2022-10-18 11:27:46 +08004702 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004703
4704 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4705
4706 if (numStreams == 0) {
developer30423732022-12-01 16:17:49 +08004707 fprintf(stderr, "The mask did not support 0 (auto).\n");
developer2de97692022-09-26 14:00:03 +08004708 return RETURN_ERR;
4709 }
4710 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004711
4712 phyId = radio_index_to_phy(radioIndex);
4713 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004714 _syscmd(cmd, buf, sizeof(buf));
4715
4716 if (strlen(buf) > 0) {
4717 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4718 return RETURN_ERR;
4719 }
4720 wifi_setRadioEnable(radioIndex, TRUE);
4721
4722 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4723 f = fopen(chain_mask_file, "w");
4724 if (f == NULL) {
4725 fprintf(stderr, "%s: fopen failed.\n", __func__);
4726 return RETURN_ERR;
4727 }
4728 fprintf(f, "%d", numStreams);
4729 fclose(f);
4730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4731 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004732}
4733
4734//P2 // outputs the number of Rx streams
4735INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4736{
developer2de97692022-09-26 14:00:03 +08004737 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4738 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4739 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004740 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004741 }
4742 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004743 return RETURN_OK;
4744}
4745
4746//P2 // sets the number of Rx streams to an enviornment variable
4747INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4748{
developer2de97692022-09-26 14:00:03 +08004749 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4750 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4751 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4752 return RETURN_ERR;
4753 }
4754 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004755 return RETURN_ERR;
4756}
4757
4758//Get radio RDG enable setting
4759INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4760{
4761 if (NULL == output_bool)
4762 return RETURN_ERR;
4763 *output_bool = TRUE;
4764 return RETURN_OK;
4765}
4766
4767//Get radio RDG enable setting
4768INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4769{
4770 if (NULL == output_bool)
4771 return RETURN_ERR;
4772 *output_bool = TRUE;
4773 return RETURN_OK;
4774}
4775
4776//Set radio RDG enable setting
4777INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4778{
4779 return RETURN_ERR;
4780}
4781
4782//Get radio ADDBA enable setting
4783INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4784{
4785 if (NULL == output_bool)
4786 return RETURN_ERR;
4787 *output_bool = TRUE;
4788 return RETURN_OK;
4789}
4790
4791//Set radio ADDBA enable setting
4792INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4793{
4794 return RETURN_ERR;
4795}
4796
4797//Get radio auto block ack enable setting
4798INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4799{
4800 if (NULL == output_bool)
4801 return RETURN_ERR;
4802 *output_bool = TRUE;
4803 return RETURN_OK;
4804}
4805
4806//Set radio auto block ack enable setting
4807INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4808{
4809 return RETURN_ERR;
4810}
4811
4812//Get radio 11n pure mode enable support
4813INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4814{
4815 if (NULL == output_bool)
4816 return RETURN_ERR;
4817 *output_bool = TRUE;
4818 return RETURN_OK;
4819}
4820
4821//Get radio 11n pure mode enable setting
4822INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4823{
4824 if (NULL == output_bool)
4825 return RETURN_ERR;
4826 *output_bool = TRUE;
4827 return RETURN_OK;
4828}
4829
4830//Set radio 11n pure mode enable setting
4831INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4832{
4833 return RETURN_ERR;
4834}
4835
4836//Get radio IGMP snooping enable setting
4837INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4838{
developerd946fd62022-12-08 18:03:28 +08004839 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004840 char cmd[128]={0};
4841 char buf[4]={0};
4842 bool bridge = FALSE, mac80211 = FALSE;
4843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4844
4845 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004846 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004847
4848 *output_bool = FALSE;
4849
4850 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4851 _syscmd(cmd, buf, sizeof(buf));
4852 if (strncmp(buf, "1", 1) == 0)
4853 bridge = TRUE;
4854
developerac6f1142022-12-20 19:26:35 +08004855 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004856 return RETURN_ERR;
4857 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 +08004858 _syscmd(cmd, buf, sizeof(buf));
4859 if (strncmp(buf, "1", 1) == 0)
4860 mac80211 = TRUE;
4861
4862 if (bridge && mac80211)
4863 *output_bool = TRUE;
4864
4865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004866 return RETURN_OK;
4867}
4868
4869//Set radio IGMP snooping enable setting
4870INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4871{
developerd946fd62022-12-08 18:03:28 +08004872 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004873 char cmd[128]={0};
4874 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004875 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4877
4878 // bridge
4879 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4880 _syscmd(cmd, buf, sizeof(buf));
4881
developer804c64f2022-10-19 13:54:40 +08004882 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004883 // mac80211
developer804c64f2022-10-19 13:54:40 +08004884 for (int i = 0; i < max_num_radios; i++) {
developerac6f1142022-12-20 19:26:35 +08004885 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004886 return RETURN_ERR;
4887 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 +08004888 _syscmd(cmd, buf, sizeof(buf));
4889 }
4890 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4891 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004892}
4893
4894//Get the Reset count of radio
4895INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4896{
4897 if (NULL == output_int)
4898 return RETURN_ERR;
4899 *output_int = (radioIndex==0)? 1: 3;
4900
4901 return RETURN_OK;
4902}
4903
4904
4905//---------------------------------------------------------------------------------------------------
4906//
4907// Additional Wifi AP level APIs used for Access Point devices
4908//
4909//---------------------------------------------------------------------------------------------------
4910
4911// creates a new ap and pushes these parameters to the hardware
4912INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4913{
developerd946fd62022-12-08 18:03:28 +08004914 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004915 char buf[1024];
4916 char cmd[128];
developer033b37b2022-10-18 11:27:46 +08004917 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004918
4919 if (NULL == essid)
4920 return RETURN_ERR;
4921
developerac6f1142022-12-20 19:26:35 +08004922 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004923 return RETURN_ERR;
4924
developer033b37b2022-10-18 11:27:46 +08004925 phyId = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +08004926 snprintf(cmd,sizeof(cmd), "wlanconfig %s create wlandev %s%d wlanmode ap", interface_name, RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08004927 _syscmd(cmd, buf, sizeof(buf));
4928
developerd946fd62022-12-08 18:03:28 +08004929 snprintf(cmd,sizeof(cmd), "iwconfig %s essid %s mode master", interface_name, essid);
developer06a01d92022-09-07 16:32:39 +08004930 _syscmd(cmd, buf, sizeof(buf));
4931
4932 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4933
developerd946fd62022-12-08 18:03:28 +08004934 snprintf(cmd,sizeof(cmd), "ifconfig %s txqueuelen 1000", interface_name);
developer06a01d92022-09-07 16:32:39 +08004935 _syscmd(cmd, buf, sizeof(buf));
4936
4937 return RETURN_OK;
4938}
4939
4940// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4941INT wifi_deleteAp(INT apIndex)
4942{
developerd946fd62022-12-08 18:03:28 +08004943 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004944 char buf[1024];
4945 char cmd[128];
4946
developerac6f1142022-12-20 19:26:35 +08004947 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004948 return RETURN_ERR;
4949 snprintf(cmd,sizeof(cmd), "wlanconfig %s destroy", interface_name);
developer06a01d92022-09-07 16:32:39 +08004950 _syscmd(cmd, buf, sizeof(buf));
4951
4952 wifi_removeApSecVaribles(apIndex);
4953
4954 return RETURN_OK;
4955}
4956
4957// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4958INT wifi_getApName(INT apIndex, CHAR *output_string)
4959{
developerd946fd62022-12-08 18:03:28 +08004960 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004961 if(NULL == output_string)
4962 return RETURN_ERR;
4963
developerac6f1142022-12-20 19:26:35 +08004964 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08004965 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08004966 else
4967 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004968 return RETURN_OK;
4969}
4970
4971// Outputs the index number in that corresponds to the SSID string
4972INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4973{
developerd946fd62022-12-08 18:03:28 +08004974 char cmd [128] = {0};
4975 char buf[32] = {0};
4976 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08004977 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08004978
developerd946fd62022-12-08 18:03:28 +08004979 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
4980 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08004981
developerac6f1142022-12-20 19:26:35 +08004982 if (strlen(buf) != 0) {
4983 apIndex_str = strtok(buf, "\n");
4984 *output_int = strtoul(apIndex_str, NULL, 10);
4985 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004986 }
developer67b8ee92022-12-20 10:48:43 +08004987
4988 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
4989 apIndex_str = strstr(inputSsidString, AP_PREFIX);
4990 if (apIndex_str) {
4991 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
4992 return RETURN_OK;
4993 }
developerd946fd62022-12-08 18:03:28 +08004994 *output_int = -1;
4995 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004996}
4997
4998INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4999{
5000 return wifi_getIndexFromName(inputSsidString, output_int);
5001}
5002
5003// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5004INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5005{
5006 char buf[MAX_BUF_SIZE] = {0};
5007 char cmd[MAX_CMD_SIZE] = {0};
5008 char config_file[MAX_BUF_SIZE] = {0};
5009
5010 if(NULL == output_string)
5011 return RETURN_ERR;
5012
5013 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5014 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5015 if((strcmp(buf,"3")==0))
5016 snprintf(output_string, 32, "WPAand11i");
5017 else if((strcmp(buf,"2")==0))
5018 snprintf(output_string, 32, "11i");
5019 else if((strcmp(buf,"1")==0))
5020 snprintf(output_string, 32, "WPA");
5021 else
5022 snprintf(output_string, 32, "None");
5023
5024 return RETURN_OK;
5025}
5026
5027// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5028INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5029{
5030 char config_file[MAX_BUF_SIZE] = {0};
5031 struct params list;
5032
5033 if (NULL == beaconTypeString)
5034 return RETURN_ERR;
5035 list.name = "wpa";
5036 list.value = "0";
5037
5038 if((strcmp(beaconTypeString,"WPAand11i")==0))
5039 list.value="3";
5040 else if((strcmp(beaconTypeString,"11i")==0))
5041 list.value="2";
5042 else if((strcmp(beaconTypeString,"WPA")==0))
5043 list.value="1";
5044
5045 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5046 wifi_hostapdWrite(config_file, &list, 1);
5047 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5048 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5049 return RETURN_OK;
5050}
5051
5052// sets the beacon interval on the hardware for this AP
5053INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5054{
developer5f222492022-09-13 15:21:52 +08005055 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5056 struct params params={'\0'};
5057 char buf[MAX_BUF_SIZE] = {'\0'};
5058 char config_file[MAX_BUF_SIZE] = {'\0'};
5059
5060 params.name = "beacon_int";
5061 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5062 params.value = buf;
5063
5064 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5065 wifi_hostapdWrite(config_file, &params, 1);
5066
5067 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5069 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005070}
5071
5072INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5073{
developer5b398df2022-11-17 20:39:48 +08005074 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5075 return RETURN_ERR;
5076 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005077}
5078
5079// Get the packet size threshold supported.
5080INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5081{
5082 //save config and apply instantly
5083 if (NULL == output_bool)
5084 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005085 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005086 return RETURN_OK;
5087}
5088
5089// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5090INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5091{
developerd946fd62022-12-08 18:03:28 +08005092 char interface_name[16] = {0};
developer514406b2022-12-05 17:20:21 +08005093 char buf[16] = {0};
5094 char config_file[128] = {0};
5095 struct params param = {0};
5096
5097 if (threshold > 65535) {
5098 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5099 return RETURN_ERR;
5100 }
developer06a01d92022-09-07 16:32:39 +08005101
developerac6f1142022-12-20 19:26:35 +08005102 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005103 return RETURN_ERR;
5104 snprintf(config_file, sizeof(config_file), "%s.conf", interface_name);
developer514406b2022-12-05 17:20:21 +08005105 snprintf(buf, sizeof(buf), "%u", threshold);
5106 param.name = "rts_threshold";
5107 param.value = buf;
5108 wifi_hostapdWrite(config_file, &param, 1);
5109 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5110 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005111
5112 return RETURN_OK;
5113}
5114
5115// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5116INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5117{
5118 if (NULL == output_string)
5119 return RETURN_ERR;
5120 snprintf(output_string, 32, "TKIPandAESEncryption");
5121 return RETURN_OK;
5122
5123}
5124
5125// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5126INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5127{
5128 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005129 char *param_name = NULL;
5130 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005131
5132 if(NULL == output_string)
5133 return RETURN_ERR;
5134
5135 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5136 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5137
5138 if(strcmp(buf,"0")==0)
5139 {
5140 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5141 snprintf(output_string, 32, "None");
5142 return RETURN_OK;
5143 }
5144 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5145 param_name = "rsn_pairwise";
5146 else if((strcmp(buf,"1")==0))
5147 param_name = "wpa_pairwise";
5148 else
5149 return RETURN_ERR;
5150 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005151 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005152 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5153 param_name = "wpa_pairwise";
5154 memset(output_string, '\0', 32);
5155 wifi_hostapdRead(config_file, param_name, output_string, 32);
5156 }
developer06a01d92022-09-07 16:32:39 +08005157 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5158
5159 if(strcmp(output_string,"TKIP") == 0)
5160 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5161 else if(strcmp(output_string,"CCMP") == 0)
5162 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5163 else if(strcmp(output_string,"TKIP CCMP") == 0)
5164 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5165
5166 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5167 return RETURN_OK;
5168}
5169
5170// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5171INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5172{
5173 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5174 struct params params={'\0'};
5175 char output_string[32];
5176 char config_file[MAX_BUF_SIZE] = {0};
5177
5178 memset(output_string,'\0',32);
5179 wifi_getApWpaEncryptionMode(apIndex,output_string);
5180
5181 if(strcmp(encMode, "TKIPEncryption") == 0)
5182 params.value = "TKIP";
5183 else if(strcmp(encMode,"AESEncryption") == 0)
5184 params.value = "CCMP";
5185 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5186 params.value = "TKIP CCMP";
5187
5188 if((strcmp(output_string,"WPAand11i")==0))
5189 {
5190 params.name = "wpa_pairwise";
5191 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5192 wifi_hostapdWrite(config_file, &params, 1);
5193 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5194
developer30423732022-12-01 16:17:49 +08005195 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5197 wifi_hostapdWrite(config_file, &params, 1);
5198 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5199
5200 return RETURN_OK;
5201 }
5202 else if((strcmp(output_string,"11i")==0))
5203 {
5204 params.name = "rsn_pairwise";
5205 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5206 wifi_hostapdWrite(config_file, &params, 1);
5207 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5208 return RETURN_OK;
5209 }
5210 else if((strcmp(output_string,"WPA")==0))
5211 {
5212 params.name = "wpa_pairwise";
5213 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5214 wifi_hostapdWrite(config_file, &params, 1);
5215 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5216 return RETURN_OK;
5217 }
5218
5219 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5220 return RETURN_OK;
5221}
5222
5223// deletes internal security varable settings for this ap
5224INT wifi_removeApSecVaribles(INT apIndex)
5225{
5226 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005227 //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 +08005228 //_syscmd(cmd, buf, sizeof(buf));
5229
developerd946fd62022-12-08 18:03:28 +08005230 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005231 //_syscmd(cmd, buf, sizeof(buf));
5232 return RETURN_ERR;
5233}
5234
5235// changes the hardware settings to disable encryption on this ap
5236INT wifi_disableApEncryption(INT apIndex)
5237{
5238 //Apply instantly
5239 return RETURN_ERR;
5240}
5241
5242// set the authorization mode on this ap
5243// mode mapping as: 1: open, 2: shared, 4:auto
5244INT wifi_setApAuthMode(INT apIndex, INT mode)
5245{
developeraf95c502022-09-13 16:18:22 +08005246 struct params params={0};
5247 char config_file[64] = {0};
5248 int ret;
5249
5250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5251
5252 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5253 params.name = "auth_algs";
5254
5255 if (mode & 1 && mode & 2)
5256 params.value = "3";
5257 else if (mode & 2)
5258 params.value = "2";
5259 else if (mode & 1)
5260 params.value = "1";
5261 else
5262 params.value = "0";
5263
5264 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5265 wifi_hostapdWrite(config_file, &params, 1);
5266 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5267 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5268
5269 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005270}
5271
5272// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5273INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5274{
5275 //save to wifi config, and wait for wifi restart to apply
5276 struct params params={'\0'};
5277 char config_file[MAX_BUF_SIZE] = {0};
5278 int ret;
5279
5280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5281 if(authMode == NULL)
5282 return RETURN_ERR;
5283
5284 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5285 params.name = "wpa_key_mgmt";
5286
5287 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5288 params.value = "WPA-PSK";
5289 else if(strcmp(authMode,"EAPAuthentication") == 0)
5290 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005291 else if (strcmp(authMode, "SAEAuthentication") == 0)
5292 params.value = "SAE";
5293 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5294 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005295 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5296 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005297 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5298 return RETURN_OK; //This is taken careof in beaconType
5299
5300 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5301 ret=wifi_hostapdWrite(config_file,&params,1);
5302 if(!ret)
5303 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5304 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5305
5306 return ret;
5307}
5308
5309// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5310INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5311{
5312 //save to wifi config, and wait for wifi restart to apply
5313 char BeaconType[50] = {0};
5314 char config_file[MAX_BUF_SIZE] = {0};
5315
5316 *authMode = 0;
5317 wifi_getApBeaconType(apIndex,BeaconType);
5318 printf("%s____%s \n",__FUNCTION__,BeaconType);
5319
5320 if(strcmp(BeaconType,"None") == 0)
5321 strcpy(authMode,"None");
5322 else
5323 {
5324 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5325 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5326 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5327 if(strcmp(authMode,"WPA-PSK") == 0)
5328 strcpy(authMode,"SharedAuthentication");
5329 else if(strcmp(authMode,"WPA-EAP") == 0)
5330 strcpy(authMode,"EAPAuthentication");
5331 }
5332
5333 return RETURN_OK;
5334}
5335
5336// Outputs the number of stations associated per AP
5337INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5338{
developerd946fd62022-12-08 18:03:28 +08005339 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005340 char cmd[128]={0};
5341 char buf[128]={0};
5342 BOOL status = false;
5343
5344 if(apIndex > MAX_APS)
5345 return RETURN_ERR;
5346
5347 wifi_getApEnable(apIndex,&status);
5348 if (!status)
5349 return RETURN_OK;
5350
developerd946fd62022-12-08 18:03:28 +08005351 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005352 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005353 return RETURN_ERR;
5354 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005355 _syscmd(cmd, buf, sizeof(buf));
5356 sscanf(buf,"%lu", output_ulong);
5357
5358 return RETURN_OK;
5359}
5360
5361// manually removes any active wi-fi association with the device specified on this ap
5362INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5363{
developerd946fd62022-12-08 18:03:28 +08005364 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005365 char buf[126]={'\0'};
5366
developerac6f1142022-12-20 19:26:35 +08005367 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005368 return RETURN_ERR;
5369 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005370 system(buf);
5371
5372 return RETURN_OK;
5373}
5374
5375// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5376INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5377{
5378 if(NULL == output_int)
5379 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005380 int max_radio_num = 0;
5381 wifi_getMaxRadioNumber(&max_radio_num);
5382 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005383 return RETURN_OK;
5384}
5385
5386// sets the radio index for the specific ap
5387INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5388{
5389 //set to config only and wait for wifi reset to apply settings
5390 return RETURN_ERR;
5391}
5392
5393// Get the ACL MAC list per AP
5394INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5395{
developerd946fd62022-12-08 18:03:28 +08005396 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005397 char cmd[MAX_CMD_SIZE]={'\0'};
5398 int ret = 0;
5399
developerac6f1142022-12-20 19:26:35 +08005400 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005401 return RETURN_ERR;
5402 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005403 ret = _syscmd(cmd,macArray,buf_size);
5404 if (ret != 0)
5405 return RETURN_ERR;
5406
5407 return RETURN_OK;
5408}
5409
developere6aafda2022-09-13 14:59:28 +08005410INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5411{
developerd946fd62022-12-08 18:03:28 +08005412 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005413 char cmd[MAX_CMD_SIZE]={'\0'};
5414 int ret = 0;
5415
developerac6f1142022-12-20 19:26:35 +08005416 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005417 return RETURN_ERR;
5418 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005419 ret = _syscmd(cmd,macArray,buf_size);
5420 if (ret != 0)
5421 return RETURN_ERR;
5422
5423 return RETURN_OK;
5424}
5425
5426
developer06a01d92022-09-07 16:32:39 +08005427// Get the list of stations associated per AP
5428INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5429{
developerd946fd62022-12-08 18:03:28 +08005430 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005431 char cmd[128];
5432
5433 if(apIndex > 3) //Currently supporting apIndex upto 3
5434 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005435 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005436 return RETURN_ERR;
5437 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5438 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005439 _syscmd(cmd, macArray, buf_size);
5440
5441 return RETURN_OK;
5442}
5443
5444// adds the mac address to the filter list
5445//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5446INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5447{
5448 char cmd[MAX_CMD_SIZE]={'\0'};
5449 char buf[MAX_BUF_SIZE]={'\0'};
5450
5451#if 0
developerd946fd62022-12-08 18:03:28 +08005452 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005453 if(_syscmd(cmd,buf,sizeof(buf)))
5454 return RETURN_ERR;
5455#endif
5456 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5457 if(_syscmd(cmd,buf,sizeof(buf)))
5458 return RETURN_ERR;
5459
5460 return RETURN_OK;
5461}
5462
5463// deletes the mac address from the filter list
5464//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5465INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5466{
5467 char cmd[MAX_CMD_SIZE]={'\0'};
5468 char buf[MAX_BUF_SIZE]={'\0'};
5469
5470#if 0
developerd946fd62022-12-08 18:03:28 +08005471 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005472 if(_syscmd(cmd,buf,sizeof(buf)))
5473 return RETURN_ERR;
5474
5475#endif
5476 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5477 if(_syscmd(cmd,buf,sizeof(buf)))
5478 return RETURN_ERR;
5479
5480 return RETURN_OK;
5481}
5482
5483// outputs the number of devices in the filter list
5484INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5485{
developere6aafda2022-09-13 14:59:28 +08005486 char cmd[MAX_BUF_SIZE]={0};
5487 char buf[MAX_CMD_SIZE]={0};
5488
5489 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5490 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005491 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005492
5493 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5494 _syscmd(cmd, buf, sizeof(buf));
5495
5496 *output_uint = atoi(buf);
5497
5498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5499 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005500}
5501
5502INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5503{
5504 char cmd[128]={'\0'};
5505 char buf[128]={'\0'};
5506
5507 if(strcmp(action,"DENY")==0)
5508 {
5509 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5510 system(buf);
5511 return RETURN_OK;
5512 }
5513
5514 if(strcmp(action,"ALLOW")==0)
5515 {
5516 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5517 system(buf);
5518 return RETURN_OK;
5519 }
5520
5521 return RETURN_ERR;
5522
5523}
5524
5525// enable kick for devices on acl black list
5526INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5527{
5528 char aclArray[512] = {0}, *acl = NULL;
5529 char assocArray[512] = {0}, *asso = NULL;
5530
developere6aafda2022-09-13 14:59:28 +08005531 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005532 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5533
5534 // if there are no devices connected there is nothing to do
5535 if (strlen(assocArray) < 17)
5536 return RETURN_OK;
5537
5538 if (enable == TRUE)
5539 {
5540 //kick off the MAC which is in ACL array (deny list)
5541 acl = strtok(aclArray, "\r\n");
5542 while (acl != NULL) {
5543 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5544 wifi_kickApAssociatedDevice(apIndex, acl);
5545
5546 acl = strtok(NULL, "\r\n");
5547 }
developere6aafda2022-09-13 14:59:28 +08005548 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005549 }
5550 else
5551 {
developere6aafda2022-09-13 14:59:28 +08005552 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005553 }
5554
5555#if 0
5556 //TODO: need to revisit below implementation
5557 char aclArray[512]={0}, *acl=NULL;
5558 char assocArray[512]={0}, *asso=NULL;
5559 char buf[256]={'\0'};
5560 char action[10]={'\0'};
5561 FILE *fr=NULL;
5562 char interface[10]={'\0'};
5563 char config_file[MAX_BUF_SIZE] = {0};
5564
5565 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5566 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5567 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5568 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5569
5570 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5571 system(buf);
5572 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5573 system(buf);
5574 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5575 system(buf);
5576 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5577 system(buf);
5578 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5579 system(buf);
5580
5581 if ( enable == TRUE )
5582 {
5583 int device_count=0;
5584 strcpy(action,"DENY");
5585 //kick off the MAC which is in ACL array (deny list)
5586 acl = strtok (aclArray,",");
5587 while (acl != NULL) {
5588 if(strlen(acl)>=17)
5589 {
5590 apply_rules(apIndex, acl,action,interface);
5591 device_count++;
5592 //Register mac to be blocked ,in syscfg.db persistent storage
5593 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5594 system(buf);
5595 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5596 system(buf);
5597 system("syscfg commit");
5598
5599 wifi_kickApAssociatedDevice(apIndex, acl);
5600 }
5601 acl = strtok (NULL, ",");
5602 }
5603 }
5604 else
5605 {
5606 int device_count=0;
5607 char cmdmac[20]={'\0'};
5608 strcpy(action,"ALLOW");
5609 //kick off the MAC which is not in ACL array (allow list)
5610 acl = strtok (aclArray,",");
5611 while (acl != NULL) {
5612 if(strlen(acl)>=17)
5613 {
5614 apply_rules(apIndex, acl,action,interface);
5615 device_count++;
5616 //Register mac to be Allowed ,in syscfg.db persistent storage
5617 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5618 system(buf);
5619 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5620 system(buf);
5621 sprintf(cmdmac,"%s",acl);
5622 }
5623 acl = strtok (NULL, ",");
5624 }
5625 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5626 system(buf);
5627
5628 //Disconnect the mac which is not in ACL
5629 asso = strtok (assocArray,",");
5630 while (asso != NULL) {
5631 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5632 wifi_kickApAssociatedDevice(apIndex, asso);
5633 asso = strtok (NULL, ",");
5634 }
5635 }
5636#endif
5637 return RETURN_OK;
5638}
5639
5640INT wifi_setPreferPrivateConnection(BOOL enable)
5641{
developer06a01d92022-09-07 16:32:39 +08005642 return RETURN_OK;
5643}
5644
5645// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5646INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5647{
developerd946fd62022-12-08 18:03:28 +08005648 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005649 int items = 1;
5650 struct params list[2];
5651 char buf[MAX_BUF_SIZE] = {0};
5652 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005653 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005654
5655 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005656
developer10adcc12022-09-13 14:39:17 +08005657 if (filterMode == 0) {
5658 sprintf(buf, "%d", 0);
5659 list[0].value = buf;
5660
5661 char cmd[128], rtn[128];
developerac6f1142022-12-20 19:26:35 +08005662 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005663 return RETURN_ERR;
5664 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
developer10adcc12022-09-13 14:39:17 +08005665 _syscmd(cmd, rtn, sizeof(rtn));
5666 memset(cmd,0,sizeof(cmd));
5667 // Delete deny_mac_file in hostapd configuration
5668 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5669 _syscmd(cmd, rtn, sizeof(rtn));
5670 }
5671 else if (filterMode == 1) {
5672 sprintf(buf, "%d", filterMode);
5673 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005674 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5675 list[1].name = "accept_mac_file";
5676 list[1].value = acl_file;
5677 items = 2;
developer10adcc12022-09-13 14:39:17 +08005678 } else if (filterMode == 2) {
5679 //TODO: deny_mac_file
5680 sprintf(buf, "%d", 0);
5681 list[0].value = buf;
5682 list[1].name = "deny_mac_file";
5683 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5684 list[1].value = deny_file;
5685 items = 2;
5686 } else {
5687 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005688 }
developer10adcc12022-09-13 14:39:17 +08005689
developer06a01d92022-09-07 16:32:39 +08005690 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5691 wifi_hostapdWrite(config_file, list, items);
5692
5693 return RETURN_OK;
5694
5695#if 0
5696 if(apIndex==0 || apIndex==1)
5697 {
5698 //set the filtermode
5699 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5700 system(buf);
5701 system("syscfg commit");
5702
5703 if(filterMode==0)
5704 {
5705 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5706 system(buf);
5707 return RETURN_OK;
5708 }
5709 }
5710 return RETURN_OK;
5711#endif
5712}
5713
5714// 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.
5715INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5716{
5717 return RETURN_ERR;
5718}
5719
5720// gets the vlan ID for this ap from an internal enviornment variable
5721INT wifi_getApVlanID(INT apIndex, INT *output_int)
5722{
developer30423732022-12-01 16:17:49 +08005723 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005724 {
5725 *output_int=100;
5726 return RETURN_OK;
5727 }
5728
5729 return RETURN_ERR;
5730}
5731
5732// sets the vlan ID for this ap to an internal enviornment variable
5733INT wifi_setApVlanID(INT apIndex, INT vlanId)
5734{
5735 //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)
5736 return RETURN_ERR;
5737}
5738
5739// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5740INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5741{
5742 snprintf(bridgeName, 32, "brlan0");
5743 snprintf(IP, 32, "10.0.0.1");
5744 snprintf(subnet, 32, "255.255.255.0");
5745
5746 return RETURN_OK;
5747}
5748
5749//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5750INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5751{
5752 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5753 return RETURN_ERR;
5754}
5755
5756// reset the vlan configuration for this ap
5757INT wifi_resetApVlanCfg(INT apIndex)
5758{
developerf5fef612022-09-20 19:38:26 +08005759 char original_config_file[64] = {0};
5760 char current_config_file[64] = {0};
5761 char buf[64] = {0};
5762 char cmd[64] = {0};
5763 char vlan_file[64] = {0};
5764 char vlan_tagged_interface[16] = {0};
5765 char vlan_bridge[16] = {0};
5766 char vlan_naming[16] = {0};
5767 struct params list[4] = {0};
5768 wifi_band band;
5769
5770 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5771
5772 band = wifi_index_to_band(apIndex);
5773 if (band == band_2_4)
5774 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08005775 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08005776 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08005777 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08005778 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5779
5780 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5781
5782 if (strlen(vlan_file) == 0)
5783 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005784
developerf5fef612022-09-20 19:38:26 +08005785 // The file should exist or this vap would not work.
5786 if (access(vlan_file, F_OK) != 0) {
5787 sprintf(cmd, "touch %s", vlan_file);
5788 _syscmd(cmd, buf, sizeof(buf));
5789 }
5790 list[0].name = "vlan_file";
5791 list[0].value = vlan_file;
5792
5793 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5794 list[1].name = "vlan_tagged_interface";
5795 list[1].value = vlan_tagged_interface;
5796
5797 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5798 list[2].name = "vlan_bridge";
5799 list[2].value = vlan_bridge;
5800
5801 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5802 list[3].name = "vlan_naming";
5803 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005804
developerf5fef612022-09-20 19:38:26 +08005805 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5806 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005807 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005808 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005809
developerf5fef612022-09-20 19:38:26 +08005810 // restart this ap
5811 wifi_setApEnable(apIndex, FALSE);
5812 wifi_setApEnable(apIndex, TRUE);
5813
5814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5815
5816 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005817}
5818
5819// 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.
5820INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5821{
5822 return RETURN_ERR;
5823}
5824
5825// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5826INT wifi_startHostApd()
5827{
5828 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5829 system("systemctl start hostapd.service");
5830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5831 return RETURN_OK;
5832 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5833}
5834
5835// stops hostapd
5836INT wifi_stopHostApd()
5837{
5838 char cmd[128] = {0};
5839 char buf[128] = {0};
5840
5841 sprintf(cmd,"systemctl stop hostapd");
5842 _syscmd(cmd, buf, sizeof(buf));
5843
5844 return RETURN_OK;
5845}
5846
5847// restart hostapd dummy function
5848INT wifi_restartHostApd()
5849{
5850 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5851 system("systemctl restart hostapd-global");
5852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5853
5854 return RETURN_OK;
5855}
5856
5857static int align_hostapd_config(int index)
5858{
5859 ULONG lval;
5860 wifi_getRadioChannel(index%2, &lval);
5861 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08005862 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005863}
5864
5865// sets the AP enable status variable for the specified ap.
5866INT wifi_setApEnable(INT apIndex, BOOL enable)
5867{
developerd946fd62022-12-08 18:03:28 +08005868 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005869 char config_file[MAX_BUF_SIZE] = {0};
5870 char cmd[MAX_CMD_SIZE] = {0};
5871 char buf[MAX_BUF_SIZE] = {0};
5872 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005873 int max_radio_num = 0;
5874 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005875
5876 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005877
5878 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005879 if (enable == status)
5880 return RETURN_OK;
5881
developerac6f1142022-12-20 19:26:35 +08005882 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005883 return RETURN_ERR;
5884
developer06a01d92022-09-07 16:32:39 +08005885 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005886 int radioIndex = apIndex % max_radio_num;
5887 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005888 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5889 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08005890 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005891 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005892 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005893 _syscmd(cmd, buf, sizeof(buf));
5894 }
5895 else {
developerd946fd62022-12-08 18:03:28 +08005896 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005897 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08005898 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08005899 _syscmd(cmd, buf, sizeof(buf));
5900 }
developer431128d2022-12-16 15:30:41 +08005901 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08005902 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08005903 _syscmd(cmd, buf, sizeof(buf));
5904 //Wait for wifi up/down to apply
5905 return RETURN_OK;
5906}
5907
5908// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5909INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5910{
developerd946fd62022-12-08 18:03:28 +08005911 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005912 char cmd[MAX_CMD_SIZE] = {'\0'};
5913 char buf[MAX_BUF_SIZE] = {'\0'};
5914
5915 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5916 return RETURN_ERR;
5917
5918 *output_bool = 0;
5919
5920 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5921 {
developerac6f1142022-12-20 19:26:35 +08005922 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08005923 *output_bool = FALSE;
5924 return RETURN_OK;
5925 }
5926 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08005927 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5928 }
5929
5930 return RETURN_OK;
5931}
5932
5933// Outputs the AP "Enabled" "Disabled" status from driver
5934INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5935{
5936 char cmd[128] = {0};
5937 char buf[128] = {0};
5938 BOOL output_bool;
5939
5940 if ( NULL == output_string)
5941 return RETURN_ERR;
5942 wifi_getApEnable(apIndex,&output_bool);
5943
5944 if(output_bool == 1)
5945 snprintf(output_string, 32, "Up");
5946 else
5947 snprintf(output_string, 32, "Disable");
5948
5949 return RETURN_OK;
5950}
5951
5952//Indicates whether or not beacons include the SSID name.
5953// outputs a 1 if SSID on the AP is enabled, else outputs 0
5954INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5955{
5956 //get the running status
5957 char config_file[MAX_BUF_SIZE] = {0};
5958 char buf[16] = {0};
5959
5960 if (!output)
5961 return RETURN_ERR;
5962
5963 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5964 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005965 // default is enable
5966 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5967 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005968
5969 return RETURN_OK;
5970}
5971
5972// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5973INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5974{
5975 //store the config, apply instantly
5976 char config_file[MAX_BUF_SIZE] = {0};
5977 struct params list;
5978
5979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5980 list.name = "ignore_broadcast_ssid";
5981 list.value = enable?"0":"1";
5982
5983 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5984 wifi_hostapdWrite(config_file, &list, 1);
5985 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5986 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005987 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005988 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5989
5990 return RETURN_OK;
5991}
5992
5993//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5994INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5995{
5996 //get the running status
5997 if(!output_uint)
5998 return RETURN_ERR;
5999 *output_uint=16;
6000 return RETURN_OK;
6001}
6002
6003INT wifi_setApRetryLimit(INT apIndex, UINT number)
6004{
6005 //apply instantly
6006 return RETURN_ERR;
6007}
6008
6009//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6010INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6011{
6012 if(!output)
6013 return RETURN_ERR;
6014 *output=TRUE;
6015 return RETURN_OK;
6016}
6017
6018//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6019INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6020{
6021 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006022 char cmd[128] = {0};
6023 char buf[128] = {0};
6024 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006025 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006026
developer0b246d12022-09-30 15:24:20 +08006027 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006028
developer0b246d12022-09-30 15:24:20 +08006029 wifi_getMaxRadioNumber(&max_radio_num);
6030 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006031 phyId = radio_index_to_phy(radioIndex);
6032 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006033 _syscmd(cmd,buf, sizeof(buf));
6034
6035 if (strlen(buf) > 0)
6036 *output = true;
6037
6038 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006039
developer06a01d92022-09-07 16:32:39 +08006040 return RETURN_OK;
6041}
6042
6043//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6044INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6045{
6046 //get the running status from driver
6047 if(!output)
6048 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006049
6050 char config_file[MAX_BUF_SIZE] = {0};
6051 char buf[16] = {0};
6052
6053 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6054 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006055 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006056 *output = TRUE;
6057 else
6058 *output = FALSE;
6059
developer06a01d92022-09-07 16:32:39 +08006060 return RETURN_OK;
6061}
6062
6063// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6064INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6065{
6066 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006067 char config_file[MAX_BUF_SIZE] = {0};
6068 struct params list;
6069
6070 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6071 list.name = "wmm_enabled";
6072 list.value = enable?"1":"0";
6073
6074 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6075 wifi_hostapdWrite(config_file, &list, 1);
6076 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6077 wifi_reloadAp(apIndex);
6078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6079
6080 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006081}
6082
6083//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.
6084INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6085{
6086 //get the running status from driver
6087 if(!output)
6088 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006089
6090 char config_file[128] = {0};
6091 char buf[16] = {0};
6092
6093 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6094 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6095 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6096 *output = TRUE;
6097 else
6098 *output = FALSE;
6099
developer06a01d92022-09-07 16:32:39 +08006100 return RETURN_OK;
6101}
6102
6103// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6104INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6105{
6106 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006107 char config_file[MAX_BUF_SIZE] = {0};
6108 struct params list;
6109
6110 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6111 list.name = "uapsd_advertisement_enabled";
6112 list.value = enable?"1":"0";
6113
6114 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6115 wifi_hostapdWrite(config_file, &list, 1);
6116 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6117 wifi_reloadAp(apIndex);
6118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6119
6120 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006121}
6122
developer6daeb3f2022-09-30 13:36:39 +08006123// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006124INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6125{
developerd946fd62022-12-08 18:03:28 +08006126 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006127 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6128 char cmd[128] = {0};
6129 char buf[128] = {0};
6130 char ack_filepath[128] = {0};
6131 uint16_t bitmap = 0;
6132 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6133 FILE *f = NULL;
6134
6135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6136
6137 // Get current setting
6138 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6139 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6140 _syscmd(cmd, buf, sizeof(buf));
6141 if (strlen(buf) > 0)
6142 bitmap = strtoul(buf, NULL, 10);
6143
6144 bitmap = strtoul(buf, NULL, 10);
6145
6146 if (ackPolicy == TRUE) { // True, unset this class
6147 bitmap &= ~class_map[class];
6148 } else { // False, set this class
6149 bitmap |= class_map[class];
6150 }
6151
6152 f = fopen(ack_filepath, "w");
6153 if (f == NULL) {
6154 fprintf(stderr, "%s: fopen failed\n", __func__);
6155 return RETURN_ERR;
6156 }
6157 fprintf(f, "%hu", bitmap);
6158 fclose(f);
6159
developerac6f1142022-12-20 19:26:35 +08006160 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006161 return RETURN_ERR;
6162 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006163 _syscmd(cmd, buf, sizeof(buf));
6164
6165 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6166 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006167}
6168
6169//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.
6170INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6171{
6172 //get the running status from driver
6173 if(!output_uint)
6174 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006175
6176 char output[16]={'\0'};
6177 char config_file[MAX_BUF_SIZE] = {0};
6178
6179 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6180 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6181 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6182 else {
6183 int device_num = atoi(output);
6184 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6185 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6186 return RETURN_ERR;
6187 }
6188 else {
6189 *output_uint = device_num;
6190 }
6191 }
6192
developer06a01d92022-09-07 16:32:39 +08006193 return RETURN_OK;
6194}
6195
6196INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6197{
6198 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006199 char str[MAX_BUF_SIZE]={'\0'};
6200 char cmd[MAX_CMD_SIZE]={'\0'};
6201 struct params params;
6202 char config_file[MAX_BUF_SIZE] = {0};
6203
6204 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006205 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006206 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6207 return RETURN_ERR;
6208 }
6209 sprintf(str, "%d", number);
6210 params.name = "max_num_sta";
6211 params.value = str;
6212
6213 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6214 int ret = wifi_hostapdWrite(config_file, &params, 1);
6215 if (ret) {
6216 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6217 ,__func__, ret);
6218 }
6219
6220 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6221 if (ret) {
6222 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6223 ,__func__, ret);
6224 }
6225 wifi_reloadAp(apIndex);
6226 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6227
6228 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006229}
6230
6231//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.
6232INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6233{
6234 //get the current threshold
6235 if(!output_uint)
6236 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006237 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6238 if (*output_uint == 0)
6239 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006240 return RETURN_OK;
6241}
6242
6243INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6244{
6245 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006246 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6247 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006248 return RETURN_ERR;
6249}
6250
6251//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.
6252INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6253{
6254 if(!output_uint)
6255 return RETURN_ERR;
6256 *output_uint = 3;
6257 return RETURN_OK;
6258}
6259
6260//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6261INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6262{
6263 if(!output_uint)
6264 return RETURN_ERR;
6265 *output_uint = 3;
6266 return RETURN_OK;
6267}
6268
6269//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.
6270INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6271{
6272 if(!output_in_seconds)
6273 return RETURN_ERR;
6274 *output_in_seconds = 0;
6275 return RETURN_OK;
6276}
6277
6278//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
6279INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6280{
6281 if(!output || apIndex>=MAX_APS)
6282 return RETURN_ERR;
6283 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006284 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006285 return RETURN_OK;
6286}
6287
6288//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6289INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6290{
developer587c1b62022-09-27 15:58:59 +08006291 char config_file[128] = {0};
6292 char wpa[16] = {0};
6293 char key_mgmt[64] = {0};
6294 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006295 if (!output)
6296 return RETURN_ERR;
6297
6298 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006299 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006300
developer587c1b62022-09-27 15:58:59 +08006301 strcpy(output, "None");//Copying "None" to output string for default case
6302 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006303 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006304 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006305 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006306 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006307 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006308 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006309 snprintf(output, 32, "WPA-WPA2-Personal");
6310
6311 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006312 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006313 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006314 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006315 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006316 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006317 snprintf(output, 32, "WPA-WPA2-Enterprise");
6318 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006319 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006320 snprintf(output, 32, "WPA3-Personal");
6321 else
developer4a359672022-10-13 15:30:46 +08006322 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006323 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6324 snprintf(output, 32, "WPA3-Enterprise");
6325 }
developer06a01d92022-09-07 16:32:39 +08006326
6327 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6328 return RETURN_OK;
6329#if 0
6330 //TODO: need to revisit below implementation
6331 char securityType[32], authMode[32];
6332 int enterpriseMode=0;
6333
6334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6335 if(!output)
6336 return RETURN_ERR;
6337
6338 wifi_getApBeaconType(apIndex, securityType);
6339 strcpy(output,"None");//By default, copying "None" to output string
6340 if (strncmp(securityType,"None", strlen("None")) == 0)
6341 return RETURN_OK;
6342
6343 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6344 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6345
6346 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6347 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6348 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6349 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6350 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6351 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6352 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6353
6354 return RETURN_OK;
6355#endif
6356}
6357
6358INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6359{
6360 char securityType[32];
6361 char authMode[32];
6362
6363 //store settings and wait for wifi up to apply
6364 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6365 if(!encMode)
6366 return RETURN_ERR;
6367
developer06a01d92022-09-07 16:32:39 +08006368 if (strcmp(encMode, "None")==0)
6369 {
6370 strcpy(securityType,"None");
6371 strcpy(authMode,"None");
6372 }
6373 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6374 {
6375 strcpy(securityType,"WPAand11i");
6376 strcpy(authMode,"PSKAuthentication");
6377 }
6378 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6379 {
6380 strcpy(securityType,"WPAand11i");
6381 strcpy(authMode,"EAPAuthentication");
6382 }
6383 else if (strcmp(encMode, "WPA-Personal")==0)
6384 {
6385 strcpy(securityType,"WPA");
6386 strcpy(authMode,"PSKAuthentication");
6387 }
6388 else if (strcmp(encMode, "WPA-Enterprise")==0)
6389 {
6390 strcpy(securityType,"WPA");
6391 strcpy(authMode,"EAPAuthentication");
6392 }
6393 else if (strcmp(encMode, "WPA2-Personal")==0)
6394 {
6395 strcpy(securityType,"11i");
6396 strcpy(authMode,"PSKAuthentication");
6397 }
6398 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6399 {
6400 strcpy(securityType,"11i");
6401 strcpy(authMode,"EAPAuthentication");
6402 }
developer587c1b62022-09-27 15:58:59 +08006403 else if (strcmp(encMode, "WPA3-Personal") == 0)
6404 {
6405 strcpy(securityType,"11i");
6406 strcpy(authMode,"SAEAuthentication");
6407 }
developer4a359672022-10-13 15:30:46 +08006408 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006409 {
6410 strcpy(securityType, "11i");
6411 strcpy(authMode, "PSK-SAEAuthentication");
6412 }
developer587c1b62022-09-27 15:58:59 +08006413 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6414 {
6415 strcpy(securityType,"11i");
6416 strcpy(authMode,"EAP_192-bit_Authentication");
6417 }
developer06a01d92022-09-07 16:32:39 +08006418 else
6419 {
6420 strcpy(securityType,"None");
6421 strcpy(authMode,"None");
6422 }
6423 wifi_setApBeaconType(apIndex, securityType);
6424 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6425 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6426
6427 return RETURN_OK;
6428}
6429
6430
6431//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6432// output_string must be pre-allocated as 64 character string by caller
6433// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6434INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6435{
developer30423732022-12-01 16:17:49 +08006436 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006437 char config_file[MAX_BUF_SIZE] = {0};
6438
6439 if(output_string==NULL)
6440 return RETURN_ERR;
6441
6442 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6443 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6444
6445 if(strcmp(buf,"0")==0)
6446 {
6447 printf("wpa_mode is %s ......... \n",buf);
6448 return RETURN_ERR;
6449 }
6450
6451 wifi_dbg_printf("\nFunc=%s\n",__func__);
6452 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6453 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6454 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6455
6456 return RETURN_OK;
6457}
6458
6459// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6460// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6461INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6462{
6463 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6464 struct params params={'\0'};
6465 int ret;
6466 char config_file[MAX_BUF_SIZE] = {0};
6467
6468 if(NULL == preSharedKey)
6469 return RETURN_ERR;
6470
6471 params.name = "wpa_passphrase";
6472
6473 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6474 {
6475 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6476 return RETURN_ERR;
6477 }
6478 params.value = preSharedKey;
6479 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6480 ret = wifi_hostapdWrite(config_file, &params, 1);
6481 if(!ret)
6482 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6483 return ret;
6484 //TODO: call hostapd_cli for dynamic_config_control
6485}
6486
6487//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6488// outputs the passphrase, maximum 63 characters
6489INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6490{
6491 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6492
6493 wifi_dbg_printf("\nFunc=%s\n",__func__);
6494 if (NULL == output_string)
6495 return RETURN_ERR;
6496
6497 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6498 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6499 if(strcmp(buf,"0")==0)
6500 {
6501 printf("wpa_mode is %s ......... \n",buf);
6502 return RETURN_ERR;
6503 }
6504
6505 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6506 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6507
6508 return RETURN_OK;
6509}
6510
6511// sets the passphrase enviornment variable, max 63 characters
6512INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6513{
6514 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6515 struct params params={'\0'};
6516 char config_file[MAX_BUF_SIZE] = {0};
6517 int ret;
6518
6519 if(NULL == passPhrase)
6520 return RETURN_ERR;
6521
6522 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6523 {
6524 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6525 return RETURN_ERR;
6526 }
6527 params.name = "wpa_passphrase";
6528 params.value = passPhrase;
6529 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6530 ret=wifi_hostapdWrite(config_file,&params,1);
6531 if(!ret)
6532 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6533
6534 return ret;
6535}
6536
6537//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.
6538INT wifi_setApSecurityReset(INT apIndex)
6539{
developer8d583982022-09-20 11:28:22 +08006540 char original_config_file[64] = {0};
6541 char current_config_file[64] = {0};
6542 char buf[64] = {0};
6543 char cmd[64] = {0};
6544 char wpa[4] = {0};
6545 char wpa_psk[64] = {0};
6546 char wpa_passphrase[64] = {0};
6547 char wpa_psk_file[128] = {0};
6548 char wpa_key_mgmt[64] = {0};
6549 char wpa_pairwise[32] = {0};
6550 wifi_band band;
6551 struct params list[6];
6552
6553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6554
6555 band = wifi_index_to_band(apIndex);
6556 if (band == band_2_4)
6557 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006558 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006559 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006560 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006561 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6562 else
6563 return RETURN_ERR;
6564
6565 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6566 list[0].name = "wpa";
6567 list[0].value = wpa;
6568
6569 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6570 list[1].name = "wpa_psk";
6571 list[1].value = wpa_psk;
6572
6573 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6574 list[2].name = "wpa_passphrase";
6575 list[2].value = wpa_passphrase;
6576
6577 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6578
6579 if (strlen(wpa_psk_file) == 0)
6580 strcpy(wpa_psk_file, PSK_FILE);
6581
6582 if (access(wpa_psk_file, F_OK) != 0) {
6583 sprintf(cmd, "touch %s", wpa_psk_file);
6584 _syscmd(cmd, buf, sizeof(buf));
6585 }
6586 list[3].name = "wpa_psk_file";
6587 list[3].value = wpa_psk_file;
6588
6589 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6590 list[4].name = "wpa_key_mgmt";
6591 list[4].value = wpa_key_mgmt;
6592
6593 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6594 list[5].name = "wpa_pairwise";
6595 list[5].value = wpa_pairwise;
6596
6597 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6598 wifi_hostapdWrite(current_config_file, list, 6);
6599
6600 wifi_setApEnable(apIndex, FALSE);
6601 wifi_setApEnable(apIndex, TRUE);
6602
6603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6604 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006605}
6606
6607//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).
6608INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6609{
developer8f2ddd52022-09-13 15:39:24 +08006610 char config_file[64] = {0};
6611 char buf[64] = {0};
6612 char cmd[256] = {0};
6613
6614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6615
developer06a01d92022-09-07 16:32:39 +08006616 if(!IP_output || !Port_output || !RadiusSecret_output)
6617 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006618
developer8f2ddd52022-09-13 15:39:24 +08006619 // Read the first matched config
6620 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6621 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6622 _syscmd(cmd, buf, sizeof(buf));
6623 strncpy(IP_output, buf, 64);
6624
6625 memset(buf, 0, sizeof(buf));
6626 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6627 _syscmd(cmd, buf, sizeof(buf));
6628 *Port_output = atoi(buf);
6629
6630 memset(buf, 0, sizeof(buf));
6631 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6632 _syscmd(cmd, buf, sizeof(buf));
6633 strncpy(RadiusSecret_output, buf, 64);
6634
6635 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006636 return RETURN_OK;
6637}
6638
6639INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6640{
developer8f2ddd52022-09-13 15:39:24 +08006641 char config_file[64] = {0};
6642 char port_str[8] = {0};
6643 char cmd[256] = {0};
6644 char buf[128] = {0};
6645
6646 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6647
6648 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6649
6650 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6651 _syscmd(cmd, buf, sizeof(buf));
6652 memset(cmd, 0, sizeof(cmd));
6653
6654 snprintf(port_str, sizeof(port_str), "%d", port);
6655 if (strlen(buf) == 0)
6656 // Append
6657 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6658 "auth_server_addr=%s\\n"
6659 "auth_server_port=%s\\n"
6660 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6661 else {
6662 // Delete the three lines setting after the "# radius 1" comment
6663 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6664 _syscmd(cmd, buf, sizeof(buf));
6665 memset(cmd, 0, sizeof(cmd));
6666 // Use "# radius 1" comment to find the location to insert the radius setting
6667 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6668 "# radius 1\\n"
6669 "auth_server_addr=%s\\n"
6670 "auth_server_port=%s\\n"
6671 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6672 }
6673 if(_syscmd(cmd, buf, sizeof(buf))) {
6674 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6675 return RETURN_ERR;
6676 }
6677
6678 wifi_reloadAp(apIndex);
6679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6680 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006681}
6682
6683INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6684{
developer8f2ddd52022-09-13 15:39:24 +08006685 char config_file[64] = {0};
6686 char buf[64] = {0};
6687 char cmd[256] = {0};
6688
6689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6690
developer06a01d92022-09-07 16:32:39 +08006691 if(!IP_output || !Port_output || !RadiusSecret_output)
6692 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006693
6694 // Read the second matched config
6695 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6696 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6697 _syscmd(cmd, buf, sizeof(buf));
6698 strncpy(IP_output, buf, 64);
6699
6700 memset(buf, 0, sizeof(buf));
6701 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6702 _syscmd(cmd, buf, sizeof(buf));
6703 *Port_output = atoi(buf);
6704
6705 memset(buf, 0, sizeof(buf));
6706 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6707 _syscmd(cmd, buf, sizeof(buf));
6708 strncpy(RadiusSecret_output, buf, 64);
6709
6710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006711 return RETURN_OK;
6712}
6713
6714INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6715{
developer8f2ddd52022-09-13 15:39:24 +08006716 char config_file[64] = {0};
6717 char port_str[8] = {0};
6718 char cmd[256] = {0};
6719 char buf[128] = {0};
6720
6721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6722
6723 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6724
6725 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6726 _syscmd(cmd, buf, sizeof(buf));
6727 memset(cmd, 0, sizeof(cmd));
6728
6729 snprintf(port_str, sizeof(port_str), "%d", port);
6730 if (strlen(buf) == 0)
6731 // Append
6732 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6733 "auth_server_addr=%s\\n"
6734 "auth_server_port=%s\\n"
6735 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6736 else {
6737 // Delete the three lines setting after the "# radius 2" comment
6738 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6739 _syscmd(cmd, buf, sizeof(buf));
6740 memset(cmd, 0, sizeof(cmd));
6741 // Use "# radius 2" comment to find the location to insert the radius setting
6742 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6743 "# radius 2\\n"
6744 "auth_server_addr=%s\\n"
6745 "auth_server_port=%s\\n"
6746 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6747 }
6748 if(_syscmd(cmd, buf, sizeof(buf))) {
6749 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6750 return RETURN_ERR;
6751 }
6752
6753 wifi_reloadAp(apIndex);
6754 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6755 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006756}
6757
6758//RadiusSettings
6759INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6760{
6761 if(!output)
6762 return RETURN_ERR;
6763
6764 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6765 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6766 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6767 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6768 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6769 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.
6770 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6771 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6772 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6773 //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.
6774
6775 return RETURN_OK;
6776}
6777
6778INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6779{
6780 //store the paramters, and apply instantly
6781 return RETURN_ERR;
6782}
6783
6784//Device.WiFi.AccessPoint.{i}.WPS.Enable
6785//Enables or disables WPS functionality for this access point.
6786// outputs the WPS enable state of this ap in output_bool
6787INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6788{
developerd946fd62022-12-08 18:03:28 +08006789 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006790 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006791 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006792 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08006793 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006794 return RETURN_ERR;
6795 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006796 _syscmd(cmd, buf, sizeof(buf));
6797 if(strstr(buf, "configured"))
6798 *output_bool=TRUE;
6799 else
6800 *output_bool=FALSE;
6801
6802 return RETURN_OK;
6803}
6804
6805//Device.WiFi.AccessPoint.{i}.WPS.Enable
6806// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6807INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6808{
6809 char config_file[MAX_BUF_SIZE] = {0};
6810 struct params params;
6811
developer06a01d92022-09-07 16:32:39 +08006812 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6813 //store the paramters, and wait for wifi up to apply
6814 params.name = "wps_state";
6815 params.value = enable ? "2":"0";
6816
6817 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6818 wifi_hostapdWrite(config_file, &params, 1);
6819 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6820 wifi_reloadAp(apIndex);
6821
6822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6823 return RETURN_OK;
6824}
6825
6826//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
6827INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6828{
6829 if(!output)
6830 return RETURN_ERR;
6831 snprintf(output, 128, "PushButton,PIN");
6832 return RETURN_OK;
6833}
6834
6835//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6836//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.
6837// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6838INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6839{
6840 if(!output)
6841 return RETURN_ERR;
6842 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6843
6844 return RETURN_OK;
6845}
6846
6847//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6848// 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
6849INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6850{
6851 //apply instantly. No setting need to be stored.
6852 char methods[MAX_BUF_SIZE], *token, *next_token;
6853 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6854 struct params params;
6855
developer5b398df2022-11-17 20:39:48 +08006856 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006857 return RETURN_ERR;
6858 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6859 //store the paramters, and wait for wifi up to apply
6860
6861 snprintf(methods, sizeof(methods), "%s", methodString);
6862 for(token=methods; *token; token=next_token)
6863 {
6864 strtok_r(token, ",", &next_token);
6865 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6866 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6867 else if(*token=='E')
6868 {
6869 if(!strcmp(methods, "Ethernet"))
6870 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6871 else if(!strcmp(methods, "ExternalNFCToken"))
6872 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6873 else
6874 printf("%s: Unknown WpsConfigMethod\n", __func__);
6875 }
6876 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6877 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6878 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6879 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6880 else if(*token=='P' )
6881 {
6882 if(!strcmp(token, "PushButton"))
6883 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6884 else if(!strcmp(token, "PIN"))
6885 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6886 else
6887 printf("%s: Unknown WpsConfigMethod\n", __func__);
6888 }
6889 else
6890 printf("%s: Unknown WpsConfigMethod\n", __func__);
6891 }
6892 params.name = "config_methods";
6893 params.value = config_methods;
6894 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6895 wifi_hostapdWrite(config_file, &params, 1);
6896 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6897 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6898
6899 return RETURN_OK;
6900}
6901
6902// outputs the pin value, ulong_pin must be allocated by the caller
6903INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6904{
6905 char buf[MAX_BUF_SIZE] = {0};
6906 char cmd[MAX_CMD_SIZE] = {0};
6907
developer5b398df2022-11-17 20:39:48 +08006908 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08006909 return RETURN_ERR;
6910 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6911 _syscmd(cmd, buf, sizeof(buf));
6912 if(strlen(buf) > 0)
6913 *output_ulong=strtoul(buf, NULL, 10);
6914
6915 return RETURN_OK;
6916}
6917
6918// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6919INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6920{
6921 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6922 char ap_pin[16] = {0};
6923 char buf[MAX_BUF_SIZE] = {0};
6924 char config_file[MAX_BUF_SIZE] = {0};
6925 ULONG prev_pin = 0;
6926 struct params params;
6927
developer06a01d92022-09-07 16:32:39 +08006928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6929 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6930 params.name = "ap_pin";
6931 params.value = ap_pin;
6932 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6933 wifi_hostapdWrite(config_file, &params, 1);
6934 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6935 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6936
6937 return RETURN_OK;
6938}
6939
6940// Output string is either Not configured or Configured, max 32 characters
6941INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6942{
developerd946fd62022-12-08 18:03:28 +08006943 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006944 char cmd[MAX_CMD_SIZE];
6945 char buf[MAX_BUF_SIZE]={0};
6946
developer5b398df2022-11-17 20:39:48 +08006947 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08006948 return RETURN_ERR;
6949 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6950 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08006951 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006952 return RETURN_ERR;
6953 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006954 _syscmd(cmd, buf, sizeof(buf));
6955
developer348e3d92022-09-13 14:48:41 +08006956 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006957 snprintf(output_string, 32, "Configured");
6958 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6959
6960 return RETURN_OK;
6961}
6962
6963// sets the WPS pin for this AP
6964INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6965{
developerd946fd62022-12-08 18:03:28 +08006966 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006967 char cmd[MAX_CMD_SIZE];
6968 char buf[MAX_BUF_SIZE]={0};
6969 BOOL enable;
6970
developer06a01d92022-09-07 16:32:39 +08006971 wifi_getApEnable(apIndex, &enable);
6972 if (!enable)
6973 return RETURN_ERR;
6974 wifi_getApWpsEnable(apIndex, &enable);
6975 if (!enable)
6976 return RETURN_ERR;
6977
developerac6f1142022-12-20 19:26:35 +08006978 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006979 return RETURN_ERR;
6980 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08006981 _syscmd(cmd, buf, sizeof(buf));
6982 if((strstr(buf, "OK"))!=NULL)
6983 return RETURN_OK;
6984
6985 return RETURN_ERR;
6986}
6987
6988// This function is called when the WPS push button has been pressed for this AP
6989INT wifi_setApWpsButtonPush(INT apIndex)
6990{
6991 char cmd[MAX_CMD_SIZE];
6992 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08006993 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006994 BOOL enable=FALSE;
6995
developer06a01d92022-09-07 16:32:39 +08006996 wifi_getApEnable(apIndex, &enable);
6997 if (!enable)
6998 return RETURN_ERR;
6999
7000 wifi_getApWpsEnable(apIndex, &enable);
7001 if (!enable)
7002 return RETURN_ERR;
7003
developerac6f1142022-12-20 19:26:35 +08007004 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007005 return RETURN_ERR;
7006
7007 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 +08007008 _syscmd(cmd, buf, sizeof(buf));
7009
7010 if((strstr(buf, "OK"))!=NULL)
7011 return RETURN_OK;
7012 return RETURN_ERR;
7013}
7014
7015// cancels WPS mode for this AP
7016INT wifi_cancelApWPS(INT apIndex)
7017{
developerd946fd62022-12-08 18:03:28 +08007018 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007019 char cmd[MAX_CMD_SIZE];
7020 char buf[MAX_BUF_SIZE]={0};
7021
developerac6f1142022-12-20 19:26:35 +08007022 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007023 return RETURN_ERR;
7024 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007025 _syscmd(cmd,buf, sizeof(buf));
7026
7027 if((strstr(buf, "OK"))!=NULL)
7028 return RETURN_OK;
7029 return RETURN_ERR;
7030}
7031
7032//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7033//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7034INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7035{
developerd946fd62022-12-08 18:03:28 +08007036 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007037 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007038 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007039 char cmd[256] = {0}, buf[2048] = {0};
7040 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007041 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007042 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007043 wifi_associated_dev_t *dev=NULL;
7044
7045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7046 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007047 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007048 return RETURN_ERR;
7049 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007050 _syscmd(cmd,buf,sizeof(buf));
7051 *output_array_size = atoi(buf);
7052
7053 if (*output_array_size <= 0)
7054 return RETURN_OK;
7055
7056 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7057 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007058 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007059 _syscmd(cmd,buf,sizeof(buf));
7060 f = fopen("/tmp/connected_devices.txt", "r");
7061 if (f==NULL)
7062 {
7063 *output_array_size=0;
7064 return RETURN_ERR;
7065 }
developer30423732022-12-01 16:17:49 +08007066 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007067 {
7068 param = strtok(line,"=");
7069 value = strtok(NULL,"=");
7070
7071 if( strcmp("flags",param) == 0 )
7072 {
7073 value[strlen(value)-1]='\0';
7074 if(strstr (value,"AUTHORIZED") != NULL )
7075 {
7076 dev[auth_temp].cli_AuthenticationState = 1;
7077 dev[auth_temp].cli_Active = 1;
7078 auth_temp++;
7079 read_flag=1;
7080 }
7081 }
7082 if(read_flag==1)
7083 {
7084 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7085 {
7086 value[strlen(value)-1]='\0';
7087 sscanf(value, "%x:%x:%x:%x:%x:%x",
7088 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7089 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7090 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7091 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7092 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7093 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7094 mac_temp++;
7095 read_flag=0;
7096 }
7097 }
7098 }
7099 *output_array_size = auth_temp;
7100 auth_temp=0;
7101 mac_temp=0;
7102 free(line);
7103 fclose(f);
7104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7105 return RETURN_OK;
7106}
7107
7108#define MACADDRESS_SIZE 6
7109
7110INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7111{
7112 FILE *fp = NULL;
7113 char str[MAX_BUF_SIZE] = {0};
7114 int wificlientindex = 0 ;
7115 int count = 0;
7116 int signalstrength = 0;
7117 int arr[MACADDRESS_SIZE] = {0};
7118 unsigned char mac[MACADDRESS_SIZE] = {0};
7119 UINT wifi_count = 0;
7120 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7121 char pipeCmd[MAX_CMD_SIZE] = {0};
7122
7123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7124 *output_array_size = 0;
7125 *associated_dev_array = NULL;
7126
7127 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7128 fp = popen(pipeCmd, "r");
7129 if (fp == NULL)
7130 {
7131 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7132 return RETURN_ERR;
7133 }
7134
7135 /* Read the output a line at a time - output it. */
7136 fgets(str, sizeof(str)-1, fp);
7137 wifi_count = (unsigned int) atoi ( str );
7138 *output_array_size = wifi_count;
7139 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7140 pclose(fp);
7141
7142 if(wifi_count == 0)
7143 {
7144 return RETURN_OK;
7145 }
7146 else
7147 {
7148 wifi_associated_dev3_t* temp = NULL;
7149 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7150 if(temp == NULL)
7151 {
7152 printf("Error Statement. Insufficient memory \n");
7153 return RETURN_ERR;
7154 }
7155
7156 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7157 system(pipeCmd);
7158 memset(pipeCmd,0,sizeof(pipeCmd));
7159 if(apIndex == 0)
7160 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7161 else if(apIndex == 1)
7162 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7163 system(pipeCmd);
7164
7165 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7166 if(fp == NULL)
7167 {
7168 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007169 free(temp);
developer06a01d92022-09-07 16:32:39 +08007170 return RETURN_ERR;
7171 }
7172 fclose(fp);
7173
developer30423732022-12-01 16:17:49 +08007174 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007175 fp = popen(pipeCmd, "r");
7176 if(fp)
7177 {
7178 for(count =0 ; count < wifi_count; count++)
7179 {
7180 fgets(str, MAX_BUF_SIZE, fp);
7181 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7182 {
7183 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7184 {
7185 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7186
7187 }
7188 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7189 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]);
7190 }
7191 temp[count].cli_AuthenticationState = 1; //TODO
7192 temp[count].cli_Active = 1; //TODO
7193 }
7194 pclose(fp);
7195 }
7196
developer30423732022-12-01 16:17:49 +08007197 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 +08007198 fp = popen(pipeCmd, "r");
7199 if(fp)
7200 {
7201 pclose(fp);
7202 }
7203 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7204 if(fp)
7205 {
7206 for(count =0 ; count < wifi_count ;count++)
7207 {
7208 fgets(str, MAX_BUF_SIZE, fp);
7209 signalstrength = atoi(str);
7210 temp[count].cli_SignalStrength = signalstrength;
7211 temp[count].cli_RSSI = signalstrength;
7212 temp[count].cli_SNR = signalstrength + 95;
7213 }
7214 pclose(fp);
7215 }
7216
7217
7218 if((apIndex == 0) || (apIndex == 4))
7219 {
7220 for(count =0 ; count < wifi_count ;count++)
7221 {
7222 strcpy(temp[count].cli_OperatingStandard,"g");
7223 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7224 }
7225
7226 //BytesSent
developer30423732022-12-01 16:17:49 +08007227 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 +08007228 fp = popen(pipeCmd, "r");
7229 if(fp)
7230 {
7231 pclose(fp);
7232 }
7233 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7234 if(fp)
7235 {
7236 for (count = 0; count < wifi_count; count++)
7237 {
7238 fgets(str, MAX_BUF_SIZE, fp);
7239 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7240 }
7241 pclose(fp);
7242 }
7243
7244 //BytesReceived
developer30423732022-12-01 16:17:49 +08007245 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 +08007246 fp = popen(pipeCmd, "r");
7247 if (fp)
7248 {
7249 pclose(fp);
7250 }
7251 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7252 if (fp)
7253 {
7254 for (count = 0; count < wifi_count; count++)
7255 {
7256 fgets(str, MAX_BUF_SIZE, fp);
7257 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7258 }
7259 pclose(fp);
7260 }
7261
7262 //PacketsSent
developer30423732022-12-01 16:17:49 +08007263 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 +08007264 fp = popen(pipeCmd, "r");
7265 if (fp)
7266 {
7267 pclose(fp);
7268 }
7269
7270 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7271 if (fp)
7272 {
7273 for (count = 0; count < wifi_count; count++)
7274 {
7275 fgets(str, MAX_BUF_SIZE, fp);
7276 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7277 }
7278 pclose(fp);
7279 }
7280
7281 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007282 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 +08007283 fp = popen(pipeCmd, "r");
7284 if (fp)
7285 {
7286 pclose(fp);
7287 }
7288 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7289 if (fp)
7290 {
7291 for (count = 0; count < wifi_count; count++)
7292 {
7293 fgets(str, MAX_BUF_SIZE, fp);
7294 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7295 }
7296 pclose(fp);
7297 }
7298
7299 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007300 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 +08007301 fp = popen(pipeCmd, "r");
7302 if (fp)
7303 {
7304 pclose(fp);
7305 }
7306 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7307 if (fp)
7308 {
7309 for (count = 0; count < wifi_count; count++)
7310 {
7311 fgets(str, MAX_BUF_SIZE, fp);
7312 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7313 }
7314 pclose(fp);
7315 }
7316
7317 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007318 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 +08007319 fp = popen(pipeCmd, "r");
7320 if (fp)
7321 {
7322 pclose(fp);
7323 }
7324 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7325 if (fp)
7326 {
7327 for (count = 0; count < wifi_count; count++)
7328 {
7329 fgets(str, MAX_BUF_SIZE, fp);
7330 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7331 }
7332 pclose(fp);
7333 }
7334
7335 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007336 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 +08007337 fp = popen(pipeCmd, "r");
7338 if (fp)
7339 {
7340 pclose(fp);
7341 }
7342 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7343 if (fp)
7344 {
7345 for (count = 0; count < wifi_count; count++)
7346 {
7347 fgets(str, MAX_BUF_SIZE, fp);
7348 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7349 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7350 }
7351 pclose(fp);
7352 }
7353
7354 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007355 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 +08007356 fp = popen(pipeCmd, "r");
7357 if (fp)
7358 {
7359 pclose(fp);
7360 }
7361 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7362 if (fp)
7363 {
7364 for (count = 0; count < wifi_count; count++)
7365 {
7366 fgets(str, MAX_BUF_SIZE, fp);
7367 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7368 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7369 }
7370 pclose(fp);
7371 }
7372
7373 }
7374 else if ((apIndex == 1) || (apIndex == 5))
7375 {
7376 for (count = 0; count < wifi_count; count++)
7377 {
7378 strcpy(temp[count].cli_OperatingStandard, "a");
7379 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7380 temp[count].cli_BytesSent = 0;
7381 temp[count].cli_BytesReceived = 0;
7382 temp[count].cli_LastDataUplinkRate = 0;
7383 temp[count].cli_LastDataDownlinkRate = 0;
7384 temp[count].cli_PacketsSent = 0;
7385 temp[count].cli_PacketsReceived = 0;
7386 temp[count].cli_ErrorsSent = 0;
7387 }
7388 }
7389
7390 for (count = 0; count < wifi_count; count++)
7391 {
7392 temp[count].cli_Retransmissions = 0;
7393 temp[count].cli_DataFramesSentAck = 0;
7394 temp[count].cli_DataFramesSentNoAck = 0;
7395 temp[count].cli_MinRSSI = 0;
7396 temp[count].cli_MaxRSSI = 0;
7397 strncpy(temp[count].cli_InterferenceSources, "", 64);
7398 memset(temp[count].cli_IPAddress, 0, 64);
7399 temp[count].cli_RetransCount = 0;
7400 temp[count].cli_FailedRetransCount = 0;
7401 temp[count].cli_RetryCount = 0;
7402 temp[count].cli_MultipleRetryCount = 0;
7403 }
7404 *associated_dev_array = temp;
7405 }
7406 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7407 return RETURN_OK;
7408}
7409
7410int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7411{
7412 FILE *fp = NULL;
7413 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7414 char cmd[MAX_CMD_SIZE];
7415 int count = 0;
7416
7417 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7418 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7419 fp = popen(cmd,"r");
7420 if(fp == NULL)
7421 {
7422 printf("Failed to run command in Function %s\n",__FUNCTION__);
7423 return 0;
7424 }
7425 if(fgets(path, sizeof(path)-1, fp) != NULL)
7426 {
7427 for(count=0;path[count]!='\n';count++)
7428 status[count]=path[count];
7429 status[count]='\0';
7430 }
7431 strcpy(wifi_status,status);
7432 pclose(fp);
7433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7434 return RETURN_OK;
7435}
7436
7437/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7438struct hostapd_sta_param {
7439 char key[50];
7440 char value[100];
7441}
7442
7443static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7444 int i = 0;
7445
7446 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7447 if (strncmp(params[i].key,key,50) == 0){
7448 return &params[i].value;
7449 }
7450 i++;
7451 }
7452 return NULL;
7453
7454} */
7455
7456static unsigned int count_occurences(const char *buf, const char *word)
7457{
7458 unsigned int n = 0;
7459 char *ptr = strstr(buf, word);
7460
7461 while (ptr++) {
7462 n++;
7463 ptr = strstr(ptr, word);
7464 }
7465
7466 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7467 return n;
7468}
7469
7470static const char *get_line_from_str_buf(const char *buf, char *line)
7471{
7472 int i;
7473 int n = strlen(buf);
7474
7475 for (i = 0; i < n; i++) {
7476 line[i] = buf[i];
7477 if (buf[i] == '\n') {
7478 line[i] = '\0';
7479 return &buf[i + 1];
7480 }
7481 }
7482
7483 return NULL;
7484}
7485
7486INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7487{
7488 unsigned int assoc_cnt = 0;
7489 char interface_name[50] = {0};
7490 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7491 char cmd[MAX_CMD_SIZE] = {'\0'};
7492 char line[256] = {'\0'};
7493 int i = 0;
7494 int ret = 0;
7495 const char *ptr = NULL;
7496 char *key = NULL;
7497 char *val = NULL;
7498 wifi_associated_dev3_t *temp = NULL;
7499 int rssi;
7500
7501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7502
7503 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7504 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7505 return RETURN_ERR;
7506 }
7507
7508 // Example filtered output of 'iw dev' command:
7509 // Station 0a:69:72:10:d2:fa (on wifi0)
7510 // signal avg:-67 [-71, -71] dBm
7511 // Station 28:c2:1f:25:5f:99 (on wifi0)
7512 // signal avg:-67 [-71, -70] dBm
7513 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7514 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7515 return RETURN_ERR;
7516 }
7517
7518 ret = _syscmd(cmd, buf, sizeof(buf));
7519 if (ret == RETURN_ERR) {
7520 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7521 return RETURN_ERR;
7522 }
7523
7524 *output_array_size = count_occurences(buf, "Station");
7525 if (*output_array_size == 0) return RETURN_OK;
7526
7527 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7528 if (temp == NULL) {
7529 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7530 return RETURN_ERR;
7531 }
7532 *associated_dev_array = temp;
7533
7534 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7535 ptr = get_line_from_str_buf(buf, line);
7536 i = -1;
7537 while (ptr) {
7538 if (strstr(line, "Station")) {
7539 i++;
7540 key = strtok(line, " ");
7541 val = strtok(NULL, " ");
7542 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7543 &temp[i].cli_MACAddress[0],
7544 &temp[i].cli_MACAddress[1],
7545 &temp[i].cli_MACAddress[2],
7546 &temp[i].cli_MACAddress[3],
7547 &temp[i].cli_MACAddress[4],
7548 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7549 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7550 free(*associated_dev_array);
7551 return RETURN_ERR;
7552 }
7553 }
7554 else if (i < 0) {
7555 ptr = get_line_from_str_buf(ptr, line);
7556 continue; // We didn't detect 'station' entry yet
7557 }
7558 else if (strstr(line, "signal avg")) {
7559 key = strtok(line, ":");
7560 val = strtok(NULL, " ");
7561 if (sscanf(val, "%d", &rssi) <= 0 ) {
7562 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7563 free(*associated_dev_array);
7564 return RETURN_ERR;
7565 }
7566 temp[i].cli_RSSI = rssi;
7567 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7568 }
7569 // Here other fields can be parsed if added to filter of 'iw dev' command
7570
7571 ptr = get_line_from_str_buf(ptr, line);
7572 };
7573
7574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7575
7576 return RETURN_OK;
7577}
7578
7579#if 0
7580//To-do
7581INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7582{
7583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7584
7585 //Using different approach to get required WiFi Parameters from system available commands
7586#if 0
7587 FILE *f;
7588 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7589 char cmd[256], buf[2048];
7590 char *param , *value, *line=NULL;
7591 size_t len = 0;
7592 ssize_t nread;
7593 wifi_associated_dev3_t *dev=NULL;
7594 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007595 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007596 _syscmd(cmd,buf,sizeof(buf));
7597 *output_array_size = atoi(buf);
7598
7599 if (*output_array_size <= 0)
7600 return RETURN_OK;
7601
7602 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7603 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007604 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007605 _syscmd(cmd,buf,sizeof(buf));
7606 f = fopen("/tmp/connected_devices.txt", "r");
7607 if (f==NULL)
7608 {
7609 *output_array_size=0;
7610 return RETURN_ERR;
7611 }
7612 while ((nread = getline(&line, &len, f)) != -1)
7613 {
7614 param = strtok(line,"=");
7615 value = strtok(NULL,"=");
7616
7617 if( strcmp("flags",param) == 0 )
7618 {
7619 value[strlen(value)-1]='\0';
7620 if(strstr (value,"AUTHORIZED") != NULL )
7621 {
7622 dev[auth_temp].cli_AuthenticationState = 1;
7623 dev[auth_temp].cli_Active = 1;
7624 auth_temp++;
7625 read_flag=1;
7626 }
7627 }
7628 if(read_flag==1)
7629 {
7630 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7631 {
7632 value[strlen(value)-1]='\0';
7633 sscanf(value, "%x:%x:%x:%x:%x:%x",
7634 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7635 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7636 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7637 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7638 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7639 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7640
7641 }
7642 else if( strcmp("rx_packets",param) == 0 )
7643 {
7644 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7645 }
7646
7647 else if( strcmp("tx_packets",param) == 0 )
7648 {
7649 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7650 }
7651
7652 else if( strcmp("rx_bytes",param) == 0 )
7653 {
7654 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7655 }
7656
7657 else if( strcmp("tx_bytes",param) == 0 )
7658 {
7659 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7660 mac_temp++;
7661 read_flag=0;
7662 }
7663 }
7664 }
7665
7666 *output_array_size = auth_temp;
7667 auth_temp=0;
7668 mac_temp=0;
7669 free(line);
7670 fclose(f);
7671#endif
7672 char interface_name[MAX_BUF_SIZE] = {0};
7673 char wifi_status[MAX_BUF_SIZE] = {0};
7674 char hostapdconf[MAX_BUF_SIZE] = {0};
7675
7676 wifi_associated_dev3_t *dev_array = NULL;
7677 ULONG wifi_count = 0;
7678
7679 *associated_dev_array = NULL;
7680 *output_array_size = 0;
7681
7682 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7683 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7684 {
7685 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7686
developerac6f1142022-12-20 19:26:35 +08007687 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08007688
7689 if(strlen(interface_name) > 1)
7690 {
7691 wifihal_interfacestatus(wifi_status,interface_name);
7692 if(strcmp(wifi_status,"RUNNING") == 0)
7693 {
7694 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7695
7696 *associated_dev_array = dev_array;
7697 *output_array_size = wifi_count;
7698 }
7699 else
7700 {
7701 *associated_dev_array = NULL;
7702 }
7703 }
7704 }
7705
7706 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7707 return RETURN_OK;
7708}
7709#endif
7710
7711/* getIPAddress function */
7712/**
7713* @description Returning IpAddress of the Matched String
7714*
7715* @param
7716* @str Having MacAddress
7717* @ipaddr Having ipaddr
7718* @return The status of the operation
7719* @retval RETURN_OK if successful
7720* @retval RETURN_ERR if any error is detected
7721*
7722*/
7723
7724INT getIPAddress(char *str,char *ipaddr)
7725{
7726 FILE *fp = NULL;
7727 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7728 int LeaseTime = 0,ret = 0;
7729 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7730 {
7731 return RETURN_ERR;
7732 }
7733
7734 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7735 {
7736 /*
7737 Sample:sss
7738 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7739 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7740 */
7741 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08007742 &(LeaseTime),
7743 phyAddr,
7744 ipAddr,
7745 hostName
7746 );
developer06a01d92022-09-07 16:32:39 +08007747 if(ret != 4)
7748 continue;
7749 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08007750 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08007751 }
developerd946fd62022-12-08 18:03:28 +08007752 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08007753 return RETURN_OK;
7754}
7755
7756/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7757/**
7758* @description Returning Inactive wireless connected clients informations
7759*
7760* @param
7761* @filename Holding private_wifi 2g/5g content files
7762* @associated_dev_array Having inactiv wireless clients informations
7763* @output_array_size Returning Inactive wireless counts
7764* @return The status of the operation
7765* @retval RETURN_OK if successful
7766* @retval RETURN_ERR if any error is detected
7767*
7768*/
7769
7770INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7771{
7772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7773 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7774 FILE *fp = NULL;
7775 int arr[MACADDRESS_SIZE] = {0};
7776 unsigned char mac[MACADDRESS_SIZE] = {0};
7777 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7778 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7779 fp = popen(buf,"r");
7780 if(fp == NULL)
7781 return RETURN_ERR;
7782 else
7783 {
7784 fgets(path,sizeof(path),fp);
7785 maccount = atoi(path);
7786 }
7787 pclose(fp);
7788 *output_array_size = maccount;
7789 wifi_associated_dev3_t* temp = NULL;
7790 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7791 *associated_dev_array = temp;
7792 if(temp == NULL)
7793 {
7794 printf("Error Statement. Insufficient memory \n");
7795 return RETURN_ERR;
7796 }
7797 memset(buf,0,sizeof(buf));
7798 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7799 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08007800 if (fp == NULL) {
7801 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7802 return RETURN_ERR;
7803 }
developer06a01d92022-09-07 16:32:39 +08007804 for(count = 0; count < maccount ; count++)
7805 {
7806 fgets(path,sizeof(path),fp);
7807 for(i = 0; path[i]!='\n';i++)
7808 str[i]=path[i];
7809 str[i]='\0';
7810 getIPAddress(str,ipaddr);
7811 memset(buf,0,sizeof(buf));
7812 if(strlen(ipaddr) > 0)
7813 {
7814 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7815 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7816 {
7817 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7818 {
7819 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7820 {
7821 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7822
7823 }
7824 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7825 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]);
7826 }
7827 temp[count].cli_AuthenticationState = 0; //TODO
7828 temp[count].cli_Active = 0; //TODO
7829 temp[count].cli_SignalStrength = 0;
7830 }
7831 else //Active wireless clients info
7832 {
7833 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7834 {
7835 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7836 {
7837 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7838
7839 }
7840 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7841 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]);
7842 }
7843 temp[count].cli_Active = 1;
7844 }
7845 }
7846 memset(ipaddr,0,sizeof(ipaddr));
7847 }
7848 pclose(fp);
7849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7850 return RETURN_OK;
7851}
7852//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7853//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7854//To get Band Steering Capability
7855INT wifi_getBandSteeringCapability(BOOL *support)
7856{
7857 *support = FALSE;
7858 return RETURN_OK;
7859}
7860
7861
7862//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7863//To get Band Steering enable status
7864INT wifi_getBandSteeringEnable(BOOL *enable)
7865{
7866 *enable = FALSE;
7867 return RETURN_OK;
7868}
7869
7870//To turn on/off Band steering
7871INT wifi_setBandSteeringEnable(BOOL enable)
7872{
7873 return RETURN_OK;
7874}
7875
7876//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7877//To get Band Steering AP group
7878INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7879{
7880 if (NULL == output_ApGroup)
7881 return RETURN_ERR;
7882
7883 strcpy(output_ApGroup, "1,2");
7884 return RETURN_OK;
7885}
7886
7887//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7888//to set and read the band steering BandUtilizationThreshold parameters
7889INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7890{
7891 return RETURN_ERR;
7892}
7893
7894INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7895{
7896 return RETURN_ERR;
7897}
7898
7899//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7900//to set and read the band steering RSSIThreshold parameters
7901INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7902{
7903 return RETURN_ERR;
7904}
7905
7906INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7907{
7908 return RETURN_ERR;
7909}
7910
7911
7912//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7913//to set and read the band steering physical modulation rate threshold parameters
7914INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7915{
7916 //If chip is not support, return -1
7917 return RETURN_ERR;
7918}
7919
7920INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7921{
7922 //If chip is not support, return -1
7923 return RETURN_ERR;
7924}
7925
7926//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7927//to set and read the inactivity time (in seconds) for steering under overload condition
7928INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7929{
7930 return RETURN_ERR;
7931}
7932
7933INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7934{
7935 return RETURN_ERR;
7936}
7937
7938//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7939//to set and read the inactivity time (in seconds) for steering under Idle condition
7940INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7941{
7942 return RETURN_ERR;
7943}
7944
7945INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7946{
7947 return RETURN_ERR;
7948}
7949
7950//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7951//pClientMAC[64]
7952//pSourceSSIDIndex[64]
7953//pDestSSIDIndex[64]
7954//pSteeringReason[256]
7955INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7956{
7957 //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
7958 *pSteeringTime=time(NULL);
7959 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7960 return RETURN_OK;
7961}
7962
7963INT wifi_ifConfigDown(INT apIndex)
7964{
7965 INT status = RETURN_OK;
7966 char cmd[64];
7967
7968 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7969 printf("%s: %s\n", __func__, cmd);
7970 system(cmd);
7971
7972 return status;
7973}
7974
7975INT wifi_ifConfigUp(INT apIndex)
7976{
developerd946fd62022-12-08 18:03:28 +08007977 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007978 char cmd[128];
7979 char buf[1024];
7980
developerac6f1142022-12-20 19:26:35 +08007981 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007982 return RETURN_ERR;
7983 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08007984 _syscmd(cmd, buf, sizeof(buf));
7985 return 0;
7986}
7987
7988//>> Deprecated. Replace with wifi_applyRadioSettings
7989INT wifi_pushBridgeInfo(INT apIndex)
7990{
developerd946fd62022-12-08 18:03:28 +08007991 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007992 char ip[32] = {0};
7993 char subnet[32] = {0};
7994 char bridge[32] = {0};
7995 int vlanId = 0;
7996 char cmd[128] = {0};
7997 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08007998
7999 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8000 wifi_getApVlanID(apIndex,&vlanId);
8001
developerac6f1142022-12-20 19:26:35 +08008002 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008003 return RETURN_ERR;
8004 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008005 _syscmd(cmd,buf, sizeof(buf));
8006
8007 return 0;
8008}
8009
8010INT wifi_pushChannel(INT radioIndex, UINT channel)
8011{
developerd946fd62022-12-08 18:03:28 +08008012 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008013 char cmd[128];
8014 char buf[1024];
8015 int apIndex;
8016
8017 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008018 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008019 return RETURN_ERR;
8020 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008021 _syscmd(cmd,buf, sizeof(buf));
8022
8023 return 0;
8024}
8025
8026INT wifi_pushChannelMode(INT radioIndex)
8027{
8028 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8029 return RETURN_ERR;
8030}
8031
8032INT wifi_pushDefaultValues(INT radioIndex)
8033{
8034 //Apply Comcast specified default radio settings instantly
8035 //AMPDU=1
8036 //AMPDUFrames=32
8037 //AMPDULim=50000
8038 //txqueuelen=1000
8039
8040 return RETURN_ERR;
8041}
8042
8043INT wifi_pushTxChainMask(INT radioIndex)
8044{
8045 //Apply default TxChainMask instantly
8046 return RETURN_ERR;
8047}
8048
8049INT wifi_pushRxChainMask(INT radioIndex)
8050{
8051 //Apply default RxChainMask instantly
8052 return RETURN_ERR;
8053}
8054
8055INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8056{
8057 INT status;
8058
8059 status = wifi_setSSIDName(apIndex,ssid);
8060 wifi_setApEnable(apIndex,FALSE);
8061 wifi_setApEnable(apIndex,TRUE);
8062
8063 return status;
8064}
8065
8066INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8067{
8068 //Apply default Ssid Advertisement instantly
8069 return RETURN_ERR;
8070}
8071
8072INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8073{
8074 INT status = RETURN_ERR;
8075 *output = 0;
8076 return RETURN_ERR;
8077}
8078
8079INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8080{
8081 return RETURN_OK;
8082}
8083
8084INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8085{
8086 return RETURN_OK;
8087}
8088
8089//To-do
8090INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8091{
developereb199ae2022-09-13 14:04:27 +08008092 char output[16]={'\0'};
8093 char config_file[MAX_BUF_SIZE] = {0};
8094
8095 if (!output_string)
8096 return RETURN_ERR;
8097
8098 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8099 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8100
8101 if (strlen(output) == 0)
8102 snprintf(output_string, 64, "Disabled");
8103 else if (strncmp(output, "0", 1) == 0)
8104 snprintf(output_string, 64, "Disabled");
8105 else if (strncmp(output, "1", 1) == 0)
8106 snprintf(output_string, 64, "Optional");
8107 else if (strncmp(output, "2", 1) == 0)
8108 snprintf(output_string, 64, "Required");
8109 else {
8110 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8111 return RETURN_ERR;
8112 }
8113
8114 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008115 return RETURN_OK;
8116}
8117INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8118{
developereb199ae2022-09-13 14:04:27 +08008119 char str[MAX_BUF_SIZE]={'\0'};
8120 char cmd[MAX_CMD_SIZE]={'\0'};
8121 struct params params;
8122 char config_file[MAX_BUF_SIZE] = {0};
8123
8124 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8125 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8126 return RETURN_ERR;
8127
8128 params.name = "ieee80211w";
8129 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8130 params.value = "0";
8131 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8132 params.value = "1";
8133 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8134 params.value = "2";
8135 else{
8136 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8137 return RETURN_ERR;
8138 }
8139 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8140 wifi_hostapdWrite(config_file, &params, 1);
8141 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008142 return RETURN_OK;
8143}
8144INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8145{
8146 char output[16]={'\0'};
8147 char config_file[MAX_BUF_SIZE] = {0};
8148
8149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8150 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8151 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8152
8153 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8154 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8155
8156 return RETURN_OK;
8157}
8158
8159INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8160{
8161 return RETURN_OK;
8162}
8163
8164INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8165{
8166 return RETURN_OK;
8167}
8168
8169INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8170{
8171 return RETURN_OK;
8172}
8173
8174INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8175{
8176 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8177 char config_file[MAX_BUF_SIZE] = {0};
8178
8179 if (NULL == output)
8180 return RETURN_ERR;
8181 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8182 wifi_hostapdRead(config_file,"hw_mode",output,64);
8183
8184 if(strcmp(output,"b")==0)
8185 sprintf(output, "%s", "1,2,5.5,11");
8186 else if (strcmp(output,"a")==0)
8187 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8188 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8189 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8190
8191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8192 return RETURN_OK;
8193}
8194
8195INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8196{
8197 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8198 char *temp;
8199 char temp_output[128];
8200 char temp_TransmitRates[128];
8201 char config_file[MAX_BUF_SIZE] = {0};
8202
8203 if (NULL == output)
8204 return RETURN_ERR;
8205
8206 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8207 wifi_hostapdRead(config_file,"supported_rates",output,64);
8208
developer5b398df2022-11-17 20:39:48 +08008209 if (strlen(output) == 0) {
8210 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8211 return RETURN_OK;
8212 }
developer06a01d92022-09-07 16:32:39 +08008213 strcpy(temp_TransmitRates,output);
8214 strcpy(temp_output,"");
8215 temp = strtok(temp_TransmitRates," ");
8216 while(temp!=NULL)
8217 {
8218 temp[strlen(temp)-1]=0;
8219 if((temp[0]=='5') && (temp[1]=='\0'))
8220 {
8221 temp="5.5";
8222 }
8223 strcat(temp_output,temp);
8224 temp = strtok(NULL," ");
8225 if(temp!=NULL)
8226 {
8227 strcat(temp_output,",");
8228 }
8229 }
8230 strcpy(output,temp_output);
8231 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8232
8233 return RETURN_OK;
8234}
8235
8236INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8237{
8238 return RETURN_OK;
8239}
8240
8241
8242INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8243{
8244 int i=0;
8245 char *temp;
developeref938762022-10-19 17:21:01 +08008246 char temp1[128] = {0};
8247 char temp_output[128] = {0};
8248 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008249 struct params params={'\0'};
8250 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008251 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008252
8253 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8254 if(NULL == output)
8255 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008256 strcpy(temp_TransmitRates,output);
8257
8258 for(i=0;i<strlen(temp_TransmitRates);i++)
8259 {
developeref938762022-10-19 17:21:01 +08008260 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008261 {
8262 continue;
8263 }
8264 else
8265 {
8266 return RETURN_ERR;
8267 }
8268 }
8269 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008270 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008271 while(temp!=NULL)
8272 {
8273 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008274 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008275 {
developeref938762022-10-19 17:21:01 +08008276 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008277 {
8278 return RETURN_ERR;
8279 }
8280 }
8281
8282 if(strcmp(temp,"5.5")==0)
8283 {
8284 strcpy(temp1,"55");
8285 }
8286 else
8287 {
8288 strcat(temp1,"0");
8289 }
8290 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008291 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008292 if(temp!=NULL)
8293 {
8294 strcat(temp_output," ");
8295 }
8296 }
8297 strcpy(output,temp_output);
8298
developer06a01d92022-09-07 16:32:39 +08008299 params.name = "supported_rates";
8300 params.value = output;
8301
8302 wifi_dbg_printf("\n%s:",__func__);
8303 wifi_dbg_printf("params.value=%s\n",params.value);
8304 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8305 wifi_hostapdWrite(config_file,&params,1);
8306 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8307
8308 return RETURN_OK;
8309}
8310
8311
8312static char *sncopy(char *dst, int dst_sz, const char *src)
8313{
8314 if (src && dst && dst_sz > 0) {
8315 strncpy(dst, src, dst_sz);
8316 dst[dst_sz - 1] = '\0';
8317 }
8318 return dst;
8319}
8320
8321static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8322{
8323 if (0 == strcmp(ht_mode, "HT40") ||
8324 0 == strcmp(ht_mode, "HT80") ||
8325 0 == strcmp(ht_mode, "HT160")) {
8326 switch (channel) {
8327 case 1 ... 7:
8328 case 36:
8329 case 44:
8330 case 52:
8331 case 60:
8332 case 100:
8333 case 108:
8334 case 116:
8335 case 124:
8336 case 132:
8337 case 140:
8338 case 149:
8339 case 157:
8340 return 1;
8341 case 8 ... 13:
8342 case 40:
8343 case 48:
8344 case 56:
8345 case 64:
8346 case 104:
8347 case 112:
8348 case 120:
8349 case 128:
8350 case 136:
8351 case 144:
8352 case 153:
8353 case 161:
8354 return -1;
8355 default:
8356 return -EINVAL;
8357 }
8358 }
8359
8360 return -EINVAL;
8361}
8362
developerb7593de2022-10-18 09:51:57 +08008363static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8364{
8365 int idx = channel%8;
8366 if (0 == strcmp(ht_mode, "HT40") ||
8367 0 == strcmp(ht_mode, "HT80") ||
8368 0 == strcmp(ht_mode, "HT160")) {
8369 switch (idx) {
8370 case 1:
8371 return 1;
8372 case 5:
8373 return -1;
8374 default:
8375 return -EINVAL;
8376 }
8377 }
8378
8379 return -EINVAL;
8380}
developer06a01d92022-09-07 16:32:39 +08008381static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8382{
8383 if (NULL == hw_mode) return;
8384
8385 if (0 == strcmp(hw_mode, "ac"))
8386 sncopy(bw_mode, bw_mode_len, "ht vht");
8387
8388 if (0 == strcmp(hw_mode, "n"))
8389 sncopy(bw_mode, bw_mode_len, "ht");
8390
8391 return;
8392}
8393
8394static int util_chan_to_freq(int chan)
8395{
8396 if (chan == 14)
8397 return 2484;
8398 else if (chan < 14)
8399 return 2407 + chan * 5;
8400 else if (chan >= 182 && chan <= 196)
8401 return 4000 + chan * 5;
8402 else
8403 return 5000 + chan * 5;
8404 return 0;
8405}
8406
developerb7593de2022-10-18 09:51:57 +08008407static int util_6G_chan_to_freq(int chan)
8408{
8409 if (chan)
8410 return 5950 + chan * 5;
8411 else
8412 return 0;
8413
8414}
developer06a01d92022-09-07 16:32:39 +08008415const int *util_unii_5g_chan2list(int chan, int width)
8416{
8417 static const int lists[] = {
8418 // <width>, <chan1>, <chan2>..., 0,
8419 20, 36, 0,
8420 20, 40, 0,
8421 20, 44, 0,
8422 20, 48, 0,
8423 20, 52, 0,
8424 20, 56, 0,
8425 20, 60, 0,
8426 20, 64, 0,
8427 20, 100, 0,
8428 20, 104, 0,
8429 20, 108, 0,
8430 20, 112, 0,
8431 20, 116, 0,
8432 20, 120, 0,
8433 20, 124, 0,
8434 20, 128, 0,
8435 20, 132, 0,
8436 20, 136, 0,
8437 20, 140, 0,
8438 20, 144, 0,
8439 20, 149, 0,
8440 20, 153, 0,
8441 20, 157, 0,
8442 20, 161, 0,
8443 20, 165, 0,
8444 40, 36, 40, 0,
8445 40, 44, 48, 0,
8446 40, 52, 56, 0,
8447 40, 60, 64, 0,
8448 40, 100, 104, 0,
8449 40, 108, 112, 0,
8450 40, 116, 120, 0,
8451 40, 124, 128, 0,
8452 40, 132, 136, 0,
8453 40, 140, 144, 0,
8454 40, 149, 153, 0,
8455 40, 157, 161, 0,
8456 80, 36, 40, 44, 48, 0,
8457 80, 52, 56, 60, 64, 0,
8458 80, 100, 104, 108, 112, 0,
8459 80, 116, 120, 124, 128, 0,
8460 80, 132, 136, 140, 144, 0,
8461 80, 149, 153, 157, 161, 0,
8462 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8463 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8464 -1 // final delimiter
8465 };
8466 const int *start;
8467 const int *p;
8468
8469 for (p = lists; *p != -1; p++) {
8470 if (*p == width) {
8471 for (start = ++p; *p != 0; p++) {
8472 if (*p == chan)
8473 return start;
8474 }
8475 }
8476 // move to the end of channel list of given width
8477 while (*p != 0) {
8478 p++;
8479 }
8480 }
8481
8482 return NULL;
8483}
8484
8485static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8486{
8487 if (NULL == ht_mode)
8488 return 0;
8489
8490 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8491 const int *chans = util_unii_5g_chan2list(channel, width);
8492 int sum = 0;
8493 int cnt = 0;
8494
8495 if (NULL == chans)
8496 return 0;
8497
8498 while (*chans) {
8499 sum += *chans;
8500 cnt++;
8501 chans++;
8502 }
developer30423732022-12-01 16:17:49 +08008503 if (cnt == 0)
8504 return 0;
developer06a01d92022-09-07 16:32:39 +08008505 return sum / cnt;
8506}
8507
developerb7593de2022-10-18 09:51:57 +08008508static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8509{
8510 if (NULL == ht_mode)
8511 return 0;
8512
8513 int width = strtol((ht_mode + 2), NULL, 10);
8514
8515 int idx = 0 ;
8516 int centerchan = 0;
8517 int chan_ofs = 1;
8518
8519 if (width == 40){
8520 idx = ((channel/4) + chan_ofs)%2;
8521 switch (idx) {
8522 case 0:
8523 centerchan = (channel - 2);
8524 break;
8525 case 1:
8526 centerchan = (channel + 2);
8527 break;
8528 default:
8529 return -EINVAL;
8530 }
8531 }else if (width == 80){
8532 idx = ((channel/4) + chan_ofs)%4;
8533 switch (idx) {
8534 case 0:
8535 centerchan = (channel - 6);
8536 break;
8537 case 1:
8538 centerchan = (channel + 6);
8539 break;
8540 case 2:
8541 centerchan = (channel + 2);
8542 break;
8543 case 3:
8544 centerchan = (channel - 2);
8545 break;
8546 default:
8547 return -EINVAL;
8548 }
8549 }else if (width == 160){
8550 switch (channel) {
8551 case 1 ... 29:
8552 centerchan = 15;
8553 break;
8554 case 33 ... 61:
8555 centerchan = 47;
8556 break;
8557 case 65 ... 93:
8558 centerchan = 79;
8559 break;
8560 case 97 ... 125:
8561 centerchan = 111;
8562 break;
8563 case 129 ... 157:
8564 centerchan = 143;
8565 break;
8566 case 161 ... 189:
8567 centerchan = 175;
8568 break;
8569 case 193 ... 221:
8570 centerchan = 207;
8571 break;
8572 default:
8573 return -EINVAL;
8574 }
8575 }
8576 return centerchan;
8577}
developer06a01d92022-09-07 16:32:39 +08008578static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8579{
8580 BOOL onlyG, onlyN, onlyA;
8581 CHAR tmp[64];
8582 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8583 if (ret == RETURN_OK) {
8584 sncopy(hw_mode, hw_mode_size, tmp);
8585 }
8586 return ret;
8587}
8588
8589INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8590{
8591 // Sample commands:
8592 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8593 // hostapd_cli -i wifi0 chan_switch 30 2437
8594 char cmd[MAX_CMD_SIZE] = {0};
8595 char buf[MAX_BUF_SIZE] = {0};
8596 int freq = 0, ret = 0;
8597 char center_freq1_str[32] = ""; // center_freq1=%d
8598 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8599 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8600 char hw_mode[16] = ""; // n|ac
8601 char bw_mode[16] = ""; // ht|ht vht
8602 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008603 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008604 int sec_chan_offset;
8605 int width;
developer4fb0b922022-09-30 14:29:09 +08008606 char config_file[64] = {0};
8607 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008608 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008609 wifi_band band = band_invalid;
8610 int center_chan = 0;
8611 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008612
developer4fb0b922022-09-30 14:29:09 +08008613 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008614
developerac6f1142022-12-20 19:26:35 +08008615 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008616 return RETURN_ERR;
8617
developer06a01d92022-09-07 16:32:39 +08008618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8619
developerb7593de2022-10-18 09:51:57 +08008620 band = wifi_index_to_band(radioIndex);
8621
developer5884e982022-10-06 10:52:50 +08008622 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008623
8624 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008625 if (channel){
developerb7593de2022-10-18 09:51:57 +08008626 if (band == band_6){
8627 freq = util_6G_chan_to_freq(channel);
8628 }else{
8629 freq = util_chan_to_freq(channel);
8630 }
developer5884e982022-10-06 10:52:50 +08008631 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008632
developer5884e982022-10-06 10:52:50 +08008633 // Provide bandwith if specified
8634 if (channel_width_MHz > 20) {
8635 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8636 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8637 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008638
developer5884e982022-10-06 10:52:50 +08008639 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8640 }else if (channel_width_MHz == 20){
8641 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8642 }
developer06a01d92022-09-07 16:32:39 +08008643
developerb7593de2022-10-18 09:51:57 +08008644
developer5884e982022-10-06 10:52:50 +08008645 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008646 if (band == band_6){
8647 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8648 if(center_chan){
8649 center_freq1 = util_6G_chan_to_freq(center_chan);
8650 }
8651 }else{
8652 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8653 if(center_chan){
8654 center_freq1 = util_chan_to_freq(center_chan);
8655 }
developer5884e982022-10-06 10:52:50 +08008656 }
developerb7593de2022-10-18 09:51:57 +08008657
8658 if (center_freq1)
8659 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8660
8661 }
8662
8663 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8664 if (band == band_6){
8665 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8666 }else{
8667 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008668 }
developerb7593de2022-10-18 09:51:57 +08008669 if (sec_chan_offset != -EINVAL)
8670 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008671
developer5884e982022-10-06 10:52:50 +08008672 // Only the first AP, other are hanging on the same radio
8673 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08008674 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8675 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08008676 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8677 wifi_dbg_printf("execute: '%s'\n", cmd);
8678 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008679
developer5884e982022-10-06 10:52:50 +08008680 ret = wifi_setRadioChannel(radioIndex, channel);
8681 if (ret != RETURN_OK) {
8682 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8683 return RETURN_ERR;
8684 }
8685
8686 if (sec_chan_offset == 1) ext_str = "Above";
8687 else if (sec_chan_offset == -1) ext_str = "Below";
8688
8689 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008690
developer5884e982022-10-06 10:52:50 +08008691 } else {
8692 if (channel_width_MHz > 20)
8693 ext_str = "Above";
8694 }
developer4fb0b922022-09-30 14:29:09 +08008695 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8696 _syscmd(cmd, buf, sizeof(buf));
8697 if (strlen(buf) != 0)
8698 stbcEnable = TRUE;
8699
developer06a01d92022-09-07 16:32:39 +08008700 wifi_setRadioExtChannel(radioIndex, ext_str);
8701
developer4fb0b922022-09-30 14:29:09 +08008702 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8703
developer06a01d92022-09-07 16:32:39 +08008704 char mhz_str[16];
8705 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8706 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8707
8708 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8709
8710 return RETURN_OK;
8711}
8712
8713INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8714{
developer615510b2022-09-27 10:14:35 +08008715 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008716 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008717 char cmd[256]={0};
8718 char buf[128]={0};
8719 char file_name[32] = {0};
8720 char filter_SSID[32] = {0};
8721 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08008722 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08008723 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008724 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008725 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008726 size_t len=0;
8727 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008728 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008729 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008730 bool filter_enable = false;
8731 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008732 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008733
developer615510b2022-09-27 10:14:35 +08008734 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008735
developer615510b2022-09-27 10:14:35 +08008736 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8737 f = fopen(file_name, "r");
8738 if (f != NULL) {
8739 fgets(filter_SSID, sizeof(file_name), f);
8740 if (strlen(filter_SSID) != 0)
8741 filter_enable = true;
8742 fclose(f);
8743 }
8744
developerac6f1142022-12-20 19:26:35 +08008745 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008746 return RETURN_ERR;
8747
developer033b37b2022-10-18 11:27:46 +08008748 phyId = radio_index_to_phy(radio_index);
8749
8750 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008751 _syscmd(cmd, buf, sizeof(buf));
8752 channels_num = strtol(buf, NULL, 10);
8753
developerd946fd62022-12-08 18:03:28 +08008754 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8755 // 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 +08008756 fprintf(stderr, "cmd: %s\n", cmd);
8757 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008758 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8759 return RETURN_ERR;
8760 }
developer5550e242022-09-30 09:59:32 +08008761
8762 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8763 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8764
developer615510b2022-09-27 10:14:35 +08008765 ret = fgets(line, sizeof(line), f);
8766 while (ret != NULL) {
8767 if(strstr(line, "BSS") != NULL) { // new neighbor info
8768 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8769 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8770 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8771
8772 if (!filter_BSS) {
8773 index++;
8774 wifi_neighbor_ap2_t *tmp;
8775 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8776 if (tmp == NULL) { // no more memory to use
8777 index--;
8778 wifi_dbg_printf("%s: realloc failed\n", __func__);
8779 break;
8780 }
8781 scan_array = tmp;
8782 }
8783 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008784
developer615510b2022-09-27 10:14:35 +08008785 filter_BSS = false;
8786 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8787 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8788 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8789 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8790 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008791 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008792 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008793
developer615510b2022-09-27 10:14:35 +08008794 if (freq >= 2412 && freq <= 2484) {
8795 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8796 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8797 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8798 }
8799 else if (freq >= 5160 && freq <= 5805) {
8800 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8801 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8802 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8803 }
developer06a01d92022-09-07 16:32:39 +08008804
developer615510b2022-09-27 10:14:35 +08008805 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008806 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008807 for (int i = 0; i < channels_num; i++) {
8808 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8809 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8810 break;
8811 }
8812 }
developer06a01d92022-09-07 16:32:39 +08008813 }
developer615510b2022-09-27 10:14:35 +08008814 } else if (strstr(line, "beacon interval") != NULL) {
8815 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8816 } else if (strstr(line, "signal") != NULL) {
8817 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8818 } else if (strstr(line,"SSID") != NULL) {
8819 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8820 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8821 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008822 }
developer615510b2022-09-27 10:14:35 +08008823 } else if (strstr(line, "Supported rates") != NULL) {
8824 char SRate[80] = {0}, *tmp = NULL;
8825 memset(buf, 0, sizeof(buf));
8826 strcpy(SRate, line);
8827 tmp = strtok(SRate, ":");
8828 tmp = strtok(NULL, ":");
8829 strcpy(buf, tmp);
8830 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008831
developer615510b2022-09-27 10:14:35 +08008832 tmp = strtok(buf, " \n");
8833 while (tmp != NULL) {
8834 strcat(SRate, tmp);
8835 if (SRate[strlen(SRate) - 1] == '*') {
8836 SRate[strlen(SRate) - 1] = '\0';
8837 }
8838 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008839
developer615510b2022-09-27 10:14:35 +08008840 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008841 }
developer615510b2022-09-27 10:14:35 +08008842 SRate[strlen(SRate) - 1] = '\0';
8843 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8844 } else if (strstr(line, "DTIM") != NULL) {
8845 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8846 } else if (strstr(line, "VHT capabilities") != NULL) {
8847 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8848 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8849 } else if (strstr(line, "HT capabilities") != NULL) {
8850 strcat(scan_array[index].ap_SupportedStandards, ",n");
8851 strcpy(scan_array[index].ap_OperatingStandards, "n");
8852 } else if (strstr(line, "VHT operation") != NULL) {
8853 ret = fgets(line, sizeof(line), f);
8854 sscanf(line," * channel width: %d", &vht_channel_width);
8855 if(vht_channel_width == 1) {
8856 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8857 } else {
8858 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8859 }
8860 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8861 continue;
8862 } else if (strstr(line, "HT operation") != NULL) {
8863 ret = fgets(line, sizeof(line), f);
8864 sscanf(line," * secondary channel offset: %s", &buf);
8865 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008866 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008867 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 +08008868 }
developer615510b2022-09-27 10:14:35 +08008869 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008870 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008871 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8872 } else {
8873 //20Mhz
8874 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 +08008875 }
developer615510b2022-09-27 10:14:35 +08008876 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008877 continue;
developer615510b2022-09-27 10:14:35 +08008878 } else if (strstr(line, "HE capabilities") != NULL) {
8879 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8880 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8881 ret = fgets(line, sizeof(line), f);
8882 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8883 if (strstr(line, "HE40/2.4GHz") != NULL)
8884 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8885 else
8886 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8887 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8888 if (strstr(line, "HE80/5GHz") != NULL) {
8889 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8890 ret = fgets(line, sizeof(line), f);
8891 } else
8892 continue;
8893 if (strstr(line, "HE160/5GHz") != NULL)
8894 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008895 }
developer615510b2022-09-27 10:14:35 +08008896 continue;
8897 } else if (strstr(line, "WPA") != NULL) {
8898 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8899 } else if (strstr(line, "RSN") != NULL) {
8900 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8901 } else if (strstr(line, "Group cipher") != NULL) {
8902 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8903 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8904 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008905 }
developer06a01d92022-09-07 16:32:39 +08008906 }
developer615510b2022-09-27 10:14:35 +08008907 ret = fgets(line, sizeof(line), f);
8908 }
8909
8910 if (!filter_BSS) {
8911 *output_array_size = index + 1;
8912 } else {
8913 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8914 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008915 }
developer06a01d92022-09-07 16:32:39 +08008916 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008917 pclose(f);
developer5550e242022-09-30 09:59:32 +08008918 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008919 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008920 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008921}
developer615510b2022-09-27 10:14:35 +08008922
developer06a01d92022-09-07 16:32:39 +08008923INT wifi_getApAssociatedDeviceStats(
8924 INT apIndex,
8925 mac_address_t *clientMacAddress,
8926 wifi_associated_dev_stats_t *associated_dev_stats,
8927 u64 *handle)
8928{
8929 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8930 char interface_name[50] = {0};
8931 char cmd[1024] = {0};
8932 char mac_str[18] = {0};
8933 char *key = NULL;
8934 char *val = NULL;
8935 FILE *f = NULL;
8936 char *line = NULL;
8937 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08008938
8939 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8940 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8941 return RETURN_ERR;
8942 }
8943
8944 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8945 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8946 if((f = popen(cmd, "r")) == NULL) {
8947 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8948 return RETURN_ERR;
8949 }
8950
developer30423732022-12-01 16:17:49 +08008951 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08008952 key = strtok(line,":");
8953 val = strtok(NULL,":");
8954
8955 if(!strncmp(key,"rx bytes",8))
8956 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8957 if(!strncmp(key,"tx bytes",8))
8958 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8959 if(!strncmp(key,"rx packets",10))
8960 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8961 if(!strncmp(key,"tx packets",10))
8962 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8963 if(!strncmp(key,"tx retries",10))
8964 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8965 if(!strncmp(key,"tx failed",9))
8966 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8967 if(!strncmp(key,"rx drop misc",13))
8968 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8969 if(!strncmp(key,"rx bitrate",10)) {
8970 val = strtok(val, " ");
8971 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8972 }
8973 if(!strncmp(key,"tx bitrate",10)) {
8974 val = strtok(val, " ");
8975 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8976 }
8977 }
8978 free(line);
8979 pclose(f);
8980 return RETURN_OK;
8981}
8982
8983INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8984{
developerd946fd62022-12-08 18:03:28 +08008985 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008986 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8987
8988 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8989 if (NULL == output_string)
8990 return RETURN_ERR;
8991
developerac6f1142022-12-20 19:26:35 +08008992 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008993 return RETURN_ERR;
8994 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 +08008995 _syscmd(cmd, buf, sizeof(buf));
8996
8997 //size of SSID name restricted to value less than 32 bytes
8998 snprintf(output_string, 32, "%s", buf);
8999 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9000
9001 return RETURN_OK;
9002}
9003
9004INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9005{
9006 //char cmd[MAX_CMD_SIZE] = {0};
9007 char config_file[MAX_BUF_SIZE] = {0};
9008 char buf[32] = {0};
9009
9010 if (!output_filterMode)
9011 return RETURN_ERR;
9012
9013 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9014 //_syscmd(cmd, buf, sizeof(buf));
9015 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9016 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009017 if(strlen(buf) == 0) {
9018 *output_filterMode = 0;
9019 }
9020 else {
9021 int macaddr_acl_mode = strtol(buf, NULL, 10);
9022 if (macaddr_acl_mode == 1) {
9023 *output_filterMode = 1;
9024 } else if (macaddr_acl_mode == 0) {
9025 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9026 if (strlen(buf) == 0) {
9027 *output_filterMode = 0;
9028 } else {
9029 *output_filterMode = 2;
9030 }
9031 } else {
9032 return RETURN_ERR;
9033 }
9034 }
developer06a01d92022-09-07 16:32:39 +08009035
9036 return RETURN_OK;
9037}
9038
9039INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9040{
9041 FILE *fp = NULL;
9042 char str[MAX_BUF_SIZE] = {0};
9043 int wificlientindex = 0 ;
9044 int count = 0;
9045 int signalstrength = 0;
9046 int arr[MACADDRESS_SIZE] = {0};
9047 unsigned char mac[MACADDRESS_SIZE] = {0};
9048 UINT wifi_count = 0;
9049 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9050 char pipeCmd[MAX_CMD_SIZE] = {0};
9051
9052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9053 *output_array_size = 0;
9054 *associated_dev_array = NULL;
9055 char interface_name[50] = {0};
9056
9057 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9058 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9059 return RETURN_ERR;
9060 }
9061
9062 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9063 fp = popen(pipeCmd, "r");
9064 if (fp == NULL)
9065 {
9066 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9067 return RETURN_ERR;
9068 }
9069
9070 /* Read the output a line at a time - output it. */
9071 fgets(str, sizeof(str)-1, fp);
9072 wifi_count = (unsigned int) atoi ( str );
9073 *output_array_size = wifi_count;
9074 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9075 pclose(fp);
9076
9077 if(wifi_count == 0)
9078 {
9079 return RETURN_OK;
9080 }
9081 else
9082 {
9083 wifi_associated_dev2_t* temp = NULL;
9084 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9085 *associated_dev_array = temp;
9086 if(temp == NULL)
9087 {
9088 printf("Error Statement. Insufficient memory \n");
9089 return RETURN_ERR;
9090 }
9091
9092 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9093 system(pipeCmd);
9094
9095 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9096 if(fp == NULL)
9097 {
9098 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9099 return RETURN_ERR;
9100 }
9101 fclose(fp);
9102
developer30423732022-12-01 16:17:49 +08009103 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009104 fp = popen(pipeCmd, "r");
9105 if(fp)
9106 {
9107 for(count =0 ; count < wifi_count; count++)
9108 {
9109 fgets(str, MAX_BUF_SIZE, fp);
9110 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9111 {
9112 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9113 {
9114 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9115
9116 }
9117 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9118 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]);
9119 }
9120 temp[count].cli_AuthenticationState = 1; //TODO
9121 temp[count].cli_Active = 1; //TODO
9122 }
9123 pclose(fp);
9124 }
9125
9126 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009127 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 +08009128 fp = popen(pipeCmd, "r");
9129 if(fp)
9130 {
9131 pclose(fp);
9132 }
9133 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9134 if(fp)
9135 {
9136 for(count =0 ; count < wifi_count ;count++)
9137 {
9138 fgets(str, MAX_BUF_SIZE, fp);
9139 signalstrength = atoi(str);
9140 temp[count].cli_RSSI = signalstrength;
9141 }
9142 pclose(fp);
9143 }
9144
9145
9146 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009147 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 +08009148 fp = popen(pipeCmd, "r");
9149 if (fp)
9150 {
9151 pclose(fp);
9152 }
9153 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9154 if (fp)
9155 {
9156 for (count = 0; count < wifi_count; count++)
9157 {
9158 fgets(str, MAX_BUF_SIZE, fp);
9159 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9160 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9161 }
9162 pclose(fp);
9163 }
9164
9165 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009166 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 +08009167 fp = popen(pipeCmd, "r");
9168 if (fp)
9169 {
9170 pclose(fp);
9171 }
9172 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9173 if (fp)
9174 {
9175 for (count = 0; count < wifi_count; count++)
9176 {
9177 fgets(str, MAX_BUF_SIZE, fp);
9178 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9179 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9180 }
9181 pclose(fp);
9182 }
9183 }
9184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9185 return RETURN_OK;
9186
9187}
9188
9189INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9190{
9191#if 0
9192 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009193 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009194 _syscmd(cmd, buf, sizeof(buf));*/
9195
9196 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9197 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9198 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9199 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9200
9201 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.
9202 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].
9203 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].
9204 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].
9205 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9206 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9207
9208 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9209 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9210 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9211 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.
9212 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.
9213 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.
9214 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.
9215 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.
9216 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.
9217 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.
9218 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9219#endif
9220
9221 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009222 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009223 char pipeCmd[128] = {0};
9224 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009225 wifi_ssidTrafficStats2_t *out = output_struct;
9226
developerce736392022-09-13 15:24:34 +08009227 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009228 if (!output_struct)
9229 return RETURN_ERR;
9230
developerce736392022-09-13 15:24:34 +08009231 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009232 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009233 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009234 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009235
developer06a01d92022-09-07 16:32:39 +08009236 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009237 if (fp == NULL) {
9238 fprintf(stderr, "%s: popen failed\n", __func__);
9239 return RETURN_ERR;
9240 }
9241 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009242 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009243
developerce736392022-09-13 15:24:34 +08009244 if (strlen(str) == 0) // interface not exist
9245 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009246
developerce736392022-09-13 15:24:34 +08009247 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9248 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009249
developerce736392022-09-13 15:24:34 +08009250 memset(str, 0, sizeof(str));
9251 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009252 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009253 if (fp == NULL) {
9254 fprintf(stderr, "%s: popen failed\n", __func__);
9255 return RETURN_ERR;
9256 }
9257 fgets(str, sizeof(str), fp);
9258
9259 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9260 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009261 pclose(fp);
developerce736392022-09-13 15:24:34 +08009262
9263 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9264 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9265
9266 // Not supported
9267 output_struct->ssid_RetransCount = 0;
9268 output_struct->ssid_FailedRetransCount = 0;
9269 output_struct->ssid_RetryCount = 0;
9270 output_struct->ssid_MultipleRetryCount = 0;
9271 output_struct->ssid_ACKFailureCount = 0;
9272 output_struct->ssid_AggregatedPacketCount = 0;
9273
developer06a01d92022-09-07 16:32:39 +08009274 return RETURN_OK;
9275}
9276
9277//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).
9278INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9279{
9280 char output_val[16]={'\0'};
9281 char config_file[MAX_BUF_SIZE] = {0};
9282
9283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9284 if (!output)
9285 return RETURN_ERR;
9286 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9287 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9288
9289 if( strcmp(output_val,"1") == 0 )
9290 *output = TRUE;
9291 else
9292 *output = FALSE;
9293 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9294
9295 return RETURN_OK;
9296}
9297
9298INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9299{
9300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9301 char str[MAX_BUF_SIZE]={'\0'};
9302 char string[MAX_BUF_SIZE]={'\0'};
9303 char cmd[MAX_CMD_SIZE]={'\0'};
9304 char *ch;
9305 char config_file[MAX_BUF_SIZE] = {0};
9306 struct params params;
9307
9308 if(enable == TRUE)
9309 strcpy(string,"1");
9310 else
9311 strcpy(string,"0");
9312
9313 params.name = "ap_isolate";
9314 params.value = string;
9315
9316 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9317 wifi_hostapdWrite(config_file,&params,1);
9318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9319
9320 return RETURN_OK;
9321}
9322
9323INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9324{
9325 if (NULL == output_dBm)
9326 return RETURN_ERR;
9327
9328 *output_dBm = 0;
9329 return RETURN_OK;
9330}
9331
9332INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9333{
9334 return RETURN_OK;
9335}
9336INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9337{
9338 return RETURN_OK;
9339}
9340INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9341{
9342 return RETURN_OK;
9343}
9344INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9345{
9346 return RETURN_OK;
9347}
9348INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9349{
9350 return RETURN_OK;
9351}
9352INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9353{
9354 char config_file[MAX_BUF_SIZE] = {0};
9355 struct params list;
9356
9357 list.name = "bss_transition";
9358 list.value = activate?"1":"0";
9359 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9360 wifi_hostapdWrite(config_file, &list, 1);
9361
9362 return RETURN_OK;
9363}
9364wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9365
9366void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9367{
9368 return;
9369}
9370
9371INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9372{
9373 // TODO Implement me!
9374 return RETURN_OK;
9375}
9376
9377INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9378{
developera3c68b92022-09-13 15:27:29 +08009379 char file_name[128] = {0};
9380 char buf[128] = {0};
9381 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009382 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009383
9384 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9385
developer804c64f2022-10-19 13:54:40 +08009386 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009387 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009388 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009389 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9390 f = fopen(file_name, "w");
9391 if (f == NULL)
9392 return RETURN_ERR;
9393 // For mode == 0 is to disable filter, just don't write to the file.
9394 if (mode)
9395 fprintf(f, "%s", essid);
9396
9397 fclose(f);
9398 }
9399 } else { // special case, need to set AP's SSID as filter for each radio.
9400 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9401 f = fopen(file_name, "w");
9402 if (f == NULL)
9403 return RETURN_ERR;
9404
9405 // For mode == 0 is to disable filter, just don't write to the file.
9406 if (mode)
9407 fprintf(f, "%s", essid);
9408
9409 fclose(f);
9410 }
9411
9412 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009413 return RETURN_OK;
9414}
9415
9416INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9417{
9418 // TODO Implement me!
9419 //Apply wifi_pushRadioChannel() instantly
9420 return RETURN_ERR;
9421}
9422
9423INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9424{
9425 // TODO Implement me!
9426 return RETURN_OK;
9427}
9428
9429#ifdef HAL_NETLINK_IMPL
9430static int tidStats_callback(struct nl_msg *msg, void *arg) {
9431 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9432 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9433 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9434 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9435 int rem , tid_index = 0;
9436
9437 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9438 wifi_associated_dev_tid_entry_t *stats_entry;
9439
9440 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9441 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9442 };
9443 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9444 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9445 };
9446
9447 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9448 genlmsg_attrlen(gnlh, 0), NULL);
9449
9450
9451 if (!tb[NL80211_ATTR_STA_INFO]) {
9452 fprintf(stderr, "station stats missing!\n");
9453 return NL_SKIP;
9454 }
9455
9456 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9457 tb[NL80211_ATTR_STA_INFO],
9458 stats_policy)) {
9459 fprintf(stderr, "failed to parse nested attributes!\n");
9460 return NL_SKIP;
9461 }
9462
9463 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9464 {
9465 stats_entry = &out->tid_array[tid_index];
9466
9467 stats_entry->tid = tid_index;
9468 stats_entry->ac = _tid_ac_index_get[tid_index];
9469
9470 if(sinfo[NL80211_STA_INFO_TID_STATS])
9471 {
9472 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9473 printf("failed to parse nested stats attributes!");
9474 return NL_SKIP;
9475 }
9476 }
9477 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9478 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9479
9480 if(tid_index < (PS_MAX_TID - 1))
9481 tid_index++;
9482 }
9483 //ToDo: sum_time_ms, ewma_time_ms
9484 return NL_SKIP;
9485}
9486#endif
9487
9488INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9489{
9490#ifdef HAL_NETLINK_IMPL
9491 Netlink nl;
9492 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009493 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009494
developerac6f1142022-12-20 19:26:35 +08009495 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009496 return RETURN_ERR;
9497
9498 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009499
9500 nl.id = initSock80211(&nl);
9501
9502 if (nl.id < 0) {
9503 fprintf(stderr, "Error initializing netlink \n");
9504 return -1;
9505 }
9506
9507 struct nl_msg* msg = nlmsg_alloc();
9508
9509 if (!msg) {
9510 fprintf(stderr, "Failed to allocate netlink message.\n");
9511 nlfree(&nl);
9512 return -2;
9513 }
9514
9515 genlmsg_put(msg,
9516 NL_AUTO_PORT,
9517 NL_AUTO_SEQ,
9518 nl.id,
9519 0,
9520 0,
9521 NL80211_CMD_GET_STATION,
9522 0);
9523
9524 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9525 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9526 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9527 nl_send_auto(nl.socket, msg);
9528 nl_recvmsgs(nl.socket, nl.cb);
9529 nlmsg_free(msg);
9530 nlfree(&nl);
9531 return RETURN_OK;
9532#else
9533//iw implementation
9534#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9535#define TOTAL_MAX_LINES 50
9536
9537 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009538 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009539 FILE *fp=NULL;
9540 char pipeCmd[1024]= {'\0'};
9541 int lines,tid_index=0;
9542 char mac_addr[20] = {'\0'};
9543
developerac6f1142022-12-20 19:26:35 +08009544 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009545 return RETURN_ERR;
9546
developer06a01d92022-09-07 16:32:39 +08009547 wifi_associated_dev_tid_entry_t *stats_entry;
9548
developer06a01d92022-09-07 16:32:39 +08009549 strcpy(mac_addr,clientMacAddress);
9550
9551 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9552 fp= popen(pipeCmd,"r");
9553 if(fp == NULL)
9554 {
9555 perror("popen for station dump failed\n");
9556 return RETURN_ERR;
9557 }
9558 pclose(fp);
9559
9560 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9561 fp=popen(pipeCmd,"r");
9562 if(fp == NULL)
9563 {
9564 perror("popen for grep station failed\n");
9565 return RETURN_ERR;
9566 }
9567 else if(fgets(buf,sizeof(buf),fp) != NULL)
9568 lines=atoi(buf);
9569 else
9570 {
9571 pclose(fp);
9572 fprintf(stderr,"No devices are connected \n");
9573 return RETURN_ERR;
9574 }
9575 pclose(fp);
9576
9577 if(lines == 1)
9578 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9579
9580 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9581 {
9582 stats_entry = &tid_stats->tid_array[tid_index];
9583 stats_entry->tid = tid_index;
9584
9585 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);
9586
9587 fp=popen(pipeCmd,"r");
9588 if(fp ==NULL)
9589 {
9590 perror("Failed to read from tid file \n");
9591 return RETURN_ERR;
9592 }
9593 else if(fgets(buf,sizeof(buf),fp) != NULL)
9594 stats_entry->num_msdus = atol(buf);
9595
9596 pclose(fp);
9597 stats_entry->ac = _tid_ac_index_get[tid_index];
9598// TODO:
9599// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9600// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9601 }
9602 return RETURN_OK;
9603#endif
9604}
9605
9606
9607INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9608{
developerd946fd62022-12-08 18:03:28 +08009609 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009610 char cmd[128]={0};
9611 char buf[128]={0};
9612 int freq = 0;
9613
9614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9615
9616 // full mode is used to scan all channels.
9617 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9618 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9619 ieee80211_channel_to_frequency(chan_list[0], &freq);
9620
developerac6f1142022-12-20 19:26:35 +08009621 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009622 return RETURN_ERR;
9623
developer615510b2022-09-27 10:14:35 +08009624 if (freq)
developerd946fd62022-12-08 18:03:28 +08009625 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009626 else
developerd946fd62022-12-08 18:03:28 +08009627 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009628
9629 _syscmd(cmd, buf, sizeof(buf));
9630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9631
developer06a01d92022-09-07 16:32:39 +08009632 return RETURN_OK;
9633}
9634
9635
9636INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9637{
9638 // TODO Implement me!
9639 return RETURN_ERR;
9640}
9641
9642INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9643{
9644 // TODO Implement me!
9645 return RETURN_ERR;
9646}
9647
9648INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9649{
9650 // TODO Implement me!
9651 return RETURN_ERR;
9652}
9653
9654INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9655{
9656 // TODO Implement me!
9657 return RETURN_ERR;
9658}
9659
9660INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9661{
9662 // TODO Implement me!
9663 return RETURN_ERR;
9664}
9665
9666INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9667{
9668 // TODO Implement me!
9669 return RETURN_ERR;
9670}
9671
9672INT wifi_steering_eventUnregister(void)
9673{
9674 // TODO Implement me!
9675 return RETURN_ERR;
9676}
9677
9678INT wifi_delApAclDevices(INT apIndex)
9679{
9680#if 0
9681 char cmd[MAX_BUF_SIZE] = {0};
9682 char buf[MAX_BUF_SIZE] = {0};
9683
9684 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +08009685 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +08009686 if(_syscmd(cmd,buf,sizeof(buf)))
9687 return RETURN_ERR;
9688#endif
developere6aafda2022-09-13 14:59:28 +08009689 char cmd[MAX_CMD_SIZE]={0};
9690 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009691
developere6aafda2022-09-13 14:59:28 +08009692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9693 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9694 if(_syscmd(cmd, buf, sizeof(buf)))
9695 return RETURN_ERR;
9696 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009697
9698 return RETURN_OK;
9699}
9700
9701#ifdef HAL_NETLINK_IMPL
9702static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9703 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9704 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9705 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9706 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9707 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9708 char mac_addr[20],dev[20];
9709
9710 nla_parse(tb,
9711 NL80211_ATTR_MAX,
9712 genlmsg_attrdata(gnlh, 0),
9713 genlmsg_attrlen(gnlh, 0),
9714 NULL);
9715
9716 if(!tb[NL80211_ATTR_STA_INFO]) {
9717 fprintf(stderr, "sta stats missing!\n");
9718 return NL_SKIP;
9719 }
9720
9721 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9722 fprintf(stderr, "failed to parse nested attributes!\n");
9723 return NL_SKIP;
9724 }
9725 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9726
9727 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9728
9729 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9730 fprintf(stderr, "failed to parse nested rate attributes!");
9731 return NL_SKIP;
9732 }
9733
9734 if(sinfo[NL80211_STA_INFO_TID_STATS])
9735 {
9736 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9737 printf("failed to parse nested stats attributes!");
9738 return NL_SKIP;
9739 }
9740 }
9741
9742 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9743 {
9744 printf("Type is VHT\n");
9745 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9746 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9747
9748 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9749 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9750 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9751 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9752 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9753 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9754 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9755 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9756 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9757 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9758 }
9759 else
9760 {
9761 printf(" OFDM or CCK \n");
9762 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9763 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9764 }
9765
9766 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9767 if(rinfo[NL80211_RATE_INFO_MCS])
9768 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9769 }
9770 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9771 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9772 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9773 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9774
9775 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9776 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9777
9778 if (sinfo[NL80211_STA_INFO_SIGNAL])
9779 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9780 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9781 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9782 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9783 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9784 //rssi_array need to be filled
9785 return NL_SKIP;
9786}
9787#endif
9788
9789INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9790{
9791#ifdef HAL_NETLINK_IMPL
9792 Netlink nl;
developerd946fd62022-12-08 18:03:28 +08009793 char if_name[32];
developerac6f1142022-12-20 19:26:35 +08009794 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009795 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009796
9797 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9798
9799 if (*output_array_size <= 0)
9800 return RETURN_OK;
9801
developer06a01d92022-09-07 16:32:39 +08009802 nl.id = initSock80211(&nl);
9803
9804 if (nl.id < 0) {
9805 fprintf(stderr, "Error initializing netlink \n");
9806 return 0;
9807 }
9808
9809 struct nl_msg* msg = nlmsg_alloc();
9810
9811 if (!msg) {
9812 fprintf(stderr, "Failed to allocate netlink message.\n");
9813 nlfree(&nl);
9814 return 0;
9815 }
9816
9817 genlmsg_put(msg,
9818 NL_AUTO_PORT,
9819 NL_AUTO_SEQ,
9820 nl.id,
9821 0,
9822 0,
9823 NL80211_CMD_GET_STATION,
9824 0);
9825
9826 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9827 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9828 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9829 nl_send_auto(nl.socket, msg);
9830 nl_recvmsgs(nl.socket, nl.cb);
9831 nlmsg_free(msg);
9832 nlfree(&nl);
9833 return RETURN_OK;
9834#else
9835 //TODO Implement me
9836 return RETURN_OK;
9837#endif
9838}
9839
9840#ifdef HAL_NETLINK_IMPL
9841static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9842 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9843 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9844 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9845 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9846 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9847 char mac_addr[20],dev[20];
9848
9849 nla_parse(tb,
9850 NL80211_ATTR_MAX,
9851 genlmsg_attrdata(gnlh, 0),
9852 genlmsg_attrlen(gnlh, 0),
9853 NULL);
9854
9855 if(!tb[NL80211_ATTR_STA_INFO]) {
9856 fprintf(stderr, "sta stats missing!\n");
9857 return NL_SKIP;
9858 }
9859
9860 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9861 fprintf(stderr, "failed to parse nested attributes!\n");
9862 return NL_SKIP;
9863 }
9864
9865 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9866
9867 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9868
9869 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9870 fprintf(stderr, "failed to parse nested rate attributes!");
9871 return NL_SKIP;
9872 }
9873
9874 if(sinfo[NL80211_STA_INFO_TID_STATS])
9875 {
9876 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9877 printf("failed to parse nested stats attributes!");
9878 return NL_SKIP;
9879 }
9880 }
9881 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9882 {
9883 printf("Type is VHT\n");
9884 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9885 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9886
9887 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9888 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9889 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9890 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9891 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9892 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9893 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9894 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9895 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9896 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9897 }
9898 else
9899 {
9900 printf(" OFDM or CCK \n");
9901 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9902 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9903 }
9904
9905 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9906 if(rinfo[NL80211_RATE_INFO_MCS])
9907 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9908 }
9909
9910 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9911 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9912 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9913 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9914
9915 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9916 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9917 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9918
9919 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9920 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9921
9922 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9923 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9924
9925 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9926 ((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]);
9927
9928 return NL_SKIP;
9929}
9930#endif
9931
9932INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9933{
9934#ifdef HAL_NETLINK_IMPL
9935 Netlink nl;
9936 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009937 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +08009938 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009939 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009940
9941 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9942
9943 if (*output_array_size <= 0)
9944 return RETURN_OK;
9945
developerd946fd62022-12-08 18:03:28 +08009946 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009947
9948 nl.id = initSock80211(&nl);
9949
9950 if(nl.id < 0) {
9951 fprintf(stderr, "Error initializing netlink \n");
9952 return 0;
9953 }
9954
9955 struct nl_msg* msg = nlmsg_alloc();
9956
9957 if(!msg) {
9958 fprintf(stderr, "Failed to allocate netlink message.\n");
9959 nlfree(&nl);
9960 return 0;
9961 }
9962
9963 genlmsg_put(msg,
9964 NL_AUTO_PORT,
9965 NL_AUTO_SEQ,
9966 nl.id,
9967 0,
9968 0,
9969 NL80211_CMD_GET_STATION,
9970 0);
9971
9972 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9973 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9974 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9975 nl_send_auto(nl.socket, msg);
9976 nl_recvmsgs(nl.socket, nl.cb);
9977 nlmsg_free(msg);
9978 nlfree(&nl);
9979 return RETURN_OK;
9980#else
9981 //TODO Implement me
9982 return RETURN_OK;
9983#endif
9984}
9985
9986INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9987{
9988 // TODO Implement me!
9989 char buf[MAX_BUF_SIZE] = {0};
9990 char config_file[MAX_BUF_SIZE] = {0};
9991
9992 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9993 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9994 *activate = (strncmp("1",buf,1) == 0);
9995
9996 return RETURN_OK;
9997}
9998
9999INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10000{
10001 char config_file[MAX_BUF_SIZE] = {0};
10002 struct params list;
10003
10004 list.name = "rrm_neighbor_report";
10005 list.value = activate?"1":"0";
10006 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10007 wifi_hostapdWrite(config_file, &list, 1);
10008
10009 return RETURN_OK;
10010}
10011
10012INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10013{
10014 char buf[32] = {0};
10015 char config_file[MAX_BUF_SIZE] = {0};
10016
10017 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10018 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10019 *activate = (strncmp("1",buf,1) == 0);
10020
10021 return RETURN_OK;
10022}
10023#undef HAL_NETLINK_IMPL
10024#ifdef HAL_NETLINK_IMPL
10025static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10026 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10027 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10028 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10029 char dev[20];
10030 int freq =0 ;
10031 static int i=0;
10032
10033 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10034
10035 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10036 };
10037
10038 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10039
10040 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10041
10042 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10043 fprintf(stderr, "survey data missing!\n");
10044 return NL_SKIP;
10045 }
10046
10047 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10048 {
10049 fprintf(stderr, "failed to parse nested attributes!\n");
10050 return NL_SKIP;
10051 }
10052
10053
10054 if(out[0].array_size == 1 )
10055 {
10056 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10057 {
10058 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10059 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10060 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10061
10062 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10063 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10064 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10065 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10066 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10067 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10068 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10069 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10070 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10071 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10072 if (sinfo[NL80211_SURVEY_INFO_TIME])
10073 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10074 return NL_STOP;
10075 }
10076 }
10077 else
10078 {
10079 if ( i <= out[0].array_size )
10080 {
10081 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10082 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10083 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10084
10085 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10086 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10087 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10088 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10089 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10090 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10091 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10092 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10093 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10094 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10095 if (sinfo[NL80211_SURVEY_INFO_TIME])
10096 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10097 }
10098 }
10099
10100 i++;
10101 return NL_SKIP;
10102}
10103#endif
10104
10105static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10106{
10107 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10108 FILE *fp;
10109
10110 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10111 {
10112 printf("Creating Frequency-Channel Map\n");
10113 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10114 }
10115 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10116 if((fp = popen(command, "r")))
10117 {
10118 fgets(output, sizeof(output), fp);
10119 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010120 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010121 }
10122
10123 return 0;
10124}
10125
10126static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10127{
10128 int freqMHz = -1;
10129 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +080010130 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080010131
10132 ieee80211_channel_to_frequency(channel, &freqMHz);
10133 if (freqMHz == -1) {
10134 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10135 return -1;
10136 }
10137
developer033b37b2022-10-18 11:27:46 +080010138 phyId = radio_index_to_phy(radioIndex);
10139 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, phyId, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010140 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10141 radioIndex, freqMHz);
10142 return -1;
10143 }
10144
10145 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10146 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10147 return -1;
10148 }
10149
10150 return 0;
10151}
10152
10153static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10154{
10155 const char *ptr = buf;
10156 char *key = NULL;
10157 char *val = NULL;
10158 char line[256] = { '\0' };
10159
10160 while (ptr = get_line_from_str_buf(ptr, line)) {
10161 if (strstr(line, "Frequency")) continue;
10162
10163 key = strtok(line, ":");
10164 val = strtok(NULL, " ");
10165 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10166
10167 if (!strcmp(key, "noise")) {
10168 sscanf(val, "%d", &stats->ch_noise);
10169 if (stats->ch_noise == 0) {
10170 // Workaround for missing noise information.
10171 // Assume -95 for 2.4G and -103 for 5G
10172 if (radioIndex == 0) stats->ch_noise = -95;
10173 if (radioIndex == 1) stats->ch_noise = -103;
10174 }
10175 }
10176 else if (!strcmp(key, "channel active time")) {
10177 sscanf(val, "%llu", &stats->ch_utilization_total);
10178 }
10179 else if (!strcmp(key, "channel busy time")) {
10180 sscanf(val, "%llu", &stats->ch_utilization_busy);
10181 }
10182 else if (!strcmp(key, "channel receive time")) {
10183 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10184 }
10185 else if (!strcmp(key, "channel transmit time")) {
10186 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10187 }
10188 };
10189
10190 return 0;
10191}
10192
10193INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10194{
10195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10196#ifdef HAL_NETLINK_IMPL
10197 Netlink nl;
10198 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010199 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010200
10201 local[0].array_size = array_size;
10202
developerac6f1142022-12-20 19:26:35 +080010203 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010204 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010205
10206 nl.id = initSock80211(&nl);
10207
10208 if (nl.id < 0) {
10209 fprintf(stderr, "Error initializing netlink \n");
10210 return -1;
10211 }
10212
10213 struct nl_msg* msg = nlmsg_alloc();
10214
10215 if (!msg) {
10216 fprintf(stderr, "Failed to allocate netlink message.\n");
10217 nlfree(&nl);
10218 return -2;
10219 }
10220
10221 genlmsg_put(msg,
10222 NL_AUTO_PORT,
10223 NL_AUTO_SEQ,
10224 nl.id,
10225 0,
10226 NLM_F_DUMP,
10227 NL80211_CMD_GET_SURVEY,
10228 0);
10229
10230 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10231 nl_send_auto(nl.socket, msg);
10232 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10233 nl_recvmsgs(nl.socket, nl.cb);
10234 nlmsg_free(msg);
10235 nlfree(&nl);
10236 //Copying the Values
10237 for(int i=0;i<array_size;i++)
10238 {
10239 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10240 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10241 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10242 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10243 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10244 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10245 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10246 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10247 }
10248#else
10249 ULONG channel = 0;
10250 int i;
10251 int number_of_channels = array_size;
10252 char buf[512];
10253 INT ret;
10254 wifi_channelStats_t tmp_stats;
10255
10256 if (number_of_channels == 0) {
10257 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10258 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10259 return RETURN_ERR;
10260 }
10261 number_of_channels = 1;
10262 input_output_channelStats_array[0].ch_number = channel;
10263 }
10264
10265 for (i = 0; i < number_of_channels; i++) {
10266
10267 input_output_channelStats_array[i].ch_noise = 0;
10268 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10269 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10270 input_output_channelStats_array[i].ch_utilization_busy = 0;
10271 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10272 input_output_channelStats_array[i].ch_utilization_total = 0;
10273
10274 memset(buf, 0, sizeof(buf));
10275 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10276 return RETURN_ERR;
10277 }
10278 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10279 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10280 return RETURN_ERR;
10281 }
10282
10283 // XXX: fake missing 'self' counter which is not available in iw survey output
10284 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10285 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10286
10287 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10288 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10289 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10290 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10291 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10292
10293 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",
10294 __func__,
10295 input_output_channelStats_array[i].ch_number,
10296 input_output_channelStats_array[i].ch_noise,
10297 input_output_channelStats_array[i].ch_utilization_total,
10298 input_output_channelStats_array[i].ch_utilization_busy,
10299 input_output_channelStats_array[i].ch_utilization_busy_rx,
10300 input_output_channelStats_array[i].ch_utilization_busy_tx,
10301 input_output_channelStats_array[i].ch_utilization_busy_self,
10302 input_output_channelStats_array[i].ch_utilization_busy_ext);
10303 }
10304#endif
10305 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10306 return RETURN_OK;
10307}
10308#define HAL_NETLINK_IMPL
10309
10310/* Hostapd events */
10311
10312#ifndef container_of
10313#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10314#define container_of(ptr, type, member) \
10315 ((type *)((char *)ptr - offset_of(type, member)))
10316#endif /* container_of */
10317
10318struct ctrl {
10319 char sockpath[128];
10320 char sockdir[128];
10321 char bss[IFNAMSIZ];
10322 char reply[4096];
10323 int ssid_index;
10324 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10325 void (*overrun)(struct ctrl *ctrl);
10326 struct wpa_ctrl *wpa;
10327 unsigned int ovfl;
10328 size_t reply_len;
10329 int initialized;
10330 ev_timer retry;
10331 ev_timer watchdog;
10332 ev_stat stat;
10333 ev_io io;
10334};
10335static wifi_newApAssociatedDevice_callback clients_connect_cb;
10336static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10337static struct ctrl wpa_ctrl[MAX_APS];
10338static int initialized;
10339
10340static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10341{
10342 char cbuf[256] = {};
10343 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10344 struct cmsghdr *cmsg;
10345 unsigned int ovfl = ctrl->ovfl;
10346 unsigned int drop;
10347
10348 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10349 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10350 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10351 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10352
10353 drop = ovfl - ctrl->ovfl;
10354 ctrl->ovfl = ovfl;
10355
10356 return drop;
10357}
10358
10359static void ctrl_close(struct ctrl *ctrl)
10360{
10361 if (ctrl->io.cb)
10362 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10363 if (ctrl->retry.cb)
10364 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10365 if (!ctrl->wpa)
10366 return;
10367
10368 wpa_ctrl_detach(ctrl->wpa);
10369 wpa_ctrl_close(ctrl->wpa);
10370 ctrl->wpa = NULL;
10371 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10372}
10373
10374static void ctrl_process(struct ctrl *ctrl)
10375{
10376 const char *str;
10377 int drops;
10378 int level;
10379 int err;
10380
10381 /* Example events:
10382 *
10383 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10384 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10385 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10386 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10387 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10388 */
10389 if (!(str = index(ctrl->reply, '>')))
10390 return;
10391 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10392 return;
10393
10394 str++;
10395
10396 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10397 if (!(str = index(ctrl->reply, ' ')))
10398 return;
10399 wifi_associated_dev_t sta;
10400 memset(&sta, 0, sizeof(sta));
10401
10402 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10403 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10404 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10405
10406 sta.cli_Active=true;
10407
10408 (clients_connect_cb)(ctrl->ssid_index, &sta);
10409 goto handled;
10410 }
10411
10412 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10413 if (!(str = index(ctrl->reply, ' ')))
10414 return;
10415
10416 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10417 goto handled;
10418 }
10419
10420 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10421 printf("CTRL_WPA: handle TERMINATING event\n");
10422 goto retry;
10423 }
10424
10425 if (strncmp("AP-DISABLED", str, 11) == 0) {
10426 printf("CTRL_WPA: handle AP-DISABLED\n");
10427 goto retry;
10428 }
10429
10430 printf("Event not supported!!\n");
10431
10432handled:
10433
10434 if ((drops = ctrl_get_drops(ctrl))) {
10435 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10436 if (ctrl->overrun)
10437 ctrl->overrun(ctrl);
10438 }
10439
10440 return;
10441
10442retry:
10443 printf("WPA_CTRL: closing\n");
10444 ctrl_close(ctrl);
10445 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10446 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10447}
10448
10449static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10450{
10451 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10452 int err;
10453
10454 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10455 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10456 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10457 ctrl->reply[ctrl->reply_len] = 0;
10458 if (err < 0) {
10459 if (errno == EAGAIN || errno == EWOULDBLOCK)
10460 return;
10461 ctrl_close(ctrl);
10462 ev_timer_again(EV_A_ &ctrl->retry);
10463 return;
10464 }
10465
10466 ctrl_process(ctrl);
10467}
10468
10469static int ctrl_open(struct ctrl *ctrl)
10470{
10471 int fd;
10472
10473 if (ctrl->wpa)
10474 return 0;
10475
10476 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10477 if (!ctrl->wpa)
10478 goto err;
10479
10480 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10481 goto err_close;
10482
10483 fd = wpa_ctrl_get_fd(ctrl->wpa);
10484 if (fd < 0)
10485 goto err_detach;
10486
10487 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10488 goto err_detach;
10489
10490 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10491 ev_io_start(EV_DEFAULT_ &ctrl->io);
10492
10493 return 0;
10494
10495err_detach:
10496 wpa_ctrl_detach(ctrl->wpa);
10497err_close:
10498 wpa_ctrl_close(ctrl->wpa);
10499err:
10500 ctrl->wpa = NULL;
10501 return -1;
10502}
10503
10504static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10505{
10506 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10507
10508 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10509 ctrl_open(ctrl);
10510}
10511
10512static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10513{
10514 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10515
10516 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10517 if (ctrl_open(ctrl) == 0) {
10518 printf("WPA_CTRL: retry successful\n");
10519 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10520 }
10521}
10522
10523int ctrl_enable(struct ctrl *ctrl)
10524{
10525 if (ctrl->wpa)
10526 return 0;
10527
10528 if (!ctrl->stat.cb) {
10529 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10530 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10531 }
10532
10533 if (!ctrl->retry.cb) {
10534 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10535 }
10536
10537 return ctrl_open(ctrl);
10538}
10539
10540static void
10541ctrl_msg_cb(char *buf, size_t len)
10542{
10543 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10544
10545 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10546 ctrl_process(ctrl);
10547}
10548
10549static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10550{
10551 int err;
10552
10553 if (!ctrl->wpa)
10554 return -1;
10555 if (*reply_len < 2)
10556 return -1;
10557
10558 (*reply_len)--;
10559 ctrl->reply_len = sizeof(ctrl->reply);
10560 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10561 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10562 if (err < 0)
10563 return err;
10564
10565 if (ctrl->reply_len > *reply_len)
10566 ctrl->reply_len = *reply_len;
10567
10568 *reply_len = ctrl->reply_len;
10569 memcpy(reply, ctrl->reply, *reply_len);
10570 reply[*reply_len - 1] = 0;
10571 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10572 return 0;
10573}
10574
10575static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10576{
10577 const char *pong = "PONG";
10578 const char *ping = "PING";
10579 char reply[1024];
10580 size_t len = sizeof(reply);
10581 int err;
10582 ULONG s, snum;
10583 INT ret;
10584 BOOL status;
10585
10586 printf("WPA_CTRL: watchdog cb\n");
10587
10588 ret = wifi_getSSIDNumberOfEntries(&snum);
10589 if (ret != RETURN_OK) {
10590 printf("%s: failed to get SSID count", __func__);
10591 return;
10592 }
10593
10594 if (snum > MAX_APS) {
10595 printf("more ssid than supported! %lu\n", snum);
10596 return;
10597 }
10598
10599 for (s = 0; s < snum; s++) {
10600 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010601 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010602 continue;
10603 }
10604 if (status == false) continue;
10605
10606 memset(reply, 0, sizeof(reply));
10607 len = sizeof(reply);
10608 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10609 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10610 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10611 continue;
10612
10613 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10614 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010615 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010616 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10617 }
10618}
10619
10620static int init_wpa()
10621{
10622 int ret = 0, i = 0;
10623 ULONG s, snum;
10624
10625 ret = wifi_getSSIDNumberOfEntries(&snum);
10626 if (ret != RETURN_OK) {
10627 printf("%s: failed to get SSID count", __func__);
10628 return RETURN_ERR;
10629 }
10630
10631 if (snum > MAX_APS) {
10632 printf("more ssid than supported! %lu\n", snum);
10633 return RETURN_ERR;
10634 }
10635
10636 for (s = 0; s < snum; s++) {
10637 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10638 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10639 wpa_ctrl[s].ssid_index = s;
10640 ctrl_enable(&wpa_ctrl[s]);
10641 }
10642
10643 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10644 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10645
10646 initialized = 1;
10647 printf("WPA_CTRL: initialized\n");
10648
10649 return RETURN_OK;
10650}
10651
10652void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10653{
10654 clients_connect_cb = callback_proc;
10655 if (!initialized)
10656 init_wpa();
10657}
10658
10659void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10660{
10661 clients_disconnect_cb = callback_proc;
10662 if (!initialized)
10663 init_wpa();
10664}
10665
10666INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10667{
10668 // TODO Implement me!
10669 return RETURN_ERR;
10670}
10671
10672INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10673{
10674 // TODO Implement me!
10675 return RETURN_ERR;
10676}
10677
10678INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10679{
10680 int i;
10681 char cmd[256];
10682 char channel_numbers_buf[256];
10683 char dfs_state_buf[256];
10684 char line[256];
10685 const char *ptr;
10686
10687 memset(cmd, 0, sizeof(cmd));
10688 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10689 memset(line, 0, sizeof(line));
10690 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10691 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10692
10693 if (radioIndex == 0) { // 2.4G - all allowed
10694 if (outputMapSize < 11) {
10695 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10696 return RETURN_ERR;
10697 }
10698
10699 for (i = 0; i < 11; i++) {
10700 outputMap[i].ch_number = i + 1;
10701 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10702 }
10703
10704 return RETURN_OK;
10705 }
10706
10707 if (radioIndex == 1) { // 5G
10708// Example output of iw list:
10709//
10710// Frequencies:
10711// * 5180 MHz [36] (17.0 dBm)
10712// * 5200 MHz [40] (17.0 dBm)
10713// * 5220 MHz [44] (17.0 dBm)
10714// * 5240 MHz [48] (17.0 dBm)
10715// * 5260 MHz [52] (23.0 dBm) (radar detection)
10716// DFS state: usable (for 78930 sec)
10717// DFS CAC time: 60000 ms
10718// * 5280 MHz [56] (23.0 dBm) (radar detection)
10719// DFS state: usable (for 78930 sec)
10720// DFS CAC time: 60000 ms
10721// * 5300 MHz [60] (23.0 dBm) (radar detection)
10722// DFS state: usable (for 78930 sec)
10723// DFS CAC time: 60000 ms
10724// * 5320 MHz [64] (23.0 dBm) (radar detection)
10725// DFS state: usable (for 78930 sec)
10726// DFS CAC time: 60000 ms
10727// * 5500 MHz [100] (disabled)
10728// * 5520 MHz [104] (disabled)
10729// * 5540 MHz [108] (disabled)
10730// * 5560 MHz [112] (disabled)
10731//
10732// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10733 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10734 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10735 return RETURN_ERR;
10736 }
10737
10738 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10739 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10740 return RETURN_ERR;
10741 }
10742
10743 ptr = channel_numbers_buf;
10744 i = 0;
10745 while (ptr = get_line_from_str_buf(ptr, line)) {
10746 if (i >= outputMapSize) {
10747 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10748 return RETURN_ERR;
10749 }
10750 sscanf(line, "%d", &outputMap[i].ch_number);
10751
10752 memset(cmd, 0, sizeof(cmd));
10753 // Below command should fetch string for DFS state (usable, available or unavailable)
10754 // Example line: "DFS state: usable (for 78930 sec)"
10755 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) {
10756 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10757 return RETURN_ERR;
10758 }
10759
10760 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10761 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10762 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10763 return RETURN_ERR;
10764 }
10765
10766 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10767
10768 if (!strcmp(dfs_state_buf, "usable")) {
10769 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10770 } else if (!strcmp(dfs_state_buf, "available")) {
10771 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10772 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10773 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10774 } else {
10775 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10776 }
10777 i++;
10778 }
10779
10780 return RETURN_OK;
10781 }
10782
10783 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10784 return RETURN_ERR;
10785}
10786
10787INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10788{
10789 // TODO Implement me!
10790 return RETURN_ERR;
10791}
10792
10793INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10794{
10795 return RETURN_OK;
10796}
10797
10798INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10799{
10800 // TODO Implement me!
10801 return RETURN_ERR;
10802}
10803
10804INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10805{
10806 // TODO API refrence Implementaion is present on RPI hal
10807 return RETURN_ERR;
10808}
10809
10810INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10811{
developerd946fd62022-12-08 18:03:28 +080010812 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080010813 char cmd[128]={'\0'};
10814 char buf[128]={'\0'};
10815 char *support;
10816 int maximum_tx = 0, current_tx = 0;
10817
10818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10819 if(txpwr_pcntg == NULL)
10820 return RETURN_ERR;
10821
developerac6f1142022-12-20 19:26:35 +080010822 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010823 return RETURN_ERR;
10824
developera5005b62022-09-13 15:43:35 +080010825 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080010826 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 +080010827 _syscmd(cmd, buf, sizeof(buf));
10828 maximum_tx = strtol(buf, NULL, 10);
10829
10830 // Get the current tx power
10831 memset(cmd, 0, sizeof(cmd));
10832 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080010833 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 +080010834 _syscmd(cmd, buf, sizeof(buf));
10835 current_tx = strtol(buf, NULL, 10);
10836
10837 // Get the power supported list and find the current power percentage in supported list
10838 memset(buf, 0, sizeof(buf));
10839 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10840 support = strtok(buf, ",");
10841 while(true)
10842 {
10843 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 +080010844 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010845 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010846 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010847 }
10848 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10849 if (tmp == current_tx) {
10850 *txpwr_pcntg = strtol(support, NULL, 10);
10851 break;
10852 }
10853 support = strtok(NULL, ",");
10854 }
10855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010856 return RETURN_OK;
10857}
10858
10859INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10860{
developer58599c22022-09-13 16:40:34 +080010861 // TODO precac feature.
10862 struct params params = {0};
10863 char config_file[128] = {0};
10864
10865 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10866
10867 params.name = "enable_background_radar";
10868 params.value = enable?"1":"0";
10869 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10870 wifi_hostapdWrite(config_file, &params, 1);
10871 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10872
10873 /* TODO precac feature */
10874
10875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10876 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010877}
10878
10879INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10880{
developer58599c22022-09-13 16:40:34 +080010881 char config_file[128] = {0};
10882 char buf[64] = {0};
10883
10884 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10885 if (NULL == enable || NULL == precac)
10886 return RETURN_ERR;
10887
10888 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10889 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10890 if (strncmp(enable, "1", 1) == 0)
10891 *enable = true;
10892 else
10893 *enable = false;
10894
10895 /* TODO precac feature */
10896
10897 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10898 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010899}
10900
10901INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10902{
developer58599c22022-09-13 16:40:34 +080010903 *supported = TRUE;
10904 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010905}
10906
developer3e6b1692022-09-30 18:04:05 +080010907INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10908{
10909 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10910 struct params params = {0};
10911 char config_file[64] = {0};
10912 char buf[64] = {0};
10913 unsigned int set_mu_type = 0;
10914 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10915
10916 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10917 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10918
10919 if (strlen(buf) > 0)
10920 set_mu_type = strtol(buf, NULL, 10);
10921
10922 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10923 set_mu_type &= ~0x05; // unset bit 0, 2
10924 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10925 set_mu_type |= 0x01;
10926 set_mu_type &= ~0x04;
10927 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10928 set_mu_type &= ~0x01;
10929 set_mu_type |= 0x04;
10930 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10931 set_mu_type |= 0x05; // set bit 0, 2
10932 }
10933
10934 params.name = "hemu_onoff";
10935 sprintf(buf, "%u", set_mu_type);
10936 params.value = buf;
10937 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10938 wifi_hostapdWrite(config_file, &params, 1);
10939 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10940
10941 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10942 return RETURN_OK;
10943}
10944
10945INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10946{
10947 struct params params={0};
10948 char config_file[64] = {0};
10949 char buf[64] = {0};
10950 unsigned int get_mu_type = 0;
10951
10952 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10953
10954 if (mu_type == NULL)
10955 return RETURN_ERR;
10956
10957 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10958 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10959 get_mu_type = strtol(buf, NULL, 10);
10960
10961 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10962 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10963 else if (get_mu_type & 0x04)
10964 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10965 else if (get_mu_type & 0x01)
10966 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10967 else
10968 *mu_type = WIFI_DL_MU_TYPE_NONE;
10969
10970 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10971 return RETURN_OK;
10972}
10973
10974INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10975{
10976 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10977 struct params params={0};
10978 char config_file[64] = {0};
10979 char buf[64] = {0};
10980 unsigned int set_mu_type = 0;
10981 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10982
10983 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10984 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10985
10986 if (strlen(buf) > 0)
10987 set_mu_type = strtol(buf, NULL, 10);
10988
10989 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10990 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10991 set_mu_type &= ~0x0a;
10992 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10993 set_mu_type |= 0x02;
10994 set_mu_type &= ~0x08;
10995 }
10996
10997 params.name = "hemu_onoff";
10998 sprintf(buf, "%u", set_mu_type);
10999 params.value = buf;
11000 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11001 wifi_hostapdWrite(config_file, &params, 1);
11002 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11003
11004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11005 return RETURN_OK;
11006}
11007
11008INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11009{
11010 struct params params={0};
11011 char config_file[64] = {0};
11012 char buf[64] = {0};
11013 unsigned int get_mu_type = 0;
11014
11015 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11016
11017 if (mu_type == NULL)
11018 return RETURN_ERR;
11019
11020 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11021 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11022
11023 get_mu_type = strtol(buf, NULL, 10);
11024 if (get_mu_type & 0x02)
11025 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11026 else
11027 *mu_type = WIFI_DL_MU_TYPE_NONE;
11028
11029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11030 return RETURN_OK;
11031}
11032
11033
developer454b9462022-09-13 15:29:16 +080011034INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11035{
11036 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011037 char buf[256] = {0};
11038 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011039 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011040 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011041 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011042 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011043
11044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11045
developer254882b2022-09-30 17:12:31 +080011046 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011047 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11048 return RETURN_ERR;
11049 }
developer454b9462022-09-13 15:29:16 +080011050
developer254882b2022-09-30 17:12:31 +080011051 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011052 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011053
developer254882b2022-09-30 17:12:31 +080011054 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11055 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011056 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011057 _syscmd(cmd, buf, sizeof(buf));
11058 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11059 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11060 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011061 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 +080011062 _syscmd(cmd, buf, sizeof(buf));
11063 }
11064 if (band == band_5) {
11065 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11066 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011067 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 +080011068 _syscmd(cmd, buf, sizeof(buf));
11069 }
11070 }
11071 }
11072 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011073
developer254882b2022-09-30 17:12:31 +080011074 if (guard_interval == wifi_guard_interval_400)
11075 strcpy(GI, "0.4");
11076 else if (guard_interval == wifi_guard_interval_800)
11077 strcpy(GI, "0.8");
11078 else if (guard_interval == wifi_guard_interval_1600)
11079 strcpy(GI, "1.6");
11080 else if (guard_interval == wifi_guard_interval_3200)
11081 strcpy(GI, "3.2");
11082 else if (guard_interval == wifi_guard_interval_auto)
11083 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011084 // Record GI for get GI function
11085 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11086 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011087 if (f == NULL)
11088 return RETURN_ERR;
11089 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011090 fclose(f);
11091 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11092 return RETURN_OK;
11093}
11094
11095INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11096{
11097 char buf[32] = {0};
11098 char cmd[64] = {0};
11099
11100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11101
11102 if (guard_interval == NULL)
11103 return RETURN_ERR;
11104
11105 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11106 _syscmd(cmd, buf, sizeof(buf));
11107
11108 if (strncmp(buf, "0.4", 3) == 0)
11109 *guard_interval = wifi_guard_interval_400;
11110 else if (strncmp(buf, "0.8", 3) == 0)
11111 *guard_interval = wifi_guard_interval_800;
11112 else if (strncmp(buf, "1.6", 3) == 0)
11113 *guard_interval = wifi_guard_interval_1600;
11114 else if (strncmp(buf, "3.2", 3) == 0)
11115 *guard_interval = wifi_guard_interval_3200;
11116 else
11117 *guard_interval = wifi_guard_interval_auto;
11118
11119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11120 return RETURN_OK;
11121}
11122
developer3cc61d12022-09-13 16:36:05 +080011123INT wifi_setBSSColor(INT radio_index, UCHAR color)
11124{
11125 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11126 struct params params = {0};
11127 char config_file[128] = {0};
11128 char bss_color[4] ={0};
11129
11130 params.name = "he_bss_color";
11131 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11132 params.value = bss_color;
11133 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11134 wifi_hostapdWrite(config_file, &params, 1);
11135 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11136
11137 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11138 return RETURN_OK;
11139}
11140
11141INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11142{
11143 char config_file[128] = {0};
11144 char buf[64] = {0};
11145 char temp_output[128] = {'\0'};
11146
11147 wifi_dbg_printf("\nFunc=%s\n", __func__);
11148 if (NULL == color)
11149 return RETURN_ERR;
11150
11151 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11152 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11153
11154 if(strlen(buf) > 0) {
11155 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11156 } else {
11157 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11158 }
11159
11160 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11161 wifi_dbg_printf("\noutput_string=%s\n", color);
11162
11163 return RETURN_OK;
11164}
11165
developer06a01d92022-09-07 16:32:39 +080011166/* multi-psk support */
11167INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11168{
11169 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011170 char interface_name[16] = {0};
11171
developerac6f1142022-12-20 19:26:35 +080011172 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011173 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011174
developerd946fd62022-12-08 18:03:28 +080011175 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11176 interface_name,
developer06a01d92022-09-07 16:32:39 +080011177 mac[0],
11178 mac[1],
11179 mac[2],
11180 mac[3],
11181 mac[4],
11182 mac[5]
11183 );
11184 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11185 _syscmd(cmd, key->wifi_keyId, 64);
11186
11187
11188 return RETURN_OK;
11189}
11190
11191INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11192{
developerd946fd62022-12-08 18:03:28 +080011193 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011194 FILE *fd = NULL;
11195 char fname[100];
11196 char cmd[128] = {0};
11197 char out[64] = {0};
11198 wifi_key_multi_psk_t * key = NULL;
11199 if(keysNumber < 0)
11200 return RETURN_ERR;
11201
developer431128d2022-12-16 15:30:41 +080011202 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011203 fd = fopen(fname, "w");
11204 if (!fd) {
11205 return RETURN_ERR;
11206 }
11207 key= (wifi_key_multi_psk_t *) keys;
11208 for(int i=0; i<keysNumber; ++i, key++) {
11209 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11210 }
11211 fclose(fd);
11212
11213 //reload file
developerac6f1142022-12-20 19:26:35 +080011214 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011215 return RETURN_ERR;
11216 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011217 _syscmd(cmd, out, 64);
11218 return RETURN_OK;
11219}
11220
11221INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11222{
11223 FILE *fd = NULL;
11224 char fname[100];
11225 char * line = NULL;
11226 char * pos = NULL;
11227 size_t len = 0;
11228 ssize_t read = 0;
11229 INT ret = RETURN_OK;
11230 wifi_key_multi_psk_t *keys_it = NULL;
11231
11232 if (keysNumber < 1) {
11233 return RETURN_ERR;
11234 }
11235
developer431128d2022-12-16 15:30:41 +080011236 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011237 fd = fopen(fname, "r");
11238 if (!fd) {
11239 return RETURN_ERR;
11240 }
11241
11242 if (keys == NULL) {
11243 ret = RETURN_ERR;
11244 goto close;
11245 }
11246
11247 keys_it = keys;
11248 while ((read = getline(&line, &len, fd)) != -1) {
11249 //Strip trailing new line if present
11250 if (read > 0 && line[read-1] == '\n') {
11251 line[read-1] = '\0';
11252 }
11253
11254 if(strcmp(line,"keyid=")) {
11255 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11256 if (!(pos = index(line, ' '))) {
11257 ret = RETURN_ERR;
11258 goto close;
11259 }
11260 pos++;
11261 //Here should be 00:00:00:00:00:00
11262 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11263 printf("Not supported MAC: %s\n", pos);
11264 }
11265 if (!(pos = index(pos, ' '))) {
11266 ret = RETURN_ERR;
11267 goto close;
11268 }
11269 pos++;
11270
11271 //The rest is PSK
11272 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11273 keys_it++;
11274
11275 if(--keysNumber <= 0)
11276 break;
11277 }
11278 }
11279
11280close:
11281 free(line);
11282 fclose(fd);
11283 return ret;
11284}
11285/* end of multi-psk support */
11286
11287INT wifi_setNeighborReports(UINT apIndex,
11288 UINT numNeighborReports,
11289 wifi_NeighborReport_t *neighborReports)
11290{
11291 char cmd[256] = { 0 };
11292 char hex_bssid[13] = { 0 };
11293 char bssid[18] = { 0 };
11294 char nr[256] = { 0 };
11295 char ssid[256];
11296 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011297 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011298 INT ret;
11299
11300 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011301 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011302 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011303 return RETURN_ERR;
11304 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 +080011305 system(cmd);
11306
11307 for(unsigned int i = 0; i < numNeighborReports; i++)
11308 {
11309 memset(ssid, 0, sizeof(ssid));
11310 ret = wifi_getSSIDName(apIndex, ssid);
11311 if (ret != RETURN_OK)
11312 return RETURN_ERR;
11313
11314 memset(hex_ssid, 0, sizeof(hex_ssid));
11315 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11316 sprintf(hex_ssid + k,"%02x", ssid[j]);
11317
11318 snprintf(hex_bssid, sizeof(hex_bssid),
11319 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11320 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11321 snprintf(bssid, sizeof(bssid),
11322 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11323 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11324
11325 snprintf(nr, sizeof(nr),
11326 "%s" // bssid
11327 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11328 "%02hhx" // operclass
11329 "%02hhx" // channel
11330 "%02hhx", // phy_mode
11331 hex_bssid,
11332 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11333 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11334 neighborReports[i].opClass,
11335 neighborReports[i].channel,
11336 neighborReports[i].phyTable);
11337
11338 snprintf(cmd, sizeof(cmd),
11339 "hostapd_cli set_neighbor "
11340 "%s " // bssid
11341 "ssid=%s " // ssid
11342 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011343 "-i %s",
11344 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011345
11346 if (WEXITSTATUS(system(cmd)) != 0)
11347 {
11348 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11349 }
11350 }
11351
11352 return RETURN_OK;
11353}
11354
11355INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11356{
11357 return RETURN_OK;
11358}
11359
11360#ifdef _WIFI_HAL_TEST_
11361int main(int argc,char **argv)
11362{
11363 int index;
11364 INT ret=0;
11365 char buf[1024]="";
11366
11367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11368 if(argc<3)
11369 {
11370 if(argc==2)
11371 {
11372 if(!strcmp(argv[1], "init"))
11373 return wifi_init();
11374 if(!strcmp(argv[1], "reset"))
11375 return wifi_reset();
11376 if(!strcmp(argv[1], "wifi_getHalVersion"))
11377 {
11378 char buffer[64];
11379 if(wifi_getHalVersion(buffer)==RETURN_OK)
11380 printf("Version: %s\n", buffer);
11381 else
11382 printf("Error in wifi_getHalVersion\n");
11383 return RETURN_OK;
11384 }
11385 }
11386 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11387 exit(-1);
11388 }
11389
11390 index = atoi(argv[2]);
11391 if(strstr(argv[1], "wifi_getApName")!=NULL)
11392 {
11393 wifi_getApName(index,buf);
11394 printf("Ap name is %s \n",buf);
11395 return 0;
11396 }
11397 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11398 {
11399 BOOL b = FALSE;
11400 BOOL *output_bool = &b;
11401 wifi_getRadioAutoChannelEnable(index,output_bool);
11402 printf("Channel enabled = %d \n",b);
11403 return 0;
11404 }
11405 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11406 {
11407 wifi_getApWpaEncryptionMode(index,buf);
11408 printf("encryption enabled = %s\n",buf);
11409 return 0;
11410 }
11411 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11412 {
11413 BOOL b = FALSE;
11414 BOOL *output_bool = &b;
11415 wifi_getApSsidAdvertisementEnable(index,output_bool);
11416 printf("advertisment enabled = %d\n",b);
11417 return 0;
11418 }
11419 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11420 {
11421 if(argc <= 3 )
11422 {
11423 printf("Insufficient arguments \n");
11424 exit(-1);
11425 }
11426
11427 char sta[20] = {'\0'};
11428 ULLONG handle= 0;
11429 strcpy(sta,argv[3]);
11430 mac_address_t st;
11431 mac_addr_aton(st,sta);
11432
11433 wifi_associated_dev_tid_stats_t tid_stats;
11434 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11435 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11436 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);
11437 }
11438
11439 if(strstr(argv[1], "getApEnable")!=NULL) {
11440 BOOL enable;
11441 ret=wifi_getApEnable(index, &enable);
11442 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11443 }
11444 else if(strstr(argv[1], "setApEnable")!=NULL) {
11445 BOOL enable = atoi(argv[3]);
11446 ret=wifi_setApEnable(index, enable);
11447 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11448 }
11449 else if(strstr(argv[1], "getApStatus")!=NULL) {
11450 char status[64];
11451 ret=wifi_getApStatus(index, status);
11452 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11453 }
11454 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11455 {
11456 wifi_getSSIDNameStatus(index,buf);
11457 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11458 return 0;
11459 }
11460 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11461 wifi_ssidTrafficStats2_t stats={0};
11462 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11463 printf("%s %d: returns %d\n", argv[1], index, ret);
11464 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11465 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11466 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11467 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11468 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11469 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11470 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11471 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11472 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11473 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11474 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11475 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11476 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11477 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11478 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11479 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11480 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11481 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11482 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11483 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11484 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11485 }
11486 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11487 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11488 UINT array_size=0;
11489 UINT i=0;
11490 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11491 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11492 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11493 printf(" neighbor %d:\n", i);
11494 printf(" ap_SSID =%s\n", pt->ap_SSID);
11495 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11496 printf(" ap_Mode =%s\n", pt->ap_Mode);
11497 printf(" ap_Channel =%d\n", pt->ap_Channel);
11498 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11499 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11500 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11501 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11502 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11503 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11504 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11505 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11506 printf(" ap_Noise =%d\n", pt->ap_Noise);
11507 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11508 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11509 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11510 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11511 }
11512 if(neighbor_ap_array)
11513 free(neighbor_ap_array); //make sure to free the list
11514 }
11515 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11516 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11517 UINT array_size=0;
11518 UINT i=0;
11519 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11520 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11521 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11522 printf(" associated_dev %d:\n", i);
11523 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11524 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11525 printf(" cli_SNR =%d\n", pt->cli_SNR);
11526 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11527 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11528 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11529 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11530 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11531 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11532 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11533 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11534 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11535 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11536 }
11537 if(associated_dev_array)
11538 free(associated_dev_array); //make sure to free the list
11539 }
11540
11541 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11542 {
11543#define MAX_ARRAY_SIZE 64
11544 int i, array_size;
11545 char *p, *ch_str;
11546 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11547
11548 if(argc != 5)
11549 {
11550 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11551 exit(-1);
11552 }
11553 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11554
11555 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11556 {
11557 strtok_r(ch_str, ",", &p);
11558 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11559 }
11560 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11561 if(!array_size)
11562 array_size=1;//Need to print current channel statistics
11563 for(i=0; i<array_size; i++)
11564 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11565 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11566 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11567 input_output_channelStats_array[i].ch_number,\
11568 input_output_channelStats_array[i].ch_noise,\
11569 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11570 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11571 input_output_channelStats_array[i].ch_utilization_busy,\
11572 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11573 input_output_channelStats_array[i].ch_utilization_total);
11574 }
11575
11576 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11577 {
11578 if(argc <= 3 )
11579 {
11580 printf("Insufficient arguments \n");
11581 exit(-1);
11582 }
11583 char mac_addr[20] = {'\0'};
11584 wifi_device_t output_struct;
11585 int dev_index = atoi(argv[3]);
11586
11587 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11588 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11589 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);
11590 }
11591
11592 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11593 {
11594 if (argc <= 3)
11595 {
11596 printf("Insufficient arguments\n");
11597 exit(-1);
11598 }
11599 char args[256];
11600 wifi_NeighborReport_t *neighborReports;
11601
11602 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11603 if (!neighborReports)
11604 {
11605 printf("Failed to allocate memory");
11606 exit(-1);
11607 }
11608
11609 for (int i = 3; i < argc; ++i)
11610 {
11611 char *val;
11612 int j = 0;
11613 memset(args, 0, sizeof(args));
11614 strncpy(args, argv[i], sizeof(args));
11615 val = strtok(args, ";");
11616 while (val != NULL)
11617 {
11618 if (j == 0)
11619 {
11620 mac_addr_aton(neighborReports[i - 3].bssid, val);
11621 } else if (j == 1)
11622 {
11623 neighborReports[i - 3].info = strtol(val, NULL, 16);
11624 } else if (j == 2)
11625 {
11626 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11627 } else if (j == 3)
11628 {
11629 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11630 } else if (j == 4)
11631 {
11632 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11633 } else {
11634 printf("Insufficient arguments]n\n");
11635 exit(-1);
11636 }
11637 val = strtok(NULL, ";");
11638 j++;
11639 }
11640 }
11641
11642 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11643 if (ret != RETURN_OK)
11644 {
11645 printf("wifi_setNeighborReports ret = %d", ret);
11646 exit(-1);
11647 }
11648 }
11649 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11650 {
11651 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11652 printf("%s.\n", buf);
11653 else
11654 printf("Error returned\n");
11655 }
11656 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11657 {
11658 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11659 printf("%s.\n", buf);
11660 else
11661 printf("Error returned\n");
11662 }
11663 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11664 {
11665 if (argc <= 2)
11666 {
11667 printf("Insufficient arguments\n");
11668 exit(-1);
11669 }
11670 char buf[64]= {'\0'};
11671 wifi_getRadioOperatingChannelBandwidth(index,buf);
11672 printf("Current bandwidth is %s \n",buf);
11673 return 0;
11674 }
11675 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11676 {
11677 if (argc <= 5)
11678 {
11679 printf("Insufficient arguments\n");
11680 exit(-1);
11681 }
11682 UINT channel = atoi(argv[3]);
11683 UINT width = atoi(argv[4]);
11684 UINT beacon = atoi(argv[5]);
11685 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11686 printf("Result = %d", ret);
11687 }
11688
11689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11690 return 0;
11691}
11692
11693#endif
11694
11695#ifdef WIFI_HAL_VERSION_3
11696
developer1e5aa162022-09-13 16:06:24 +080011697INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11698{
11699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11700 if (bitMap & WIFI_BITRATE_1MBPS)
11701 strcat(BasicRate, "1,");
11702 if (bitMap & WIFI_BITRATE_2MBPS)
11703 strcat(BasicRate, "2,");
11704 if (bitMap & WIFI_BITRATE_5_5MBPS)
11705 strcat(BasicRate, "5.5,");
11706 if (bitMap & WIFI_BITRATE_6MBPS)
11707 strcat(BasicRate, "6,");
11708 if (bitMap & WIFI_BITRATE_9MBPS)
11709 strcat(BasicRate, "9,");
11710 if (bitMap & WIFI_BITRATE_11MBPS)
11711 strcat(BasicRate, "11,");
11712 if (bitMap & WIFI_BITRATE_12MBPS)
11713 strcat(BasicRate, "12,");
11714 if (bitMap & WIFI_BITRATE_18MBPS)
11715 strcat(BasicRate, "18,");
11716 if (bitMap & WIFI_BITRATE_24MBPS)
11717 strcat(BasicRate, "24,");
11718 if (bitMap & WIFI_BITRATE_36MBPS)
11719 strcat(BasicRate, "36,");
11720 if (bitMap & WIFI_BITRATE_48MBPS)
11721 strcat(BasicRate, "48,");
11722 if (bitMap & WIFI_BITRATE_54MBPS)
11723 strcat(BasicRate, "54,");
11724 if (strlen(BasicRate) != 0) // remove last comma
11725 BasicRate[strlen(BasicRate) - 1] = '\0';
11726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11727 return RETURN_OK;
11728}
11729
11730INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11731{
11732 UINT BitMap = 0;
11733 char *rate;
11734
11735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11736 rate = strtok(BasicRatesList, ",");
11737 while(rate != NULL)
11738 {
11739 if (strcmp(rate, "1") == 0)
11740 BitMap |= WIFI_BITRATE_1MBPS;
11741 else if (strcmp(rate, "2") == 0)
11742 BitMap |= WIFI_BITRATE_2MBPS;
11743 else if (strcmp(rate, "5.5") == 0)
11744 BitMap |= WIFI_BITRATE_5_5MBPS;
11745 else if (strcmp(rate, "6") == 0)
11746 BitMap |= WIFI_BITRATE_6MBPS;
11747 else if (strcmp(rate, "9") == 0)
11748 BitMap |= WIFI_BITRATE_9MBPS;
11749 else if (strcmp(rate, "11") == 0)
11750 BitMap |= WIFI_BITRATE_11MBPS;
11751 else if (strcmp(rate, "12") == 0)
11752 BitMap |= WIFI_BITRATE_12MBPS;
11753 else if (strcmp(rate, "18") == 0)
11754 BitMap |= WIFI_BITRATE_18MBPS;
11755 else if (strcmp(rate, "24") == 0)
11756 BitMap |= WIFI_BITRATE_24MBPS;
11757 else if (strcmp(rate, "36") == 0)
11758 BitMap |= WIFI_BITRATE_36MBPS;
11759 else if (strcmp(rate, "48") == 0)
11760 BitMap |= WIFI_BITRATE_48MBPS;
11761 else if (strcmp(rate, "54") == 0)
11762 BitMap |= WIFI_BITRATE_54MBPS;
11763 rate = strtok(NULL, ",");
11764 }
11765 *basicRateBitMap = BitMap;
11766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11767 return RETURN_OK;
11768}
11769
11770// 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 +080011771INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11772{
developer1e5aa162022-09-13 16:06:24 +080011773 char buf[128] = {0};
11774 char cmd[128] = {0};
11775 char config_file[64] = {0};
11776 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011777 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011778 wifi_radio_operationParam_t current_param;
11779
11780 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11781
11782 multiple_set = TRUE;
11783 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11784 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11785 return RETURN_ERR;
11786 }
11787 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11788 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11789 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11790 return RETURN_ERR;
11791 }
11792 }
developer5884e982022-10-06 10:52:50 +080011793
11794 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11795 bandwidth = 20;
11796 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11797 bandwidth = 40;
11798 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11799 bandwidth = 80;
11800 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11801 bandwidth = 160;
11802 if (operationParam->autoChannelEnabled){
11803 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11804 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11805 return RETURN_ERR;
11806 }
11807 }else{
developer1e5aa162022-09-13 16:06:24 +080011808 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11809 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11810 return RETURN_ERR;
11811 }
11812 }
developer5884e982022-10-06 10:52:50 +080011813
developer1e5aa162022-09-13 16:06:24 +080011814 if (current_param.variant != operationParam->variant) {
11815 // Two different definition bit map, so need to check every bit.
11816 if (operationParam->variant & WIFI_80211_VARIANT_A)
11817 set_mode |= WIFI_MODE_A;
11818 if (operationParam->variant & WIFI_80211_VARIANT_B)
11819 set_mode |= WIFI_MODE_B;
11820 if (operationParam->variant & WIFI_80211_VARIANT_G)
11821 set_mode |= WIFI_MODE_G;
11822 if (operationParam->variant & WIFI_80211_VARIANT_N)
11823 set_mode |= WIFI_MODE_N;
11824 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11825 set_mode |= WIFI_MODE_AC;
11826 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11827 set_mode |= WIFI_MODE_AX;
11828 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11829 memset(buf, 0, sizeof(buf));
11830 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11831 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11832 return RETURN_ERR;
11833 }
11834 }
11835 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11836 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11837 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11838 return RETURN_ERR;
11839 }
11840 }
11841 if (current_param.beaconInterval != operationParam->beaconInterval) {
11842 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11843 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11844 return RETURN_ERR;
11845 }
11846 }
11847 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11848 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11849 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11850 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11851 return RETURN_ERR;
11852 }
11853 }
11854 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11855 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11856 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11857 return RETURN_ERR;
11858 }
11859 }
11860 if (current_param.guardInterval != operationParam->guardInterval) {
11861 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11862 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11863 return RETURN_ERR;
11864 }
11865 }
11866 if (current_param.transmitPower != operationParam->transmitPower) {
11867 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11868 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11869 return RETURN_ERR;
11870 }
11871 }
11872 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11873 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11874 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11875 return RETURN_ERR;
11876 }
11877 }
11878 if (current_param.obssCoex != operationParam->obssCoex) {
11879 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11880 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11881 return RETURN_ERR;
11882 }
11883 }
11884 if (current_param.stbcEnable != operationParam->stbcEnable) {
11885 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11886 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11887 return RETURN_ERR;
11888 }
11889 }
11890 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11891 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11892 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11893 return RETURN_ERR;
11894 }
11895 }
11896
11897 // if enable is true, then restart the radio
11898 wifi_setRadioEnable(index, FALSE);
11899 if (operationParam->enable == TRUE)
11900 wifi_setRadioEnable(index, TRUE);
11901 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11902
developer06a01d92022-09-07 16:32:39 +080011903 return RETURN_OK;
11904}
11905
11906INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11907{
developer1e5aa162022-09-13 16:06:24 +080011908 char band[64] = {0};
11909 char buf[256] = {0};
11910 char config_file[64] = {0};
11911 char cmd[128] = {0};
11912 int ret = RETURN_ERR;
11913 int mode = 0;
11914 ULONG channel = 0;
11915 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011916
11917 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11918 printf("Entering %s index = %d\n", __func__, (int)index);
11919
developer1e5aa162022-09-13 16:06:24 +080011920 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11921 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11922 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011923 {
developer1e5aa162022-09-13 16:06:24 +080011924 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011925 return RETURN_ERR;
11926 }
11927 operationParam->enable = enabled;
11928
11929 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011930 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011931 {
developer1e5aa162022-09-13 16:06:24 +080011932 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011933 return RETURN_ERR;
11934 }
11935
11936 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011937 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011938 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011939 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011940 else if (!strcmp(band, "6GHz"))
11941 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011942 else
11943 {
developer1e5aa162022-09-13 16:06:24 +080011944 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011945 band);
11946 }
11947
developer1e5aa162022-09-13 16:06:24 +080011948 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11949 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11950 operationParam->channel = 0;
11951 operationParam->autoChannelEnabled = TRUE;
11952 } else {
11953 operationParam->channel = strtol(buf, NULL, 10);
11954 operationParam->autoChannelEnabled = FALSE;
11955 }
11956
developer06a01d92022-09-07 16:32:39 +080011957 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011958 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11959 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11960 return RETURN_ERR;
11961 }
developer06a01d92022-09-07 16:32:39 +080011962 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11963 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11964 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011965 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11966 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011967 else
11968 {
developer1e5aa162022-09-13 16:06:24 +080011969 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11970 return false;
developer06a01d92022-09-07 16:32:39 +080011971 }
11972
developer1e5aa162022-09-13 16:06:24 +080011973 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11974 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11975 return RETURN_ERR;
11976 }
11977 // Two different definition bit map, so need to check every bit.
11978 if (mode & WIFI_MODE_A)
11979 operationParam->variant |= WIFI_80211_VARIANT_A;
11980 if (mode & WIFI_MODE_B)
11981 operationParam->variant |= WIFI_80211_VARIANT_B;
11982 if (mode & WIFI_MODE_G)
11983 operationParam->variant |= WIFI_80211_VARIANT_G;
11984 if (mode & WIFI_MODE_N)
11985 operationParam->variant |= WIFI_80211_VARIANT_N;
11986 if (mode & WIFI_MODE_AC)
11987 operationParam->variant |= WIFI_80211_VARIANT_AC;
11988 if (mode & WIFI_MODE_AX)
11989 operationParam->variant |= WIFI_80211_VARIANT_AX;
11990 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11991 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11992 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011993 }
developer1e5aa162022-09-13 16:06:24 +080011994 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11995 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11996 return RETURN_ERR;
11997 }
11998 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11999 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12000 return RETURN_ERR;
12001 }
developer06a01d92022-09-07 16:32:39 +080012002
developer1e5aa162022-09-13 16:06:24 +080012003 memset(buf, 0, sizeof(buf));
12004 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12005 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12006 return RETURN_ERR;
12007 }
12008 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12009
12010 memset(buf, 0, sizeof(buf));
12011 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12012 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12013 return RETURN_ERR;
12014 }
12015 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12016
12017 memset(buf, 0, sizeof(buf));
12018 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12019 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12020
12021 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12022 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12023 return RETURN_ERR;
12024 }
12025 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12026 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12027 return RETURN_ERR;
12028 }
12029
12030 memset(buf, 0, sizeof(buf));
12031 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12032 if (strcmp(buf, "-1") == 0) {
12033 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12034 operationParam->ctsProtection = FALSE;
12035 } else {
12036 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12037 operationParam->ctsProtection = TRUE;
12038 }
12039
12040 memset(buf, 0, sizeof(buf));
12041 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12042 if (strcmp(buf, "0") == 0)
12043 operationParam->obssCoex = FALSE;
12044 else
12045 operationParam->obssCoex = TRUE;
12046
12047 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12048 _syscmd(cmd, buf, sizeof(buf));
12049 if (strlen(buf) != 0)
12050 operationParam->stbcEnable = TRUE;
12051 else
12052 operationParam->stbcEnable = FALSE;
12053
12054 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12055 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12056 return RETURN_ERR;
12057 }
12058
12059 // Below value is hardcoded
12060
12061 operationParam->numSecondaryChannels = 0;
12062 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12063 operationParam->channelSecondary[i] = 0;
12064 }
12065 operationParam->csa_beacon_count = 15;
12066 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012067
12068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12069 return RETURN_OK;
12070}
12071
12072static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12073{
developerc086fb72022-10-04 10:18:22 +080012074 int max_radio_num = 0;
12075
12076 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012077 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012078 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12079 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012080 }
12081
developerc086fb72022-10-04 10:18:22 +080012082 return (arrayIndex * max_radio_num) + radioIndex;
12083}
developer06a01d92022-09-07 16:32:39 +080012084
developerc086fb72022-10-04 10:18:22 +080012085wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12086 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12087 return WIFI_BITRATE_1MBPS;
12088 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12089 return WIFI_BITRATE_2MBPS;
12090 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12091 return WIFI_BITRATE_5_5MBPS;
12092 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12093 return WIFI_BITRATE_6MBPS;
12094 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12095 return WIFI_BITRATE_9MBPS;
12096 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12097 return WIFI_BITRATE_11MBPS;
12098 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12099 return WIFI_BITRATE_12MBPS;
12100 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12101 return WIFI_BITRATE_18MBPS;
12102 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12103 return WIFI_BITRATE_24MBPS;
12104 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12105 return WIFI_BITRATE_36MBPS;
12106 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12107 return WIFI_BITRATE_48MBPS;
12108 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12109 return WIFI_BITRATE_54MBPS;
12110 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012111}
12112
developer1d57d002022-10-12 18:03:15 +080012113INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12114{
12115 if (beacon == WIFI_BITRATE_1MBPS)
12116 strcpy(beacon_str, "1Mbps");
12117 else if (beacon == WIFI_BITRATE_2MBPS)
12118 strcpy(beacon_str, "2Mbps");
12119 else if (beacon == WIFI_BITRATE_5_5MBPS)
12120 strcpy(beacon_str, "5.5Mbps");
12121 else if (beacon == WIFI_BITRATE_6MBPS)
12122 strcpy(beacon_str, "6Mbps");
12123 else if (beacon == WIFI_BITRATE_9MBPS)
12124 strcpy(beacon_str, "9Mbps");
12125 else if (beacon == WIFI_BITRATE_11MBPS)
12126 strcpy(beacon_str, "11Mbps");
12127 else if (beacon == WIFI_BITRATE_12MBPS)
12128 strcpy(beacon_str, "12Mbps");
12129 else if (beacon == WIFI_BITRATE_18MBPS)
12130 strcpy(beacon_str, "18Mbps");
12131 else if (beacon == WIFI_BITRATE_24MBPS)
12132 strcpy(beacon_str, "24Mbps");
12133 else if (beacon == WIFI_BITRATE_36MBPS)
12134 strcpy(beacon_str, "36Mbps");
12135 else if (beacon == WIFI_BITRATE_48MBPS)
12136 strcpy(beacon_str, "48Mbps");
12137 else if (beacon == WIFI_BITRATE_54MBPS)
12138 strcpy(beacon_str, "54Mbps");
12139 return RETURN_OK;
12140}
12141
developer06a01d92022-09-07 16:32:39 +080012142INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12143{
developerc086fb72022-10-04 10:18:22 +080012144 INT mode = 0;
12145 INT ret = -1;
12146 INT output = 0;
12147 int i = 0;
12148 int vap_index = 0;
12149 BOOL enabled = FALSE;
12150 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012151 wifi_vap_security_t security = {0};
developerc086fb72022-10-04 10:18:22 +080012152 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080012153
12154 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12155 printf("Entering %s index = %d\n", __func__, (int)index);
12156
developer06a01d92022-09-07 16:32:39 +080012157 for (i = 0; i < 5; i++)
12158 {
developerc086fb72022-10-04 10:18:22 +080012159 map->vap_array[i].radio_index = index;
12160
developer06a01d92022-09-07 16:32:39 +080012161 vap_index = array_index_to_vap_index(index, i);
12162 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012163 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012164
developerc086fb72022-10-04 10:18:22 +080012165 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012166
12167 map->vap_array[i].vap_index = vap_index;
12168
12169 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012170 ret = wifi_getApName(vap_index, buf);
12171 if (ret != RETURN_OK) {
12172 printf("%s: wifi_getApName return error\n", __func__);
12173 return RETURN_ERR;
12174 }
12175 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12176
12177 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012178 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012179 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012180 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012181 return RETURN_ERR;
12182 }
12183 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 +080012184
12185 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012186 if (ret != RETURN_OK) {
12187 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012188 return RETURN_ERR;
12189 }
12190 map->vap_array[i].u.bss_info.enabled = enabled;
12191
developerc086fb72022-10-04 10:18:22 +080012192 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12193 if (ret != RETURN_OK) {
12194 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12195 return RETURN_ERR;
12196 }
developer06a01d92022-09-07 16:32:39 +080012197 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012198
12199 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12200 if (ret != RETURN_OK) {
12201 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12202 return RETURN_ERR;
12203 }
12204 map->vap_array[i].u.bss_info.isolation = enabled;
12205
12206 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12207 if (ret != RETURN_OK) {
12208 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12209 return RETURN_ERR;
12210 }
12211 map->vap_array[i].u.bss_info.bssMaxSta = output;
12212
12213 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12214 if (ret != RETURN_OK) {
12215 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12216 return RETURN_ERR;
12217 }
12218 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012219
developerc086fb72022-10-04 10:18:22 +080012220 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12221 if (ret != RETURN_OK) {
12222 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12223 return RETURN_ERR;
12224 }
12225 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012226
developerc086fb72022-10-04 10:18:22 +080012227 ret = wifi_getApSecurity(vap_index, &security);
12228 if (ret != RETURN_OK) {
12229 printf("%s: wifi_getApSecurity return error\n", __func__);
12230 return RETURN_ERR;
12231 }
12232 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012233
developerc086fb72022-10-04 10:18:22 +080012234 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12235 if (ret != RETURN_OK) {
12236 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12237 return RETURN_ERR;
12238 }
12239 if (mode == 0)
12240 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12241 else
12242 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12243 if (mode == 1)
12244 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12245 else if (mode == 2)
12246 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012247
developerc086fb72022-10-04 10:18:22 +080012248 ret = wifi_getApWmmEnable(vap_index, &enabled);
12249 if (ret != RETURN_OK) {
12250 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12251 return RETURN_ERR;
12252 }
12253 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012254
developerc086fb72022-10-04 10:18:22 +080012255 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12256 if (ret != RETURN_OK) {
12257 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012258 return RETURN_ERR;
12259 }
developerc086fb72022-10-04 10:18:22 +080012260 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012261
12262 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012263 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012264 if (ret != RETURN_OK) {
12265 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12266 return RETURN_ERR;
12267 }
12268 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012269
developerc086fb72022-10-04 10:18:22 +080012270 memset(buf, 0, sizeof(buf));
12271 ret = wifi_getBaseBSSID(vap_index, buf);
12272 if (ret != RETURN_OK) {
12273 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12274 return RETURN_ERR;
12275 }
12276 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12277 &map->vap_array[i].u.bss_info.bssid[0],
12278 &map->vap_array[i].u.bss_info.bssid[1],
12279 &map->vap_array[i].u.bss_info.bssid[2],
12280 &map->vap_array[i].u.bss_info.bssid[3],
12281 &map->vap_array[i].u.bss_info.bssid[4],
12282 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012283 // 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]);
12284
12285 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12286 if (ret != RETURN_OK) {
12287 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12288 return RETURN_ERR;
12289 }
12290 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012291
developerc086fb72022-10-04 10:18:22 +080012292 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012293 }
12294 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12295 return RETURN_OK;
12296}
12297
developer431128d2022-12-16 15:30:41 +080012298void checkVapStatus(int apIndex, bool *enable)
12299{
12300 char if_name[16] = {0};
12301 char cmd[128] = {0};
12302 char buf[128] = {0};
12303
12304 *enable = FALSE;
developerac6f1142022-12-20 19:26:35 +080012305 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
developer431128d2022-12-16 15:30:41 +080012306 return;
12307
12308 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12309 _syscmd(cmd, buf, sizeof(buf));
12310 if (strlen(buf) > 0)
12311 *enable = TRUE;
12312 return;
12313}
12314
developerd946fd62022-12-08 18:03:28 +080012315static int prepareInterface(UINT apIndex, char *new_interface)
12316{
12317 char cur_interface[16] = {0};
12318 char config_file[128] = {0};
12319 char cmd[128] = {0};
12320 char buf[16] = {0};
12321 int max_radio_num = 0;
12322 int radioIndex = -1;
12323 int phyIndex = -1;
12324
12325 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12326 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12327
12328 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12329 wifi_getMaxRadioNumber(&max_radio_num);
12330 radioIndex = apIndex % max_radio_num;
12331 phyIndex = radio_index_to_phy(radioIndex);
12332 // disable and del old interface, then add new interface
12333 wifi_setApEnable(apIndex, FALSE);
developer431128d2022-12-16 15:30:41 +080012334 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 +080012335 _syscmd(cmd, buf, sizeof(buf));
12336 }
developer431128d2022-12-16 15:30:41 +080012337 // update the vap status file
12338 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12339 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012340 return RETURN_OK;
12341}
12342
developer06a01d92022-09-07 16:32:39 +080012343INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12344{
developerd946fd62022-12-08 18:03:28 +080012345 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012346 unsigned int i;
12347 wifi_vap_info_t *vap_info = NULL;
12348 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012349 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012350 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012351 char buf[256] = {0};
12352 char cmd[128] = {0};
12353 char config_file[64] = {0};
12354 char bssid[32] = {0};
12355 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012356 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012357
12358 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12359 printf("Entering %s index = %d\n", __func__, (int)index);
12360 for (i = 0; i < map->num_vaps; i++)
12361 {
developer1d57d002022-10-12 18:03:15 +080012362 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012363 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012364
12365 // Check vap status file to enable multiple ap if the system boot.
12366 checkVapStatus(vap_info->vap_index, &enable);
12367 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012368 continue;
developer06a01d92022-09-07 16:32:39 +080012369
developer1d57d002022-10-12 18:03:15 +080012370 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12371
developer431128d2022-12-16 15:30:41 +080012372 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12373 enable = FALSE;
12374
12375 // multi-ap first up need to copy current radio config
12376 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012377 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12378 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012379 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12380 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12381 } else {
12382 // Check whether the interface name is valid or this ap change it.
12383 int apIndex = -1;
12384 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12385 if (apIndex != -1 && apIndex != vap_info->vap_index)
12386 continue;
12387 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012388 }
developer06a01d92022-09-07 16:32:39 +080012389
developer1d57d002022-10-12 18:03:15 +080012390 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012391 params[0].name = "interface";
12392 params[0].value = vap_info->vap_name;
12393 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12394 params[1].name = "bssid";
12395 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012396 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012397 params[2].name = "wpa_psk_file";
12398 params[2].value = psk_file;
12399
12400 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12401 wifi_hostapdWrite(config_file, params, 3);
12402
12403 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12404 _syscmd(cmd, buf, sizeof(buf));
12405
12406 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12407 if (ret != RETURN_OK) {
12408 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12409 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012410 }
developer1d57d002022-10-12 18:03:15 +080012411
12412 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12413 if (ret != RETURN_OK) {
12414 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12415 return RETURN_ERR;
12416 }
12417
12418 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12419 if (ret != RETURN_OK) {
12420 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12421 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012422 }
12423
developer1d57d002022-10-12 18:03:15 +080012424 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12425 if (ret != RETURN_OK) {
12426 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12427 return RETURN_ERR;
12428 }
developer06a01d92022-09-07 16:32:39 +080012429
developer1d57d002022-10-12 18:03:15 +080012430 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12431 if (ret != RETURN_OK) {
12432 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12433 return RETURN_ERR;
12434 }
developer06a01d92022-09-07 16:32:39 +080012435
developer1d57d002022-10-12 18:03:15 +080012436 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12437 if (ret != RETURN_OK) {
12438 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12439 return RETURN_ERR;
12440 }
12441
developer804c64f2022-10-19 13:54:40 +080012442 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012443 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012444 }else {
12445 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012446 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012447 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12448 _syscmd(cmd, buf, sizeof(buf));
12449 }else{
developer1d57d002022-10-12 18:03:15 +080012450 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012451 }
developer1d57d002022-10-12 18:03:15 +080012452 }
12453
12454 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12455 if (ret != RETURN_OK) {
12456 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12457 return RETURN_ERR;
12458 }
12459
12460 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12461 if (ret != RETURN_OK) {
12462 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12463 return RETURN_ERR;
12464 }
12465
12466 memset(buf, 0, sizeof(buf));
12467 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12468 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12469 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12470 if (ret != RETURN_OK) {
12471 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12472 return RETURN_ERR;
12473 }
12474
12475 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12476 if (ret != RETURN_OK) {
12477 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12478 return RETURN_ERR;
12479 }
12480
12481 wifi_setApEnable(vap_info->vap_index, TRUE);
12482 multiple_set = FALSE;
12483
12484 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12485 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12486 if (ret != RETURN_OK) {
12487 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12488 return RETURN_ERR;
12489 }
12490
12491 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12492 if (ret != RETURN_OK) {
12493 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12494 return RETURN_ERR;
12495 }
developer06a01d92022-09-07 16:32:39 +080012496
developer1d57d002022-10-12 18:03:15 +080012497 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012498 }
12499 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12500 return RETURN_OK;
12501}
12502
12503int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12504{
12505 char *token, *next;
12506 const char s[2] = ",";
12507 int count =0;
12508
12509 /* get the first token */
12510 token = strtok_r(pchannels, s, &next);
12511
12512 /* walk through other tokens */
12513 while( token != NULL && count < MAX_CHANNELS) {
12514 chlistptr->channels_list[count++] = atoi(token);
12515 token = strtok_r(NULL, s, &next);
12516 }
12517
12518 return count;
12519}
12520
12521static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12522{
12523 INT status;
12524 wifi_channels_list_t *chlistp;
12525 CHAR output_string[64];
12526 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012527 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012528 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012529
12530 if(rcap == NULL)
12531 {
12532 return RETURN_ERR;
12533 }
12534
12535 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012536 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012537
developer1e5aa162022-09-13 16:06:24 +080012538 if (band == band_2_4)
12539 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12540 else if (band == band_5)
12541 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12542 else if (band == band_6)
12543 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012544
12545 chlistp = &(rcap->channel_list[0]);
12546 memset(pchannels, 0, sizeof(pchannels));
12547
12548 /* possible number of radio channels */
12549 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12550 {
12551 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12552 }
12553 /* Number of channels and list*/
12554 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12555
12556 /* autoChannelSupported */
12557 /* always ON with wifi_getRadioAutoChannelSupported */
12558 rcap->autoChannelSupported = TRUE;
12559
12560 /* DCSSupported */
12561 /* always ON with wifi_getRadioDCSSupported */
12562 rcap->DCSSupported = TRUE;
12563
12564 /* zeroDFSSupported - TBD */
12565 rcap->zeroDFSSupported = FALSE;
12566
12567 /* Supported Country List*/
12568 memset(output_string, 0, sizeof(output_string));
12569 status = wifi_getRadioCountryCode(radioIndex, output_string);
12570 if( status != 0 ) {
12571 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12572 return RETURN_ERR;
12573 } else {
12574 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12575 }
12576 if(!strcmp(output_string,"US")){
12577 rcap->countrySupported[0] = wifi_countrycode_US;
12578 rcap->countrySupported[1] = wifi_countrycode_CA;
12579 } else if (!strcmp(output_string,"CA")) {
12580 rcap->countrySupported[0] = wifi_countrycode_CA;
12581 rcap->countrySupported[1] = wifi_countrycode_US;
12582 } else {
12583 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12584 }
12585
12586 rcap->numcountrySupported = 2;
12587
12588 /* csi */
12589 rcap->csi.maxDevices = 8;
12590 rcap->csi.soudingFrameSupported = TRUE;
12591
developer033b37b2022-10-18 11:27:46 +080012592 phyId = radio_index_to_phy(radioIndex);
12593 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012594
12595 /* channelWidth - all supported bandwidths */
12596 int i=0;
12597 rcap->channelWidth[i] = 0;
12598 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12599 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12600 WIFI_CHANNELBANDWIDTH_40MHZ);
12601
12602 }
developer1e5aa162022-09-13 16:06:24 +080012603 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012604 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12605 WIFI_CHANNELBANDWIDTH_40MHZ |
12606 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12607 }
12608
12609
12610 /* mode - all supported variants */
12611 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12612 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012613 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012614 }
12615 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012616 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12617 }
12618 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12619 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012620 }
12621 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12622 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12623
12624 /* supportedBitRate - all supported bitrates */
12625 rcap->supportedBitRate[i] = 0;
12626 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12627 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12628 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12629 }
developer1e5aa162022-09-13 16:06:24 +080012630 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012631 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12632 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12633 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12634 }
12635
12636
12637 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12638 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12639 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12640 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12641 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12642 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12643 rcap->cipherSupported = 0;
12644 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12645 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12646
12647 return RETURN_OK;
12648}
12649
12650INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12651{
developer30423732022-12-01 16:17:49 +080012652 INT status = 0, radioIndex = 0;
12653 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080012654 int iter = 0;
developer30423732022-12-01 16:17:49 +080012655 unsigned int j = 0;
12656 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080012657
12658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12659
12660 memset(cap, 0, sizeof(wifi_hal_capability_t));
12661
12662 /* version */
12663 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12664 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12665
12666 /* number of radios platform property */
12667 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12668 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012669 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012670
12671 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12672 {
12673 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12674 if (status != 0) {
12675 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12676 return RETURN_ERR;
12677 }
12678
12679 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12680 {
developer804c64f2022-10-19 13:54:40 +080012681 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012682 {
12683 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12684 return RETURN_ERR;
12685 }
12686 iface_info = &cap->wifi_prop.interface_map[iter];
12687 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12688 iface_info->rdk_radio_index = radioIndex;
12689 memset(output, 0, sizeof(output));
12690 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12691 {
12692 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12693 }
12694 // TODO: bridge name
12695 // TODO: vlan id
12696 // TODO: primary
12697 iface_info->index = array_index_to_vap_index(radioIndex, j);
12698 memset(output, 0, sizeof(output));
developer30423732022-12-01 16:17:49 +080012699 if (iface_info->index >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012700 {
12701 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12702 }
12703 iter++;
12704 }
12705 }
12706
12707 cap->BandSteeringSupported = FALSE;
12708 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12709 return RETURN_OK;
12710}
12711
developer9df4e652022-10-11 11:27:38 +080012712INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12713{
12714 struct params h_config={0};
12715 char config_file[64] = {0};
12716
12717 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12718
12719 h_config.name = "okc";
12720 h_config.value = okc_enable?"1":"0";
12721
12722 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12723 wifi_hostapdWrite(config_file, &h_config, 1);
12724 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12725
12726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12727 return RETURN_OK;
12728}
12729
12730INT wifi_setSAEMFP(int ap_index, BOOL enable)
12731{
12732 struct params h_config={0};
12733 char config_file[64] = {0};
12734 char buf[128] = {0};
12735
12736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12737
12738 h_config.name = "sae_require_mfp";
12739 h_config.value = enable?"1":"0";
12740
12741 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12742 wifi_hostapdWrite(config_file, &h_config, 1);
12743 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12744
12745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12746 return RETURN_OK;
12747}
12748
12749INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12750{
12751 struct params h_config={0};
12752 char config_file[64] = {0};
12753 char buf[128] = {0};
12754
12755 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12756
12757 h_config.name = "sae_pwe";
12758 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12759 h_config.value = buf;
12760
12761 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12762 wifi_hostapdWrite(config_file, &h_config, 1);
12763 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12764
12765 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12766 return RETURN_OK;
12767}
12768
12769INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12770{
12771 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12772 struct params h_config={0};
12773 char config_file[64] = {0};
12774
12775 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12776
12777 h_config.name = "wpa_disable_eapol_key_retries";
12778 h_config.value = disable_EAPOL_retries?"1":"0";
12779
12780 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12781 wifi_hostapdWrite(config_file, &h_config, 1);
12782 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12783
12784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12785 return RETURN_OK;
12786}
12787
developer06a01d92022-09-07 16:32:39 +080012788INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12789{
developer587c1b62022-09-27 15:58:59 +080012790 char buf[128] = {0};
12791 char config_file[128] = {0};
12792 char password[64] = {0};
12793 char mfp[32] = {0};
12794 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012795 BOOL okc_enable = FALSE;
12796 BOOL sae_MFP = FALSE;
12797 BOOL disable_EAPOL_retries = TRUE;
12798 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012799 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012800 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012801
12802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12803
12804 multiple_set = TRUE;
12805 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12806 if (security->mode == wifi_security_mode_none) {
12807 strcpy(wpa_mode, "None");
12808 } else if (security->mode == wifi_security_mode_wpa_personal)
12809 strcpy(wpa_mode, "WPA-Personal");
12810 else if (security->mode == wifi_security_mode_wpa2_personal)
12811 strcpy(wpa_mode, "WPA2-Personal");
12812 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12813 strcpy(wpa_mode, "WPA-WPA2-Personal");
12814 else if (security->mode == wifi_security_mode_wpa_enterprise)
12815 strcpy(wpa_mode, "WPA-Enterprise");
12816 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12817 strcpy(wpa_mode, "WPA2-Enterprise");
12818 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12819 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012820 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012821 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012822 okc_enable = TRUE;
12823 sae_MFP = TRUE;
12824 sae_pwe = 2;
12825 disable_EAPOL_retries = FALSE;
12826 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012827 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012828 okc_enable = TRUE;
12829 sae_MFP = TRUE;
12830 sae_pwe = 2;
12831 disable_EAPOL_retries = FALSE;
12832 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012833 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012834 sae_MFP = TRUE;
12835 sae_pwe = 2;
12836 disable_EAPOL_retries = FALSE;
12837 }
12838
12839 band = wifi_index_to_band(ap_index);
12840 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12841 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12842 return RETURN_ERR;
12843 }
developer587c1b62022-09-27 15:58:59 +080012844
12845 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012846 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012847 wifi_setSAEMFP(ap_index, sae_MFP);
12848 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012849 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012850
developer9df4e652022-10-11 11:27:38 +080012851 if (security->mode != wifi_security_mode_none) {
12852 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12853 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12854 password[63] = '\0';
12855 wifi_setApSecurityKeyPassphrase(ap_index, password);
12856 }
12857 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12858 params.name = "sae_password";
12859 params.value = security->u.key.key;
12860 wifi_hostapdWrite(config_file, &params, 1);
12861 }
12862 }
developer587c1b62022-09-27 15:58:59 +080012863
12864 if (security->mode != wifi_security_mode_none) {
12865 memset(&params, 0, sizeof(params));
12866 params.name = "wpa_pairwise";
12867 if (security->encr == wifi_encryption_tkip)
12868 params.value = "TKIP";
12869 else if (security->encr == wifi_encryption_aes)
12870 params.value = "CCMP";
12871 else if (security->encr == wifi_encryption_aes_tkip)
12872 params.value = "TKIP CCMP";
12873 wifi_hostapdWrite(config_file, &params, 1);
12874 }
12875
12876 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012877 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012878 else if (security->mfp == wifi_mfp_cfg_optional)
12879 strcpy(mfp, "Optional");
12880 else if (security->mfp == wifi_mfp_cfg_required)
12881 strcpy(mfp, "Required");
12882 wifi_setApSecurityMFPConfig(ap_index, mfp);
12883
12884 memset(&params, 0, sizeof(params));
12885 params.name = "transition_disable";
12886 if (security->wpa3_transition_disable == TRUE)
12887 params.value = "0x01";
12888 else
12889 params.value = "0x00";
12890 wifi_hostapdWrite(config_file, &params, 1);
12891
12892 memset(&params, 0, sizeof(params));
12893 params.name = "wpa_group_rekey";
12894 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12895 params.value = buf;
12896 wifi_hostapdWrite(config_file, &params, 1);
12897
12898 memset(&params, 0, sizeof(params));
12899 params.name = "wpa_strict_rekey";
12900 params.value = security->strict_rekey?"1":"0";
12901 wifi_hostapdWrite(config_file, &params, 1);
12902
12903 memset(&params, 0, sizeof(params));
12904 params.name = "wpa_pairwise_update_count";
12905 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12906 params.value = buf;
12907 wifi_hostapdWrite(config_file, &params, 1);
12908
12909 memset(&params, 0, sizeof(params));
12910 params.name = "disable_pmksa_caching";
12911 params.value = security->disable_pmksa_caching?"1":"0";
12912 wifi_hostapdWrite(config_file, &params, 1);
12913
12914 wifi_setApEnable(ap_index, FALSE);
12915 wifi_setApEnable(ap_index, TRUE);
12916
12917 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12918
developer06a01d92022-09-07 16:32:39 +080012919 return RETURN_OK;
12920}
12921
12922INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12923{
developer9df4e652022-10-11 11:27:38 +080012924 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012925 char config_file[128] = {0};
12926 int disable = 0;
12927 // struct params params = {0};
12928
12929 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12930 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12931 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12932 security->mode = wifi_security_mode_none;
12933 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012934 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012935 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012936 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012937 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012938 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012939 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012940 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012941 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012942 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012943 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012944 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012945 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012946 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012947 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012948 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012949 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012950 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012951 security->mode = wifi_security_mode_wpa3_enterprise;
12952 }
12953
12954 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12955 if (security->mode == wifi_security_mode_none)
12956 security->encr = wifi_encryption_none;
12957 else {
12958 if (strcmp(buf, "TKIP") == 0)
12959 security->encr = wifi_encryption_tkip;
12960 else if (strcmp(buf, "CCMP") == 0)
12961 security->encr = wifi_encryption_aes;
12962 else
12963 security->encr = wifi_encryption_aes_tkip;
12964 }
12965
developer9df4e652022-10-11 11:27:38 +080012966 if (security->mode != wifi_encryption_none) {
12967 memset(buf, 0, sizeof(buf));
12968 // wpa3 can use one or both configs as password, so we check sae_password first.
12969 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12970 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12971 security->u.key.type = wifi_security_key_type_sae;
12972 } else {
12973 security->u.key.type = wifi_security_key_type_psk;
12974 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12975 }
12976 strncpy(security->u.key.key, buf, sizeof(buf));
12977 security->u.key.key[255] = '\0';
12978 }
12979
developer587c1b62022-09-27 15:58:59 +080012980 memset(buf, 0, sizeof(buf));
12981 wifi_getApSecurityMFPConfig(ap_index, buf);
12982 if (strcmp(buf, "Disabled") == 0)
12983 security->mfp = wifi_mfp_cfg_disabled;
12984 else if (strcmp(buf, "Optional") == 0)
12985 security->mfp = wifi_mfp_cfg_optional;
12986 else if (strcmp(buf, "Required") == 0)
12987 security->mfp = wifi_mfp_cfg_required;
12988
12989 memset(buf, 0, sizeof(buf));
12990 security->wpa3_transition_disable = FALSE;
12991 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12992 disable = strtol(buf, NULL, 16);
12993 if (disable != 0)
12994 security->wpa3_transition_disable = TRUE;
12995
12996 memset(buf, 0, sizeof(buf));
12997 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12998 if (strlen(buf) == 0)
12999 security->rekey_interval = 86400;
13000 else
13001 security->rekey_interval = strtol(buf, NULL, 10);
13002
13003 memset(buf, 0, sizeof(buf));
13004 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13005 if (strlen(buf) == 0)
13006 security->strict_rekey = 1;
13007 else
13008 security->strict_rekey = strtol(buf, NULL, 10);
13009
13010 memset(buf, 0, sizeof(buf));
13011 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13012 if (strlen(buf) == 0)
13013 security->eapol_key_retries = 4;
13014 else
13015 security->eapol_key_retries = strtol(buf, NULL, 10);
13016
13017 memset(buf, 0, sizeof(buf));
13018 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13019 if (strlen(buf) == 0)
13020 security->disable_pmksa_caching = FALSE;
13021 else
13022 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13023
13024 /* TODO
13025 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13026 */
13027 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13028 security->eap_identity_req_timeout = 0;
13029 security->eap_identity_req_retries = 0;
13030 security->eap_req_timeout = 0;
13031 security->eap_req_retries = 0;
13032 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013033 return RETURN_OK;
13034}
13035
13036#endif /* WIFI_HAL_VERSION_3 */
13037
13038#ifdef WIFI_HAL_VERSION_3_PHASE2
13039INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13040{
developerd946fd62022-12-08 18:03:28 +080013041 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013042 char cmd[128] = {0};
13043 char buf[128] = {0};
13044 char *mac_addr = NULL;
13045 BOOL status = FALSE;
13046 size_t len = 0;
13047
13048 if(ap_index > MAX_APS)
13049 return RETURN_ERR;
13050
13051 *output_numDevices = 0;
13052 wifi_getApEnable(ap_index, &status);
13053 if (status == FALSE)
13054 return RETURN_OK;
13055
developerac6f1142022-12-20 19:26:35 +080013056 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013057 return RETURN_ERR;
13058 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013059 _syscmd(cmd, buf, sizeof(buf));
13060
13061 mac_addr = strtok(buf, "\n");
13062 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13063 *output_numDevices = i + 1;
13064 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13065 addr_ptr = output_deviceMacAddressArray[i];
13066 mac_addr_aton(addr_ptr, mac_addr);
13067 mac_addr = strtok(NULL, "\n");
13068 }
13069
13070 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013071}
13072#else
13073INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13074{
developerd946fd62022-12-08 18:03:28 +080013075 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013076 char cmd[128];
13077 BOOL status = false;
13078
13079 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13080 return RETURN_ERR;
13081
13082 output_buf[0] = '\0';
13083
13084 wifi_getApEnable(ap_index,&status);
13085 if (!status)
13086 return RETURN_OK;
13087
developerac6f1142022-12-20 19:26:35 +080013088 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013089 return RETURN_ERR;
13090 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013091 _syscmd(cmd, output_buf, output_buf_size);
13092
13093 return RETURN_OK;
13094}
13095#endif
developer2f513ab2022-09-13 14:26:06 +080013096
13097INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13098{
13099 char output[16]={'\0'};
13100 char config_file[MAX_BUF_SIZE] = {0};
13101
13102 if (!enable)
13103 return RETURN_ERR;
13104
13105 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13106 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13107
13108 if (strlen(output) == 0)
13109 *enable = FALSE;
13110 else if (strncmp(output, "1", 1) == 0)
13111 *enable = TRUE;
13112 else
13113 *enable = FALSE;
13114
13115 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13116 return RETURN_OK;
13117}
developer2d9c30f2022-09-13 15:06:14 +080013118
13119INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13120{
developer804c64f2022-10-19 13:54:40 +080013121 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013122 return RETURN_ERR;
13123 *output_enable=TRUE;
13124 return RETURN_OK;
13125}
developerfd7d2892022-09-13 16:44:53 +080013126
13127INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13128{
13129 char cmd[128] = {0};
13130 char buf[128] = {0};
13131 char line[128] = {0};
13132 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013133 FILE *f = NULL;
13134 int index = 0;
13135 int exp = 0;
13136 int mantissa = 0;
13137 int duration = 0;
13138 int radio_index = 0;
13139 int max_radio_num = 0;
13140 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013141 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013142 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13143
13144 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013145
developerfd7d2892022-09-13 16:44:53 +080013146 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013147
13148 phyId = radio_index_to_phy(radio_index);
13149 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013150 _syscmd(cmd, buf, sizeof(buf));
13151 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13152 if (*numSessionReturned > maxNumberSessions)
13153 *numSessionReturned = maxNumberSessions;
13154 else if (*numSessionReturned < 1) {
13155 *numSessionReturned = 0;
13156 return RETURN_OK;
13157 }
13158
developer033b37b2022-10-18 11:27:46 +080013159 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 +080013160 if ((f = popen(cmd, "r")) == NULL) {
13161 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13162 return RETURN_ERR;
13163 }
13164
13165 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013166 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013167 char *tmp = NULL;
13168 strcpy(buf, line);
13169 tmp = strtok(buf, " ");
13170 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13171 tmp = strtok(NULL, " ");
13172 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13173 tmp = strtok(NULL, " ");
13174 if (strstr(tmp, "t")) {
13175 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13176 }
13177 if (strstr(tmp, "a")) {
13178 twtSessions[index].twtParameters.operation.announced = TRUE;
13179 }
13180 tmp = strtok(NULL, " ");
13181 exp = strtol(tmp, NULL, 10);
13182 tmp = strtok(NULL, " ");
13183 mantissa = strtol(tmp, NULL, 10);
13184 tmp = strtok(NULL, " ");
13185 duration = strtol(tmp, NULL, 10);
13186
13187 // only implicit supported
13188 twtSessions[index].twtParameters.operation.implicit = TRUE;
13189 // only individual agreement supported
13190 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13191
13192 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13193 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013194 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013195 // Overflow handling
13196 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13197 } else {
13198 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13199 }
13200 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13201 index++;
13202 }
13203
13204 pclose(f);
13205 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13206 return RETURN_OK;
13207}