blob: 464a2db85c3423dbdbba08abbf335adb94ecf154 [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"
71#define ACL_PREFIX "/tmp/hostapd-acl"
developer10adcc12022-09-13 14:39:17 +080072#define DENY_PREFIX "/tmp/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"
75#define VAP_STATUS_FILE "/tmp/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"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/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) {
463 fprintf(stderr, "%s: failed to get phy index\n", __func__);
464 return RETURN_ERR;
465 }
466 sscanf(buf, "phy%d", &phyIndex);
467
468 return phyIndex;
469}
developer026ac9e2022-11-07 13:46:24 +0800470
471wifi_band wifi_index_to_band(int radioIndex)
developerc707e972022-09-13 15:38:02 +0800472{
473 char cmd[128] = {0};
474 char buf[64] = {0};
developer026ac9e2022-11-07 13:46:24 +0800475 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800476 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800477 int phyIndex = 0;
developerc707e972022-09-13 15:38:02 +0800478 wifi_band band = band_invalid;
479
480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800481
482 phyIndex = radio_index_to_phy(radioIndex);
developer5884e982022-10-06 10:52:50 +0800483 while(i < 10){
developer026ac9e2022-11-07 13:46:24 +0800484 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 +0800485 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800486 nl80211_band = strtol(buf, NULL, 10);
487 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800488 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800489 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800490 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800491 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800492 band = band_6;
493
494 if(band != band_invalid)
495 break;
496
497 i++;
498 sleep(1);
499 }
developerc707e972022-09-13 15:38:02 +0800500
501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
502 return band;
503}
504
developer06a01d92022-09-07 16:32:39 +0800505static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
506{
507 char cmd[MAX_CMD_SIZE]={'\0'};
508 char buf[MAX_BUF_SIZE]={'\0'};
509 int ret = 0;
510
developerd946fd62022-12-08 18:03:28 +0800511 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 +0800512 ret = _syscmd(cmd, buf, sizeof(buf));
513 if ((ret != 0) && (strlen(buf) == 0))
514 return -1;
515 snprintf(output, output_size, "%s", buf);
516
517 return 0;
518}
519
520static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
521{
522 char cmd[MAX_CMD_SIZE]={'\0'};
523 char buf[MAX_BUF_SIZE]={'\0'};
524
525 for(int i=0;i<item_count;i++)
526 {
527 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
528 if (strlen(buf) == 0) //Insert
529 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
530 else //Update
531 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 +0800532
developer06a01d92022-09-07 16:32:39 +0800533 if(_syscmd(cmd, buf, sizeof(buf)))
534 return -1;
535 }
536
537 return 0;
538}
539
developerd946fd62022-12-08 18:03:28 +0800540//For Getting Current Interface Name from corresponding hostapd configuration
541static int GetInterfaceName(int apIndex, char *interface_name)
542{
543 char config_file[128] = {0};
544
545 if (interface_name == NULL)
546 return RETURN_ERR;
547
548 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
549
550 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
551 wifi_hostapdRead(config_file, "interface", interface_name, 16);
552 if (strlen(interface_name) == 0)
553 return RETURN_ERR;
554
555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
556 return RETURN_OK;
557}
558
developer06a01d92022-09-07 16:32:39 +0800559static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
560{
developerd946fd62022-12-08 18:03:28 +0800561 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800562 if (multiple_set == TRUE)
563 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800564 char cmd[MAX_CMD_SIZE]="", output[32]="";
565 FILE *fp;
566 int i;
567 //NOTE RELOAD should be done in ApplySSIDSettings
developerd946fd62022-12-08 18:03:28 +0800568 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
569 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800570 for(i=0; i<item_count; i++, list++)
571 {
developerd946fd62022-12-08 18:03:28 +0800572 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800573 if((fp = popen(cmd, "r"))==NULL)
574 {
575 perror("popen failed");
576 return -1;
577 }
578 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
579 {
580 pclose(fp);
581 perror("fgets failed");
582 return -1;
583 }
584 pclose(fp);
585 }
586 return 0;
587}
588
589static int wifi_reloadAp(int apIndex)
590{
developerd946fd62022-12-08 18:03:28 +0800591 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800592 if (multiple_set == TRUE)
593 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800594 char cmd[MAX_CMD_SIZE]="";
595 char buf[MAX_BUF_SIZE]="";
596
developerd946fd62022-12-08 18:03:28 +0800597 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
598 return RETURN_ERR;
599 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800600 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
601 return RETURN_ERR;
602
developerd946fd62022-12-08 18:03:28 +0800603 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800604 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
605 return RETURN_ERR;
606
developerd946fd62022-12-08 18:03:28 +0800607 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800608 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
609 return RETURN_ERR;
610
611 return RETURN_OK;
612}
613
developer06a01d92022-09-07 16:32:39 +0800614INT File_Reading(CHAR *file, char *Value)
615{
616 FILE *fp = NULL;
617 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
618 int count = 0;
619
620 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
621 fp = popen(file,"r");
622 if(fp == NULL)
623 return RETURN_ERR;
624
625 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
626 {
627 for(count=0;buf[count]!='\n';count++)
628 copy_buf[count]=buf[count];
629 copy_buf[count]='\0';
630 }
631 strcpy(Value,copy_buf);
632 pclose(fp);
633 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
634
635 return RETURN_OK;
636}
637
638void wifi_RestartHostapd_2G()
639{
640 int Public2GApIndex = 4;
641
642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
643 wifi_setApEnable(Public2GApIndex, FALSE);
644 wifi_setApEnable(Public2GApIndex, TRUE);
645 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
646}
647
648void wifi_RestartHostapd_5G()
649{
650 int Public5GApIndex = 5;
651
652 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
653 wifi_setApEnable(Public5GApIndex, FALSE);
654 wifi_setApEnable(Public5GApIndex, TRUE);
655 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
656}
657
658void wifi_RestartPrivateWifi_2G()
659{
660 int PrivateApIndex = 0;
661
662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
663 wifi_setApEnable(PrivateApIndex, FALSE);
664 wifi_setApEnable(PrivateApIndex, TRUE);
665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
666}
667
668void wifi_RestartPrivateWifi_5G()
669{
670 int Private5GApIndex = 1;
671
672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
673 wifi_setApEnable(Private5GApIndex, FALSE);
674 wifi_setApEnable(Private5GApIndex, TRUE);
675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
676}
677
678static int writeBandWidth(int radioIndex,char *bw_value)
679{
680 char buf[MAX_BUF_SIZE];
681 char cmd[MAX_CMD_SIZE];
682
683 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
684 if(_syscmd(cmd, buf, sizeof(buf)))
685 {
686 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
687 _syscmd(cmd, buf, sizeof(buf));
688 return RETURN_OK;
689 }
690
691 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
692 _syscmd(cmd,buf,sizeof(buf));
693 return RETURN_OK;
694}
695
696static int readBandWidth(int radioIndex,char *bw_value)
697{
developer30423732022-12-01 16:17:49 +0800698 char buf[MAX_BUF_SIZE] = {0};
699 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800700 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
701 _syscmd(cmd,buf,sizeof(buf));
702 if(NULL!=strstr(buf,"20MHz"))
703 {
704 strcpy(bw_value,"20MHz");
705 }
706 else if(NULL!=strstr(buf,"40MHz"))
707 {
708 strcpy(bw_value,"40MHz");
709 }
710 else if(NULL!=strstr(buf,"80MHz"))
711 {
712 strcpy(bw_value,"80MHz");
713 }
714 else
715 {
716 return RETURN_ERR;
717 }
718 return RETURN_OK;
719}
720
developer39a5efb2022-09-13 16:09:06 +0800721INT wifi_getMaxRadioNumber(INT *max_radio_num)
722{
723 char cmd[64] = {0};
724 char buf[4] = {0};
725
726 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
727
728 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
729 _syscmd(cmd, buf, sizeof(buf));
developer804c64f2022-10-19 13:54:40 +0800730 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
developer39a5efb2022-09-13 16:09:06 +0800731
732 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
733
734 return RETURN_OK;
735}
736
developer264159b2022-11-02 09:41:35 +0800737// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800738INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
739{
developer5f222492022-09-13 15:21:52 +0800740 struct params params={'\0'};
741 char config_file[MAX_BUF_SIZE] = {0};
742 char buf[MAX_BUF_SIZE] = {'\0'};
743
744 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800745 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800746 if (strlen (beaconRate) >= 5) {
747 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
748 buf[strlen(beaconRate) - 4] = '\0';
749 } else if (strlen(beaconRate) > 0)
750 strcpy(buf, beaconRate);
751 else
752 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800753
754 params.name = "beacon_rate";
755 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
756 if (strncmp(buf, "5.5", 3) == 0) {
757 snprintf(buf, sizeof(buf), "55");
758 params.value = buf;
759 } else {
760 strcat(buf, "0");
761 params.value = buf;
762 }
763
764 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
765 wifi_hostapdWrite(config_file, &params, 1);
766 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
768
769 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800770}
771
772INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
773{
developer1d57d002022-10-12 18:03:15 +0800774 char config_file[128] = {'\0'};
775 char temp_output[128] = {'\0'};
776 char buf[128] = {'\0'};
777 char cmd[128] = {'\0'};
778 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800779 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800780
781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
782 if (NULL == beaconRate)
783 return RETURN_ERR;
784
785 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
786 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800787 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800788 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
789 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800790 if (strncmp(buf, "55", 2) == 0)
791 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
792 else {
793 rate = strtol(buf, NULL, 10)/10;
794 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
795 }
developer5f222492022-09-13 15:21:52 +0800796 } else {
developer1d57d002022-10-12 18:03:15 +0800797 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800798 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 +0800799 _syscmd(cmd, buf, sizeof(buf));
800 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800801 }
802 strncpy(beaconRate, temp_output, sizeof(temp_output));
803 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
804
805 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800806}
807
808INT wifi_setLED(INT radioIndex, BOOL enable)
809{
810 return 0;
811}
812INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
813{
814 return RETURN_OK;
815}
816/**********************************************************************************
817 *
818 * Wifi Subsystem level function prototypes
819 *
820**********************************************************************************/
821//---------------------------------------------------------------------------------------------------
822//Wifi system api
823//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
824INT wifi_getHalVersion(CHAR *output_string) //RDKB
825{
826 if(!output_string)
827 return RETURN_ERR;
828 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
829
830 return RETURN_OK;
831}
832
833
834/* wifi_factoryReset() function */
835/**
836* @description Clears internal variables to implement a factory reset of the Wi-Fi
837* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
838*
839* @param None
840*
841* @return The status of the operation.
842* @retval RETURN_OK if successful.
843* @retval RETURN_ERR if any error is detected
844*
845* @execution Synchronous
846* @sideeffect None
847*
848* @note This function must not suspend and must not invoke any blocking system
849* calls. It should probably just send a message to a driver event handler task.
850*
851*/
852INT wifi_factoryReset()
853{
854 char cmd[128];
855
856 /*delete running hostapd conf files*/
857 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
858 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
859 system(cmd);
860 system("systemctl restart hostapd.service");
861
862 return RETURN_OK;
863}
864
865/* wifi_factoryResetRadios() function */
866/**
867* @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.
868*
869* @param None
870* @return The status of the operation
871* @retval RETURN_OK if successful
872* @retval RETURN_ERR if any error is detected
873*
874* @execution Synchronous
875*
876* @sideeffect None
877*
878* @note This function must not suspend and must not invoke any blocking system
879* calls. It should probably just send a message to a driver event handler task.
880*
881*/
882INT wifi_factoryResetRadios()
883{
884 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
885 return RETURN_OK;
886
887 return RETURN_ERR;
888}
889
890
891/* wifi_factoryResetRadio() function */
892/**
893* @description Restore selected radio parameters without touching access point parameters
894*
895* @param radioIndex - Index of Wi-Fi Radio channel
896*
897* @return The status of the operation.
898* @retval RETURN_OK if successful.
899* @retval RETURN_ERR if any error is detected
900*
901* @execution Synchronous.
902* @sideeffect None.
903*
904* @note This function must not suspend and must not invoke any blocking system
905* calls. It should probably just send a message to a driver event handler task.
906*
907*/
908INT wifi_factoryResetRadio(int radioIndex) //RDKB
909{
developer5ff7f5f2022-09-13 15:12:16 +0800910 system("systemctl stop hostapd.service");
911
developer06a01d92022-09-07 16:32:39 +0800912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
913 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800914 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800915 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800916 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800917 else
918 return RETURN_ERR;
919
developer5ff7f5f2022-09-13 15:12:16 +0800920 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
922 return RETURN_OK;
923}
924
925/* wifi_initRadio() function */
926/**
927* Description: This function call initializes the specified radio.
928* Implementation specifics may dictate the functionality since
929* different hardware implementations may have different initilization requirements.
930* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
931*
932* @return The status of the operation.
933* @retval RETURN_OK if successful.
934* @retval RETURN_ERR if any error is detected
935*
936* @execution Synchronous.
937* @sideeffect None.
938*
939* @note This function must not suspend and must not invoke any blocking system
940* calls. It should probably just send a message to a driver event handler task.
941*
942*/
943INT wifi_initRadio(INT radioIndex)
944{
945 //TODO: Initializes the wifi subsystem (for specified radio)
946 return RETURN_OK;
947}
948void macfilter_init()
949{
950 char count[4]={'\0'};
951 char buf[253]={'\0'};
952 char tmp[19]={'\0'};
953 int dev_count,block,mac_entry=0;
954 char res[4]={'\0'};
955 char acl_file_path[64] = {'\0'};
956 FILE *fp = NULL;
957 int index=0;
958 char iface[10]={'\0'};
959 char config_file[MAX_BUF_SIZE] = {0};
960
961
962 sprintf(acl_file_path,"/tmp/mac_filter.sh");
963
964 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800965 if (fp == NULL) {
966 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
967 return RETURN_ERR;
968 }
developer06a01d92022-09-07 16:32:39 +0800969 sprintf(buf,"#!/bin/sh \n");
970 fprintf(fp,"%s\n",buf);
971
972 system("chmod 0777 /tmp/mac_filter.sh");
973
974 for(index=0;index<=1;index++)
975 {
976 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
977 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
978 sprintf(buf,"syscfg get %dcountfilter",index);
979 _syscmd(buf,count,sizeof(count));
980 mac_entry=atoi(count);
981
982 sprintf(buf,"syscfg get %dblockall",index);
983 _syscmd(buf,res,sizeof(res));
984 block = atoi(res);
985
986 //Allow only those macs mentioned in ACL
987 if(block==1)
988 {
989 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
990 fprintf(fp,"%s\n",buf);
991 for(dev_count=1;dev_count<=mac_entry;dev_count++)
992 {
993 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
994 _syscmd(buf,tmp,sizeof(tmp));
995 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
996 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
997 fprintf(fp,"%s\n",buf);
998 }
999 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1000 fprintf(fp,"%s\n",buf);
1001 }
1002
1003 //Block all the macs mentioned in ACL
1004 else if(block==2)
1005 {
1006 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1007 fprintf(fp,"%s\n",buf);
1008
1009 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1010 {
1011 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1012 _syscmd(buf,tmp,sizeof(tmp));
1013 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1014 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1015 fprintf(fp,"%s\n",buf);
1016 }
1017 }
1018 }
1019 fclose(fp);
1020}
1021
1022// Initializes the wifi subsystem (all radios)
1023INT wifi_init() //RDKB
1024{
1025 char interface[MAX_BUF_SIZE]={'\0'};
1026 char bridge_name[MAX_BUF_SIZE]={'\0'};
1027 INT len=0;
1028
1029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1030 //Not intitializing macfilter for Turris-Omnia Platform for now
1031 //macfilter_init();
1032
1033 system("/usr/sbin/iw reg set US");
1034 system("systemctl start hostapd.service");
1035 sleep(2);//sleep to wait for hostapd to start
1036
1037 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1038
1039 return RETURN_OK;
1040}
1041
1042/* wifi_reset() function */
1043/**
1044* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1045* Implementation specifics may dictate what is actualy reset since
1046* different hardware implementations may have different requirements.
1047* Parameters : None
1048*
1049* @return The status of the operation.
1050* @retval RETURN_OK if successful.
1051* @retval RETURN_ERR if any error is detected
1052*
1053* @execution Synchronous.
1054* @sideeffect None.
1055*
1056* @note This function must not suspend and must not invoke any blocking system
1057* calls. It should probably just send a message to a driver event handler task.
1058*
1059*/
1060INT wifi_reset()
1061{
1062 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001063 system("systemctl stop hostapd.service");
1064 sleep(2);
1065 system("systemctl start hostapd.service");
1066 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001067 return RETURN_OK;
1068}
1069
1070/* wifi_down() function */
1071/**
1072* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1073* Implementation specifics may dictate some functionality since
1074* different hardware implementations may have different requirements.
1075*
1076* @param None
1077*
1078* @return The status of the operation
1079* @retval RETURN_OK if successful
1080* @retval RETURN_ERR if any error is detected
1081*
1082* @execution Synchronous
1083* @sideeffect None
1084*
1085* @note This function must not suspend and must not invoke any blocking system
1086* calls. It should probably just send a message to a driver event handler task.
1087*
1088*/
1089INT wifi_down()
1090{
1091 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001092 system("systemctl stop hostapd.service");
1093 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001094 return RETURN_OK;
1095}
1096
1097
1098/* wifi_createInitialConfigFiles() function */
1099/**
1100* @description This function creates wifi configuration files. The format
1101* and content of these files are implementation dependent. This function call is
1102* used to trigger this task if necessary. Some implementations may not need this
1103* function. If an implementation does not need to create config files the function call can
1104* do nothing and return RETURN_OK.
1105*
1106* @param None
1107*
1108* @return The status of the operation
1109* @retval RETURN_OK if successful
1110* @retval RETURN_ERR if any error is detected
1111*
1112* @execution Synchronous
1113* @sideeffect None
1114*
1115* @note This function must not suspend and must not invoke any blocking system
1116* calls. It should probably just send a message to a driver event handler task.
1117*
1118*/
1119INT wifi_createInitialConfigFiles()
1120{
1121 //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)
1122 return RETURN_OK;
1123}
1124
1125// outputs the country code to a max 64 character string
1126INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1127{
developerd946fd62022-12-08 18:03:28 +08001128 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001129 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001130 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001131 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001132
developerd946fd62022-12-08 18:03:28 +08001133 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1134 return RETURN_ERR;
1135 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001136 _syscmd(cmd, buf, sizeof(buf));
1137 if(strlen(buf) > 0)
1138 snprintf(output_string, 64, "%s", buf);
1139 else
1140 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001141
1142 return RETURN_OK;
1143}
1144
1145INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1146{
1147 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001148 char str[MAX_BUF_SIZE]={'\0'};
1149 char cmd[MAX_CMD_SIZE]={'\0'};
1150 struct params params;
1151 char config_file[MAX_BUF_SIZE] = {0};
1152
1153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1154 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1155 return RETURN_ERR;
1156
developerb86c6f32022-10-07 14:34:58 +08001157 if (strlen(CountryCode) == 0)
1158 strcpy(CountryCode, "US");
1159
developer7543b3b2022-09-13 13:47:17 +08001160 params.name = "country_code";
1161 params.value = CountryCode;
1162 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1163 int ret = wifi_hostapdWrite(config_file, &params, 1);
1164 if (ret) {
1165 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1166 ,__func__, ret);
1167 }
1168
1169 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1170 if (ret) {
1171 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1172 ,__func__, ret);
1173 }
developer7543b3b2022-09-13 13:47:17 +08001174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1175
developer06a01d92022-09-07 16:32:39 +08001176 return RETURN_OK;
1177}
1178
developera748dcf2022-09-13 15:56:48 +08001179INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1180{
developerd946fd62022-12-08 18:03:28 +08001181 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001182 char channel_util_file[64] = {0};
1183 char cmd[128] = {0};
1184 char buf[128] = {0};
1185 char line[128] = {0};
1186 char *param = NULL, *value = NULL;
1187 int read = 0;
1188 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1189 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1190 size_t len = 0;
1191 FILE *f = NULL;
1192
1193 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1194
developerd946fd62022-12-08 18:03:28 +08001195 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1196 return RETURN_ERR;
1197 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001198 _syscmd(cmd, buf, sizeof(buf));
1199 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1200
1201 memset(cmd, 0, sizeof(cmd));
1202 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001203 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001204 if ((f = popen(cmd, "r")) == NULL) {
1205 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1206 return RETURN_ERR;
1207 }
1208
1209 read = getline(&line, &len, f);
1210 while (read != -1) {
1211 param = strtok(line, ":\t");
1212 value = strtok(NULL, " ");
1213 if(strstr(param, "frequency") != NULL) {
1214 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1215 }
1216 if(strstr(param, "noise") != NULL) {
1217 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1218 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1219 }
1220 if(strstr(param, "channel active time") != NULL) {
1221 ActiveTime = strtol(value, NULL, 10);
1222 }
1223 if(strstr(param, "channel busy time") != NULL) {
1224 BusyTime = strtol(value, NULL, 10);
1225 }
1226 if(strstr(param, "channel transmit time") != NULL) {
1227 TransmitTime = strtol(value, NULL, 10);
1228 }
1229 read = getline(&line, &len, f);
1230 }
1231 pclose(f);
1232
1233 // The file should store the last active, busy and transmit time
1234 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1235 f = fopen(channel_util_file, "r");
1236 if (f != NULL) {
1237 read = getline(&line, &len, f);
1238 preActiveTime = strtol(line, NULL, 10);
1239 read = getline(&line, &len, f);
1240 preBusyTime = strtol(line, NULL, 10);
1241 read = getline(&line, &len, f);
1242 preTransmitTime = strtol(line, NULL, 10);
1243 fclose(f);
1244 }
1245
1246 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1247 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1248
1249 f = fopen(channel_util_file, "w");
1250 if (f != NULL) {
1251 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1252 fclose(f);
1253 }
1254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1255 return RETURN_OK;
1256}
1257
developer06a01d92022-09-07 16:32:39 +08001258/**********************************************************************************
1259 *
1260 * Wifi radio level function prototypes
1261 *
1262**********************************************************************************/
1263
1264//Get the total number of radios in this wifi subsystem
1265INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1266{
1267 if (NULL == output)
1268 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001269 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001270
1271 return RETURN_OK;
1272}
1273
1274//Get the total number of SSID entries in this wifi subsystem
1275INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1276{
1277 if (NULL == output)
1278 return RETURN_ERR;
1279 *output = MAX_APS;
1280
1281 return RETURN_OK;
1282}
1283
1284//Get the Radio enable config parameter
1285INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1286{
developerd946fd62022-12-08 18:03:28 +08001287 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001288 char interface_path[MAX_CMD_SIZE] = {0};
1289 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001290 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001291
1292 if (NULL == output_bool)
1293 return RETURN_ERR;
1294
1295 *output_bool = FALSE;
developer804c64f2022-10-19 13:54:40 +08001296 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001297 return RETURN_ERR;
1298
developer033b37b2022-10-18 11:27:46 +08001299 phyId = radio_index_to_phy(radioIndex);
1300
1301 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001302 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001303 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001304 {
developercf48e482022-09-13 14:49:50 +08001305 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001306 }
developerd946fd62022-12-08 18:03:28 +08001307 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001308 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001309 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
developerd946fd62022-12-08 18:03:28 +08001310 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1311 return RETURN_ERR;
1312 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
developercf48e482022-09-13 14:49:50 +08001313 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001314
developercf48e482022-09-13 14:49:50 +08001315 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1316 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08001317 return RETURN_OK;
1318}
1319
1320INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1321{
developerd946fd62022-12-08 18:03:28 +08001322 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001323 char cmd[MAX_CMD_SIZE] = {0};
1324 char buf[MAX_CMD_SIZE] = {0};
1325 int apIndex, ret;
1326 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001327 int max_radio_num = 0;
1328 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001329
1330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001331
1332 phyId = radio_index_to_phy(radioIndex);
1333
1334 wifi_getMaxRadioNumber(&max_radio_num);
1335
developerd946fd62022-12-08 18:03:28 +08001336 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1337 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001338 if(enable==FALSE)
1339 {
developer033b37b2022-10-18 11:27:46 +08001340 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001341 {
1342 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001343 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001344 _syscmd(cmd, buf, sizeof(buf));
1345 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001346 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1347 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08001348 _syscmd(cmd, buf, sizeof(buf));
1349 }
developer033b37b2022-10-18 11:27:46 +08001350 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001351 _syscmd(cmd, buf, sizeof(buf));
1352 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001353 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001354 }
1355 else
1356 {
developer033b37b2022-10-18 11:27:46 +08001357 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001358 _syscmd(cmd, buf, sizeof(buf));
1359 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001360 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001361 sleep(1);
developer033b37b2022-10-18 11:27:46 +08001362
1363 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001364 {
developerd946fd62022-12-08 18:03:28 +08001365 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s type __ap", RADIO_PREFIX, phyId, interface_name);
developer06a01d92022-09-07 16:32:39 +08001366 ret = _syscmd(cmd, buf, sizeof(buf));
1367 if ( ret == RETURN_ERR)
1368 {
1369 fprintf(stderr, "VAP interface creation failed\n");
1370 continue;
1371 }
developerd946fd62022-12-08 18:03:28 +08001372 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001373 _syscmd(cmd, buf, sizeof(buf));
1374 if(*buf == '1')
1375 {
1376 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001377 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001378 _syscmd(cmd, buf, sizeof(buf));
1379 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001380 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001381 }
1382 }
1383 }
1384
1385 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1386 return RETURN_OK;
1387}
1388
1389//Get the Radio enable status
1390INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1391{
1392 if (NULL == output_bool)
1393 return RETURN_ERR;
1394
1395 return wifi_getRadioEnable(radioIndex, output_bool);
1396}
1397
1398//Get the Radio Interface name from platform, eg "wlan0"
1399INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1400{
developer033b37b2022-10-18 11:27:46 +08001401 int phyId = 0;
developer804c64f2022-10-19 13:54:40 +08001402 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001403 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08001404 phyId = radio_index_to_phy(radioIndex);
1405 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001406
1407 return RETURN_OK;
1408}
1409
1410//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1411//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.
1412INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1413{
developerbcc556a2022-09-22 20:02:45 +08001414 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1415 // For max bit rate, we should always choose the best MCS
1416 char mode[64] = {0};
1417 char channel_bandwidth_str[16] = {0};
1418 char *tmp = NULL;
1419 UINT mode_map = 0;
1420 UINT num_subcarrier = 0;
1421 UINT code_bits = 0;
1422 float code_rate = 0; // use max code rate
1423 int NSS = 0;
1424 UINT Symbol_duration = 0;
1425 UINT GI_duration = 0;
1426 wifi_band band = band_invalid;
1427 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1428 BOOL enable = FALSE;
1429 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001430
1431 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1432 if (NULL == output_string)
1433 return RETURN_ERR;
1434
developerbcc556a2022-09-22 20:02:45 +08001435 wifi_getRadioEnable(radioIndex, &enable);
1436 if (enable == FALSE) {
1437 snprintf(output_string, 64, "0 Mb/s");
1438 return RETURN_OK;
1439 }
1440
1441 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1442 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1443 return RETURN_ERR;
1444 }
1445
1446 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1447 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1448 return RETURN_ERR;
1449 }
1450
1451 if (gi == wifi_guard_interval_3200)
1452 GI_duration = 32;
1453 else if (gi == wifi_guard_interval_1600)
1454 GI_duration = 16;
1455 else if (gi == wifi_guard_interval_800)
1456 GI_duration = 8;
1457 else // auto, 400
1458 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001459
developerbcc556a2022-09-22 20:02:45 +08001460 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1461 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1462 return RETURN_ERR;
1463 }
1464
1465 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1466 strcpy(channel_bandwidth_str, "160");
1467
1468 if (mode_map & WIFI_MODE_AX) {
1469 if (strstr(channel_bandwidth_str, "160") != NULL)
1470 num_subcarrier = 1960;
1471 else if (strstr(channel_bandwidth_str, "80") != NULL)
1472 num_subcarrier = 980;
1473 else if (strstr(channel_bandwidth_str, "40") != NULL)
1474 num_subcarrier = 468;
1475 else if (strstr(channel_bandwidth_str, "20") != NULL)
1476 num_subcarrier = 234;
1477 code_bits = 10;
1478 code_rate = (float)5/6;
1479 Symbol_duration = 128;
1480 } else if (mode_map & WIFI_MODE_AC) {
1481 if (strstr(channel_bandwidth_str, "160") != NULL)
1482 num_subcarrier = 468;
1483 else if (strstr(channel_bandwidth_str, "80") != NULL)
1484 num_subcarrier = 234;
1485 else if (strstr(channel_bandwidth_str, "40") != NULL)
1486 num_subcarrier = 108;
1487 else if (strstr(channel_bandwidth_str, "20") != NULL)
1488 num_subcarrier = 52;
1489 code_bits = 8;
1490 code_rate = (float)5/6;
1491 Symbol_duration = 32;
1492 } else if (mode_map & WIFI_MODE_N) {
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 = 6;
1502 code_rate = (float)3/4;
1503 Symbol_duration = 32;
1504 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1505 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1506 snprintf(output_string, 64, "65 Mb/s");
1507 return RETURN_OK;
1508 } else {
1509 snprintf(output_string, 64, "0 Mb/s");
1510 return RETURN_OK;
1511 }
developer06a01d92022-09-07 16:32:39 +08001512
developerbcc556a2022-09-22 20:02:45 +08001513 // Spatial streams
1514 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1515 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1516 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001517 }
developerbcc556a2022-09-22 20:02:45 +08001518
1519 // multiple 10 is to align duration unit (0.1 us)
1520 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1521 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1522
developer06a01d92022-09-07 16:32:39 +08001523 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1524
1525 return RETURN_OK;
1526}
1527#if 0
1528INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1529{
1530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1531 char cmd[64];
1532 char buf[1024];
1533 int apIndex;
1534
1535 if (NULL == output_string)
1536 return RETURN_ERR;
1537
1538 apIndex=(radioIndex==0)?0:1;
1539
developerd946fd62022-12-08 18:03:28 +08001540 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001541 _syscmd(cmd,buf, sizeof(buf));
1542
1543 snprintf(output_string, 64, "%s", buf);
1544 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1545 return RETURN_OK;
1546}
1547#endif
1548
1549
1550//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1551//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.
1552INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1553{
developer963da0c2022-09-13 15:58:27 +08001554 wifi_band band = band_invalid;
1555
developer06a01d92022-09-07 16:32:39 +08001556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1557 if (NULL == output_string)
1558 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001559
1560 band = wifi_index_to_band(radioIndex);
1561
1562 memset(output_string, 0, 10);
1563 if (band == band_2_4)
1564 strcpy(output_string, "2.4GHz");
1565 else if (band == band_5)
1566 strcpy(output_string, "5GHz");
1567 else if (band == band_6)
1568 strcpy(output_string, "6GHz");
1569 else
1570 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1572
1573 return RETURN_OK;
1574#if 0
1575 char buf[MAX_BUF_SIZE]={'\0'};
1576 char str[MAX_BUF_SIZE]={'\0'};
1577 char cmd[MAX_CMD_SIZE]={'\0'};
1578 char *ch=NULL;
1579 char *ch2=NULL;
1580
1581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1582 if (NULL == output_string)
1583 return RETURN_ERR;
1584
1585
1586 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1587
1588 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1589 {
1590 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1591 return RETURN_ERR;
1592 }
1593 ch=strchr(buf,'\n');
1594 *ch='\0';
1595 ch=strchr(buf,'=');
1596 if(ch==NULL)
1597 return RETURN_ERR;
1598
1599
1600 ch++;
1601
1602 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1603 strcpy(buf,"0");
1604 if(strlen(ch) == 1)
1605 ch=strcat(buf,ch);
1606
1607
1608 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1609
1610 if(_syscmd(cmd,str,64) == RETURN_ERR)
1611 {
1612 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1613 return RETURN_ERR;
1614 }
1615
1616
1617 ch2=strchr(str,'\n');
1618 //replace \n with \0
1619 *ch2='\0';
1620 ch2=strchr(str,'=');
1621 if(ch2==NULL)
1622 {
1623 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1624 return RETURN_ERR;
1625 }
1626 else
1627 wifi_dbg_printf("%s",ch2+1);
1628
1629
1630 ch2++;
1631
1632
1633 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1634
1635 memset(buf,'\0',sizeof(buf));
1636 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1637 {
1638 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1639 return RETURN_ERR;
1640 }
1641 if (strstr(buf,"2.4") != NULL )
1642 strcpy(output_string,"2.4GHz");
1643 else if(strstr(buf,"5.") != NULL )
1644 strcpy(output_string,"5GHz");
1645 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1646
1647 return RETURN_OK;
1648#endif
1649}
1650
1651//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1652//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.
1653INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1654{
developerb7593de2022-10-18 09:51:57 +08001655 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1657 if (NULL == output_string)
1658 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001659 band = wifi_index_to_band(radioIndex);
1660
1661 if (band == band_2_4)
1662 snprintf(output_string, 64, "2.4GHz");
1663 else if (band == band_5)
1664 snprintf(output_string, 64, "5GHz");
1665 else if (band == band_6)
1666 snprintf(output_string, 64, "6GHz");
1667
developer06a01d92022-09-07 16:32:39 +08001668 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1669
1670 return RETURN_OK;
1671#if 0
1672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1673 char buf[MAX_BUF_SIZE]={'\0'};
1674 char str[MAX_BUF_SIZE]={'\0'};
1675 char cmd[MAX_CMD_SIZE]={'\0'};
1676 char *ch=NULL;
1677 char *ch2=NULL;
1678 char ch1[5]="0";
1679
1680 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1681
1682 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1683 {
1684 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1685 return RETURN_ERR;
1686 }
1687
1688 ch=strchr(buf,'\n');
1689 *ch='\0';
1690 ch=strchr(buf,'=');
1691 if(ch==NULL)
1692 return RETURN_ERR;
1693 ch++;
1694
1695 if(strlen(ch)==1)
1696 {
1697 strcat(ch1,ch);
1698
1699 }
1700 else
1701 {
1702 strcpy(ch1,ch);
1703 }
1704
1705
1706
1707 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1708 if(_syscmd(cmd,str,64) == RETURN_ERR)
1709 {
1710 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1711 return RETURN_ERR;
1712 }
1713
1714
1715 ch2=strchr(str,'\n');
1716 //replace \n with \0
1717 *ch2='\0';
1718 ch2=strchr(str,'=');
1719 if(ch2==NULL)
1720 {
1721 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1722 return RETURN_ERR;
1723 }
1724 else
1725 wifi_dbg_printf("%s",ch2+1);
1726 ch2++;
1727
1728
1729 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1730 memset(buf,'\0',sizeof(buf));
1731 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1732 {
1733 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1734 return RETURN_ERR;
1735 }
1736
1737
1738 if(strstr(buf,"2.4")!=NULL)
1739 {
1740 strcpy(output_string,"2.4GHz");
1741 }
1742 if(strstr(buf,"5.")!=NULL)
1743 {
1744 strcpy(output_string,"5GHz");
1745 }
1746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1747 return RETURN_OK;
1748#endif
1749}
1750
1751//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1752//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.
1753INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1754{
developer963da0c2022-09-13 15:58:27 +08001755 char cmd[128]={0};
1756 char buf[128]={0};
1757 char temp_output[128] = {0};
1758 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001759 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001760
1761 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001762 if (NULL == output_string)
1763 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001764
1765 band = wifi_index_to_band(radioIndex);
1766 if (band == band_2_4) {
1767 strcat(temp_output, "b,g,");
1768 } else if (band == band_5) {
1769 strcat(temp_output, "a,");
1770 }
developer033b37b2022-10-18 11:27:46 +08001771 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001772 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001773 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 +08001774 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001775 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001776 strcat(temp_output, "n,");
1777 }
developer06a01d92022-09-07 16:32:39 +08001778
developer963da0c2022-09-13 15:58:27 +08001779 // vht capabilities
1780 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001781 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 +08001782 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001783 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001784 strcat(temp_output, "ac,");
1785 }
1786 }
1787
1788 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001789 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 +08001790 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001791 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001792 strcat(temp_output, "ax,");
1793 }
1794
1795 // Remove the last comma
1796 if (strlen(temp_output) != 0)
1797 temp_output[strlen(temp_output)-1] = '\0';
1798 strncpy(output_string, temp_output, strlen(temp_output));
1799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001800 return RETURN_OK;
1801}
1802
1803//Get the radio operating mode, and pure mode flag. eg: "ac"
1804//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.
1805INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1806{
1807 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1808 if (NULL == output_string)
1809 return RETURN_ERR;
1810
1811 if (radioIndex == 0) {
1812 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1813 *gOnly = FALSE;
1814 *nOnly = TRUE;
1815 *acOnly = FALSE;
1816 } else {
1817 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1818 *gOnly = FALSE;
1819 *nOnly = FALSE;
1820 *acOnly = FALSE;
1821 }
1822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1823
1824 return RETURN_OK;
1825#if 0
1826 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1827 char buf[64] = {0};
1828 char config_file[MAX_BUF_SIZE] = {0};
1829
1830 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1831 return RETURN_ERR;
1832
1833 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1834 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1835
1836 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1837 if (strlen(buf) == 0)
1838 {
1839 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1840 return RETURN_ERR;
1841 }
1842 if(strcmp(buf,"g")==0)
1843 {
1844 wifi_dbg_printf("\nG\n");
1845 *gOnly=TRUE;
1846 *nOnly=FALSE;
1847 *acOnly=FALSE;
1848 }
1849 else if(strcmp(buf,"n")==0)
1850 {
1851 wifi_dbg_printf("\nN\n");
1852 *gOnly=FALSE;
1853 *nOnly=TRUE;
1854 *acOnly=FALSE;
1855 }
1856 else if(strcmp(buf,"ac")==0)
1857 {
1858 wifi_dbg_printf("\nac\n");
1859 *gOnly=FALSE;
1860 *nOnly=FALSE;
1861 *acOnly=TRUE;
1862 }
1863 /* hostapd-5G.conf has "a" as hw_mode */
1864 else if(strcmp(buf,"a")==0)
1865 {
1866 wifi_dbg_printf("\na\n");
1867 *gOnly=FALSE;
1868 *nOnly=FALSE;
1869 *acOnly=FALSE;
1870 }
1871 else
1872 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1873
1874 //for a,n mode
1875 if(radioIndex == 1)
1876 {
1877 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1878 if(strcmp(buf,"1")==0)
1879 {
1880 strncpy(output_string, "n", 1);
1881 *nOnly=FALSE;
1882 }
1883 }
1884
1885 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1886 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1887 return RETURN_OK;
1888#endif
1889}
1890
developerdb744382022-09-13 15:34:54 +08001891INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1892{
1893 char cmd[128] = {0};
1894 char buf[64] = {0};
1895 char config_file[64] = {0};
1896 wifi_band band;
1897
1898 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1899 if(NULL == output_string || NULL == pureMode)
1900 return RETURN_ERR;
1901
1902 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001903 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerdb744382022-09-13 15:34:54 +08001904 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1905 _syscmd(cmd, buf, sizeof(buf));
1906
1907 band = wifi_index_to_band(radioIndex);
1908 // puremode is a bit map
1909 *pureMode = 0;
1910 if (band == band_2_4) {
1911 strcat(output_string, "b,g");
1912 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1913 if (strstr(buf, "n") != NULL) {
1914 strcat(output_string, ",n");
1915 *pureMode |= WIFI_MODE_N;
1916 }
1917 if (strstr(buf, "ax") != NULL) {
1918 strcat(output_string, ",ax");
1919 *pureMode |= WIFI_MODE_AX;
1920 }
1921 } else if (band == band_5) {
1922 strcat(output_string, "a");
1923 *pureMode |= WIFI_MODE_A;
1924 if (strstr(buf, "n") != NULL) {
1925 strcat(output_string, ",n");
1926 *pureMode |= WIFI_MODE_N;
1927 }
1928 if (strstr(buf, "ac") != NULL) {
1929 strcat(output_string, ",ac");
1930 *pureMode |= WIFI_MODE_AC;
1931 }
1932 if (strstr(buf, "ax") != NULL) {
1933 strcat(output_string, ",ax");
1934 *pureMode |= WIFI_MODE_AX;
1935 }
1936 } else if (band == band_6) {
1937 if (strstr(buf, "ax") != NULL) {
1938 strcat(output_string, "ax");
1939 *pureMode |= WIFI_MODE_AX;
1940 }
1941 }
1942
1943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1944 return RETURN_OK;
1945}
1946
1947// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001948INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1949{
1950 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1951 if (strcmp (channelMode,"11A") == 0)
1952 {
1953 writeBandWidth(radioIndex,"20MHz");
1954 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1955 printf("\nChannel Mode is 802.11a (5GHz)\n");
1956 }
1957 else if (strcmp (channelMode,"11NAHT20") == 0)
1958 {
1959 writeBandWidth(radioIndex,"20MHz");
1960 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1961 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1962 }
1963 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1964 {
1965 writeBandWidth(radioIndex,"40MHz");
1966 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1967 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1968 }
1969 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1970 {
1971 writeBandWidth(radioIndex,"40MHz");
1972 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1973 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1974 }
1975 else if (strcmp (channelMode,"11ACVHT20") == 0)
1976 {
1977 writeBandWidth(radioIndex,"20MHz");
1978 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1979 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1980 }
1981 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1982 {
1983 writeBandWidth(radioIndex,"40MHz");
1984 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1985 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1986 }
1987 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1988 {
1989 writeBandWidth(radioIndex,"40MHz");
1990 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1991 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1992 }
1993 else if (strcmp (channelMode,"11ACVHT80") == 0)
1994 {
1995 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1996 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1997 }
1998 else if (strcmp (channelMode,"11ACVHT160") == 0)
1999 {
2000 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2001 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2002 }
2003 else if (strcmp (channelMode,"11B") == 0)
2004 {
2005 writeBandWidth(radioIndex,"20MHz");
2006 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2007 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2008 }
2009 else if (strcmp (channelMode,"11G") == 0)
2010 {
2011 writeBandWidth(radioIndex,"20MHz");
2012 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2013 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2014 }
2015 else if (strcmp (channelMode,"11NGHT20") == 0)
2016 {
2017 writeBandWidth(radioIndex,"20MHz");
2018 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2019 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2020 }
2021 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2022 {
2023 writeBandWidth(radioIndex,"40MHz");
2024 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2025 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2026 }
2027 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2028 {
2029 writeBandWidth(radioIndex,"40MHz");
2030 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2031 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2032 }
2033 else
2034 {
2035 return RETURN_ERR;
2036 }
2037 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2038
2039 return RETURN_OK;
2040}
2041
developerdb744382022-09-13 15:34:54 +08002042// Set the radio operating mode, and pure mode flag.
2043INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2044{
2045 int num_hostapd_support_mode = 3; // n, ac, ax
2046 struct params list[num_hostapd_support_mode];
2047 char config_file[64] = {0};
2048 char bandwidth[16] = {0};
2049 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002050
developerdb744382022-09-13 15:34:54 +08002051
2052 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2053 // Set radio mode
2054 list[0].name = "ieee80211n";
2055 list[1].name = "ieee80211ac";
2056 list[2].name = "ieee80211ax";
2057 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2058
2059 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002060 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002061 list[0].value = "1";
2062 else
2063 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002064 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002065 list[1].value = "1";
2066 else
2067 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002068 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002069 list[2].value = "1";
2070 else
2071 list[2].value = "0";
2072 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2073
2074 if (channelMode == NULL || strlen(channelMode) == 0)
2075 return RETURN_OK;
2076 // Set bandwidth
2077 if (strstr(channelMode, "40") != NULL)
2078 strcpy(bandwidth, "40MHz");
2079 else if (strstr(channelMode, "80") != NULL)
2080 strcpy(bandwidth, "80MHz");
2081 else if (strstr(channelMode, "160") != NULL)
2082 strcpy(bandwidth, "160MHz");
2083 else // 11A, 11B, 11G....
2084 strcpy(bandwidth, "20MHz");
2085
2086 writeBandWidth(radioIndex, bandwidth);
2087 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2088
2089 wifi_reloadAp(radioIndex);
2090 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2091
2092 return RETURN_OK;
2093}
2094
developer1d12ebf2022-10-04 15:13:38 +08002095INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2096
2097 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002098 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002099 struct params params = {0};
2100 wifi_band band = band_invalid;
2101
2102 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2103
2104 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002105
2106 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002107 return RETURN_ERR;
2108 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2109 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002110 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2111 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002112
2113 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2114 params.name = "hw_mode";
2115 params.value = hw_mode;
2116 wifi_hostapdWrite(config_file, &params, 1);
2117 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2118
developeref938762022-10-19 17:21:01 +08002119 if (band == band_2_4) {
2120 if (strncmp(hw_mode, "b", 1) == 0) {
2121 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2122 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2123 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2124 snprintf(buf, sizeof(buf), "%s", "1,2");
2125 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2126 } else {
2127 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2128
2129 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2130 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2131 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2132 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2133 }
2134 }
2135
developer1d12ebf2022-10-04 15:13:38 +08002136 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2137 return RETURN_OK;
2138}
2139
developere8988ba2022-10-18 17:42:30 +08002140INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2141{
2142 char config_file[64] = {0};
2143 struct params params = {0};
2144 wifi_band band = band_invalid;
2145
2146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2147
2148 band = wifi_index_to_band(radioIndex);
developer30423732022-12-01 16:17:49 +08002149 if (band != band_2_4)
2150 return RETURN_OK;
developere8988ba2022-10-18 17:42:30 +08002151
2152 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2153 params.name = "noscan";
2154 params.value = noscan;
2155 wifi_hostapdWrite(config_file, &params, 1);
2156 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2157
2158 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2159 return RETURN_OK;
2160}
2161
developer06a01d92022-09-07 16:32:39 +08002162//Get the list of supported channel. eg: "1-11"
2163//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.
2164INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2165{
developer6318ed52022-09-13 15:17:58 +08002166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002167 if (NULL == output_string)
2168 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002169 char cmd[256] = {0};
2170 char buf[128] = {0};
2171 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002172 int phyId = 0;
2173
developer6318ed52022-09-13 15:17:58 +08002174 // Parse possible channel number and separate them with commas.
2175 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002176 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002177 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002178 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002179 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 +08002180 else
developer033b37b2022-10-18 11:27:46 +08002181 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 +08002182
2183 _syscmd(cmd,buf,sizeof(buf));
2184 strncpy(output_string, buf, sizeof(buf));
2185
2186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2187 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002188}
2189
2190//Get the list for used channel. eg: "1,6,9,11"
2191//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.
2192INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2193{
developerd946fd62022-12-08 18:03:28 +08002194 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002195 char cmd[128] = {0};
2196 char buf[128] = {0};
2197 char config_file[64] = {0};
2198 int channel = 0;
2199 int freq = 0;
2200 int bandwidth = 0;
2201 int center_freq = 0;
2202 int center_channel = 0;
2203 int channel_delta = 0;
2204 wifi_band band = band_invalid;
2205
2206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2207
developer06a01d92022-09-07 16:32:39 +08002208 if (NULL == output_string)
2209 return RETURN_ERR;
2210
developerd946fd62022-12-08 18:03:28 +08002211 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2212 return RETURN_ERR;
2213 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002214 _syscmd(cmd, buf, sizeof(buf));
2215 if (strlen(buf) == 0) {
2216 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2217 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002218 }
developerf5745ee2022-10-05 16:09:53 +08002219 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2220
2221 if (bandwidth == 20) {
2222 snprintf(output_string, 256, "%d", channel);
2223 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002224 }
developerf5745ee2022-10-05 16:09:53 +08002225
2226 center_channel = ieee80211_frequency_to_channel(center_freq);
2227
2228 band = wifi_index_to_band(radioIndex);
2229 if (band == band_2_4 && bandwidth == 40) {
2230 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2231 memset(buf, 0, sizeof(buf));
2232 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2233
2234 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2235 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2236 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2237 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2238 } else {
2239 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2240 return RETURN_ERR;
2241 }
2242 } else if (band == band_5 || band == band_6){
2243 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2244 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2245 channel_delta = (bandwidth-20)/10;
2246 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2247 } else
2248 return RETURN_ERR;
2249
2250 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002251 return RETURN_OK;
2252}
2253
2254//Get the running channel number
2255INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2256{
developer5b398df2022-11-17 20:39:48 +08002257 char channel_str[16] = {0};
2258 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002259
developer5b398df2022-11-17 20:39:48 +08002260 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002261 return RETURN_ERR;
2262
developer5b398df2022-11-17 20:39:48 +08002263 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2264 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002265
developer5b398df2022-11-17 20:39:48 +08002266 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002267
developer06a01d92022-09-07 16:32:39 +08002268 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002269}
2270
2271
2272INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2273{
2274 char cmd[1024] = {0}, buf[5] = {0};
2275 char interface_name[50] = {0};
2276
2277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2278 if (NULL == output_ulong)
2279 return RETURN_ERR;
2280
developer06a01d92022-09-07 16:32:39 +08002281 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerd946fd62022-12-08 18:03:28 +08002282 wifi_getApName(apIndex,interface_name);
developer06a01d92022-09-07 16:32:39 +08002283 _syscmd(cmd,buf,sizeof(buf));
2284 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2285 if (*output_ulong == 0) {
2286 return RETURN_ERR;
2287 }
2288
2289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2290 return RETURN_OK;
2291}
2292
2293//Storing the previous channel value
2294INT wifi_storeprevchanval(INT radioIndex)
2295{
2296 char buf[256] = {0};
2297 char output[4]={'\0'};
2298 char config_file[MAX_BUF_SIZE] = {0};
2299 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2300 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2301 if(radioIndex == 0)
2302 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2303 else if(radioIndex == 1)
2304 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2305 system(buf);
2306 Radio_flag = FALSE;
2307 return RETURN_OK;
2308}
2309
2310//Set the running channel number
2311INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2312{
developer76989232022-10-04 14:13:19 +08002313 // We only write hostapd config here
2314 char str_channel[8]={0};
2315 char *list_channel;
2316 char config_file[128] = {0};
2317 char possible_channels[256] = {0};
2318 int max_radio_num = 0;
2319 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002320
developer76989232022-10-04 14:13:19 +08002321 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002322
developer76989232022-10-04 14:13:19 +08002323 // Check valid
2324 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002325
developer76989232022-10-04 14:13:19 +08002326 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2327 list_channel = strtok(possible_channels, ",");
2328 while(true)
developer06a01d92022-09-07 16:32:39 +08002329 {
developer76989232022-10-04 14:13:19 +08002330 if(list_channel == NULL) { // input not in the list
2331 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2332 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002333 }
developer76989232022-10-04 14:13:19 +08002334 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2335 break;
2336 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002337 }
2338
developer76989232022-10-04 14:13:19 +08002339 list.name = "channel";
2340 list.value = str_channel;
2341 wifi_getMaxRadioNumber(&max_radio_num);
2342 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002343 {
developer76989232022-10-04 14:13:19 +08002344 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2345 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002346 }
2347
developer76989232022-10-04 14:13:19 +08002348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002349 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002350}
developer06a01d92022-09-07 16:32:39 +08002351
2352INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2353{
developer76989232022-10-04 14:13:19 +08002354 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002355 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002356 char config_file[64];
2357 int max_num_radios = 0;
2358 wifi_band band = band_invalid;
2359
2360 band = wifi_index_to_band(radioIndex);
2361 if (band == band_2_4)
2362 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002363
developer30423732022-12-01 16:17:49 +08002364 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002365 list[0].name = "vht_oper_centr_freq_seg0_idx";
2366 list[0].value = str_idx;
2367 list[1].name = "he_oper_centr_freq_seg0_idx";
2368 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002369
developer76989232022-10-04 14:13:19 +08002370 wifi_getMaxRadioNumber(&max_num_radios);
2371 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002372 {
developer76989232022-10-04 14:13:19 +08002373 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2374 if (band == band_6)
2375 wifi_hostapdWrite(config_file, &list[1], 1);
2376 else
2377 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002378 }
2379
2380 return RETURN_OK;
2381}
2382
2383//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2384//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2385INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2386{
2387 //Set to wifi config only. Wait for wifi reset to apply.
2388 char buf[256] = {0};
2389 char str_channel[256] = {0};
2390 int count = 0;
2391 ULONG Value = 0;
2392 FILE *fp = NULL;
2393 if(enable == TRUE)
2394 {
developer06a01d92022-09-07 16:32:39 +08002395 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002396 }
developer5884e982022-10-06 10:52:50 +08002397 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002398}
2399
developer0b246d12022-09-30 15:24:20 +08002400INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2401{
2402 if (output_bool == NULL)
2403 return RETURN_ERR;
2404
2405 *output_bool = TRUE;
2406
2407 return RETURN_OK;
2408}
2409
developer06a01d92022-09-07 16:32:39 +08002410INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2411{
2412 if (NULL == output_bool)
2413 return RETURN_ERR;
2414 *output_bool=FALSE;
2415 return RETURN_OK;
2416}
2417
2418INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2419{
2420 if (NULL == output_bool)
2421 return RETURN_ERR;
2422 *output_bool=FALSE;
2423 return RETURN_OK;
2424}
2425
2426INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2427{
2428 //Set to wifi config only. Wait for wifi reset to apply.
2429 return RETURN_OK;
2430}
2431
2432INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2433{
2434 return RETURN_OK;
2435}
2436
2437INT wifi_factoryResetAP(int apIndex)
2438{
developer838cca92022-10-03 13:19:57 +08002439 char ap_config_file[64] = {0};
2440 char cmd[128] = {0};
2441
developer06a01d92022-09-07 16:32:39 +08002442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002443
2444 wifi_setApEnable(apIndex, FALSE);
2445 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2446 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2447 wifi_setApEnable(apIndex, TRUE);
2448
developer06a01d92022-09-07 16:32:39 +08002449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002450
developer06a01d92022-09-07 16:32:39 +08002451 return RETURN_OK;
2452}
2453
2454//To set Band Steering AP group
2455//To-do
2456INT wifi_setBandSteeringApGroup(char *ApGroup)
2457{
2458 return RETURN_OK;
2459}
2460
developer1e5aa162022-09-13 16:06:24 +08002461INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2462{
2463 char config_file[128] = {'\0'};
2464 char buf[128] = {'\0'};
2465
2466 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2467 if (dtimInterval == NULL)
2468 return RETURN_ERR;
2469
2470 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2471 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2472
2473 if (strlen(buf) == 0) {
2474 *dtimInterval = 2;
2475 } else {
2476 *dtimInterval = strtoul(buf, NULL, 10);
2477 }
2478
2479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2480 return RETURN_OK;
2481}
2482
developer06a01d92022-09-07 16:32:39 +08002483INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2484{
developer5f222492022-09-13 15:21:52 +08002485 struct params params={0};
2486 char config_file[MAX_BUF_SIZE] = {'\0'};
2487 char buf[MAX_BUF_SIZE] = {'\0'};
2488
2489 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2490 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002491 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002492 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002493 }
2494
2495 params.name = "dtim_period";
2496 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2497 params.value = buf;
2498
2499 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2500 wifi_hostapdWrite(config_file, &params, 1);
2501 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2502
2503 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2504 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002505}
2506
2507//Check if the driver support the Dfs
2508INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2509{
developer78a15382022-11-02 10:57:40 +08002510 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002511 if (NULL == output_bool)
2512 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002513 *output_bool=FALSE;
2514
2515 band = wifi_index_to_band(radioIndex);
2516 if (band == band_5)
2517 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002518 return RETURN_OK;
2519}
2520
2521//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.
2522//The value of this parameter is a comma seperated list of channel number
2523INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2524{
2525 if (NULL == output_pool)
2526 return RETURN_ERR;
2527 if (radioIndex==1)
2528 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2529 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2530
2531 return RETURN_OK;
2532}
2533
2534INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2535{
2536 //Set to wifi config. And apply instantly.
2537 return RETURN_OK;
2538}
2539
2540INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2541{
2542 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2543 return RETURN_ERR;
2544 *output_interval_seconds=1800;
2545 *output_dwell_milliseconds=40;
2546
2547 return RETURN_OK;
2548}
2549
2550INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2551{
2552 //Set to wifi config. And apply instantly.
2553 return RETURN_OK;
2554}
2555
developerbfc18512022-10-05 17:54:28 +08002556INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2557{
2558 if (output_bool == NULL)
2559 return RETURN_ERR;
2560 *output_bool = true;
2561 return RETURN_OK;
2562}
2563
2564INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2565{
2566 return RETURN_OK;
2567}
2568
developer06a01d92022-09-07 16:32:39 +08002569//Get the Dfs enable status
2570INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2571{
developer9964b5b2022-09-13 15:59:34 +08002572 char buf[16] = {0};
2573 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002574
2575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2576
developer30423732022-12-01 16:17:49 +08002577 if (output_bool == NULL)
2578 return RETURN_ERR;
2579
developer9964b5b2022-09-13 15:59:34 +08002580 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002581 if (NULL == output_bool)
2582 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002583
developer9964b5b2022-09-13 15:59:34 +08002584 f = fopen(DFS_ENABLE_FILE, "r");
2585 if (f != NULL) {
2586 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002587 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002588 *output_bool = FALSE;
2589 fclose(f);
2590 }
2591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002592 return RETURN_OK;
2593}
2594
2595//Set the Dfs enable status
2596INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2597{
developer9964b5b2022-09-13 15:59:34 +08002598 char config_file[128] = {0};
2599 FILE *f = NULL;
2600 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002601
2602 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2603
developer9964b5b2022-09-13 15:59:34 +08002604 f = fopen(DFS_ENABLE_FILE, "w");
2605 if (f == NULL)
2606 return RETURN_ERR;
2607 fprintf(f, "%d", enable);
2608 fclose(f);
2609
2610 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002611 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002612 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2613 wifi_hostapdWrite(config_file, &params, 1);
2614 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2615
2616 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2617
developer9964b5b2022-09-13 15:59:34 +08002618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002619 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002620}
2621
2622//Check if the driver support the AutoChannelRefreshPeriod
2623INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2624{
2625 if (NULL == output_bool)
2626 return RETURN_ERR;
2627 *output_bool=FALSE; //not support
2628
2629 return RETURN_OK;
2630}
2631
2632//Get the ACS refresh period in seconds
2633INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2634{
2635 if (NULL == output_ulong)
2636 return RETURN_ERR;
2637 *output_ulong=300;
2638
2639 return RETURN_OK;
2640}
2641
2642//Set the ACS refresh period in seconds
2643INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2644{
2645 return RETURN_ERR;
2646}
2647
2648//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2649//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.
2650INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2651{
developer70490032022-09-13 15:45:20 +08002652 char cmd[128] = {0}, buf[64] = {0};
2653 char interface_name[64] = {0};
2654 int ret = 0, len=0;
2655 BOOL radio_enable = FALSE;
2656
2657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2658
developer06a01d92022-09-07 16:32:39 +08002659 if (NULL == output_string)
2660 return RETURN_ERR;
2661
developer70490032022-09-13 15:45:20 +08002662 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2663 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002664
developer70490032022-09-13 15:45:20 +08002665 if (radio_enable != TRUE)
2666 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002667
developerd946fd62022-12-08 18:03:28 +08002668 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2669 return RETURN_ERR;
2670 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6", interface_name);
developer06a01d92022-09-07 16:32:39 +08002671 ret = _syscmd(cmd, buf, sizeof(buf));
2672 len = strlen(buf);
2673 if((ret != 0) || (len == 0))
2674 {
2675 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2676 return RETURN_ERR;
2677 }
2678
2679 buf[len-1] = '\0';
2680 snprintf(output_string, 64, "%sMHz", buf);
2681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2682
2683#if 0
2684 //TODO: revisit below implementation
2685 char output_buf[8]={0};
2686 char bw_value[10];
2687 char config_file[MAX_BUF_SIZE] = {0};
2688
2689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2690 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2691 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2692 readBandWidth(radioIndex,bw_value);
2693
2694 if(strstr (output_buf,"0") != NULL )
2695 {
2696 strcpy(output_string,bw_value);
2697 }
2698 else if (strstr (output_buf,"1") != NULL)
2699 {
2700 strcpy(output_string,"80MHz");
2701 }
2702 else if (strstr (output_buf,"2") != NULL)
2703 {
2704 strcpy(output_string,"160MHz");
2705 }
2706 else if (strstr (output_buf,"3") != NULL)
2707 {
2708 strcpy(output_string,"80+80");
2709 }
2710 else
2711 {
2712 strcpy(output_string,"Auto");
2713 }
2714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2715#endif
2716
2717 return RETURN_OK;
2718}
2719
2720//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002721INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002722{
developerf7a466e2022-09-29 11:55:56 +08002723 char config_file[128];
2724 char set_value[16];
2725 struct params params[2];
2726 int max_radio_num = 0;
2727
developer06a01d92022-09-07 16:32:39 +08002728 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002729
developerf7a466e2022-09-29 11:55:56 +08002730 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002731 return RETURN_ERR;
2732
developerf7a466e2022-09-29 11:55:56 +08002733 if(strstr(bandwidth,"80+80") != NULL)
2734 strcpy(set_value, "3");
2735 else if(strstr(bandwidth,"160") != NULL)
2736 strcpy(set_value, "2");
2737 else if(strstr(bandwidth,"80") != NULL)
2738 strcpy(set_value, "1");
2739 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2740 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002741 else
2742 {
developerf7a466e2022-09-29 11:55:56 +08002743 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002744 return RETURN_ERR;
2745 }
2746
developerf7a466e2022-09-29 11:55:56 +08002747 params[0].name = "vht_oper_chwidth";
2748 params[0].value = set_value;
2749 params[1].name = "he_oper_chwidth";
2750 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002751
developerf7a466e2022-09-29 11:55:56 +08002752 wifi_getMaxRadioNumber(&max_radio_num);
2753 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002754 {
developerf7a466e2022-09-29 11:55:56 +08002755 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2756 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002757 }
2758
2759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2760 return RETURN_OK;
2761}
2762
2763//Getting current radio extension channel
2764INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2765{
2766 CHAR buf[150] = {0};
2767 CHAR cmd[150] = {0};
2768 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2769 _syscmd(cmd, buf, sizeof(buf));
2770 if(NULL != strstr(buf,"HT40+"))
2771 strcpy(Value,"AboveControlChannel");
2772 else if(NULL != strstr(buf,"HT40-"))
2773 strcpy(Value,"BelowControlChannel");
2774 return RETURN_OK;
2775}
2776
2777//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2778//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.
2779INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2780{
2781 if (NULL == output_string)
2782 return RETURN_ERR;
2783
2784 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2785#if 0
2786 CHAR Value[100] = {0};
2787 if (NULL == output_string)
2788 return RETURN_ERR;
2789 if(radioIndex == 0)
2790 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2791 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2792 {
2793 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2794 if(strcmp(Value,"40MHz") == 0)
2795 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2796 else
2797 strcpy(Value,"Auto");
2798 }
2799 strcpy(output_string,Value);
2800#endif
2801
2802 return RETURN_OK;
2803}
2804
2805//Set the extension channel.
2806INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2807{
2808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2809 struct params params={'\0'};
2810 char config_file[MAX_BUF_SIZE] = {0};
2811 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002812 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002813 params.name = "ht_capab";
2814
developer033b37b2022-10-18 11:27:46 +08002815 if(NULL!= strstr(string,"Above"))
2816 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2817 else if(NULL!= strstr(string,"Below"))
2818 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2819 else
2820 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2821
developer06a01d92022-09-07 16:32:39 +08002822
2823 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002824
2825 wifi_getMaxRadioNumber(&max_radio_num);
2826 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002827 {
developer033b37b2022-10-18 11:27:46 +08002828 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002829 wifi_hostapdWrite(config_file, &params, 1);
2830 }
2831
2832 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2833 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2834 return RETURN_OK;
2835}
2836
2837//Get the guard interval value. eg "400nsec" or "800nsec"
2838//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.
2839INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2840{
developer454b9462022-09-13 15:29:16 +08002841 wifi_guard_interval_t GI;
2842
2843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2844
2845 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002846 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002847
2848 if (GI == wifi_guard_interval_400)
2849 strcpy(output_string, "400nsec");
2850 else if (GI == wifi_guard_interval_800)
2851 strcpy(output_string, "800nsec");
2852 else if (GI == wifi_guard_interval_1600)
2853 strcpy(output_string, "1600nsec");
2854 else if (GI == wifi_guard_interval_3200)
2855 strcpy(output_string, "3200nsec");
2856 else
developer78a15382022-11-02 10:57:40 +08002857 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002858
developer454b9462022-09-13 15:29:16 +08002859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002860 return RETURN_OK;
2861}
2862
2863//Set the guard interval value.
2864INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2865{
developer454b9462022-09-13 15:29:16 +08002866 wifi_guard_interval_t GI;
2867 int ret = 0;
2868
2869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2870
2871 if (strcmp(string, "400nsec") == 0)
2872 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002873 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002874 GI = wifi_guard_interval_800;
2875 else if (strcmp(string , "1600nsec") == 0)
2876 GI = wifi_guard_interval_1600;
2877 else if (strcmp(string , "3200nsec") == 0)
2878 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002879 else
2880 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002881
2882 ret = wifi_setGuardInterval(radioIndex, GI);
2883
2884 if (ret == RETURN_ERR) {
2885 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2886 return RETURN_ERR;
2887 }
2888
2889 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2890 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002891}
2892
2893//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2894INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2895{
developerf49437e2022-09-29 19:58:21 +08002896 char buf[32]={0};
2897 char mcs_file[64] = {0};
2898 char cmd[64] = {0};
2899 int mode_bitmap = 0;
2900
2901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2902 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002903 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002904 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2905
2906 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2907 _syscmd(cmd, buf, sizeof(buf));
2908 if (strlen(buf) > 0)
2909 *output_int = strtol(buf, NULL, 10);
2910 else {
2911 // output the max MCS for the current radio mode
2912 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2913 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2914 return RETURN_ERR;
2915 }
2916 if (mode_bitmap & WIFI_MODE_AX) {
2917 *output_int = 11;
2918 } else if (mode_bitmap & WIFI_MODE_AC) {
2919 *output_int = 9;
2920 } else if (mode_bitmap & WIFI_MODE_N) {
2921 *output_int = 7;
2922 }
2923 }
2924 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002925
2926 return RETURN_OK;
2927}
2928
2929//Set the Modulation Coding Scheme index
2930INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2931{
developerf49437e2022-09-29 19:58:21 +08002932 // 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).
2933 char config_file[64] = {0};
2934 char set_value[16] = {0};
2935 char mcs_file[32] = {0};
2936 wifi_band band = band_invalid;
2937 struct params set_config = {0};
2938 FILE *f = NULL;
2939
2940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2941
2942 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2943
developer78a15382022-11-02 10:57:40 +08002944 // -1 means auto
2945 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08002946 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2947 return RETURN_ERR;
2948 }
2949
developer78a15382022-11-02 10:57:40 +08002950 if (MCS > 9 || MCS == -1)
2951 strcpy(set_value, "2");
2952 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08002953 strcpy(set_value, "1");
2954 else
developer78a15382022-11-02 10:57:40 +08002955 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08002956
2957 set_config.name = "he_basic_mcs_nss_set";
2958 set_config.value = set_value;
2959
2960 wifi_hostapdWrite(config_file, &set_config, 1);
2961 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2962
2963 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2964 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2965 f = fopen(mcs_file, "w");
2966 if (f == NULL) {
2967 fprintf(stderr, "%s: fopen failed\n", __func__);
2968 return RETURN_ERR;
2969 }
2970 fprintf(f, "%d", MCS);
2971 fclose(f);
2972
2973 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2974 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002975}
2976
2977//Get supported Transmit Power list, eg : "0,25,50,75,100"
2978//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.
2979INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2980{
2981 if (NULL == output_list)
2982 return RETURN_ERR;
2983 snprintf(output_list, 64,"0,25,50,75,100");
2984 return RETURN_OK;
2985}
2986
developera5005b62022-09-13 15:43:35 +08002987//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002988//The transmite power level is in units of full power for this radio.
2989INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2990{
developerd946fd62022-12-08 18:03:28 +08002991 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002992 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002993 char buf[16]={0};
2994 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002995
developera5005b62022-09-13 15:43:35 +08002996 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002997 return RETURN_ERR;
2998
developerd946fd62022-12-08 18:03:28 +08002999 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3000 return RETURN_ERR;
3001 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 +08003002 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003003
developera5005b62022-09-13 15:43:35 +08003004 *output_ulong = strtol(buf, NULL, 10);
3005
3006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003007 return RETURN_OK;
3008}
3009
3010//Set Transmit Power
3011//The transmite power level is in units of full power for this radio.
3012INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3013{
developerd946fd62022-12-08 18:03:28 +08003014 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003015 char *support;
developer06a01d92022-09-07 16:32:39 +08003016 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003017 char buf[128]={0};
3018 char txpower_str[64] = {0};
3019 int txpower = 0;
3020 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08003021 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003022
3023 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003024
developerd946fd62022-12-08 18:03:28 +08003025 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3026 return RETURN_ERR;
3027 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 +08003028 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003029 maximum_tx = strtol(buf, NULL, 10);
3030
3031 // Get the Tx power supported list and check that is the input in the list
3032 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3033 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3034 support = strtok(buf, ",");
3035 while(true)
3036 {
3037 if(support == NULL) { // input not in the list
3038 wifi_dbg_printf("Input value is invalid.\n");
3039 return RETURN_ERR;
3040 }
3041 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3042 break;
3043 }
3044 support = strtok(NULL, ",");
3045 }
3046 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003047 phyId = radio_index_to_phy(radioIndex);
3048 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003049 _syscmd(cmd, buf, sizeof(buf));
3050 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003051
3052 return RETURN_OK;
3053}
3054
3055//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3056INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3057{
3058 if (NULL == Supported)
3059 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003060 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003061
3062 return RETURN_OK;
3063}
3064
3065//Get 80211h feature enable
3066INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3067{
developer3885fec2022-09-13 15:13:47 +08003068 char buf[64]={'\0'};
3069 char config_file[64] = {'\0'};
3070
3071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3072 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003073 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003074
3075 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3076 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003077
developer3885fec2022-09-13 15:13:47 +08003078 if (strncmp(buf, "1", 1) == 0)
3079 *enable = TRUE;
3080 else
3081 *enable = FALSE;
3082
3083 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003084 return RETURN_OK;
3085}
3086
3087//Set 80211h feature enable
3088INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3089{
developer3885fec2022-09-13 15:13:47 +08003090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3091 struct params params={'\0'};
3092 char config_file[MAX_BUF_SIZE] = {0};
3093
3094 params.name = "ieee80211h";
3095
3096 if (enable) {
3097 params.value = "1";
3098 } else {
3099 params.value = "0";
3100 }
3101
3102 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3103 wifi_hostapdWrite(config_file, &params, 1);
3104
3105 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3106 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3107 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003108}
3109
3110//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.
3111INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3112{
3113 if (NULL == output)
3114 return RETURN_ERR;
3115 *output=100;
3116
3117 return RETURN_OK;
3118}
3119
3120//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.
3121INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3122{
3123 if (NULL == output)
3124 return RETURN_ERR;
3125 *output = -99;
3126
3127 return RETURN_OK;
3128}
3129
3130INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3131{
3132 return RETURN_ERR;
3133}
3134
3135
3136//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3137INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3138{
developerd946fd62022-12-08 18:03:28 +08003139 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003140 char cmd[MAX_BUF_SIZE]={'\0'};
3141 char buf[MAX_CMD_SIZE]={'\0'};
3142
3143 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3144 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003145 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003146
developerd946fd62022-12-08 18:03:28 +08003147 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3148 return RETURN_ERR;
3149 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 +08003150 _syscmd(cmd, buf, sizeof(buf));
3151 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003152
developer5f222492022-09-13 15:21:52 +08003153 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003154 return RETURN_OK;
3155}
3156
3157INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3158{
developer5f222492022-09-13 15:21:52 +08003159 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3160 struct params params={'\0'};
3161 char buf[MAX_BUF_SIZE] = {'\0'};
3162 char config_file[MAX_BUF_SIZE] = {'\0'};
3163
developer5b398df2022-11-17 20:39:48 +08003164 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3165 return RETURN_ERR;
3166
developer5f222492022-09-13 15:21:52 +08003167 params.name = "beacon_int";
3168 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3169 params.value = buf;
3170
3171 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3172 wifi_hostapdWrite(config_file, &params, 1);
3173
3174 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3176 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003177}
3178
3179//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.
3180INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3181{
developer06a01d92022-09-07 16:32:39 +08003182 //TODO: need to revisit below implementation
3183 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003184 char temp_output[128] = {0};
3185 char temp_TransmitRates[64] = {0};
3186 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003187
3188 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3189 if (NULL == output)
3190 return RETURN_ERR;
3191 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003192 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3193
3194 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3195 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3196 } else {
3197 temp = strtok(temp_TransmitRates," ");
3198 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003199 {
developere9d0abd2022-09-13 15:40:57 +08003200 // Convert 100 kbps to Mbps
3201 temp[strlen(temp)-1]=0;
3202 if((temp[0]=='5') && (temp[1]=='\0'))
3203 {
3204 temp="5.5";
3205 }
3206 strcat(temp_output,temp);
3207 temp = strtok(NULL," ");
3208 if(temp!=NULL)
3209 {
3210 strcat(temp_output,",");
3211 }
developer06a01d92022-09-07 16:32:39 +08003212 }
developere9d0abd2022-09-13 15:40:57 +08003213 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003214 }
developer06a01d92022-09-07 16:32:39 +08003215 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003216 return RETURN_OK;
3217}
3218
3219INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3220{
3221 char *temp;
3222 char temp1[128];
3223 char temp_output[128];
3224 char temp_TransmitRates[128];
3225 char set[128];
3226 char sub_set[128];
3227 int set_count=0,subset_count=0;
3228 int set_index=0,subset_index=0;
3229 char *token;
3230 int flag=0, i=0;
3231 struct params params={'\0'};
3232 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003233 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003234
3235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3236 if(NULL == TransmitRates)
3237 return RETURN_ERR;
3238 strcpy(sub_set,TransmitRates);
3239
3240 //Allow only supported Data transmit rate to be set
3241 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3242 token = strtok(sub_set,",");
3243 while( token != NULL ) /* split the basic rate to be set, by comma */
3244 {
3245 sub_set[subset_count]=atoi(token);
3246 subset_count++;
3247 token=strtok(NULL,",");
3248 }
3249 token=strtok(set,",");
3250 while(token!=NULL) /* split the supported rate by comma */
3251 {
3252 set[set_count]=atoi(token);
3253 set_count++;
3254 token=strtok(NULL,",");
3255 }
3256 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3257 {
3258 for(set_index=0;set_index < set_count;set_index++)
3259 {
3260 flag=0;
3261 if(sub_set[subset_index]==set[set_index])
3262 break;
3263 else
3264 flag=1; /* No match found */
3265 }
3266 if(flag==1)
3267 return RETURN_ERR; //If value not found return Error
3268 }
3269 strcpy(temp_TransmitRates,TransmitRates);
3270
3271 for(i=0;i<strlen(temp_TransmitRates);i++)
3272 {
3273 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003274 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003275 {
3276 continue;
3277 }
3278 else
3279 {
3280 return RETURN_ERR;
3281 }
3282 }
3283 strcpy(temp_output,"");
3284 temp = strtok(temp_TransmitRates,",");
3285 while(temp!=NULL)
3286 {
3287 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003288 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003289 {
developeref938762022-10-19 17:21:01 +08003290 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003291 {
3292 return RETURN_ERR;
3293 }
3294 }
3295
3296 if(strcmp(temp,"5.5")==0)
3297 {
3298 strcpy(temp1,"55");
3299 }
3300 else
3301 {
3302 strcat(temp1,"0");
3303 }
3304 strcat(temp_output,temp1);
3305 temp = strtok(NULL,",");
3306 if(temp!=NULL)
3307 {
3308 strcat(temp_output," ");
3309 }
3310 }
3311 strcpy(TransmitRates,temp_output);
3312
3313 params.name= "basic_rates";
3314 params.value =TransmitRates;
3315
3316 wifi_dbg_printf("\n%s:",__func__);
3317 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3318 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3319 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3320 wifi_hostapdWrite(config_file,&params,1);
3321 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3322 return RETURN_OK;
3323}
3324
3325//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3326INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3327{
3328 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3329 FILE *fp = NULL;
3330 char path[256] = {0}, output_string[256] = {0};
3331 int count = 0;
3332 char *interface = NULL;
3333
3334 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3335 if (fp == NULL)
3336 {
3337 printf("Failed to run command in Function %s\n", __FUNCTION__);
3338 return RETURN_ERR;
3339 }
3340 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3341 {
3342 interface = strchr(path, '=');
3343
3344 if (interface != NULL)
3345 {
3346 strcpy(output_string, interface + 1);
3347 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3348 interface_name[count] = output_string[count];
3349
3350 interface_name[count] = '\0';
3351 }
3352 }
3353 pclose(fp);
3354 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3355 return RETURN_OK;
3356}
3357
3358INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3359{
3360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3361 output_struct->radio_BytesSent = 0;
3362 output_struct->radio_BytesReceived = 0;
3363 output_struct->radio_PacketsSent = 0;
3364 output_struct->radio_PacketsReceived = 0;
3365 output_struct->radio_ErrorsSent = 0;
3366 output_struct->radio_ErrorsReceived = 0;
3367 output_struct->radio_DiscardPacketsSent = 0;
3368 output_struct->radio_DiscardPacketsReceived = 0;
3369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3370 return RETURN_OK;
3371}
3372
3373
3374INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3375{
3376 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3377 CHAR buf[MAX_CMD_SIZE] = {0};
3378 CHAR Value[MAX_BUF_SIZE] = {0};
3379 FILE *fp = NULL;
3380
3381 if (ifname == NULL || strlen(ifname) <= 1)
3382 return RETURN_OK;
3383
3384 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3385 system(buf);
3386
3387 fp = fopen("/tmp/Radio_Stats.txt", "r");
3388 if(fp == NULL)
3389 {
3390 printf("/tmp/Radio_Stats.txt not exists \n");
3391 return RETURN_ERR;
3392 }
3393 fclose(fp);
3394
3395 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3396 File_Reading(buf, Value);
3397 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3398
3399 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3400 File_Reading(buf, Value);
3401 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3402
3403 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3404 File_Reading(buf, Value);
3405 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3406
3407 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3408 File_Reading(buf, Value);
3409 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3410
3411 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3412 File_Reading(buf, Value);
3413 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3414
3415 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3416 File_Reading(buf, Value);
3417 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3418
3419 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3420 File_Reading(buf, Value);
3421 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3422
3423 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3424 File_Reading(buf, Value);
3425 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3426
3427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3428 return RETURN_OK;
3429}
3430
3431INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3432{
3433 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3434 CHAR buf[MAX_CMD_SIZE] = {0};
3435 FILE *fp = NULL;
3436 INT count = 0;
3437
3438 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3439 {
3440 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3441 File_Reading(buf, status);
3442 }
3443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3444 return RETURN_OK;
3445}
3446
3447//Get detail radio traffic static info
3448INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3449{
3450
3451#if 0
3452 //ifconfig radio_x
3453 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3454 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3455 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3456 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3457
3458 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3459 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3460 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.
3461 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.
3462
3463 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3464 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].
3465 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3466 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.
3467 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
3468 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
3469 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
3470 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
3471 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
3472
3473 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
3474 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
3475 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
3476 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.
3477
3478 return RETURN_OK;
3479#endif
3480
developera91d99f2022-09-29 15:59:10 +08003481 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003482 BOOL iface_status = FALSE;
3483 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003484
3485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3486 if (NULL == output_struct)
3487 return RETURN_ERR;
3488
developerd946fd62022-12-08 18:03:28 +08003489 GetInterfaceName(radioIndex, interface_name);
developer06a01d92022-09-07 16:32:39 +08003490
developera91d99f2022-09-29 15:59:10 +08003491 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003492
developera91d99f2022-09-29 15:59:10 +08003493 if (iface_status == TRUE)
3494 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3495 else
3496 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003497
developera91d99f2022-09-29 15:59:10 +08003498 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3499 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3500 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3501 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3502 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3503 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3504 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3505 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003506
3507 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3508 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].
3509 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3510 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.
3511 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
3512 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
3513 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
3514 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
3515 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
3516
3517 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
3518 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
3519 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
3520 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.
3521
3522 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3523
3524 return RETURN_OK;
3525}
3526
3527//Set radio traffic static Measureing rules
3528INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3529{
3530 //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
3531 // Else, save the MeasuringRate and MeasuringInterval for future usage
3532
3533 return RETURN_OK;
3534}
3535
3536//To start or stop RadioTrafficStats
3537INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3538{
3539 //zqiu: If the RadioTrafficStats process running
3540 // if(enable)
3541 // return RETURN_OK.
3542 // else
3543 // Stop RadioTrafficStats process
3544 // Else
3545 // if(enable)
3546 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3547 // else
3548 // return RETURN_OK.
3549
3550 return RETURN_OK;
3551}
3552
3553//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
3554INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3555{
3556 //zqiu: Please ignor signalIndex.
3557 if (NULL == SignalLevel)
3558 return RETURN_ERR;
3559 *SignalLevel=(radioIndex==0)?-19:-19;
3560
3561 return RETURN_OK;
3562}
3563
3564//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3565INT wifi_applyRadioSettings(INT radioIndex)
3566{
3567 return RETURN_OK;
3568}
3569
3570//Get the radio index assocated with this SSID entry
3571INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3572{
developer5b398df2022-11-17 20:39:48 +08003573 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003574 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003575 int max_radio_num = 0;
3576 wifi_getMaxRadioNumber(&max_radio_num);
3577 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003578 return RETURN_OK;
3579}
3580
3581//Device.WiFi.SSID.{i}.Enable
3582//Get SSID enable configuration parameters (not the SSID enable status)
3583INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3584{
3585 if (NULL == output_bool)
3586 return RETURN_ERR;
3587
developer06a01d92022-09-07 16:32:39 +08003588 return wifi_getApEnable(ssidIndex, output_bool);
3589}
3590
3591//Device.WiFi.SSID.{i}.Enable
3592//Set SSID enable configuration parameters
3593INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3594{
developer06a01d92022-09-07 16:32:39 +08003595 return wifi_setApEnable(ssidIndex, enable);
3596}
3597
3598//Device.WiFi.SSID.{i}.Status
3599//Get the SSID enable status
3600INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3601{
3602 char cmd[MAX_CMD_SIZE]={0};
3603 char buf[MAX_BUF_SIZE]={0};
3604 BOOL output_bool;
3605
3606 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3607 if (NULL == output_string)
3608 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003609
developer06a01d92022-09-07 16:32:39 +08003610 wifi_getApEnable(ssidIndex,&output_bool);
3611 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3612
3613 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3614 return RETURN_OK;
3615}
3616
3617// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3618INT wifi_getSSIDName(INT apIndex, CHAR *output)
3619{
3620 char config_file[MAX_BUF_SIZE] = {0};
3621
3622 if (NULL == output)
3623 return RETURN_ERR;
3624
3625 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3626 wifi_hostapdRead(config_file,"ssid",output,32);
3627
3628 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3629 return RETURN_OK;
3630}
3631
3632// Set a max 32 byte string and sets an internal variable to the SSID name
3633INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3634{
3635 char str[MAX_BUF_SIZE]={'\0'};
3636 char cmd[MAX_CMD_SIZE]={'\0'};
3637 struct params params;
3638 char config_file[MAX_BUF_SIZE] = {0};
3639
3640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3641 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3642 return RETURN_ERR;
3643
3644 params.name = "ssid";
3645 params.value = ssid_string;
3646 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3647 wifi_hostapdWrite(config_file, &params, 1);
3648 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3649 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3650
3651 return RETURN_OK;
3652}
3653
3654//Get the BSSID
3655INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3656{
3657 char cmd[MAX_CMD_SIZE]="";
3658
3659 if (NULL == output_string)
3660 return RETURN_ERR;
3661
3662 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3663 {
developer1d57d002022-10-12 18:03:15 +08003664 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 +08003665 _syscmd(cmd, output_string, 64);
3666 return RETURN_OK;
3667 }
3668 strncpy(output_string, "\0", 1);
3669
3670 return RETURN_ERR;
3671}
3672
3673//Get the MAC address associated with this Wifi SSID
3674INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3675{
3676 wifi_getBaseBSSID(ssidIndex,output_string);
3677 return RETURN_OK;
3678}
3679
3680//Get the basic SSID traffic static info
3681//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3682//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3683INT wifi_applySSIDSettings(INT ssidIndex)
3684{
developerd946fd62022-12-08 18:03:28 +08003685 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003686 BOOL status = false;
3687 char cmd[MAX_CMD_SIZE] = {0};
3688 char buf[MAX_CMD_SIZE] = {0};
3689 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003690 int max_radio_num = 0;
3691 int radioIndex = 0;
3692
3693 wifi_getMaxRadioNumber(&max_radio_num);
3694
3695 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003696
3697 wifi_getApEnable(ssidIndex,&status);
3698 // Do not apply when ssid index is disabled
3699 if (status == false)
3700 return RETURN_OK;
3701
3702 /* Doing full remove and add for ssid Index
3703 * Not all hostapd options are supported with reload
3704 * for example macaddr_acl
3705 */
3706 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3707 return RETURN_ERR;
3708
3709 ret = wifi_setApEnable(ssidIndex,true);
3710
3711 /* Workaround for hostapd issue with multiple bss definitions
3712 * when first created interface will be removed
3713 * then all vaps other vaps on same phy are removed
3714 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003715 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003716 apIndex = max_radio_num*i+radioIndex;
3717 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3718 return RETURN_ERR;
3719 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003720 _syscmd(cmd, buf, sizeof(buf));
3721 if(*buf == '1')
3722 wifi_setApEnable(apIndex, true);
3723 }
3724
3725 return ret;
3726}
3727
developera3c68b92022-09-13 15:27:29 +08003728struct channels_noise {
3729 int channel;
3730 int noise;
3731};
3732
3733// Return noise array for each channel
3734int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3735{
developerd946fd62022-12-08 18:03:28 +08003736 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003737 FILE *f = NULL;
3738 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003739 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003740 size_t len = 0;
3741 ssize_t read = 0;
3742 int tmp = 0, arr_index = -1;
3743
developerd946fd62022-12-08 18:03:28 +08003744 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3745 return RETURN_ERR;
3746 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003747
3748 if ((f = popen(cmd, "r")) == NULL) {
3749 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3750 return RETURN_ERR;
3751 }
developer5550e242022-09-30 09:59:32 +08003752
3753 while(fgets(line, sizeof(line), f) != NULL) {
3754 if(arr_index < channels_num){
3755 sscanf(line, "%d", &tmp);
3756 if (tmp > 0) { // channel frequency, the first line must be frequency
3757 arr_index++;
3758 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3759 } else { // noise
3760 channels_noise_arr[arr_index].noise = tmp;
3761 }
3762 }else{
3763 break;
developera3c68b92022-09-13 15:27:29 +08003764 }
3765 }
developera3c68b92022-09-13 15:27:29 +08003766 pclose(f);
3767 return RETURN_OK;
3768}
3769
developer06a01d92022-09-07 16:32:39 +08003770//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3771//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3772INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3773{
developera3c68b92022-09-13 15:27:29 +08003774 int index = -1;
3775 wifi_neighbor_ap2_t *scan_array = NULL;
3776 char cmd[256]={0};
3777 char buf[128]={0};
3778 char file_name[32] = {0};
3779 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003780 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003781 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003782 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003783 int freq=0;
3784 FILE *f = NULL;
3785 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003786 int channels_num = 0;
3787 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003788 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003789 bool filter_enable = false;
3790 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003791 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003792
developer615510b2022-09-27 10:14:35 +08003793 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003794
developerd946fd62022-12-08 18:03:28 +08003795 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3796 return RETURN_ERR;
3797
developera3c68b92022-09-13 15:27:29 +08003798 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3799 f = fopen(file_name, "r");
3800 if (f != NULL) {
3801 fgets(filter_SSID, sizeof(file_name), f);
3802 if (strlen(filter_SSID) != 0)
3803 filter_enable = true;
3804 fclose(f);
3805 }
3806
developer033b37b2022-10-18 11:27:46 +08003807 phyId = radio_index_to_phy(radioIndex);
3808 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003809 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003810 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003811
developer5550e242022-09-30 09:59:32 +08003812
developer06a01d92022-09-07 16:32:39 +08003813
developerd946fd62022-12-08 18:03:28 +08003814 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3815 // 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 +08003816 fprintf(stderr, "cmd: %s\n", cmd);
3817 if ((f = popen(cmd, "r")) == NULL) {
3818 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3819 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003820 }
developer5550e242022-09-30 09:59:32 +08003821
3822 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3823 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3824
developer615510b2022-09-27 10:14:35 +08003825 ret = fgets(line, sizeof(line), f);
3826 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003827 if(strstr(line, "BSS") != NULL) { // new neighbor info
3828 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3829 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3830 // 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 +08003831
developera3c68b92022-09-13 15:27:29 +08003832 if (!filter_BSS) {
3833 index++;
3834 wifi_neighbor_ap2_t *tmp;
3835 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3836 if (tmp == NULL) { // no more memory to use
3837 index--;
3838 wifi_dbg_printf("%s: realloc failed\n", __func__);
3839 break;
3840 }
3841 scan_array = tmp;
3842 }
3843 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3844
3845 filter_BSS = false;
3846 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3847 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3848 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3849 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3850 } else if (strstr(line, "freq") != NULL) {
3851 sscanf(line," freq: %d", &freq);
3852 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3853
3854 if (freq >= 2412 && freq <= 2484) {
3855 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3856 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3857 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3858 }
3859 else if (freq >= 5160 && freq <= 5805) {
3860 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3861 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3862 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3863 }
3864
3865 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003866 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003867 for (int i = 0; i < channels_num; i++) {
3868 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3869 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3870 break;
3871 }
3872 }
3873 }
3874 } else if (strstr(line, "beacon interval") != NULL) {
3875 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3876 } else if (strstr(line, "signal") != NULL) {
3877 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3878 } else if (strstr(line,"SSID") != NULL) {
3879 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3880 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3881 filter_BSS = true;
3882 }
3883 } else if (strstr(line, "Supported rates") != NULL) {
3884 char SRate[80] = {0}, *tmp = NULL;
3885 memset(buf, 0, sizeof(buf));
3886 strcpy(SRate, line);
3887 tmp = strtok(SRate, ":");
3888 tmp = strtok(NULL, ":");
3889 strcpy(buf, tmp);
3890 memset(SRate, 0, sizeof(SRate));
3891
3892 tmp = strtok(buf, " \n");
3893 while (tmp != NULL) {
3894 strcat(SRate, tmp);
3895 if (SRate[strlen(SRate) - 1] == '*') {
3896 SRate[strlen(SRate) - 1] = '\0';
3897 }
3898 strcat(SRate, ",");
3899
3900 tmp = strtok(NULL, " \n");
3901 }
3902 SRate[strlen(SRate) - 1] = '\0';
3903 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3904 } else if (strstr(line, "DTIM") != NULL) {
3905 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3906 } else if (strstr(line, "VHT capabilities") != NULL) {
3907 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3908 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3909 } else if (strstr(line, "HT capabilities") != NULL) {
3910 strcat(scan_array[index].ap_SupportedStandards, ",n");
3911 strcpy(scan_array[index].ap_OperatingStandards, "n");
3912 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003913 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003914 sscanf(line," * channel width: %d", &vht_channel_width);
3915 if(vht_channel_width == 1) {
3916 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3917 } else {
3918 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3919 }
3920 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3921 continue;
3922 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003923 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003924 sscanf(line," * secondary channel offset: %s", &buf);
3925 if (!strcmp(buf, "above")) {
3926 //40Mhz +
3927 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3928 }
3929 else if (!strcmp(buf, "below")) {
3930 //40Mhz -
3931 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3932 } else {
3933 //20Mhz
3934 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3935 }
3936 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3937 continue;
3938 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003939 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3940 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3941 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003942 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3943 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003944 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003945 else
developer615510b2022-09-27 10:14:35 +08003946 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003947 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003948 if (strstr(line, "HE80/5GHz") != NULL) {
3949 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3950 ret = fgets(line, sizeof(line), f);
3951 } else
3952 continue;
developera3c68b92022-09-13 15:27:29 +08003953 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003954 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003955 }
developer615510b2022-09-27 10:14:35 +08003956 continue;
developera3c68b92022-09-13 15:27:29 +08003957 } else if (strstr(line, "WPA") != NULL) {
3958 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3959 } else if (strstr(line, "RSN") != NULL) {
3960 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3961 } else if (strstr(line, "Group cipher") != NULL) {
3962 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3963 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3964 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3965 }
3966 }
developer615510b2022-09-27 10:14:35 +08003967 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003968 }
3969
3970 if (!filter_BSS) {
3971 *output_array_size = index + 1;
3972 } else {
3973 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3974 *output_array_size = index;
3975 }
3976 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003977 pclose(f);
developer5550e242022-09-30 09:59:32 +08003978 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003980 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003981}
3982
3983//>> Deprecated: used for old RDKB code.
3984INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3985{
3986 INT status = RETURN_ERR;
3987
3988 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3989 output_struct->wifi_PLCPErrorCount = 0;
3990 output_struct->wifi_FCSErrorCount = 0;
3991 output_struct->wifi_InvalidMACCount = 0;
3992 output_struct->wifi_PacketsOtherReceived = 0;
3993 output_struct->wifi_Noise = 0;
3994 status = RETURN_OK;
3995 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3996 return status;
3997}
3998
3999INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4000{
developerd946fd62022-12-08 18:03:28 +08004001 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004002 char cmd[128] = {0};
4003 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004004 char *pos = NULL;
4005
4006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4007 if (NULL == output_struct)
4008 return RETURN_ERR;
4009
developerd946fd62022-12-08 18:03:28 +08004010 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4011 return RETURN_ERR;
4012
developer06a01d92022-09-07 16:32:39 +08004013 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4014
developerd946fd62022-12-08 18:03:28 +08004015 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004016 _syscmd(cmd, buf, sizeof(buf));
4017
4018 pos = buf;
4019 if ((pos = strstr(pos, "RX packets:")) == NULL)
4020 return RETURN_ERR;
4021 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4022
4023 if ((pos = strstr(pos, "TX packets:")) == NULL)
4024 return RETURN_ERR;
4025 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4026
4027 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4028 return RETURN_ERR;
4029 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4030
4031 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4032 return RETURN_ERR;
4033 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4034
developerd946fd62022-12-08 18:03:28 +08004035 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004036 _syscmd(cmd, buf, sizeof(buf));
4037 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4038
4039#if 0
4040 //TODO: need to revisit below implementation
4041 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4042 char interface_name[MAX_BUF_SIZE] = {0};
4043 char interface_status[MAX_BUF_SIZE] = {0};
4044 char Value[MAX_BUF_SIZE] = {0};
4045 char buf[MAX_CMD_SIZE] = {0};
4046 char cmd[MAX_CMD_SIZE] = {0};
4047 FILE *fp = NULL;
4048
4049 if (NULL == output_struct) {
4050 return RETURN_ERR;
4051 }
4052
4053 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4054
4055 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4056 {
4057 if(apIndex == 0) //private_wifi for 2.4G
4058 {
4059 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4060 }
4061 else if(apIndex == 1) //private_wifi for 5G
4062 {
4063 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4064 }
4065 else if(apIndex == 4) //public_wifi for 2.4G
4066 {
4067 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4068 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4069 {
4070 return RETURN_ERR;
4071 }
4072 if(buf[0] == '#')//tp-link
4073 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4074 else//tenda
4075 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4076 }
4077 else if(apIndex == 5) //public_wifi for 5G
4078 {
4079 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4080 }
4081
4082 GetIfacestatus(interface_name, interface_status);
4083
4084 if(0 != strcmp(interface_status, "1"))
4085 return RETURN_ERR;
4086
4087 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4088 system(cmd);
4089
4090 fp = fopen("/tmp/SSID_Stats.txt", "r");
4091 if(fp == NULL)
4092 {
4093 printf("/tmp/SSID_Stats.txt not exists \n");
4094 return RETURN_ERR;
4095 }
4096 fclose(fp);
4097
4098 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4099 File_Reading(buf, Value);
4100 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4101
4102 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4103 File_Reading(buf, Value);
4104 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4105
4106 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4107 File_Reading(buf, Value);
4108 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4109
4110 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4111 File_Reading(buf, Value);
4112 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4113
4114 /* There is no specific parameter from caller to associate the value wifi_Associations */
4115 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4116 //_syscmd(cmd, buf, sizeof(buf));
4117 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4118 }
4119#endif
4120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4121 return RETURN_OK;
4122}
4123
4124INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4125{
4126 char interface_name[MAX_BUF_SIZE] = {0};
4127 char interface_status[MAX_BUF_SIZE] = {0};
4128 char Value[MAX_BUF_SIZE] = {0};
4129 char buf[MAX_CMD_SIZE] = {0};
4130 char cmd[MAX_CMD_SIZE] = {0};
4131 FILE *fp = NULL;
4132
4133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4134 if (NULL == output_struct)
4135 return RETURN_ERR;
4136
4137 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4138
developerd946fd62022-12-08 18:03:28 +08004139 GetInterfaceName(apIndex,interface_name);
4140 GetIfacestatus(apIndex, interface_status);
developer06a01d92022-09-07 16:32:39 +08004141
developerd946fd62022-12-08 18:03:28 +08004142 if(0 != strcmp(interface_status, "1"))
4143 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004144
developerd946fd62022-12-08 18:03:28 +08004145 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4146 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004147
developerd946fd62022-12-08 18:03:28 +08004148 fp = fopen("/tmp/SSID_Stats.txt", "r");
4149 if(fp == NULL)
4150 {
4151 printf("/tmp/SSID_Stats.txt not exists \n");
4152 return RETURN_ERR;
4153 }
4154 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004155
developerd946fd62022-12-08 18:03:28 +08004156 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4157 File_Reading(buf, Value);
4158 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004159
developerd946fd62022-12-08 18:03:28 +08004160 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4161 File_Reading(buf, Value);
4162 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004163
developerd946fd62022-12-08 18:03:28 +08004164 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4165 File_Reading(buf, Value);
4166 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004167
developerd946fd62022-12-08 18:03:28 +08004168 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4169 File_Reading(buf, Value);
4170 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004171
4172 output_struct->wifi_UnicastPacketsSent = 0;
4173 output_struct->wifi_UnicastPacketsReceived = 0;
4174 output_struct->wifi_MulticastPacketsSent = 0;
4175 output_struct->wifi_MulticastPacketsReceived = 0;
4176 output_struct->wifi_BroadcastPacketsSent = 0;
4177 output_struct->wifi_BroadcastPacketsRecevied = 0;
4178 output_struct->wifi_UnknownPacketsReceived = 0;
4179
4180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4181 return RETURN_OK;
4182}
4183
4184INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4185{
4186 INT status = RETURN_ERR;
4187
4188 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4189 //Below values should get updated from hal
4190 output_struct->wifi_RetransCount=0;
4191 output_struct->wifi_FailedRetransCount=0;
4192 output_struct->wifi_RetryCount=0;
4193 output_struct->wifi_MultipleRetryCount=0;
4194 output_struct->wifi_ACKFailureCount=0;
4195 output_struct->wifi_AggregatedPacketCount=0;
4196
4197 status = RETURN_OK;
4198 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4199
4200 return status;
4201}
4202
4203INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4204{
4205 INT status = RETURN_ERR;
4206 UINT index;
4207 wifi_neighbor_ap_t *pt=NULL;
4208
4209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4210 *output_array_size=2;
4211 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4212 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4213 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4214 strcpy(pt->ap_Radio,"");
4215 strcpy(pt->ap_SSID,"");
4216 strcpy(pt->ap_BSSID,"");
4217 strcpy(pt->ap_Mode,"");
4218 pt->ap_Channel=1;
4219 pt->ap_SignalStrength=0;
4220 strcpy(pt->ap_SecurityModeEnabled,"");
4221 strcpy(pt->ap_EncryptionMode,"");
4222 strcpy(pt->ap_OperatingFrequencyBand,"");
4223 strcpy(pt->ap_SupportedStandards,"");
4224 strcpy(pt->ap_OperatingStandards,"");
4225 strcpy(pt->ap_OperatingChannelBandwidth,"");
4226 pt->ap_BeaconPeriod=1;
4227 pt->ap_Noise=0;
4228 strcpy(pt->ap_BasicDataTransferRates,"");
4229 strcpy(pt->ap_SupportedDataTransferRates,"");
4230 pt->ap_DTIMPeriod=1;
4231 pt->ap_ChannelUtilization = 1;
4232 }
4233
4234 status = RETURN_OK;
4235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4236
4237 return status;
4238}
4239
4240//----------------- AP HAL -------------------------------
4241
4242//>> Deprecated: used for old RDKB code.
4243INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4244{
4245 if (NULL == output_ulong || NULL == output_struct)
4246 return RETURN_ERR;
4247 *output_ulong = 0;
4248 *output_struct = NULL;
4249 return RETURN_OK;
4250}
4251
4252#ifdef HAL_NETLINK_IMPL
4253static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4254 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4255 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4256 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4257 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4258 char mac_addr[20];
4259 static int count=0;
4260 int rate=0;
4261
4262 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4263
4264 nla_parse(tb,
4265 NL80211_ATTR_MAX,
4266 genlmsg_attrdata(gnlh, 0),
4267 genlmsg_attrlen(gnlh, 0),
4268 NULL);
4269
4270 if(!tb[NL80211_ATTR_STA_INFO]) {
4271 fprintf(stderr, "sta stats missing!\n");
4272 return NL_SKIP;
4273 }
4274
4275
4276 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4277 fprintf(stderr, "failed to parse nested attributes!\n");
4278 return NL_SKIP;
4279 }
4280
4281 //devIndex starts from 1
4282 if( ++count == out->wifi_devIndex )
4283 {
4284 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4285 //Getting the mac addrress
4286 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4287
4288 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4289 fprintf(stderr, "failed to parse nested rate attributes!");
4290 return NL_SKIP;
4291 }
4292
4293 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4294 if(rinfo[NL80211_RATE_INFO_BITRATE])
4295 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4296 out->wifi_devTxRate = rate/10;
4297 }
4298
4299 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4300 fprintf(stderr, "failed to parse nested rate attributes!");
4301 return NL_SKIP;
4302 }
4303
4304 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4305 if(rinfo[NL80211_RATE_INFO_BITRATE])
4306 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4307 out->wifi_devRxRate = rate/10;
4308 }
4309 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4310 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4311
4312 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4313 count = 0; //starts the count for next cycle
4314 return NL_STOP;
4315 }
4316
4317 return NL_SKIP;
4318
4319}
4320#endif
4321
4322INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4323{
4324#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004325 Netlink nl = {0};
4326 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004327 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004328
developer30423732022-12-01 16:17:49 +08004329 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004330 info.wifi_devIndex = devIndex;
4331
developerd946fd62022-12-08 18:03:28 +08004332 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4333 return RETURN_ERR;
4334
4335 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004336
4337 nl.id = initSock80211(&nl);
4338
4339 if (nl.id < 0) {
4340 fprintf(stderr, "Error initializing netlink \n");
4341 return -1;
4342 }
4343
4344 struct nl_msg* msg = nlmsg_alloc();
4345
4346 if (!msg) {
4347 fprintf(stderr, "Failed to allocate netlink message.\n");
4348 nlfree(&nl);
4349 return -2;
4350 }
4351
4352 genlmsg_put(msg,
4353 NL_AUTO_PORT,
4354 NL_AUTO_SEQ,
4355 nl.id,
4356 0,
4357 NLM_F_DUMP,
4358 NL80211_CMD_GET_STATION,
4359 0);
4360
4361 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4362 nl_send_auto(nl.socket, msg);
4363 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4364 nl_recvmsgs(nl.socket, nl.cb);
4365 nlmsg_free(msg);
4366 nlfree(&nl);
4367
4368 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4369 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4370 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4371 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4372 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4373 return RETURN_OK;
4374#else
4375 //iw utility to retrieve station information
4376#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4377#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4378#define MACFILE "/tmp/wifi_AssoMac.txt"
4379#define TXRATEFILE "/tmp/wifi_txrate.txt"
4380#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4381 FILE *file = NULL;
4382 char if_name[10] = {'\0'};
4383 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004384 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004385 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004386 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004387
developerd946fd62022-12-08 18:03:28 +08004388 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4389 return RETURN_ERR;
4390
4391 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004392
4393 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4394 file = popen(pipeCmd, "r");
4395
4396 if(file == NULL)
4397 return RETURN_ERR; //popen failed
4398
4399 fgets(line, sizeof line, file);
4400 device = atoi(line);
4401 pclose(file);
4402
4403 if(device == 0)
4404 return RETURN_ERR; //No devices are connected
4405
4406 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4407 system(pipeCmd);
4408
4409 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4410
4411 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4412
4413 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4414
4415 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4416
4417 //devIndex starts from 1, ++count
4418 if((file = fopen(SIGNALFILE, "r")) != NULL )
4419 {
4420 for(count =0;fgets(line, sizeof line, file) != NULL;)
4421 {
4422 if (++count == devIndex)
4423 {
4424 output_struct->wifi_devSignalStrength = atoi(line);
4425 break;
4426 }
4427 }
4428 fclose(file);
4429 }
4430 else
4431 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4432
4433 if((file = fopen(MACFILE, "r")) != NULL )
4434 {
4435 for(count =0;fgets(line, sizeof line, file) != NULL;)
4436 {
4437 if (++count == devIndex)
4438 {
4439 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]);
4440 break;
4441 }
4442 }
4443 fclose(file);
4444 }
4445 else
4446 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4447
4448 if((file = fopen(TXRATEFILE, "r")) != NULL )
4449 {
4450 for(count =0;fgets(line, sizeof line, file) != NULL;)
4451 {
4452 if (++count == devIndex)
4453 {
4454 output_struct->wifi_devTxRate = atoi(line);
4455 break;
4456 }
4457 }
4458 fclose(file);
4459 }
4460 else
4461 fprintf(stderr,"fopen wifi_txrate.txt failed");
4462
4463 if((file = fopen(RXRATEFILE, "r")) != NULL)
4464 {
4465 for(count =0;fgets(line, sizeof line, file) != NULL;)
4466 {
4467 if (++count == devIndex)
4468 {
4469 output_struct->wifi_devRxRate = atoi(line);
4470 break;
4471 }
4472 }
4473 fclose(file);
4474 }
4475 else
4476 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4477
4478 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4479
4480 return RETURN_OK;
4481#endif
4482}
4483
4484INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4485{
4486 if (NULL == device)
4487 return RETURN_ERR;
4488 return RETURN_OK;
4489}
4490//<<
4491
4492
4493//--------------wifi_ap_hal-----------------------------
4494//enables CTS protection for the radio used by this AP
4495INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4496{
4497 //save config and Apply instantly
4498 return RETURN_ERR;
4499}
4500
4501// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4502INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4503{
developer463d39a2022-09-13 15:32:51 +08004504 char config_file[64] = {'\0'};
4505 char buf[64] = {'\0'};
4506 struct params list;
4507
4508 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4509 list.name = "ht_coex";
4510 snprintf(buf, sizeof(buf), "%d", enable);
4511 list.value = buf;
4512
4513 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4514 wifi_hostapdWrite(config_file, &list, 1);
4515 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4516
4517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4518
4519 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004520}
4521
4522//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4523INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4524{
developerea4bcce2022-09-13 15:26:13 +08004525 char config_file[MAX_BUF_SIZE] = {'\0'};
4526 char buf[MAX_BUF_SIZE] = {'\0'};
4527 struct params list;
4528
4529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4530 if (threshold < 256 || threshold > 2346 )
4531 return RETURN_ERR;
4532 list.name = "fragm_threshold";
4533 snprintf(buf, sizeof(buf), "%d", threshold);
4534 list.value = buf;
4535
4536 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4537 wifi_hostapdWrite(config_file, &list, 1);
4538 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004539
developerea4bcce2022-09-13 15:26:13 +08004540 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004541
4542 return RETURN_OK;
4543}
4544
4545// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4546INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4547{
developer51a927d2022-09-13 15:42:22 +08004548 char config_file[64] = {'\0'};
4549 char cmd[128] = {'\0'};
4550 char buf[64] = {'\0'};
4551 char stbc_config[16] = {'\0'};
4552 wifi_band band;
4553 int iterator = 0;
4554 BOOL current_stbc = FALSE;
4555
4556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4557
4558 band = wifi_index_to_band(radioIndex);
4559 if (band == band_invalid)
4560 return RETURN_ERR;
4561
4562 if (band == band_2_4)
4563 iterator = 1;
4564 else if (band == band_5)
4565 iterator = 2;
4566 else
4567 return RETURN_OK;
4568
4569 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4570
4571 // set ht and vht config
4572 for (int i = 0; i < iterator; i++) {
4573 memset(stbc_config, 0, sizeof(stbc_config));
4574 memset(cmd, 0, sizeof(cmd));
4575 memset(buf, 0, sizeof(buf));
4576 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4577 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4578 _syscmd(cmd, buf, sizeof(buf));
4579 if (strlen(buf) != 0)
4580 current_stbc = TRUE;
4581 if (current_stbc == STBC_Enable)
4582 continue;
4583
4584 if (STBC_Enable == TRUE) {
4585 // Append the STBC flags in capab config
4586 memset(cmd, 0, sizeof(cmd));
4587 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004588 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004589 else
developer6372c2b2022-10-27 17:39:51 +08004590 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 +08004591 _syscmd(cmd, buf, sizeof(buf));
4592 } else if (STBC_Enable == FALSE) {
4593 // Remove the STBC flags and remain other flags in capab
4594 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004595 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004596 _syscmd(cmd, buf, sizeof(buf));
4597 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004598 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004599 _syscmd(cmd, buf, sizeof(buf));
4600 }
4601 }
4602
4603 wifi_reloadAp(radioIndex);
4604
4605 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4606 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004607}
4608
4609// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4610INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4611{
developer54e6b9f2022-09-28 14:41:20 +08004612 char AMSDU_file_path[64] = {0};
4613
4614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4615
4616 if(output_bool == NULL)
4617 return RETURN_ERR;
4618
4619 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4620
4621 if (access(AMSDU_file_path, F_OK) == 0)
4622 *output_bool = TRUE;
4623 else
4624 *output_bool = FALSE;
4625
4626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4627 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004628}
4629
4630// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4631INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4632{
developerd946fd62022-12-08 18:03:28 +08004633 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004634 char cmd[64]={0};
4635 char buf[64]={0};
4636 char AMSDU_file_path[64] = {0};
4637
4638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4639
developerd946fd62022-12-08 18:03:28 +08004640 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4641 return RETURN_ERR;
4642 sprintf(cmd, "mt76-vendor %s set ap_wireless amsdu=%d", interface_name, amsduEnable);
developer54e6b9f2022-09-28 14:41:20 +08004643 _syscmd(cmd, buf, sizeof(buf));
4644
4645 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4646 memset(cmd, 0, sizeof(cmd));
4647 if (amsduEnable == TRUE)
4648 sprintf(cmd, "touch %s", AMSDU_file_path);
4649 else
4650 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4651 _syscmd(cmd, buf, sizeof(buf));
4652
4653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4654 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004655}
4656
4657//P2 // outputs the number of Tx streams
4658INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4659{
developer2de97692022-09-26 14:00:03 +08004660 char buf[8] = {0};
4661 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004662 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004663
4664 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4665
4666 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4667 _syscmd(cmd, buf, sizeof(buf));
4668
developer033b37b2022-10-18 11:27:46 +08004669 phyId = radio_index_to_phy(radioIndex);
developer2de97692022-09-26 14:00:03 +08004670 // if there is no record, output the max number of spatial streams
4671 if (strlen(buf) == 0) {
developer033b37b2022-10-18 11:27:46 +08004672 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 +08004673 _syscmd(cmd, buf, sizeof(buf));
4674 }
4675
4676 *output_int = (INT)strtol(buf, NULL, 10);
4677
4678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4679
4680 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004681}
4682
4683//P2 // sets the number of Tx streams to an enviornment variable
4684INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4685{
developer2de97692022-09-26 14:00:03 +08004686 char cmd[128] = {0};
4687 char buf[128] = {0};
4688 char chain_mask_file[128] = {0};
4689 FILE *f = NULL;
developer033b37b2022-10-18 11:27:46 +08004690 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004691
4692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4693
4694 if (numStreams == 0) {
developer30423732022-12-01 16:17:49 +08004695 fprintf(stderr, "The mask did not support 0 (auto).\n");
developer2de97692022-09-26 14:00:03 +08004696 return RETURN_ERR;
4697 }
4698 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004699
4700 phyId = radio_index_to_phy(radioIndex);
4701 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004702 _syscmd(cmd, buf, sizeof(buf));
4703
4704 if (strlen(buf) > 0) {
4705 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4706 return RETURN_ERR;
4707 }
4708 wifi_setRadioEnable(radioIndex, TRUE);
4709
4710 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4711 f = fopen(chain_mask_file, "w");
4712 if (f == NULL) {
4713 fprintf(stderr, "%s: fopen failed.\n", __func__);
4714 return RETURN_ERR;
4715 }
4716 fprintf(f, "%d", numStreams);
4717 fclose(f);
4718 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4719 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004720}
4721
4722//P2 // outputs the number of Rx streams
4723INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4724{
developer2de97692022-09-26 14:00:03 +08004725 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4726 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4727 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004728 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004729 }
4730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004731 return RETURN_OK;
4732}
4733
4734//P2 // sets the number of Rx streams to an enviornment variable
4735INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4736{
developer2de97692022-09-26 14:00:03 +08004737 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4738 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4739 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4740 return RETURN_ERR;
4741 }
4742 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004743 return RETURN_ERR;
4744}
4745
4746//Get radio RDG enable setting
4747INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4748{
4749 if (NULL == output_bool)
4750 return RETURN_ERR;
4751 *output_bool = TRUE;
4752 return RETURN_OK;
4753}
4754
4755//Get radio RDG enable setting
4756INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4757{
4758 if (NULL == output_bool)
4759 return RETURN_ERR;
4760 *output_bool = TRUE;
4761 return RETURN_OK;
4762}
4763
4764//Set radio RDG enable setting
4765INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4766{
4767 return RETURN_ERR;
4768}
4769
4770//Get radio ADDBA enable setting
4771INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4772{
4773 if (NULL == output_bool)
4774 return RETURN_ERR;
4775 *output_bool = TRUE;
4776 return RETURN_OK;
4777}
4778
4779//Set radio ADDBA enable setting
4780INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4781{
4782 return RETURN_ERR;
4783}
4784
4785//Get radio auto block ack enable setting
4786INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4787{
4788 if (NULL == output_bool)
4789 return RETURN_ERR;
4790 *output_bool = TRUE;
4791 return RETURN_OK;
4792}
4793
4794//Set radio auto block ack enable setting
4795INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4796{
4797 return RETURN_ERR;
4798}
4799
4800//Get radio 11n pure mode enable support
4801INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4802{
4803 if (NULL == output_bool)
4804 return RETURN_ERR;
4805 *output_bool = TRUE;
4806 return RETURN_OK;
4807}
4808
4809//Get radio 11n pure mode enable setting
4810INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4811{
4812 if (NULL == output_bool)
4813 return RETURN_ERR;
4814 *output_bool = TRUE;
4815 return RETURN_OK;
4816}
4817
4818//Set radio 11n pure mode enable setting
4819INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4820{
4821 return RETURN_ERR;
4822}
4823
4824//Get radio IGMP snooping enable setting
4825INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4826{
developerd946fd62022-12-08 18:03:28 +08004827 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004828 char cmd[128]={0};
4829 char buf[4]={0};
4830 bool bridge = FALSE, mac80211 = FALSE;
4831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4832
4833 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004834 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004835
4836 *output_bool = FALSE;
4837
4838 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4839 _syscmd(cmd, buf, sizeof(buf));
4840 if (strncmp(buf, "1", 1) == 0)
4841 bridge = TRUE;
4842
developerd946fd62022-12-08 18:03:28 +08004843 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4844 return RETURN_ERR;
4845 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 +08004846 _syscmd(cmd, buf, sizeof(buf));
4847 if (strncmp(buf, "1", 1) == 0)
4848 mac80211 = TRUE;
4849
4850 if (bridge && mac80211)
4851 *output_bool = TRUE;
4852
4853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004854 return RETURN_OK;
4855}
4856
4857//Set radio IGMP snooping enable setting
4858INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4859{
developerd946fd62022-12-08 18:03:28 +08004860 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004861 char cmd[128]={0};
4862 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004863 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4865
4866 // bridge
4867 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4868 _syscmd(cmd, buf, sizeof(buf));
4869
developer804c64f2022-10-19 13:54:40 +08004870 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004871 // mac80211
developer804c64f2022-10-19 13:54:40 +08004872 for (int i = 0; i < max_num_radios; i++) {
developerd946fd62022-12-08 18:03:28 +08004873 if (GetInterfaceName(i, interface_name) != RETURN_OK)
4874 return RETURN_ERR;
4875 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 +08004876 _syscmd(cmd, buf, sizeof(buf));
4877 }
4878 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4879 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004880}
4881
4882//Get the Reset count of radio
4883INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4884{
4885 if (NULL == output_int)
4886 return RETURN_ERR;
4887 *output_int = (radioIndex==0)? 1: 3;
4888
4889 return RETURN_OK;
4890}
4891
4892
4893//---------------------------------------------------------------------------------------------------
4894//
4895// Additional Wifi AP level APIs used for Access Point devices
4896//
4897//---------------------------------------------------------------------------------------------------
4898
4899// creates a new ap and pushes these parameters to the hardware
4900INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4901{
developerd946fd62022-12-08 18:03:28 +08004902 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004903 char buf[1024];
4904 char cmd[128];
developer033b37b2022-10-18 11:27:46 +08004905 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004906
4907 if (NULL == essid)
4908 return RETURN_ERR;
4909
developerd946fd62022-12-08 18:03:28 +08004910 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4911 return RETURN_ERR;
4912
developer033b37b2022-10-18 11:27:46 +08004913 phyId = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +08004914 snprintf(cmd,sizeof(cmd), "wlanconfig %s create wlandev %s%d wlanmode ap", interface_name, RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08004915 _syscmd(cmd, buf, sizeof(buf));
4916
developerd946fd62022-12-08 18:03:28 +08004917 snprintf(cmd,sizeof(cmd), "iwconfig %s essid %s mode master", interface_name, essid);
developer06a01d92022-09-07 16:32:39 +08004918 _syscmd(cmd, buf, sizeof(buf));
4919
4920 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4921
developerd946fd62022-12-08 18:03:28 +08004922 snprintf(cmd,sizeof(cmd), "ifconfig %s txqueuelen 1000", interface_name);
developer06a01d92022-09-07 16:32:39 +08004923 _syscmd(cmd, buf, sizeof(buf));
4924
4925 return RETURN_OK;
4926}
4927
4928// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4929INT wifi_deleteAp(INT apIndex)
4930{
developerd946fd62022-12-08 18:03:28 +08004931 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004932 char buf[1024];
4933 char cmd[128];
4934
developerd946fd62022-12-08 18:03:28 +08004935 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4936 return RETURN_ERR;
4937 snprintf(cmd,sizeof(cmd), "wlanconfig %s destroy", interface_name);
developer06a01d92022-09-07 16:32:39 +08004938 _syscmd(cmd, buf, sizeof(buf));
4939
4940 wifi_removeApSecVaribles(apIndex);
4941
4942 return RETURN_OK;
4943}
4944
4945// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4946INT wifi_getApName(INT apIndex, CHAR *output_string)
4947{
developerd946fd62022-12-08 18:03:28 +08004948 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004949 if(NULL == output_string)
4950 return RETURN_ERR;
4951
developerd946fd62022-12-08 18:03:28 +08004952 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4953 memset(output_string, 0, 16);
4954 else
4955 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004956 return RETURN_OK;
4957}
4958
4959// Outputs the index number in that corresponds to the SSID string
4960INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4961{
developerd946fd62022-12-08 18:03:28 +08004962 char cmd [128] = {0};
4963 char buf[32] = {0};
4964 char *apIndex_str = NULL;
4965 INT apIndex = 0;
4966 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08004967
developerd946fd62022-12-08 18:03:28 +08004968 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
4969 _syscmd(cmd, buf, sizeof(buf));
4970 // May get multiple output, so we need to check which ap is enable.
4971 apIndex_str = strtok(buf, "\n");
4972 while (apIndex_str != NULL) {
4973 apIndex = strtoul(apIndex_str, NULL, 10);
4974 wifi_getApEnable(apIndex, &enable);
4975 if (enable == TRUE) {
4976 *output_int = apIndex;
4977 return RETURN_OK;
4978 }
4979 apIndex_str = strtok(NULL, "\n");
developer06a01d92022-09-07 16:32:39 +08004980 }
developerd946fd62022-12-08 18:03:28 +08004981 *output_int = -1;
4982 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004983}
4984
4985INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4986{
4987 return wifi_getIndexFromName(inputSsidString, output_int);
4988}
4989
4990// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4991INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4992{
4993 char buf[MAX_BUF_SIZE] = {0};
4994 char cmd[MAX_CMD_SIZE] = {0};
4995 char config_file[MAX_BUF_SIZE] = {0};
4996
4997 if(NULL == output_string)
4998 return RETURN_ERR;
4999
5000 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5001 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5002 if((strcmp(buf,"3")==0))
5003 snprintf(output_string, 32, "WPAand11i");
5004 else if((strcmp(buf,"2")==0))
5005 snprintf(output_string, 32, "11i");
5006 else if((strcmp(buf,"1")==0))
5007 snprintf(output_string, 32, "WPA");
5008 else
5009 snprintf(output_string, 32, "None");
5010
5011 return RETURN_OK;
5012}
5013
5014// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5015INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5016{
5017 char config_file[MAX_BUF_SIZE] = {0};
5018 struct params list;
5019
5020 if (NULL == beaconTypeString)
5021 return RETURN_ERR;
5022 list.name = "wpa";
5023 list.value = "0";
5024
5025 if((strcmp(beaconTypeString,"WPAand11i")==0))
5026 list.value="3";
5027 else if((strcmp(beaconTypeString,"11i")==0))
5028 list.value="2";
5029 else if((strcmp(beaconTypeString,"WPA")==0))
5030 list.value="1";
5031
5032 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5033 wifi_hostapdWrite(config_file, &list, 1);
5034 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5035 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5036 return RETURN_OK;
5037}
5038
5039// sets the beacon interval on the hardware for this AP
5040INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5041{
developer5f222492022-09-13 15:21:52 +08005042 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5043 struct params params={'\0'};
5044 char buf[MAX_BUF_SIZE] = {'\0'};
5045 char config_file[MAX_BUF_SIZE] = {'\0'};
5046
5047 params.name = "beacon_int";
5048 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5049 params.value = buf;
5050
5051 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5052 wifi_hostapdWrite(config_file, &params, 1);
5053
5054 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5056 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005057}
5058
5059INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5060{
developer5b398df2022-11-17 20:39:48 +08005061 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5062 return RETURN_ERR;
5063 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005064}
5065
5066// Get the packet size threshold supported.
5067INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5068{
5069 //save config and apply instantly
5070 if (NULL == output_bool)
5071 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005072 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005073 return RETURN_OK;
5074}
5075
5076// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5077INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5078{
developerd946fd62022-12-08 18:03:28 +08005079 char interface_name[16] = {0};
developer514406b2022-12-05 17:20:21 +08005080 char buf[16] = {0};
5081 char config_file[128] = {0};
5082 struct params param = {0};
5083
5084 if (threshold > 65535) {
5085 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5086 return RETURN_ERR;
5087 }
developer06a01d92022-09-07 16:32:39 +08005088
developerd946fd62022-12-08 18:03:28 +08005089 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5090 return RETURN_ERR;
5091 snprintf(config_file, sizeof(config_file), "%s.conf", interface_name);
developer514406b2022-12-05 17:20:21 +08005092 snprintf(buf, sizeof(buf), "%u", threshold);
5093 param.name = "rts_threshold";
5094 param.value = buf;
5095 wifi_hostapdWrite(config_file, &param, 1);
5096 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5097 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005098
5099 return RETURN_OK;
5100}
5101
5102// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5103INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5104{
5105 if (NULL == output_string)
5106 return RETURN_ERR;
5107 snprintf(output_string, 32, "TKIPandAESEncryption");
5108 return RETURN_OK;
5109
5110}
5111
5112// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5113INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5114{
5115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005116 char *param_name = NULL;
5117 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005118
5119 if(NULL == output_string)
5120 return RETURN_ERR;
5121
5122 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5123 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5124
5125 if(strcmp(buf,"0")==0)
5126 {
5127 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5128 snprintf(output_string, 32, "None");
5129 return RETURN_OK;
5130 }
5131 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5132 param_name = "rsn_pairwise";
5133 else if((strcmp(buf,"1")==0))
5134 param_name = "wpa_pairwise";
5135 else
5136 return RETURN_ERR;
5137 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005138 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005139 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5140 param_name = "wpa_pairwise";
5141 memset(output_string, '\0', 32);
5142 wifi_hostapdRead(config_file, param_name, output_string, 32);
5143 }
developer06a01d92022-09-07 16:32:39 +08005144 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5145
5146 if(strcmp(output_string,"TKIP") == 0)
5147 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5148 else if(strcmp(output_string,"CCMP") == 0)
5149 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5150 else if(strcmp(output_string,"TKIP CCMP") == 0)
5151 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5152
5153 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5154 return RETURN_OK;
5155}
5156
5157// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5158INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5159{
5160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5161 struct params params={'\0'};
5162 char output_string[32];
5163 char config_file[MAX_BUF_SIZE] = {0};
5164
5165 memset(output_string,'\0',32);
5166 wifi_getApWpaEncryptionMode(apIndex,output_string);
5167
5168 if(strcmp(encMode, "TKIPEncryption") == 0)
5169 params.value = "TKIP";
5170 else if(strcmp(encMode,"AESEncryption") == 0)
5171 params.value = "CCMP";
5172 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5173 params.value = "TKIP CCMP";
5174
5175 if((strcmp(output_string,"WPAand11i")==0))
5176 {
5177 params.name = "wpa_pairwise";
5178 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5179 wifi_hostapdWrite(config_file, &params, 1);
5180 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5181
developer30423732022-12-01 16:17:49 +08005182 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005183 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5184 wifi_hostapdWrite(config_file, &params, 1);
5185 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5186
5187 return RETURN_OK;
5188 }
5189 else if((strcmp(output_string,"11i")==0))
5190 {
5191 params.name = "rsn_pairwise";
5192 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5193 wifi_hostapdWrite(config_file, &params, 1);
5194 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5195 return RETURN_OK;
5196 }
5197 else if((strcmp(output_string,"WPA")==0))
5198 {
5199 params.name = "wpa_pairwise";
5200 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5201 wifi_hostapdWrite(config_file, &params, 1);
5202 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5203 return RETURN_OK;
5204 }
5205
5206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5207 return RETURN_OK;
5208}
5209
5210// deletes internal security varable settings for this ap
5211INT wifi_removeApSecVaribles(INT apIndex)
5212{
5213 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005214 //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 +08005215 //_syscmd(cmd, buf, sizeof(buf));
5216
developerd946fd62022-12-08 18:03:28 +08005217 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005218 //_syscmd(cmd, buf, sizeof(buf));
5219 return RETURN_ERR;
5220}
5221
5222// changes the hardware settings to disable encryption on this ap
5223INT wifi_disableApEncryption(INT apIndex)
5224{
5225 //Apply instantly
5226 return RETURN_ERR;
5227}
5228
5229// set the authorization mode on this ap
5230// mode mapping as: 1: open, 2: shared, 4:auto
5231INT wifi_setApAuthMode(INT apIndex, INT mode)
5232{
developeraf95c502022-09-13 16:18:22 +08005233 struct params params={0};
5234 char config_file[64] = {0};
5235 int ret;
5236
5237 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5238
5239 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5240 params.name = "auth_algs";
5241
5242 if (mode & 1 && mode & 2)
5243 params.value = "3";
5244 else if (mode & 2)
5245 params.value = "2";
5246 else if (mode & 1)
5247 params.value = "1";
5248 else
5249 params.value = "0";
5250
5251 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5252 wifi_hostapdWrite(config_file, &params, 1);
5253 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5255
5256 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005257}
5258
5259// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5260INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5261{
5262 //save to wifi config, and wait for wifi restart to apply
5263 struct params params={'\0'};
5264 char config_file[MAX_BUF_SIZE] = {0};
5265 int ret;
5266
5267 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5268 if(authMode == NULL)
5269 return RETURN_ERR;
5270
5271 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5272 params.name = "wpa_key_mgmt";
5273
5274 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5275 params.value = "WPA-PSK";
5276 else if(strcmp(authMode,"EAPAuthentication") == 0)
5277 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005278 else if (strcmp(authMode, "SAEAuthentication") == 0)
5279 params.value = "SAE";
5280 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5281 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005282 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5283 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005284 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5285 return RETURN_OK; //This is taken careof in beaconType
5286
5287 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5288 ret=wifi_hostapdWrite(config_file,&params,1);
5289 if(!ret)
5290 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5292
5293 return ret;
5294}
5295
5296// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5297INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5298{
5299 //save to wifi config, and wait for wifi restart to apply
5300 char BeaconType[50] = {0};
5301 char config_file[MAX_BUF_SIZE] = {0};
5302
5303 *authMode = 0;
5304 wifi_getApBeaconType(apIndex,BeaconType);
5305 printf("%s____%s \n",__FUNCTION__,BeaconType);
5306
5307 if(strcmp(BeaconType,"None") == 0)
5308 strcpy(authMode,"None");
5309 else
5310 {
5311 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5312 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5313 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5314 if(strcmp(authMode,"WPA-PSK") == 0)
5315 strcpy(authMode,"SharedAuthentication");
5316 else if(strcmp(authMode,"WPA-EAP") == 0)
5317 strcpy(authMode,"EAPAuthentication");
5318 }
5319
5320 return RETURN_OK;
5321}
5322
5323// Outputs the number of stations associated per AP
5324INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5325{
developerd946fd62022-12-08 18:03:28 +08005326 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005327 char cmd[128]={0};
5328 char buf[128]={0};
5329 BOOL status = false;
5330
5331 if(apIndex > MAX_APS)
5332 return RETURN_ERR;
5333
5334 wifi_getApEnable(apIndex,&status);
5335 if (!status)
5336 return RETURN_OK;
5337
developerd946fd62022-12-08 18:03:28 +08005338 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
5339 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5340 return RETURN_ERR;
5341 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005342 _syscmd(cmd, buf, sizeof(buf));
5343 sscanf(buf,"%lu", output_ulong);
5344
5345 return RETURN_OK;
5346}
5347
5348// manually removes any active wi-fi association with the device specified on this ap
5349INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5350{
developerd946fd62022-12-08 18:03:28 +08005351 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005352 char buf[126]={'\0'};
5353
developerd946fd62022-12-08 18:03:28 +08005354 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5355 return RETURN_ERR;
5356 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005357 system(buf);
5358
5359 return RETURN_OK;
5360}
5361
5362// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5363INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5364{
5365 if(NULL == output_int)
5366 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005367 int max_radio_num = 0;
5368 wifi_getMaxRadioNumber(&max_radio_num);
5369 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005370 return RETURN_OK;
5371}
5372
5373// sets the radio index for the specific ap
5374INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5375{
5376 //set to config only and wait for wifi reset to apply settings
5377 return RETURN_ERR;
5378}
5379
5380// Get the ACL MAC list per AP
5381INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5382{
developerd946fd62022-12-08 18:03:28 +08005383 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005384 char cmd[MAX_CMD_SIZE]={'\0'};
5385 int ret = 0;
5386
developerd946fd62022-12-08 18:03:28 +08005387 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5388 return RETURN_ERR;
5389 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005390 ret = _syscmd(cmd,macArray,buf_size);
5391 if (ret != 0)
5392 return RETURN_ERR;
5393
5394 return RETURN_OK;
5395}
5396
developere6aafda2022-09-13 14:59:28 +08005397INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5398{
developerd946fd62022-12-08 18:03:28 +08005399 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005400 char cmd[MAX_CMD_SIZE]={'\0'};
5401 int ret = 0;
5402
developerd946fd62022-12-08 18:03:28 +08005403 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5404 return RETURN_ERR;
5405 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005406 ret = _syscmd(cmd,macArray,buf_size);
5407 if (ret != 0)
5408 return RETURN_ERR;
5409
5410 return RETURN_OK;
5411}
5412
5413
developer06a01d92022-09-07 16:32:39 +08005414// Get the list of stations associated per AP
5415INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5416{
developerd946fd62022-12-08 18:03:28 +08005417 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005418 char cmd[128];
5419
5420 if(apIndex > 3) //Currently supporting apIndex upto 3
5421 return RETURN_ERR;
developerd946fd62022-12-08 18:03:28 +08005422 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5423 return RETURN_ERR;
5424 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5425 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005426 _syscmd(cmd, macArray, buf_size);
5427
5428 return RETURN_OK;
5429}
5430
5431// adds the mac address to the filter list
5432//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5433INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5434{
5435 char cmd[MAX_CMD_SIZE]={'\0'};
5436 char buf[MAX_BUF_SIZE]={'\0'};
5437
5438#if 0
developerd946fd62022-12-08 18:03:28 +08005439 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005440 if(_syscmd(cmd,buf,sizeof(buf)))
5441 return RETURN_ERR;
5442#endif
5443 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5444 if(_syscmd(cmd,buf,sizeof(buf)))
5445 return RETURN_ERR;
5446
5447 return RETURN_OK;
5448}
5449
5450// deletes the mac address from the filter list
5451//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5452INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5453{
5454 char cmd[MAX_CMD_SIZE]={'\0'};
5455 char buf[MAX_BUF_SIZE]={'\0'};
5456
5457#if 0
developerd946fd62022-12-08 18:03:28 +08005458 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005459 if(_syscmd(cmd,buf,sizeof(buf)))
5460 return RETURN_ERR;
5461
5462#endif
5463 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5464 if(_syscmd(cmd,buf,sizeof(buf)))
5465 return RETURN_ERR;
5466
5467 return RETURN_OK;
5468}
5469
5470// outputs the number of devices in the filter list
5471INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5472{
developere6aafda2022-09-13 14:59:28 +08005473 char cmd[MAX_BUF_SIZE]={0};
5474 char buf[MAX_CMD_SIZE]={0};
5475
5476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5477 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005478 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005479
5480 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5481 _syscmd(cmd, buf, sizeof(buf));
5482
5483 *output_uint = atoi(buf);
5484
5485 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5486 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005487}
5488
5489INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5490{
5491 char cmd[128]={'\0'};
5492 char buf[128]={'\0'};
5493
5494 if(strcmp(action,"DENY")==0)
5495 {
5496 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5497 system(buf);
5498 return RETURN_OK;
5499 }
5500
5501 if(strcmp(action,"ALLOW")==0)
5502 {
5503 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5504 system(buf);
5505 return RETURN_OK;
5506 }
5507
5508 return RETURN_ERR;
5509
5510}
5511
5512// enable kick for devices on acl black list
5513INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5514{
5515 char aclArray[512] = {0}, *acl = NULL;
5516 char assocArray[512] = {0}, *asso = NULL;
5517
developere6aafda2022-09-13 14:59:28 +08005518 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005519 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5520
5521 // if there are no devices connected there is nothing to do
5522 if (strlen(assocArray) < 17)
5523 return RETURN_OK;
5524
5525 if (enable == TRUE)
5526 {
5527 //kick off the MAC which is in ACL array (deny list)
5528 acl = strtok(aclArray, "\r\n");
5529 while (acl != NULL) {
5530 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5531 wifi_kickApAssociatedDevice(apIndex, acl);
5532
5533 acl = strtok(NULL, "\r\n");
5534 }
developere6aafda2022-09-13 14:59:28 +08005535 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005536 }
5537 else
5538 {
developere6aafda2022-09-13 14:59:28 +08005539 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005540 }
5541
5542#if 0
5543 //TODO: need to revisit below implementation
5544 char aclArray[512]={0}, *acl=NULL;
5545 char assocArray[512]={0}, *asso=NULL;
5546 char buf[256]={'\0'};
5547 char action[10]={'\0'};
5548 FILE *fr=NULL;
5549 char interface[10]={'\0'};
5550 char config_file[MAX_BUF_SIZE] = {0};
5551
5552 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5553 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5554 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5555 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5556
5557 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5558 system(buf);
5559 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5560 system(buf);
5561 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5562 system(buf);
5563 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5564 system(buf);
5565 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5566 system(buf);
5567
5568 if ( enable == TRUE )
5569 {
5570 int device_count=0;
5571 strcpy(action,"DENY");
5572 //kick off the MAC which is in ACL array (deny list)
5573 acl = strtok (aclArray,",");
5574 while (acl != NULL) {
5575 if(strlen(acl)>=17)
5576 {
5577 apply_rules(apIndex, acl,action,interface);
5578 device_count++;
5579 //Register mac to be blocked ,in syscfg.db persistent storage
5580 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5581 system(buf);
5582 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5583 system(buf);
5584 system("syscfg commit");
5585
5586 wifi_kickApAssociatedDevice(apIndex, acl);
5587 }
5588 acl = strtok (NULL, ",");
5589 }
5590 }
5591 else
5592 {
5593 int device_count=0;
5594 char cmdmac[20]={'\0'};
5595 strcpy(action,"ALLOW");
5596 //kick off the MAC which is not in ACL array (allow list)
5597 acl = strtok (aclArray,",");
5598 while (acl != NULL) {
5599 if(strlen(acl)>=17)
5600 {
5601 apply_rules(apIndex, acl,action,interface);
5602 device_count++;
5603 //Register mac to be Allowed ,in syscfg.db persistent storage
5604 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5605 system(buf);
5606 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5607 system(buf);
5608 sprintf(cmdmac,"%s",acl);
5609 }
5610 acl = strtok (NULL, ",");
5611 }
5612 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5613 system(buf);
5614
5615 //Disconnect the mac which is not in ACL
5616 asso = strtok (assocArray,",");
5617 while (asso != NULL) {
5618 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5619 wifi_kickApAssociatedDevice(apIndex, asso);
5620 asso = strtok (NULL, ",");
5621 }
5622 }
5623#endif
5624 return RETURN_OK;
5625}
5626
5627INT wifi_setPreferPrivateConnection(BOOL enable)
5628{
developer06a01d92022-09-07 16:32:39 +08005629 return RETURN_OK;
5630}
5631
5632// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5633INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5634{
developerd946fd62022-12-08 18:03:28 +08005635 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005636 int items = 1;
5637 struct params list[2];
5638 char buf[MAX_BUF_SIZE] = {0};
5639 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005640 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005641
5642 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005643
developer10adcc12022-09-13 14:39:17 +08005644 if (filterMode == 0) {
5645 sprintf(buf, "%d", 0);
5646 list[0].value = buf;
5647
5648 char cmd[128], rtn[128];
developerd946fd62022-12-08 18:03:28 +08005649 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5650 return RETURN_ERR;
5651 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
developer10adcc12022-09-13 14:39:17 +08005652 _syscmd(cmd, rtn, sizeof(rtn));
5653 memset(cmd,0,sizeof(cmd));
5654 // Delete deny_mac_file in hostapd configuration
5655 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5656 _syscmd(cmd, rtn, sizeof(rtn));
5657 }
5658 else if (filterMode == 1) {
5659 sprintf(buf, "%d", filterMode);
5660 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005661 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5662 list[1].name = "accept_mac_file";
5663 list[1].value = acl_file;
5664 items = 2;
developer10adcc12022-09-13 14:39:17 +08005665 } else if (filterMode == 2) {
5666 //TODO: deny_mac_file
5667 sprintf(buf, "%d", 0);
5668 list[0].value = buf;
5669 list[1].name = "deny_mac_file";
5670 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5671 list[1].value = deny_file;
5672 items = 2;
5673 } else {
5674 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005675 }
developer10adcc12022-09-13 14:39:17 +08005676
developer06a01d92022-09-07 16:32:39 +08005677 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5678 wifi_hostapdWrite(config_file, list, items);
5679
5680 return RETURN_OK;
5681
5682#if 0
5683 if(apIndex==0 || apIndex==1)
5684 {
5685 //set the filtermode
5686 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5687 system(buf);
5688 system("syscfg commit");
5689
5690 if(filterMode==0)
5691 {
5692 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5693 system(buf);
5694 return RETURN_OK;
5695 }
5696 }
5697 return RETURN_OK;
5698#endif
5699}
5700
5701// 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.
5702INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5703{
5704 return RETURN_ERR;
5705}
5706
5707// gets the vlan ID for this ap from an internal enviornment variable
5708INT wifi_getApVlanID(INT apIndex, INT *output_int)
5709{
developer30423732022-12-01 16:17:49 +08005710 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005711 {
5712 *output_int=100;
5713 return RETURN_OK;
5714 }
5715
5716 return RETURN_ERR;
5717}
5718
5719// sets the vlan ID for this ap to an internal enviornment variable
5720INT wifi_setApVlanID(INT apIndex, INT vlanId)
5721{
5722 //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)
5723 return RETURN_ERR;
5724}
5725
5726// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5727INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5728{
5729 snprintf(bridgeName, 32, "brlan0");
5730 snprintf(IP, 32, "10.0.0.1");
5731 snprintf(subnet, 32, "255.255.255.0");
5732
5733 return RETURN_OK;
5734}
5735
5736//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5737INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5738{
5739 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5740 return RETURN_ERR;
5741}
5742
5743// reset the vlan configuration for this ap
5744INT wifi_resetApVlanCfg(INT apIndex)
5745{
developerf5fef612022-09-20 19:38:26 +08005746 char original_config_file[64] = {0};
5747 char current_config_file[64] = {0};
5748 char buf[64] = {0};
5749 char cmd[64] = {0};
5750 char vlan_file[64] = {0};
5751 char vlan_tagged_interface[16] = {0};
5752 char vlan_bridge[16] = {0};
5753 char vlan_naming[16] = {0};
5754 struct params list[4] = {0};
5755 wifi_band band;
5756
5757 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5758
5759 band = wifi_index_to_band(apIndex);
5760 if (band == band_2_4)
5761 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08005762 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08005763 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08005764 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08005765 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5766
5767 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5768
5769 if (strlen(vlan_file) == 0)
5770 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005771
developerf5fef612022-09-20 19:38:26 +08005772 // The file should exist or this vap would not work.
5773 if (access(vlan_file, F_OK) != 0) {
5774 sprintf(cmd, "touch %s", vlan_file);
5775 _syscmd(cmd, buf, sizeof(buf));
5776 }
5777 list[0].name = "vlan_file";
5778 list[0].value = vlan_file;
5779
5780 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5781 list[1].name = "vlan_tagged_interface";
5782 list[1].value = vlan_tagged_interface;
5783
5784 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5785 list[2].name = "vlan_bridge";
5786 list[2].value = vlan_bridge;
5787
5788 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5789 list[3].name = "vlan_naming";
5790 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005791
developerf5fef612022-09-20 19:38:26 +08005792 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5793 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005794 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005795 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005796
developerf5fef612022-09-20 19:38:26 +08005797 // restart this ap
5798 wifi_setApEnable(apIndex, FALSE);
5799 wifi_setApEnable(apIndex, TRUE);
5800
5801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5802
5803 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005804}
5805
5806// 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.
5807INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5808{
5809 return RETURN_ERR;
5810}
5811
5812// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5813INT wifi_startHostApd()
5814{
5815 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5816 system("systemctl start hostapd.service");
5817 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5818 return RETURN_OK;
5819 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5820}
5821
5822// stops hostapd
5823INT wifi_stopHostApd()
5824{
5825 char cmd[128] = {0};
5826 char buf[128] = {0};
5827
5828 sprintf(cmd,"systemctl stop hostapd");
5829 _syscmd(cmd, buf, sizeof(buf));
5830
5831 return RETURN_OK;
5832}
5833
5834// restart hostapd dummy function
5835INT wifi_restartHostApd()
5836{
5837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5838 system("systemctl restart hostapd-global");
5839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5840
5841 return RETURN_OK;
5842}
5843
5844static int align_hostapd_config(int index)
5845{
5846 ULONG lval;
5847 wifi_getRadioChannel(index%2, &lval);
5848 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08005849 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005850}
5851
5852// sets the AP enable status variable for the specified ap.
5853INT wifi_setApEnable(INT apIndex, BOOL enable)
5854{
developerd946fd62022-12-08 18:03:28 +08005855 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005856 char config_file[MAX_BUF_SIZE] = {0};
5857 char cmd[MAX_CMD_SIZE] = {0};
5858 char buf[MAX_BUF_SIZE] = {0};
5859 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005860 int max_radio_num = 0;
5861 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005862
5863 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005864
5865 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005866 if (enable == status)
5867 return RETURN_OK;
5868
developerd946fd62022-12-08 18:03:28 +08005869 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5870 return RETURN_ERR;
5871
developer06a01d92022-09-07 16:32:39 +08005872 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005873 int radioIndex = apIndex % max_radio_num;
5874 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005875 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5876 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08005877 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005878 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005879 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005880 _syscmd(cmd, buf, sizeof(buf));
5881 }
5882 else {
developerd946fd62022-12-08 18:03:28 +08005883 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005884 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08005885 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08005886 _syscmd(cmd, buf, sizeof(buf));
5887 }
developerd946fd62022-12-08 18:03:28 +08005888 snprintf(cmd, sizeof(cmd), "sed '/%s/c %s=%d' -i %s",
5889 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08005890 _syscmd(cmd, buf, sizeof(buf));
5891 //Wait for wifi up/down to apply
5892 return RETURN_OK;
5893}
5894
5895// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5896INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5897{
developerd946fd62022-12-08 18:03:28 +08005898 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005899 char cmd[MAX_CMD_SIZE] = {'\0'};
5900 char buf[MAX_BUF_SIZE] = {'\0'};
5901
5902 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5903 return RETURN_ERR;
5904
5905 *output_bool = 0;
5906
5907 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5908 {
developerd946fd62022-12-08 18:03:28 +08005909 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
5910 *output_bool = FALSE;
5911 return RETURN_OK;
5912 }
5913 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08005914 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5915 }
5916
5917 return RETURN_OK;
5918}
5919
5920// Outputs the AP "Enabled" "Disabled" status from driver
5921INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5922{
5923 char cmd[128] = {0};
5924 char buf[128] = {0};
5925 BOOL output_bool;
5926
5927 if ( NULL == output_string)
5928 return RETURN_ERR;
5929 wifi_getApEnable(apIndex,&output_bool);
5930
5931 if(output_bool == 1)
5932 snprintf(output_string, 32, "Up");
5933 else
5934 snprintf(output_string, 32, "Disable");
5935
5936 return RETURN_OK;
5937}
5938
5939//Indicates whether or not beacons include the SSID name.
5940// outputs a 1 if SSID on the AP is enabled, else outputs 0
5941INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5942{
5943 //get the running status
5944 char config_file[MAX_BUF_SIZE] = {0};
5945 char buf[16] = {0};
5946
5947 if (!output)
5948 return RETURN_ERR;
5949
5950 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5951 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005952 // default is enable
5953 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5954 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005955
5956 return RETURN_OK;
5957}
5958
5959// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5960INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5961{
5962 //store the config, apply instantly
5963 char config_file[MAX_BUF_SIZE] = {0};
5964 struct params list;
5965
5966 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5967 list.name = "ignore_broadcast_ssid";
5968 list.value = enable?"0":"1";
5969
5970 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5971 wifi_hostapdWrite(config_file, &list, 1);
5972 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5973 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005974 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005975 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5976
5977 return RETURN_OK;
5978}
5979
5980//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5981INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5982{
5983 //get the running status
5984 if(!output_uint)
5985 return RETURN_ERR;
5986 *output_uint=16;
5987 return RETURN_OK;
5988}
5989
5990INT wifi_setApRetryLimit(INT apIndex, UINT number)
5991{
5992 //apply instantly
5993 return RETURN_ERR;
5994}
5995
5996//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5997INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5998{
5999 if(!output)
6000 return RETURN_ERR;
6001 *output=TRUE;
6002 return RETURN_OK;
6003}
6004
6005//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6006INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6007{
6008 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006009 char cmd[128] = {0};
6010 char buf[128] = {0};
6011 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006012 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006013
developer0b246d12022-09-30 15:24:20 +08006014 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006015
developer0b246d12022-09-30 15:24:20 +08006016 wifi_getMaxRadioNumber(&max_radio_num);
6017 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006018 phyId = radio_index_to_phy(radioIndex);
6019 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006020 _syscmd(cmd,buf, sizeof(buf));
6021
6022 if (strlen(buf) > 0)
6023 *output = true;
6024
6025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006026
developer06a01d92022-09-07 16:32:39 +08006027 return RETURN_OK;
6028}
6029
6030//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6031INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6032{
6033 //get the running status from driver
6034 if(!output)
6035 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006036
6037 char config_file[MAX_BUF_SIZE] = {0};
6038 char buf[16] = {0};
6039
6040 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6041 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006042 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006043 *output = TRUE;
6044 else
6045 *output = FALSE;
6046
developer06a01d92022-09-07 16:32:39 +08006047 return RETURN_OK;
6048}
6049
6050// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6051INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6052{
6053 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006054 char config_file[MAX_BUF_SIZE] = {0};
6055 struct params list;
6056
6057 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6058 list.name = "wmm_enabled";
6059 list.value = enable?"1":"0";
6060
6061 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6062 wifi_hostapdWrite(config_file, &list, 1);
6063 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6064 wifi_reloadAp(apIndex);
6065 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6066
6067 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006068}
6069
6070//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.
6071INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6072{
6073 //get the running status from driver
6074 if(!output)
6075 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006076
6077 char config_file[128] = {0};
6078 char buf[16] = {0};
6079
6080 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6081 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6082 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6083 *output = TRUE;
6084 else
6085 *output = FALSE;
6086
developer06a01d92022-09-07 16:32:39 +08006087 return RETURN_OK;
6088}
6089
6090// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6091INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6092{
6093 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006094 char config_file[MAX_BUF_SIZE] = {0};
6095 struct params list;
6096
6097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6098 list.name = "uapsd_advertisement_enabled";
6099 list.value = enable?"1":"0";
6100
6101 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6102 wifi_hostapdWrite(config_file, &list, 1);
6103 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6104 wifi_reloadAp(apIndex);
6105 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6106
6107 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006108}
6109
developer6daeb3f2022-09-30 13:36:39 +08006110// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006111INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6112{
developerd946fd62022-12-08 18:03:28 +08006113 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006114 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6115 char cmd[128] = {0};
6116 char buf[128] = {0};
6117 char ack_filepath[128] = {0};
6118 uint16_t bitmap = 0;
6119 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6120 FILE *f = NULL;
6121
6122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6123
6124 // Get current setting
6125 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6126 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6127 _syscmd(cmd, buf, sizeof(buf));
6128 if (strlen(buf) > 0)
6129 bitmap = strtoul(buf, NULL, 10);
6130
6131 bitmap = strtoul(buf, NULL, 10);
6132
6133 if (ackPolicy == TRUE) { // True, unset this class
6134 bitmap &= ~class_map[class];
6135 } else { // False, set this class
6136 bitmap |= class_map[class];
6137 }
6138
6139 f = fopen(ack_filepath, "w");
6140 if (f == NULL) {
6141 fprintf(stderr, "%s: fopen failed\n", __func__);
6142 return RETURN_ERR;
6143 }
6144 fprintf(f, "%hu", bitmap);
6145 fclose(f);
6146
developerd946fd62022-12-08 18:03:28 +08006147 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6148 return RETURN_ERR;
6149 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006150 _syscmd(cmd, buf, sizeof(buf));
6151
6152 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6153 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006154}
6155
6156//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.
6157INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6158{
6159 //get the running status from driver
6160 if(!output_uint)
6161 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006162
6163 char output[16]={'\0'};
6164 char config_file[MAX_BUF_SIZE] = {0};
6165
6166 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6167 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6168 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6169 else {
6170 int device_num = atoi(output);
6171 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6172 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6173 return RETURN_ERR;
6174 }
6175 else {
6176 *output_uint = device_num;
6177 }
6178 }
6179
developer06a01d92022-09-07 16:32:39 +08006180 return RETURN_OK;
6181}
6182
6183INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6184{
6185 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006186 char str[MAX_BUF_SIZE]={'\0'};
6187 char cmd[MAX_CMD_SIZE]={'\0'};
6188 struct params params;
6189 char config_file[MAX_BUF_SIZE] = {0};
6190
6191 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006192 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006193 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6194 return RETURN_ERR;
6195 }
6196 sprintf(str, "%d", number);
6197 params.name = "max_num_sta";
6198 params.value = str;
6199
6200 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6201 int ret = wifi_hostapdWrite(config_file, &params, 1);
6202 if (ret) {
6203 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6204 ,__func__, ret);
6205 }
6206
6207 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6208 if (ret) {
6209 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6210 ,__func__, ret);
6211 }
6212 wifi_reloadAp(apIndex);
6213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6214
6215 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006216}
6217
6218//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.
6219INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6220{
6221 //get the current threshold
6222 if(!output_uint)
6223 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006224 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6225 if (*output_uint == 0)
6226 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006227 return RETURN_OK;
6228}
6229
6230INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6231{
6232 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006233 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6234 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006235 return RETURN_ERR;
6236}
6237
6238//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.
6239INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6240{
6241 if(!output_uint)
6242 return RETURN_ERR;
6243 *output_uint = 3;
6244 return RETURN_OK;
6245}
6246
6247//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6248INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6249{
6250 if(!output_uint)
6251 return RETURN_ERR;
6252 *output_uint = 3;
6253 return RETURN_OK;
6254}
6255
6256//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.
6257INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6258{
6259 if(!output_in_seconds)
6260 return RETURN_ERR;
6261 *output_in_seconds = 0;
6262 return RETURN_OK;
6263}
6264
6265//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
6266INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6267{
6268 if(!output || apIndex>=MAX_APS)
6269 return RETURN_ERR;
6270 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006271 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006272 return RETURN_OK;
6273}
6274
6275//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6276INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6277{
developer587c1b62022-09-27 15:58:59 +08006278 char config_file[128] = {0};
6279 char wpa[16] = {0};
6280 char key_mgmt[64] = {0};
6281 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006282 if (!output)
6283 return RETURN_ERR;
6284
6285 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006286 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006287
developer587c1b62022-09-27 15:58:59 +08006288 strcpy(output, "None");//Copying "None" to output string for default case
6289 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006290 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006291 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006292 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006293 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006294 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006295 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006296 snprintf(output, 32, "WPA-WPA2-Personal");
6297
6298 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006299 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006300 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006301 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006302 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006303 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006304 snprintf(output, 32, "WPA-WPA2-Enterprise");
6305 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006306 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006307 snprintf(output, 32, "WPA3-Personal");
6308 else
developer4a359672022-10-13 15:30:46 +08006309 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006310 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6311 snprintf(output, 32, "WPA3-Enterprise");
6312 }
developer06a01d92022-09-07 16:32:39 +08006313
6314 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6315 return RETURN_OK;
6316#if 0
6317 //TODO: need to revisit below implementation
6318 char securityType[32], authMode[32];
6319 int enterpriseMode=0;
6320
6321 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6322 if(!output)
6323 return RETURN_ERR;
6324
6325 wifi_getApBeaconType(apIndex, securityType);
6326 strcpy(output,"None");//By default, copying "None" to output string
6327 if (strncmp(securityType,"None", strlen("None")) == 0)
6328 return RETURN_OK;
6329
6330 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6331 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6332
6333 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6334 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6335 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6336 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6337 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6338 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6340
6341 return RETURN_OK;
6342#endif
6343}
6344
6345INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6346{
6347 char securityType[32];
6348 char authMode[32];
6349
6350 //store settings and wait for wifi up to apply
6351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6352 if(!encMode)
6353 return RETURN_ERR;
6354
developer06a01d92022-09-07 16:32:39 +08006355 if (strcmp(encMode, "None")==0)
6356 {
6357 strcpy(securityType,"None");
6358 strcpy(authMode,"None");
6359 }
6360 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6361 {
6362 strcpy(securityType,"WPAand11i");
6363 strcpy(authMode,"PSKAuthentication");
6364 }
6365 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6366 {
6367 strcpy(securityType,"WPAand11i");
6368 strcpy(authMode,"EAPAuthentication");
6369 }
6370 else if (strcmp(encMode, "WPA-Personal")==0)
6371 {
6372 strcpy(securityType,"WPA");
6373 strcpy(authMode,"PSKAuthentication");
6374 }
6375 else if (strcmp(encMode, "WPA-Enterprise")==0)
6376 {
6377 strcpy(securityType,"WPA");
6378 strcpy(authMode,"EAPAuthentication");
6379 }
6380 else if (strcmp(encMode, "WPA2-Personal")==0)
6381 {
6382 strcpy(securityType,"11i");
6383 strcpy(authMode,"PSKAuthentication");
6384 }
6385 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6386 {
6387 strcpy(securityType,"11i");
6388 strcpy(authMode,"EAPAuthentication");
6389 }
developer587c1b62022-09-27 15:58:59 +08006390 else if (strcmp(encMode, "WPA3-Personal") == 0)
6391 {
6392 strcpy(securityType,"11i");
6393 strcpy(authMode,"SAEAuthentication");
6394 }
developer4a359672022-10-13 15:30:46 +08006395 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006396 {
6397 strcpy(securityType, "11i");
6398 strcpy(authMode, "PSK-SAEAuthentication");
6399 }
developer587c1b62022-09-27 15:58:59 +08006400 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6401 {
6402 strcpy(securityType,"11i");
6403 strcpy(authMode,"EAP_192-bit_Authentication");
6404 }
developer06a01d92022-09-07 16:32:39 +08006405 else
6406 {
6407 strcpy(securityType,"None");
6408 strcpy(authMode,"None");
6409 }
6410 wifi_setApBeaconType(apIndex, securityType);
6411 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6412 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6413
6414 return RETURN_OK;
6415}
6416
6417
6418//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6419// output_string must be pre-allocated as 64 character string by caller
6420// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6421INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6422{
developer30423732022-12-01 16:17:49 +08006423 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006424 char config_file[MAX_BUF_SIZE] = {0};
6425
6426 if(output_string==NULL)
6427 return RETURN_ERR;
6428
6429 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6430 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6431
6432 if(strcmp(buf,"0")==0)
6433 {
6434 printf("wpa_mode is %s ......... \n",buf);
6435 return RETURN_ERR;
6436 }
6437
6438 wifi_dbg_printf("\nFunc=%s\n",__func__);
6439 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6440 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6441 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6442
6443 return RETURN_OK;
6444}
6445
6446// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6447// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6448INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6449{
6450 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6451 struct params params={'\0'};
6452 int ret;
6453 char config_file[MAX_BUF_SIZE] = {0};
6454
6455 if(NULL == preSharedKey)
6456 return RETURN_ERR;
6457
6458 params.name = "wpa_passphrase";
6459
6460 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6461 {
6462 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6463 return RETURN_ERR;
6464 }
6465 params.value = preSharedKey;
6466 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6467 ret = wifi_hostapdWrite(config_file, &params, 1);
6468 if(!ret)
6469 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6470 return ret;
6471 //TODO: call hostapd_cli for dynamic_config_control
6472}
6473
6474//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6475// outputs the passphrase, maximum 63 characters
6476INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6477{
6478 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6479
6480 wifi_dbg_printf("\nFunc=%s\n",__func__);
6481 if (NULL == output_string)
6482 return RETURN_ERR;
6483
6484 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6485 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6486 if(strcmp(buf,"0")==0)
6487 {
6488 printf("wpa_mode is %s ......... \n",buf);
6489 return RETURN_ERR;
6490 }
6491
6492 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6493 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6494
6495 return RETURN_OK;
6496}
6497
6498// sets the passphrase enviornment variable, max 63 characters
6499INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6500{
6501 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6502 struct params params={'\0'};
6503 char config_file[MAX_BUF_SIZE] = {0};
6504 int ret;
6505
6506 if(NULL == passPhrase)
6507 return RETURN_ERR;
6508
6509 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6510 {
6511 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6512 return RETURN_ERR;
6513 }
6514 params.name = "wpa_passphrase";
6515 params.value = passPhrase;
6516 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6517 ret=wifi_hostapdWrite(config_file,&params,1);
6518 if(!ret)
6519 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6520
6521 return ret;
6522}
6523
6524//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.
6525INT wifi_setApSecurityReset(INT apIndex)
6526{
developer8d583982022-09-20 11:28:22 +08006527 char original_config_file[64] = {0};
6528 char current_config_file[64] = {0};
6529 char buf[64] = {0};
6530 char cmd[64] = {0};
6531 char wpa[4] = {0};
6532 char wpa_psk[64] = {0};
6533 char wpa_passphrase[64] = {0};
6534 char wpa_psk_file[128] = {0};
6535 char wpa_key_mgmt[64] = {0};
6536 char wpa_pairwise[32] = {0};
6537 wifi_band band;
6538 struct params list[6];
6539
6540 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6541
6542 band = wifi_index_to_band(apIndex);
6543 if (band == band_2_4)
6544 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006545 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006546 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006547 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006548 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6549 else
6550 return RETURN_ERR;
6551
6552 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6553 list[0].name = "wpa";
6554 list[0].value = wpa;
6555
6556 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6557 list[1].name = "wpa_psk";
6558 list[1].value = wpa_psk;
6559
6560 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6561 list[2].name = "wpa_passphrase";
6562 list[2].value = wpa_passphrase;
6563
6564 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6565
6566 if (strlen(wpa_psk_file) == 0)
6567 strcpy(wpa_psk_file, PSK_FILE);
6568
6569 if (access(wpa_psk_file, F_OK) != 0) {
6570 sprintf(cmd, "touch %s", wpa_psk_file);
6571 _syscmd(cmd, buf, sizeof(buf));
6572 }
6573 list[3].name = "wpa_psk_file";
6574 list[3].value = wpa_psk_file;
6575
6576 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6577 list[4].name = "wpa_key_mgmt";
6578 list[4].value = wpa_key_mgmt;
6579
6580 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6581 list[5].name = "wpa_pairwise";
6582 list[5].value = wpa_pairwise;
6583
6584 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6585 wifi_hostapdWrite(current_config_file, list, 6);
6586
6587 wifi_setApEnable(apIndex, FALSE);
6588 wifi_setApEnable(apIndex, TRUE);
6589
6590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6591 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006592}
6593
6594//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).
6595INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6596{
developer8f2ddd52022-09-13 15:39:24 +08006597 char config_file[64] = {0};
6598 char buf[64] = {0};
6599 char cmd[256] = {0};
6600
6601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6602
developer06a01d92022-09-07 16:32:39 +08006603 if(!IP_output || !Port_output || !RadiusSecret_output)
6604 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006605
developer8f2ddd52022-09-13 15:39:24 +08006606 // Read the first matched config
6607 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6608 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6609 _syscmd(cmd, buf, sizeof(buf));
6610 strncpy(IP_output, buf, 64);
6611
6612 memset(buf, 0, sizeof(buf));
6613 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6614 _syscmd(cmd, buf, sizeof(buf));
6615 *Port_output = atoi(buf);
6616
6617 memset(buf, 0, sizeof(buf));
6618 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6619 _syscmd(cmd, buf, sizeof(buf));
6620 strncpy(RadiusSecret_output, buf, 64);
6621
6622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006623 return RETURN_OK;
6624}
6625
6626INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6627{
developer8f2ddd52022-09-13 15:39:24 +08006628 char config_file[64] = {0};
6629 char port_str[8] = {0};
6630 char cmd[256] = {0};
6631 char buf[128] = {0};
6632
6633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6634
6635 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6636
6637 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6638 _syscmd(cmd, buf, sizeof(buf));
6639 memset(cmd, 0, sizeof(cmd));
6640
6641 snprintf(port_str, sizeof(port_str), "%d", port);
6642 if (strlen(buf) == 0)
6643 // Append
6644 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6645 "auth_server_addr=%s\\n"
6646 "auth_server_port=%s\\n"
6647 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6648 else {
6649 // Delete the three lines setting after the "# radius 1" comment
6650 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6651 _syscmd(cmd, buf, sizeof(buf));
6652 memset(cmd, 0, sizeof(cmd));
6653 // Use "# radius 1" comment to find the location to insert the radius setting
6654 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6655 "# radius 1\\n"
6656 "auth_server_addr=%s\\n"
6657 "auth_server_port=%s\\n"
6658 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6659 }
6660 if(_syscmd(cmd, buf, sizeof(buf))) {
6661 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6662 return RETURN_ERR;
6663 }
6664
6665 wifi_reloadAp(apIndex);
6666 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6667 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006668}
6669
6670INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6671{
developer8f2ddd52022-09-13 15:39:24 +08006672 char config_file[64] = {0};
6673 char buf[64] = {0};
6674 char cmd[256] = {0};
6675
6676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6677
developer06a01d92022-09-07 16:32:39 +08006678 if(!IP_output || !Port_output || !RadiusSecret_output)
6679 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006680
6681 // Read the second matched config
6682 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6683 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6684 _syscmd(cmd, buf, sizeof(buf));
6685 strncpy(IP_output, buf, 64);
6686
6687 memset(buf, 0, sizeof(buf));
6688 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6689 _syscmd(cmd, buf, sizeof(buf));
6690 *Port_output = atoi(buf);
6691
6692 memset(buf, 0, sizeof(buf));
6693 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6694 _syscmd(cmd, buf, sizeof(buf));
6695 strncpy(RadiusSecret_output, buf, 64);
6696
6697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006698 return RETURN_OK;
6699}
6700
6701INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6702{
developer8f2ddd52022-09-13 15:39:24 +08006703 char config_file[64] = {0};
6704 char port_str[8] = {0};
6705 char cmd[256] = {0};
6706 char buf[128] = {0};
6707
6708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6709
6710 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6711
6712 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6713 _syscmd(cmd, buf, sizeof(buf));
6714 memset(cmd, 0, sizeof(cmd));
6715
6716 snprintf(port_str, sizeof(port_str), "%d", port);
6717 if (strlen(buf) == 0)
6718 // Append
6719 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6720 "auth_server_addr=%s\\n"
6721 "auth_server_port=%s\\n"
6722 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6723 else {
6724 // Delete the three lines setting after the "# radius 2" comment
6725 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6726 _syscmd(cmd, buf, sizeof(buf));
6727 memset(cmd, 0, sizeof(cmd));
6728 // Use "# radius 2" comment to find the location to insert the radius setting
6729 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6730 "# radius 2\\n"
6731 "auth_server_addr=%s\\n"
6732 "auth_server_port=%s\\n"
6733 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6734 }
6735 if(_syscmd(cmd, buf, sizeof(buf))) {
6736 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6737 return RETURN_ERR;
6738 }
6739
6740 wifi_reloadAp(apIndex);
6741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6742 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006743}
6744
6745//RadiusSettings
6746INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6747{
6748 if(!output)
6749 return RETURN_ERR;
6750
6751 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6752 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6753 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6754 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6755 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6756 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.
6757 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6758 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6759 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6760 //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.
6761
6762 return RETURN_OK;
6763}
6764
6765INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6766{
6767 //store the paramters, and apply instantly
6768 return RETURN_ERR;
6769}
6770
6771//Device.WiFi.AccessPoint.{i}.WPS.Enable
6772//Enables or disables WPS functionality for this access point.
6773// outputs the WPS enable state of this ap in output_bool
6774INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6775{
developerd946fd62022-12-08 18:03:28 +08006776 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006777 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006778 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006779 return RETURN_ERR;
developerd946fd62022-12-08 18:03:28 +08006780 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6781 return RETURN_ERR;
6782 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006783 _syscmd(cmd, buf, sizeof(buf));
6784 if(strstr(buf, "configured"))
6785 *output_bool=TRUE;
6786 else
6787 *output_bool=FALSE;
6788
6789 return RETURN_OK;
6790}
6791
6792//Device.WiFi.AccessPoint.{i}.WPS.Enable
6793// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6794INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6795{
6796 char config_file[MAX_BUF_SIZE] = {0};
6797 struct params params;
6798
developer06a01d92022-09-07 16:32:39 +08006799 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6800 //store the paramters, and wait for wifi up to apply
6801 params.name = "wps_state";
6802 params.value = enable ? "2":"0";
6803
6804 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6805 wifi_hostapdWrite(config_file, &params, 1);
6806 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6807 wifi_reloadAp(apIndex);
6808
6809 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6810 return RETURN_OK;
6811}
6812
6813//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
6814INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6815{
6816 if(!output)
6817 return RETURN_ERR;
6818 snprintf(output, 128, "PushButton,PIN");
6819 return RETURN_OK;
6820}
6821
6822//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6823//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.
6824// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6825INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6826{
6827 if(!output)
6828 return RETURN_ERR;
6829 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6830
6831 return RETURN_OK;
6832}
6833
6834//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6835// 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
6836INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6837{
6838 //apply instantly. No setting need to be stored.
6839 char methods[MAX_BUF_SIZE], *token, *next_token;
6840 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6841 struct params params;
6842
developer5b398df2022-11-17 20:39:48 +08006843 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006844 return RETURN_ERR;
6845 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6846 //store the paramters, and wait for wifi up to apply
6847
6848 snprintf(methods, sizeof(methods), "%s", methodString);
6849 for(token=methods; *token; token=next_token)
6850 {
6851 strtok_r(token, ",", &next_token);
6852 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6853 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6854 else if(*token=='E')
6855 {
6856 if(!strcmp(methods, "Ethernet"))
6857 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6858 else if(!strcmp(methods, "ExternalNFCToken"))
6859 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6860 else
6861 printf("%s: Unknown WpsConfigMethod\n", __func__);
6862 }
6863 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6864 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6865 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6866 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6867 else if(*token=='P' )
6868 {
6869 if(!strcmp(token, "PushButton"))
6870 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6871 else if(!strcmp(token, "PIN"))
6872 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6873 else
6874 printf("%s: Unknown WpsConfigMethod\n", __func__);
6875 }
6876 else
6877 printf("%s: Unknown WpsConfigMethod\n", __func__);
6878 }
6879 params.name = "config_methods";
6880 params.value = config_methods;
6881 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6882 wifi_hostapdWrite(config_file, &params, 1);
6883 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6884 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6885
6886 return RETURN_OK;
6887}
6888
6889// outputs the pin value, ulong_pin must be allocated by the caller
6890INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6891{
6892 char buf[MAX_BUF_SIZE] = {0};
6893 char cmd[MAX_CMD_SIZE] = {0};
6894
developer5b398df2022-11-17 20:39:48 +08006895 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08006896 return RETURN_ERR;
6897 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6898 _syscmd(cmd, buf, sizeof(buf));
6899 if(strlen(buf) > 0)
6900 *output_ulong=strtoul(buf, NULL, 10);
6901
6902 return RETURN_OK;
6903}
6904
6905// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6906INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6907{
6908 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6909 char ap_pin[16] = {0};
6910 char buf[MAX_BUF_SIZE] = {0};
6911 char config_file[MAX_BUF_SIZE] = {0};
6912 ULONG prev_pin = 0;
6913 struct params params;
6914
developer06a01d92022-09-07 16:32:39 +08006915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6916 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6917 params.name = "ap_pin";
6918 params.value = ap_pin;
6919 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6920 wifi_hostapdWrite(config_file, &params, 1);
6921 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6922 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6923
6924 return RETURN_OK;
6925}
6926
6927// Output string is either Not configured or Configured, max 32 characters
6928INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6929{
developerd946fd62022-12-08 18:03:28 +08006930 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006931 char cmd[MAX_CMD_SIZE];
6932 char buf[MAX_BUF_SIZE]={0};
6933
developer5b398df2022-11-17 20:39:48 +08006934 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08006935 return RETURN_ERR;
6936 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6937 snprintf(output_string, 32, "Not configured");
developerd946fd62022-12-08 18:03:28 +08006938 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6939 return RETURN_ERR;
6940 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006941 _syscmd(cmd, buf, sizeof(buf));
6942
developer348e3d92022-09-13 14:48:41 +08006943 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006944 snprintf(output_string, 32, "Configured");
6945 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6946
6947 return RETURN_OK;
6948}
6949
6950// sets the WPS pin for this AP
6951INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6952{
developerd946fd62022-12-08 18:03:28 +08006953 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006954 char cmd[MAX_CMD_SIZE];
6955 char buf[MAX_BUF_SIZE]={0};
6956 BOOL enable;
6957
developer06a01d92022-09-07 16:32:39 +08006958 wifi_getApEnable(apIndex, &enable);
6959 if (!enable)
6960 return RETURN_ERR;
6961 wifi_getApWpsEnable(apIndex, &enable);
6962 if (!enable)
6963 return RETURN_ERR;
6964
developerd946fd62022-12-08 18:03:28 +08006965 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6966 return RETURN_ERR;
6967 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08006968 _syscmd(cmd, buf, sizeof(buf));
6969 if((strstr(buf, "OK"))!=NULL)
6970 return RETURN_OK;
6971
6972 return RETURN_ERR;
6973}
6974
6975// This function is called when the WPS push button has been pressed for this AP
6976INT wifi_setApWpsButtonPush(INT apIndex)
6977{
6978 char cmd[MAX_CMD_SIZE];
6979 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08006980 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006981 BOOL enable=FALSE;
6982
developer06a01d92022-09-07 16:32:39 +08006983 wifi_getApEnable(apIndex, &enable);
6984 if (!enable)
6985 return RETURN_ERR;
6986
6987 wifi_getApWpsEnable(apIndex, &enable);
6988 if (!enable)
6989 return RETURN_ERR;
6990
developerd946fd62022-12-08 18:03:28 +08006991 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6992 return RETURN_ERR;
6993
6994 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 +08006995 _syscmd(cmd, buf, sizeof(buf));
6996
6997 if((strstr(buf, "OK"))!=NULL)
6998 return RETURN_OK;
6999 return RETURN_ERR;
7000}
7001
7002// cancels WPS mode for this AP
7003INT wifi_cancelApWPS(INT apIndex)
7004{
developerd946fd62022-12-08 18:03:28 +08007005 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007006 char cmd[MAX_CMD_SIZE];
7007 char buf[MAX_BUF_SIZE]={0};
7008
developerd946fd62022-12-08 18:03:28 +08007009 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7010 return RETURN_ERR;
7011 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007012 _syscmd(cmd,buf, sizeof(buf));
7013
7014 if((strstr(buf, "OK"))!=NULL)
7015 return RETURN_OK;
7016 return RETURN_ERR;
7017}
7018
7019//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7020//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7021INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7022{
developerd946fd62022-12-08 18:03:28 +08007023 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007024 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007025 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007026 char cmd[256] = {0}, buf[2048] = {0};
7027 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007028 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007029 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007030 wifi_associated_dev_t *dev=NULL;
7031
7032 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7033 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007034 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7035 return RETURN_ERR;
7036 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007037 _syscmd(cmd,buf,sizeof(buf));
7038 *output_array_size = atoi(buf);
7039
7040 if (*output_array_size <= 0)
7041 return RETURN_OK;
7042
7043 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7044 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007045 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007046 _syscmd(cmd,buf,sizeof(buf));
7047 f = fopen("/tmp/connected_devices.txt", "r");
7048 if (f==NULL)
7049 {
7050 *output_array_size=0;
7051 return RETURN_ERR;
7052 }
developer30423732022-12-01 16:17:49 +08007053 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007054 {
7055 param = strtok(line,"=");
7056 value = strtok(NULL,"=");
7057
7058 if( strcmp("flags",param) == 0 )
7059 {
7060 value[strlen(value)-1]='\0';
7061 if(strstr (value,"AUTHORIZED") != NULL )
7062 {
7063 dev[auth_temp].cli_AuthenticationState = 1;
7064 dev[auth_temp].cli_Active = 1;
7065 auth_temp++;
7066 read_flag=1;
7067 }
7068 }
7069 if(read_flag==1)
7070 {
7071 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7072 {
7073 value[strlen(value)-1]='\0';
7074 sscanf(value, "%x:%x:%x:%x:%x:%x",
7075 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7076 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7077 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7078 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7079 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7080 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7081 mac_temp++;
7082 read_flag=0;
7083 }
7084 }
7085 }
7086 *output_array_size = auth_temp;
7087 auth_temp=0;
7088 mac_temp=0;
7089 free(line);
7090 fclose(f);
7091 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7092 return RETURN_OK;
7093}
7094
7095#define MACADDRESS_SIZE 6
7096
7097INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7098{
7099 FILE *fp = NULL;
7100 char str[MAX_BUF_SIZE] = {0};
7101 int wificlientindex = 0 ;
7102 int count = 0;
7103 int signalstrength = 0;
7104 int arr[MACADDRESS_SIZE] = {0};
7105 unsigned char mac[MACADDRESS_SIZE] = {0};
7106 UINT wifi_count = 0;
7107 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7108 char pipeCmd[MAX_CMD_SIZE] = {0};
7109
7110 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7111 *output_array_size = 0;
7112 *associated_dev_array = NULL;
7113
7114 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7115 fp = popen(pipeCmd, "r");
7116 if (fp == NULL)
7117 {
7118 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7119 return RETURN_ERR;
7120 }
7121
7122 /* Read the output a line at a time - output it. */
7123 fgets(str, sizeof(str)-1, fp);
7124 wifi_count = (unsigned int) atoi ( str );
7125 *output_array_size = wifi_count;
7126 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7127 pclose(fp);
7128
7129 if(wifi_count == 0)
7130 {
7131 return RETURN_OK;
7132 }
7133 else
7134 {
7135 wifi_associated_dev3_t* temp = NULL;
7136 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7137 if(temp == NULL)
7138 {
7139 printf("Error Statement. Insufficient memory \n");
7140 return RETURN_ERR;
7141 }
7142
7143 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7144 system(pipeCmd);
7145 memset(pipeCmd,0,sizeof(pipeCmd));
7146 if(apIndex == 0)
7147 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7148 else if(apIndex == 1)
7149 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7150 system(pipeCmd);
7151
7152 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7153 if(fp == NULL)
7154 {
7155 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007156 free(temp);
developer06a01d92022-09-07 16:32:39 +08007157 return RETURN_ERR;
7158 }
7159 fclose(fp);
7160
developer30423732022-12-01 16:17:49 +08007161 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007162 fp = popen(pipeCmd, "r");
7163 if(fp)
7164 {
7165 for(count =0 ; count < wifi_count; count++)
7166 {
7167 fgets(str, MAX_BUF_SIZE, fp);
7168 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7169 {
7170 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7171 {
7172 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7173
7174 }
7175 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7176 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]);
7177 }
7178 temp[count].cli_AuthenticationState = 1; //TODO
7179 temp[count].cli_Active = 1; //TODO
7180 }
7181 pclose(fp);
7182 }
7183
developer30423732022-12-01 16:17:49 +08007184 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 +08007185 fp = popen(pipeCmd, "r");
7186 if(fp)
7187 {
7188 pclose(fp);
7189 }
7190 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7191 if(fp)
7192 {
7193 for(count =0 ; count < wifi_count ;count++)
7194 {
7195 fgets(str, MAX_BUF_SIZE, fp);
7196 signalstrength = atoi(str);
7197 temp[count].cli_SignalStrength = signalstrength;
7198 temp[count].cli_RSSI = signalstrength;
7199 temp[count].cli_SNR = signalstrength + 95;
7200 }
7201 pclose(fp);
7202 }
7203
7204
7205 if((apIndex == 0) || (apIndex == 4))
7206 {
7207 for(count =0 ; count < wifi_count ;count++)
7208 {
7209 strcpy(temp[count].cli_OperatingStandard,"g");
7210 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7211 }
7212
7213 //BytesSent
developer30423732022-12-01 16:17:49 +08007214 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 +08007215 fp = popen(pipeCmd, "r");
7216 if(fp)
7217 {
7218 pclose(fp);
7219 }
7220 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7221 if(fp)
7222 {
7223 for (count = 0; count < wifi_count; count++)
7224 {
7225 fgets(str, MAX_BUF_SIZE, fp);
7226 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7227 }
7228 pclose(fp);
7229 }
7230
7231 //BytesReceived
developer30423732022-12-01 16:17:49 +08007232 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 +08007233 fp = popen(pipeCmd, "r");
7234 if (fp)
7235 {
7236 pclose(fp);
7237 }
7238 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7239 if (fp)
7240 {
7241 for (count = 0; count < wifi_count; count++)
7242 {
7243 fgets(str, MAX_BUF_SIZE, fp);
7244 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7245 }
7246 pclose(fp);
7247 }
7248
7249 //PacketsSent
developer30423732022-12-01 16:17:49 +08007250 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 +08007251 fp = popen(pipeCmd, "r");
7252 if (fp)
7253 {
7254 pclose(fp);
7255 }
7256
7257 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7258 if (fp)
7259 {
7260 for (count = 0; count < wifi_count; count++)
7261 {
7262 fgets(str, MAX_BUF_SIZE, fp);
7263 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7264 }
7265 pclose(fp);
7266 }
7267
7268 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007269 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 +08007270 fp = popen(pipeCmd, "r");
7271 if (fp)
7272 {
7273 pclose(fp);
7274 }
7275 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7276 if (fp)
7277 {
7278 for (count = 0; count < wifi_count; count++)
7279 {
7280 fgets(str, MAX_BUF_SIZE, fp);
7281 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7282 }
7283 pclose(fp);
7284 }
7285
7286 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007287 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 +08007288 fp = popen(pipeCmd, "r");
7289 if (fp)
7290 {
7291 pclose(fp);
7292 }
7293 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7294 if (fp)
7295 {
7296 for (count = 0; count < wifi_count; count++)
7297 {
7298 fgets(str, MAX_BUF_SIZE, fp);
7299 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7300 }
7301 pclose(fp);
7302 }
7303
7304 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007305 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 +08007306 fp = popen(pipeCmd, "r");
7307 if (fp)
7308 {
7309 pclose(fp);
7310 }
7311 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7312 if (fp)
7313 {
7314 for (count = 0; count < wifi_count; count++)
7315 {
7316 fgets(str, MAX_BUF_SIZE, fp);
7317 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7318 }
7319 pclose(fp);
7320 }
7321
7322 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007323 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 +08007324 fp = popen(pipeCmd, "r");
7325 if (fp)
7326 {
7327 pclose(fp);
7328 }
7329 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7330 if (fp)
7331 {
7332 for (count = 0; count < wifi_count; count++)
7333 {
7334 fgets(str, MAX_BUF_SIZE, fp);
7335 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7336 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7337 }
7338 pclose(fp);
7339 }
7340
7341 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007342 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 +08007343 fp = popen(pipeCmd, "r");
7344 if (fp)
7345 {
7346 pclose(fp);
7347 }
7348 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7349 if (fp)
7350 {
7351 for (count = 0; count < wifi_count; count++)
7352 {
7353 fgets(str, MAX_BUF_SIZE, fp);
7354 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7355 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7356 }
7357 pclose(fp);
7358 }
7359
7360 }
7361 else if ((apIndex == 1) || (apIndex == 5))
7362 {
7363 for (count = 0; count < wifi_count; count++)
7364 {
7365 strcpy(temp[count].cli_OperatingStandard, "a");
7366 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7367 temp[count].cli_BytesSent = 0;
7368 temp[count].cli_BytesReceived = 0;
7369 temp[count].cli_LastDataUplinkRate = 0;
7370 temp[count].cli_LastDataDownlinkRate = 0;
7371 temp[count].cli_PacketsSent = 0;
7372 temp[count].cli_PacketsReceived = 0;
7373 temp[count].cli_ErrorsSent = 0;
7374 }
7375 }
7376
7377 for (count = 0; count < wifi_count; count++)
7378 {
7379 temp[count].cli_Retransmissions = 0;
7380 temp[count].cli_DataFramesSentAck = 0;
7381 temp[count].cli_DataFramesSentNoAck = 0;
7382 temp[count].cli_MinRSSI = 0;
7383 temp[count].cli_MaxRSSI = 0;
7384 strncpy(temp[count].cli_InterferenceSources, "", 64);
7385 memset(temp[count].cli_IPAddress, 0, 64);
7386 temp[count].cli_RetransCount = 0;
7387 temp[count].cli_FailedRetransCount = 0;
7388 temp[count].cli_RetryCount = 0;
7389 temp[count].cli_MultipleRetryCount = 0;
7390 }
7391 *associated_dev_array = temp;
7392 }
7393 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7394 return RETURN_OK;
7395}
7396
7397int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7398{
7399 FILE *fp = NULL;
7400 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7401 char cmd[MAX_CMD_SIZE];
7402 int count = 0;
7403
7404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7405 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7406 fp = popen(cmd,"r");
7407 if(fp == NULL)
7408 {
7409 printf("Failed to run command in Function %s\n",__FUNCTION__);
7410 return 0;
7411 }
7412 if(fgets(path, sizeof(path)-1, fp) != NULL)
7413 {
7414 for(count=0;path[count]!='\n';count++)
7415 status[count]=path[count];
7416 status[count]='\0';
7417 }
7418 strcpy(wifi_status,status);
7419 pclose(fp);
7420 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7421 return RETURN_OK;
7422}
7423
7424/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7425struct hostapd_sta_param {
7426 char key[50];
7427 char value[100];
7428}
7429
7430static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7431 int i = 0;
7432
7433 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7434 if (strncmp(params[i].key,key,50) == 0){
7435 return &params[i].value;
7436 }
7437 i++;
7438 }
7439 return NULL;
7440
7441} */
7442
7443static unsigned int count_occurences(const char *buf, const char *word)
7444{
7445 unsigned int n = 0;
7446 char *ptr = strstr(buf, word);
7447
7448 while (ptr++) {
7449 n++;
7450 ptr = strstr(ptr, word);
7451 }
7452
7453 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7454 return n;
7455}
7456
7457static const char *get_line_from_str_buf(const char *buf, char *line)
7458{
7459 int i;
7460 int n = strlen(buf);
7461
7462 for (i = 0; i < n; i++) {
7463 line[i] = buf[i];
7464 if (buf[i] == '\n') {
7465 line[i] = '\0';
7466 return &buf[i + 1];
7467 }
7468 }
7469
7470 return NULL;
7471}
7472
7473INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7474{
7475 unsigned int assoc_cnt = 0;
7476 char interface_name[50] = {0};
7477 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7478 char cmd[MAX_CMD_SIZE] = {'\0'};
7479 char line[256] = {'\0'};
7480 int i = 0;
7481 int ret = 0;
7482 const char *ptr = NULL;
7483 char *key = NULL;
7484 char *val = NULL;
7485 wifi_associated_dev3_t *temp = NULL;
7486 int rssi;
7487
7488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7489
7490 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7491 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7492 return RETURN_ERR;
7493 }
7494
7495 // Example filtered output of 'iw dev' command:
7496 // Station 0a:69:72:10:d2:fa (on wifi0)
7497 // signal avg:-67 [-71, -71] dBm
7498 // Station 28:c2:1f:25:5f:99 (on wifi0)
7499 // signal avg:-67 [-71, -70] dBm
7500 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7501 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7502 return RETURN_ERR;
7503 }
7504
7505 ret = _syscmd(cmd, buf, sizeof(buf));
7506 if (ret == RETURN_ERR) {
7507 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7508 return RETURN_ERR;
7509 }
7510
7511 *output_array_size = count_occurences(buf, "Station");
7512 if (*output_array_size == 0) return RETURN_OK;
7513
7514 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7515 if (temp == NULL) {
7516 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7517 return RETURN_ERR;
7518 }
7519 *associated_dev_array = temp;
7520
7521 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7522 ptr = get_line_from_str_buf(buf, line);
7523 i = -1;
7524 while (ptr) {
7525 if (strstr(line, "Station")) {
7526 i++;
7527 key = strtok(line, " ");
7528 val = strtok(NULL, " ");
7529 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7530 &temp[i].cli_MACAddress[0],
7531 &temp[i].cli_MACAddress[1],
7532 &temp[i].cli_MACAddress[2],
7533 &temp[i].cli_MACAddress[3],
7534 &temp[i].cli_MACAddress[4],
7535 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7536 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7537 free(*associated_dev_array);
7538 return RETURN_ERR;
7539 }
7540 }
7541 else if (i < 0) {
7542 ptr = get_line_from_str_buf(ptr, line);
7543 continue; // We didn't detect 'station' entry yet
7544 }
7545 else if (strstr(line, "signal avg")) {
7546 key = strtok(line, ":");
7547 val = strtok(NULL, " ");
7548 if (sscanf(val, "%d", &rssi) <= 0 ) {
7549 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7550 free(*associated_dev_array);
7551 return RETURN_ERR;
7552 }
7553 temp[i].cli_RSSI = rssi;
7554 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7555 }
7556 // Here other fields can be parsed if added to filter of 'iw dev' command
7557
7558 ptr = get_line_from_str_buf(ptr, line);
7559 };
7560
7561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7562
7563 return RETURN_OK;
7564}
7565
7566#if 0
7567//To-do
7568INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7569{
7570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7571
7572 //Using different approach to get required WiFi Parameters from system available commands
7573#if 0
7574 FILE *f;
7575 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7576 char cmd[256], buf[2048];
7577 char *param , *value, *line=NULL;
7578 size_t len = 0;
7579 ssize_t nread;
7580 wifi_associated_dev3_t *dev=NULL;
7581 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007582 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007583 _syscmd(cmd,buf,sizeof(buf));
7584 *output_array_size = atoi(buf);
7585
7586 if (*output_array_size <= 0)
7587 return RETURN_OK;
7588
7589 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7590 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007591 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007592 _syscmd(cmd,buf,sizeof(buf));
7593 f = fopen("/tmp/connected_devices.txt", "r");
7594 if (f==NULL)
7595 {
7596 *output_array_size=0;
7597 return RETURN_ERR;
7598 }
7599 while ((nread = getline(&line, &len, f)) != -1)
7600 {
7601 param = strtok(line,"=");
7602 value = strtok(NULL,"=");
7603
7604 if( strcmp("flags",param) == 0 )
7605 {
7606 value[strlen(value)-1]='\0';
7607 if(strstr (value,"AUTHORIZED") != NULL )
7608 {
7609 dev[auth_temp].cli_AuthenticationState = 1;
7610 dev[auth_temp].cli_Active = 1;
7611 auth_temp++;
7612 read_flag=1;
7613 }
7614 }
7615 if(read_flag==1)
7616 {
7617 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7618 {
7619 value[strlen(value)-1]='\0';
7620 sscanf(value, "%x:%x:%x:%x:%x:%x",
7621 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7622 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7623 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7624 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7625 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7626 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7627
7628 }
7629 else if( strcmp("rx_packets",param) == 0 )
7630 {
7631 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7632 }
7633
7634 else if( strcmp("tx_packets",param) == 0 )
7635 {
7636 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7637 }
7638
7639 else if( strcmp("rx_bytes",param) == 0 )
7640 {
7641 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7642 }
7643
7644 else if( strcmp("tx_bytes",param) == 0 )
7645 {
7646 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7647 mac_temp++;
7648 read_flag=0;
7649 }
7650 }
7651 }
7652
7653 *output_array_size = auth_temp;
7654 auth_temp=0;
7655 mac_temp=0;
7656 free(line);
7657 fclose(f);
7658#endif
7659 char interface_name[MAX_BUF_SIZE] = {0};
7660 char wifi_status[MAX_BUF_SIZE] = {0};
7661 char hostapdconf[MAX_BUF_SIZE] = {0};
7662
7663 wifi_associated_dev3_t *dev_array = NULL;
7664 ULONG wifi_count = 0;
7665
7666 *associated_dev_array = NULL;
7667 *output_array_size = 0;
7668
7669 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7670 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7671 {
7672 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7673
7674 GetInterfaceName(interface_name, hostapdconf);
7675
7676 if(strlen(interface_name) > 1)
7677 {
7678 wifihal_interfacestatus(wifi_status,interface_name);
7679 if(strcmp(wifi_status,"RUNNING") == 0)
7680 {
7681 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7682
7683 *associated_dev_array = dev_array;
7684 *output_array_size = wifi_count;
7685 }
7686 else
7687 {
7688 *associated_dev_array = NULL;
7689 }
7690 }
7691 }
7692
7693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7694 return RETURN_OK;
7695}
7696#endif
7697
7698/* getIPAddress function */
7699/**
7700* @description Returning IpAddress of the Matched String
7701*
7702* @param
7703* @str Having MacAddress
7704* @ipaddr Having ipaddr
7705* @return The status of the operation
7706* @retval RETURN_OK if successful
7707* @retval RETURN_ERR if any error is detected
7708*
7709*/
7710
7711INT getIPAddress(char *str,char *ipaddr)
7712{
7713 FILE *fp = NULL;
7714 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7715 int LeaseTime = 0,ret = 0;
7716 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7717 {
7718 return RETURN_ERR;
7719 }
7720
7721 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7722 {
7723 /*
7724 Sample:sss
7725 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7726 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7727 */
7728 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08007729 &(LeaseTime),
7730 phyAddr,
7731 ipAddr,
7732 hostName
7733 );
developer06a01d92022-09-07 16:32:39 +08007734 if(ret != 4)
7735 continue;
7736 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08007737 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08007738 }
developerd946fd62022-12-08 18:03:28 +08007739 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08007740 return RETURN_OK;
7741}
7742
7743/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7744/**
7745* @description Returning Inactive wireless connected clients informations
7746*
7747* @param
7748* @filename Holding private_wifi 2g/5g content files
7749* @associated_dev_array Having inactiv wireless clients informations
7750* @output_array_size Returning Inactive wireless counts
7751* @return The status of the operation
7752* @retval RETURN_OK if successful
7753* @retval RETURN_ERR if any error is detected
7754*
7755*/
7756
7757INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7758{
7759 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7760 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7761 FILE *fp = NULL;
7762 int arr[MACADDRESS_SIZE] = {0};
7763 unsigned char mac[MACADDRESS_SIZE] = {0};
7764 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7765 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7766 fp = popen(buf,"r");
7767 if(fp == NULL)
7768 return RETURN_ERR;
7769 else
7770 {
7771 fgets(path,sizeof(path),fp);
7772 maccount = atoi(path);
7773 }
7774 pclose(fp);
7775 *output_array_size = maccount;
7776 wifi_associated_dev3_t* temp = NULL;
7777 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7778 *associated_dev_array = temp;
7779 if(temp == NULL)
7780 {
7781 printf("Error Statement. Insufficient memory \n");
7782 return RETURN_ERR;
7783 }
7784 memset(buf,0,sizeof(buf));
7785 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7786 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08007787 if (fp == NULL) {
7788 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7789 return RETURN_ERR;
7790 }
developer06a01d92022-09-07 16:32:39 +08007791 for(count = 0; count < maccount ; count++)
7792 {
7793 fgets(path,sizeof(path),fp);
7794 for(i = 0; path[i]!='\n';i++)
7795 str[i]=path[i];
7796 str[i]='\0';
7797 getIPAddress(str,ipaddr);
7798 memset(buf,0,sizeof(buf));
7799 if(strlen(ipaddr) > 0)
7800 {
7801 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7802 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7803 {
7804 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7805 {
7806 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7807 {
7808 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7809
7810 }
7811 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7812 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]);
7813 }
7814 temp[count].cli_AuthenticationState = 0; //TODO
7815 temp[count].cli_Active = 0; //TODO
7816 temp[count].cli_SignalStrength = 0;
7817 }
7818 else //Active wireless clients info
7819 {
7820 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7821 {
7822 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7823 {
7824 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7825
7826 }
7827 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7828 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]);
7829 }
7830 temp[count].cli_Active = 1;
7831 }
7832 }
7833 memset(ipaddr,0,sizeof(ipaddr));
7834 }
7835 pclose(fp);
7836 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7837 return RETURN_OK;
7838}
7839//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7840//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7841//To get Band Steering Capability
7842INT wifi_getBandSteeringCapability(BOOL *support)
7843{
7844 *support = FALSE;
7845 return RETURN_OK;
7846}
7847
7848
7849//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7850//To get Band Steering enable status
7851INT wifi_getBandSteeringEnable(BOOL *enable)
7852{
7853 *enable = FALSE;
7854 return RETURN_OK;
7855}
7856
7857//To turn on/off Band steering
7858INT wifi_setBandSteeringEnable(BOOL enable)
7859{
7860 return RETURN_OK;
7861}
7862
7863//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7864//To get Band Steering AP group
7865INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7866{
7867 if (NULL == output_ApGroup)
7868 return RETURN_ERR;
7869
7870 strcpy(output_ApGroup, "1,2");
7871 return RETURN_OK;
7872}
7873
7874//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7875//to set and read the band steering BandUtilizationThreshold parameters
7876INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7877{
7878 return RETURN_ERR;
7879}
7880
7881INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7882{
7883 return RETURN_ERR;
7884}
7885
7886//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7887//to set and read the band steering RSSIThreshold parameters
7888INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7889{
7890 return RETURN_ERR;
7891}
7892
7893INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7894{
7895 return RETURN_ERR;
7896}
7897
7898
7899//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7900//to set and read the band steering physical modulation rate threshold parameters
7901INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7902{
7903 //If chip is not support, return -1
7904 return RETURN_ERR;
7905}
7906
7907INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7908{
7909 //If chip is not support, return -1
7910 return RETURN_ERR;
7911}
7912
7913//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7914//to set and read the inactivity time (in seconds) for steering under overload condition
7915INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7916{
7917 return RETURN_ERR;
7918}
7919
7920INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7921{
7922 return RETURN_ERR;
7923}
7924
7925//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7926//to set and read the inactivity time (in seconds) for steering under Idle condition
7927INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7928{
7929 return RETURN_ERR;
7930}
7931
7932INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7933{
7934 return RETURN_ERR;
7935}
7936
7937//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7938//pClientMAC[64]
7939//pSourceSSIDIndex[64]
7940//pDestSSIDIndex[64]
7941//pSteeringReason[256]
7942INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7943{
7944 //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
7945 *pSteeringTime=time(NULL);
7946 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7947 return RETURN_OK;
7948}
7949
7950INT wifi_ifConfigDown(INT apIndex)
7951{
7952 INT status = RETURN_OK;
7953 char cmd[64];
7954
7955 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7956 printf("%s: %s\n", __func__, cmd);
7957 system(cmd);
7958
7959 return status;
7960}
7961
7962INT wifi_ifConfigUp(INT apIndex)
7963{
developerd946fd62022-12-08 18:03:28 +08007964 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007965 char cmd[128];
7966 char buf[1024];
7967
developerd946fd62022-12-08 18:03:28 +08007968 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7969 return RETURN_ERR;
7970 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08007971 _syscmd(cmd, buf, sizeof(buf));
7972 return 0;
7973}
7974
7975//>> Deprecated. Replace with wifi_applyRadioSettings
7976INT wifi_pushBridgeInfo(INT apIndex)
7977{
developerd946fd62022-12-08 18:03:28 +08007978 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007979 char ip[32] = {0};
7980 char subnet[32] = {0};
7981 char bridge[32] = {0};
7982 int vlanId = 0;
7983 char cmd[128] = {0};
7984 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08007985
7986 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7987 wifi_getApVlanID(apIndex,&vlanId);
7988
developerd946fd62022-12-08 18:03:28 +08007989 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7990 return RETURN_ERR;
7991 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08007992 _syscmd(cmd,buf, sizeof(buf));
7993
7994 return 0;
7995}
7996
7997INT wifi_pushChannel(INT radioIndex, UINT channel)
7998{
developerd946fd62022-12-08 18:03:28 +08007999 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008000 char cmd[128];
8001 char buf[1024];
8002 int apIndex;
8003
8004 apIndex=(radioIndex==0)?0:1;
developerd946fd62022-12-08 18:03:28 +08008005 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8006 return RETURN_ERR;
8007 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008008 _syscmd(cmd,buf, sizeof(buf));
8009
8010 return 0;
8011}
8012
8013INT wifi_pushChannelMode(INT radioIndex)
8014{
8015 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8016 return RETURN_ERR;
8017}
8018
8019INT wifi_pushDefaultValues(INT radioIndex)
8020{
8021 //Apply Comcast specified default radio settings instantly
8022 //AMPDU=1
8023 //AMPDUFrames=32
8024 //AMPDULim=50000
8025 //txqueuelen=1000
8026
8027 return RETURN_ERR;
8028}
8029
8030INT wifi_pushTxChainMask(INT radioIndex)
8031{
8032 //Apply default TxChainMask instantly
8033 return RETURN_ERR;
8034}
8035
8036INT wifi_pushRxChainMask(INT radioIndex)
8037{
8038 //Apply default RxChainMask instantly
8039 return RETURN_ERR;
8040}
8041
8042INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8043{
8044 INT status;
8045
8046 status = wifi_setSSIDName(apIndex,ssid);
8047 wifi_setApEnable(apIndex,FALSE);
8048 wifi_setApEnable(apIndex,TRUE);
8049
8050 return status;
8051}
8052
8053INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8054{
8055 //Apply default Ssid Advertisement instantly
8056 return RETURN_ERR;
8057}
8058
8059INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8060{
8061 INT status = RETURN_ERR;
8062 *output = 0;
8063 return RETURN_ERR;
8064}
8065
8066INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8067{
8068 return RETURN_OK;
8069}
8070
8071INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8072{
8073 return RETURN_OK;
8074}
8075
8076//To-do
8077INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8078{
developereb199ae2022-09-13 14:04:27 +08008079 char output[16]={'\0'};
8080 char config_file[MAX_BUF_SIZE] = {0};
8081
8082 if (!output_string)
8083 return RETURN_ERR;
8084
8085 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8086 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8087
8088 if (strlen(output) == 0)
8089 snprintf(output_string, 64, "Disabled");
8090 else if (strncmp(output, "0", 1) == 0)
8091 snprintf(output_string, 64, "Disabled");
8092 else if (strncmp(output, "1", 1) == 0)
8093 snprintf(output_string, 64, "Optional");
8094 else if (strncmp(output, "2", 1) == 0)
8095 snprintf(output_string, 64, "Required");
8096 else {
8097 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8098 return RETURN_ERR;
8099 }
8100
8101 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008102 return RETURN_OK;
8103}
8104INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8105{
developereb199ae2022-09-13 14:04:27 +08008106 char str[MAX_BUF_SIZE]={'\0'};
8107 char cmd[MAX_CMD_SIZE]={'\0'};
8108 struct params params;
8109 char config_file[MAX_BUF_SIZE] = {0};
8110
8111 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8112 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8113 return RETURN_ERR;
8114
8115 params.name = "ieee80211w";
8116 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8117 params.value = "0";
8118 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8119 params.value = "1";
8120 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8121 params.value = "2";
8122 else{
8123 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8124 return RETURN_ERR;
8125 }
8126 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8127 wifi_hostapdWrite(config_file, &params, 1);
8128 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008129 return RETURN_OK;
8130}
8131INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8132{
8133 char output[16]={'\0'};
8134 char config_file[MAX_BUF_SIZE] = {0};
8135
8136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8137 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8138 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8139
8140 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8141 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8142
8143 return RETURN_OK;
8144}
8145
8146INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8147{
8148 return RETURN_OK;
8149}
8150
8151INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8152{
8153 return RETURN_OK;
8154}
8155
8156INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8157{
8158 return RETURN_OK;
8159}
8160
8161INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8162{
8163 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8164 char config_file[MAX_BUF_SIZE] = {0};
8165
8166 if (NULL == output)
8167 return RETURN_ERR;
8168 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8169 wifi_hostapdRead(config_file,"hw_mode",output,64);
8170
8171 if(strcmp(output,"b")==0)
8172 sprintf(output, "%s", "1,2,5.5,11");
8173 else if (strcmp(output,"a")==0)
8174 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8175 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8176 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8177
8178 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8179 return RETURN_OK;
8180}
8181
8182INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8183{
8184 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8185 char *temp;
8186 char temp_output[128];
8187 char temp_TransmitRates[128];
8188 char config_file[MAX_BUF_SIZE] = {0};
8189
8190 if (NULL == output)
8191 return RETURN_ERR;
8192
8193 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8194 wifi_hostapdRead(config_file,"supported_rates",output,64);
8195
developer5b398df2022-11-17 20:39:48 +08008196 if (strlen(output) == 0) {
8197 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8198 return RETURN_OK;
8199 }
developer06a01d92022-09-07 16:32:39 +08008200 strcpy(temp_TransmitRates,output);
8201 strcpy(temp_output,"");
8202 temp = strtok(temp_TransmitRates," ");
8203 while(temp!=NULL)
8204 {
8205 temp[strlen(temp)-1]=0;
8206 if((temp[0]=='5') && (temp[1]=='\0'))
8207 {
8208 temp="5.5";
8209 }
8210 strcat(temp_output,temp);
8211 temp = strtok(NULL," ");
8212 if(temp!=NULL)
8213 {
8214 strcat(temp_output,",");
8215 }
8216 }
8217 strcpy(output,temp_output);
8218 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8219
8220 return RETURN_OK;
8221}
8222
8223INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8224{
8225 return RETURN_OK;
8226}
8227
8228
8229INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8230{
8231 int i=0;
8232 char *temp;
developeref938762022-10-19 17:21:01 +08008233 char temp1[128] = {0};
8234 char temp_output[128] = {0};
8235 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008236 struct params params={'\0'};
8237 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008238 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008239
8240 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8241 if(NULL == output)
8242 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008243 strcpy(temp_TransmitRates,output);
8244
8245 for(i=0;i<strlen(temp_TransmitRates);i++)
8246 {
developeref938762022-10-19 17:21:01 +08008247 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008248 {
8249 continue;
8250 }
8251 else
8252 {
8253 return RETURN_ERR;
8254 }
8255 }
8256 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008257 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008258 while(temp!=NULL)
8259 {
8260 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008261 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008262 {
developeref938762022-10-19 17:21:01 +08008263 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008264 {
8265 return RETURN_ERR;
8266 }
8267 }
8268
8269 if(strcmp(temp,"5.5")==0)
8270 {
8271 strcpy(temp1,"55");
8272 }
8273 else
8274 {
8275 strcat(temp1,"0");
8276 }
8277 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008278 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008279 if(temp!=NULL)
8280 {
8281 strcat(temp_output," ");
8282 }
8283 }
8284 strcpy(output,temp_output);
8285
developer06a01d92022-09-07 16:32:39 +08008286 params.name = "supported_rates";
8287 params.value = output;
8288
8289 wifi_dbg_printf("\n%s:",__func__);
8290 wifi_dbg_printf("params.value=%s\n",params.value);
8291 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8292 wifi_hostapdWrite(config_file,&params,1);
8293 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8294
8295 return RETURN_OK;
8296}
8297
8298
8299static char *sncopy(char *dst, int dst_sz, const char *src)
8300{
8301 if (src && dst && dst_sz > 0) {
8302 strncpy(dst, src, dst_sz);
8303 dst[dst_sz - 1] = '\0';
8304 }
8305 return dst;
8306}
8307
8308static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8309{
8310 if (0 == strcmp(ht_mode, "HT40") ||
8311 0 == strcmp(ht_mode, "HT80") ||
8312 0 == strcmp(ht_mode, "HT160")) {
8313 switch (channel) {
8314 case 1 ... 7:
8315 case 36:
8316 case 44:
8317 case 52:
8318 case 60:
8319 case 100:
8320 case 108:
8321 case 116:
8322 case 124:
8323 case 132:
8324 case 140:
8325 case 149:
8326 case 157:
8327 return 1;
8328 case 8 ... 13:
8329 case 40:
8330 case 48:
8331 case 56:
8332 case 64:
8333 case 104:
8334 case 112:
8335 case 120:
8336 case 128:
8337 case 136:
8338 case 144:
8339 case 153:
8340 case 161:
8341 return -1;
8342 default:
8343 return -EINVAL;
8344 }
8345 }
8346
8347 return -EINVAL;
8348}
8349
developerb7593de2022-10-18 09:51:57 +08008350static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8351{
8352 int idx = channel%8;
8353 if (0 == strcmp(ht_mode, "HT40") ||
8354 0 == strcmp(ht_mode, "HT80") ||
8355 0 == strcmp(ht_mode, "HT160")) {
8356 switch (idx) {
8357 case 1:
8358 return 1;
8359 case 5:
8360 return -1;
8361 default:
8362 return -EINVAL;
8363 }
8364 }
8365
8366 return -EINVAL;
8367}
developer06a01d92022-09-07 16:32:39 +08008368static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8369{
8370 if (NULL == hw_mode) return;
8371
8372 if (0 == strcmp(hw_mode, "ac"))
8373 sncopy(bw_mode, bw_mode_len, "ht vht");
8374
8375 if (0 == strcmp(hw_mode, "n"))
8376 sncopy(bw_mode, bw_mode_len, "ht");
8377
8378 return;
8379}
8380
8381static int util_chan_to_freq(int chan)
8382{
8383 if (chan == 14)
8384 return 2484;
8385 else if (chan < 14)
8386 return 2407 + chan * 5;
8387 else if (chan >= 182 && chan <= 196)
8388 return 4000 + chan * 5;
8389 else
8390 return 5000 + chan * 5;
8391 return 0;
8392}
8393
developerb7593de2022-10-18 09:51:57 +08008394static int util_6G_chan_to_freq(int chan)
8395{
8396 if (chan)
8397 return 5950 + chan * 5;
8398 else
8399 return 0;
8400
8401}
developer06a01d92022-09-07 16:32:39 +08008402const int *util_unii_5g_chan2list(int chan, int width)
8403{
8404 static const int lists[] = {
8405 // <width>, <chan1>, <chan2>..., 0,
8406 20, 36, 0,
8407 20, 40, 0,
8408 20, 44, 0,
8409 20, 48, 0,
8410 20, 52, 0,
8411 20, 56, 0,
8412 20, 60, 0,
8413 20, 64, 0,
8414 20, 100, 0,
8415 20, 104, 0,
8416 20, 108, 0,
8417 20, 112, 0,
8418 20, 116, 0,
8419 20, 120, 0,
8420 20, 124, 0,
8421 20, 128, 0,
8422 20, 132, 0,
8423 20, 136, 0,
8424 20, 140, 0,
8425 20, 144, 0,
8426 20, 149, 0,
8427 20, 153, 0,
8428 20, 157, 0,
8429 20, 161, 0,
8430 20, 165, 0,
8431 40, 36, 40, 0,
8432 40, 44, 48, 0,
8433 40, 52, 56, 0,
8434 40, 60, 64, 0,
8435 40, 100, 104, 0,
8436 40, 108, 112, 0,
8437 40, 116, 120, 0,
8438 40, 124, 128, 0,
8439 40, 132, 136, 0,
8440 40, 140, 144, 0,
8441 40, 149, 153, 0,
8442 40, 157, 161, 0,
8443 80, 36, 40, 44, 48, 0,
8444 80, 52, 56, 60, 64, 0,
8445 80, 100, 104, 108, 112, 0,
8446 80, 116, 120, 124, 128, 0,
8447 80, 132, 136, 140, 144, 0,
8448 80, 149, 153, 157, 161, 0,
8449 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8450 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8451 -1 // final delimiter
8452 };
8453 const int *start;
8454 const int *p;
8455
8456 for (p = lists; *p != -1; p++) {
8457 if (*p == width) {
8458 for (start = ++p; *p != 0; p++) {
8459 if (*p == chan)
8460 return start;
8461 }
8462 }
8463 // move to the end of channel list of given width
8464 while (*p != 0) {
8465 p++;
8466 }
8467 }
8468
8469 return NULL;
8470}
8471
8472static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8473{
8474 if (NULL == ht_mode)
8475 return 0;
8476
8477 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8478 const int *chans = util_unii_5g_chan2list(channel, width);
8479 int sum = 0;
8480 int cnt = 0;
8481
8482 if (NULL == chans)
8483 return 0;
8484
8485 while (*chans) {
8486 sum += *chans;
8487 cnt++;
8488 chans++;
8489 }
developer30423732022-12-01 16:17:49 +08008490 if (cnt == 0)
8491 return 0;
developer06a01d92022-09-07 16:32:39 +08008492 return sum / cnt;
8493}
8494
developerb7593de2022-10-18 09:51:57 +08008495static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8496{
8497 if (NULL == ht_mode)
8498 return 0;
8499
8500 int width = strtol((ht_mode + 2), NULL, 10);
8501
8502 int idx = 0 ;
8503 int centerchan = 0;
8504 int chan_ofs = 1;
8505
8506 if (width == 40){
8507 idx = ((channel/4) + chan_ofs)%2;
8508 switch (idx) {
8509 case 0:
8510 centerchan = (channel - 2);
8511 break;
8512 case 1:
8513 centerchan = (channel + 2);
8514 break;
8515 default:
8516 return -EINVAL;
8517 }
8518 }else if (width == 80){
8519 idx = ((channel/4) + chan_ofs)%4;
8520 switch (idx) {
8521 case 0:
8522 centerchan = (channel - 6);
8523 break;
8524 case 1:
8525 centerchan = (channel + 6);
8526 break;
8527 case 2:
8528 centerchan = (channel + 2);
8529 break;
8530 case 3:
8531 centerchan = (channel - 2);
8532 break;
8533 default:
8534 return -EINVAL;
8535 }
8536 }else if (width == 160){
8537 switch (channel) {
8538 case 1 ... 29:
8539 centerchan = 15;
8540 break;
8541 case 33 ... 61:
8542 centerchan = 47;
8543 break;
8544 case 65 ... 93:
8545 centerchan = 79;
8546 break;
8547 case 97 ... 125:
8548 centerchan = 111;
8549 break;
8550 case 129 ... 157:
8551 centerchan = 143;
8552 break;
8553 case 161 ... 189:
8554 centerchan = 175;
8555 break;
8556 case 193 ... 221:
8557 centerchan = 207;
8558 break;
8559 default:
8560 return -EINVAL;
8561 }
8562 }
8563 return centerchan;
8564}
developer06a01d92022-09-07 16:32:39 +08008565static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8566{
8567 BOOL onlyG, onlyN, onlyA;
8568 CHAR tmp[64];
8569 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8570 if (ret == RETURN_OK) {
8571 sncopy(hw_mode, hw_mode_size, tmp);
8572 }
8573 return ret;
8574}
8575
8576INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8577{
8578 // Sample commands:
8579 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8580 // hostapd_cli -i wifi0 chan_switch 30 2437
8581 char cmd[MAX_CMD_SIZE] = {0};
8582 char buf[MAX_BUF_SIZE] = {0};
8583 int freq = 0, ret = 0;
8584 char center_freq1_str[32] = ""; // center_freq1=%d
8585 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8586 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8587 char hw_mode[16] = ""; // n|ac
8588 char bw_mode[16] = ""; // ht|ht vht
8589 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008590 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008591 int sec_chan_offset;
8592 int width;
developer4fb0b922022-09-30 14:29:09 +08008593 char config_file[64] = {0};
8594 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008595 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008596 wifi_band band = band_invalid;
8597 int center_chan = 0;
8598 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008599
developer4fb0b922022-09-30 14:29:09 +08008600 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008601
developerd946fd62022-12-08 18:03:28 +08008602 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8603 return RETURN_ERR;
8604
developer06a01d92022-09-07 16:32:39 +08008605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8606
developerb7593de2022-10-18 09:51:57 +08008607 band = wifi_index_to_band(radioIndex);
8608
developer5884e982022-10-06 10:52:50 +08008609 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008610
8611 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008612 if (channel){
developerb7593de2022-10-18 09:51:57 +08008613 if (band == band_6){
8614 freq = util_6G_chan_to_freq(channel);
8615 }else{
8616 freq = util_chan_to_freq(channel);
8617 }
developer5884e982022-10-06 10:52:50 +08008618 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008619
developer5884e982022-10-06 10:52:50 +08008620 // Provide bandwith if specified
8621 if (channel_width_MHz > 20) {
8622 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8623 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8624 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008625
developer5884e982022-10-06 10:52:50 +08008626 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8627 }else if (channel_width_MHz == 20){
8628 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8629 }
developer06a01d92022-09-07 16:32:39 +08008630
developerb7593de2022-10-18 09:51:57 +08008631
developer5884e982022-10-06 10:52:50 +08008632 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008633 if (band == band_6){
8634 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8635 if(center_chan){
8636 center_freq1 = util_6G_chan_to_freq(center_chan);
8637 }
8638 }else{
8639 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8640 if(center_chan){
8641 center_freq1 = util_chan_to_freq(center_chan);
8642 }
developer5884e982022-10-06 10:52:50 +08008643 }
developerb7593de2022-10-18 09:51:57 +08008644
8645 if (center_freq1)
8646 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8647
8648 }
8649
8650 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8651 if (band == band_6){
8652 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8653 }else{
8654 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008655 }
developerb7593de2022-10-18 09:51:57 +08008656 if (sec_chan_offset != -EINVAL)
8657 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008658
developer5884e982022-10-06 10:52:50 +08008659 // Only the first AP, other are hanging on the same radio
8660 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08008661 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8662 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08008663 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8664 wifi_dbg_printf("execute: '%s'\n", cmd);
8665 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008666
developer5884e982022-10-06 10:52:50 +08008667 ret = wifi_setRadioChannel(radioIndex, channel);
8668 if (ret != RETURN_OK) {
8669 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8670 return RETURN_ERR;
8671 }
8672
8673 if (sec_chan_offset == 1) ext_str = "Above";
8674 else if (sec_chan_offset == -1) ext_str = "Below";
8675
8676 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008677
developer5884e982022-10-06 10:52:50 +08008678 } else {
8679 if (channel_width_MHz > 20)
8680 ext_str = "Above";
8681 }
developer4fb0b922022-09-30 14:29:09 +08008682 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8683 _syscmd(cmd, buf, sizeof(buf));
8684 if (strlen(buf) != 0)
8685 stbcEnable = TRUE;
8686
developer06a01d92022-09-07 16:32:39 +08008687 wifi_setRadioExtChannel(radioIndex, ext_str);
8688
developer4fb0b922022-09-30 14:29:09 +08008689 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8690
developer06a01d92022-09-07 16:32:39 +08008691 char mhz_str[16];
8692 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8693 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8694
8695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8696
8697 return RETURN_OK;
8698}
8699
8700INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8701{
developer615510b2022-09-27 10:14:35 +08008702 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008703 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008704 char cmd[256]={0};
8705 char buf[128]={0};
8706 char file_name[32] = {0};
8707 char filter_SSID[32] = {0};
8708 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08008709 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08008710 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008711 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008712 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008713 size_t len=0;
8714 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008715 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008716 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008717 bool filter_enable = false;
8718 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008719 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008720
developer615510b2022-09-27 10:14:35 +08008721 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008722
developer615510b2022-09-27 10:14:35 +08008723 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8724 f = fopen(file_name, "r");
8725 if (f != NULL) {
8726 fgets(filter_SSID, sizeof(file_name), f);
8727 if (strlen(filter_SSID) != 0)
8728 filter_enable = true;
8729 fclose(f);
8730 }
8731
developerd946fd62022-12-08 18:03:28 +08008732 if (GetInterfaceName(radio_index, interface_name) != RETURN_OK)
8733 return RETURN_ERR;
8734
developer033b37b2022-10-18 11:27:46 +08008735 phyId = radio_index_to_phy(radio_index);
8736
8737 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008738 _syscmd(cmd, buf, sizeof(buf));
8739 channels_num = strtol(buf, NULL, 10);
8740
developerd946fd62022-12-08 18:03:28 +08008741 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8742 // 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 +08008743 fprintf(stderr, "cmd: %s\n", cmd);
8744 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008745 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8746 return RETURN_ERR;
8747 }
developer5550e242022-09-30 09:59:32 +08008748
8749 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8750 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8751
developer615510b2022-09-27 10:14:35 +08008752 ret = fgets(line, sizeof(line), f);
8753 while (ret != NULL) {
8754 if(strstr(line, "BSS") != NULL) { // new neighbor info
8755 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8756 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8757 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8758
8759 if (!filter_BSS) {
8760 index++;
8761 wifi_neighbor_ap2_t *tmp;
8762 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8763 if (tmp == NULL) { // no more memory to use
8764 index--;
8765 wifi_dbg_printf("%s: realloc failed\n", __func__);
8766 break;
8767 }
8768 scan_array = tmp;
8769 }
8770 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008771
developer615510b2022-09-27 10:14:35 +08008772 filter_BSS = false;
8773 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8774 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8775 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8776 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8777 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008778 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008779 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008780
developer615510b2022-09-27 10:14:35 +08008781 if (freq >= 2412 && freq <= 2484) {
8782 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8783 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8784 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8785 }
8786 else if (freq >= 5160 && freq <= 5805) {
8787 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8788 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8789 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8790 }
developer06a01d92022-09-07 16:32:39 +08008791
developer615510b2022-09-27 10:14:35 +08008792 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008793 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008794 for (int i = 0; i < channels_num; i++) {
8795 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8796 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8797 break;
8798 }
8799 }
developer06a01d92022-09-07 16:32:39 +08008800 }
developer615510b2022-09-27 10:14:35 +08008801 } else if (strstr(line, "beacon interval") != NULL) {
8802 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8803 } else if (strstr(line, "signal") != NULL) {
8804 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8805 } else if (strstr(line,"SSID") != NULL) {
8806 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8807 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8808 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008809 }
developer615510b2022-09-27 10:14:35 +08008810 } else if (strstr(line, "Supported rates") != NULL) {
8811 char SRate[80] = {0}, *tmp = NULL;
8812 memset(buf, 0, sizeof(buf));
8813 strcpy(SRate, line);
8814 tmp = strtok(SRate, ":");
8815 tmp = strtok(NULL, ":");
8816 strcpy(buf, tmp);
8817 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008818
developer615510b2022-09-27 10:14:35 +08008819 tmp = strtok(buf, " \n");
8820 while (tmp != NULL) {
8821 strcat(SRate, tmp);
8822 if (SRate[strlen(SRate) - 1] == '*') {
8823 SRate[strlen(SRate) - 1] = '\0';
8824 }
8825 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008826
developer615510b2022-09-27 10:14:35 +08008827 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008828 }
developer615510b2022-09-27 10:14:35 +08008829 SRate[strlen(SRate) - 1] = '\0';
8830 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8831 } else if (strstr(line, "DTIM") != NULL) {
8832 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8833 } else if (strstr(line, "VHT capabilities") != NULL) {
8834 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8835 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8836 } else if (strstr(line, "HT capabilities") != NULL) {
8837 strcat(scan_array[index].ap_SupportedStandards, ",n");
8838 strcpy(scan_array[index].ap_OperatingStandards, "n");
8839 } else if (strstr(line, "VHT operation") != NULL) {
8840 ret = fgets(line, sizeof(line), f);
8841 sscanf(line," * channel width: %d", &vht_channel_width);
8842 if(vht_channel_width == 1) {
8843 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8844 } else {
8845 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8846 }
8847 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8848 continue;
8849 } else if (strstr(line, "HT operation") != NULL) {
8850 ret = fgets(line, sizeof(line), f);
8851 sscanf(line," * secondary channel offset: %s", &buf);
8852 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008853 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008854 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 +08008855 }
developer615510b2022-09-27 10:14:35 +08008856 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008857 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008858 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8859 } else {
8860 //20Mhz
8861 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 +08008862 }
developer615510b2022-09-27 10:14:35 +08008863 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008864 continue;
developer615510b2022-09-27 10:14:35 +08008865 } else if (strstr(line, "HE capabilities") != NULL) {
8866 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8867 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8868 ret = fgets(line, sizeof(line), f);
8869 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8870 if (strstr(line, "HE40/2.4GHz") != NULL)
8871 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8872 else
8873 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8874 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8875 if (strstr(line, "HE80/5GHz") != NULL) {
8876 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8877 ret = fgets(line, sizeof(line), f);
8878 } else
8879 continue;
8880 if (strstr(line, "HE160/5GHz") != NULL)
8881 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008882 }
developer615510b2022-09-27 10:14:35 +08008883 continue;
8884 } else if (strstr(line, "WPA") != NULL) {
8885 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8886 } else if (strstr(line, "RSN") != NULL) {
8887 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8888 } else if (strstr(line, "Group cipher") != NULL) {
8889 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8890 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8891 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008892 }
developer06a01d92022-09-07 16:32:39 +08008893 }
developer615510b2022-09-27 10:14:35 +08008894 ret = fgets(line, sizeof(line), f);
8895 }
8896
8897 if (!filter_BSS) {
8898 *output_array_size = index + 1;
8899 } else {
8900 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8901 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008902 }
developer06a01d92022-09-07 16:32:39 +08008903 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008904 pclose(f);
developer5550e242022-09-30 09:59:32 +08008905 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008906 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008907 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008908}
developer615510b2022-09-27 10:14:35 +08008909
developer06a01d92022-09-07 16:32:39 +08008910INT wifi_getApAssociatedDeviceStats(
8911 INT apIndex,
8912 mac_address_t *clientMacAddress,
8913 wifi_associated_dev_stats_t *associated_dev_stats,
8914 u64 *handle)
8915{
8916 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8917 char interface_name[50] = {0};
8918 char cmd[1024] = {0};
8919 char mac_str[18] = {0};
8920 char *key = NULL;
8921 char *val = NULL;
8922 FILE *f = NULL;
8923 char *line = NULL;
8924 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08008925
8926 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8927 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8928 return RETURN_ERR;
8929 }
8930
8931 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8932 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8933 if((f = popen(cmd, "r")) == NULL) {
8934 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8935 return RETURN_ERR;
8936 }
8937
developer30423732022-12-01 16:17:49 +08008938 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08008939 key = strtok(line,":");
8940 val = strtok(NULL,":");
8941
8942 if(!strncmp(key,"rx bytes",8))
8943 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8944 if(!strncmp(key,"tx bytes",8))
8945 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8946 if(!strncmp(key,"rx packets",10))
8947 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8948 if(!strncmp(key,"tx packets",10))
8949 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8950 if(!strncmp(key,"tx retries",10))
8951 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8952 if(!strncmp(key,"tx failed",9))
8953 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8954 if(!strncmp(key,"rx drop misc",13))
8955 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8956 if(!strncmp(key,"rx bitrate",10)) {
8957 val = strtok(val, " ");
8958 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8959 }
8960 if(!strncmp(key,"tx bitrate",10)) {
8961 val = strtok(val, " ");
8962 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8963 }
8964 }
8965 free(line);
8966 pclose(f);
8967 return RETURN_OK;
8968}
8969
8970INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8971{
developerd946fd62022-12-08 18:03:28 +08008972 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008973 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8974
8975 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8976 if (NULL == output_string)
8977 return RETURN_ERR;
8978
developerd946fd62022-12-08 18:03:28 +08008979 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8980 return RETURN_ERR;
8981 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 +08008982 _syscmd(cmd, buf, sizeof(buf));
8983
8984 //size of SSID name restricted to value less than 32 bytes
8985 snprintf(output_string, 32, "%s", buf);
8986 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8987
8988 return RETURN_OK;
8989}
8990
8991INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8992{
8993 //char cmd[MAX_CMD_SIZE] = {0};
8994 char config_file[MAX_BUF_SIZE] = {0};
8995 char buf[32] = {0};
8996
8997 if (!output_filterMode)
8998 return RETURN_ERR;
8999
9000 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9001 //_syscmd(cmd, buf, sizeof(buf));
9002 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9003 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009004 if(strlen(buf) == 0) {
9005 *output_filterMode = 0;
9006 }
9007 else {
9008 int macaddr_acl_mode = strtol(buf, NULL, 10);
9009 if (macaddr_acl_mode == 1) {
9010 *output_filterMode = 1;
9011 } else if (macaddr_acl_mode == 0) {
9012 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9013 if (strlen(buf) == 0) {
9014 *output_filterMode = 0;
9015 } else {
9016 *output_filterMode = 2;
9017 }
9018 } else {
9019 return RETURN_ERR;
9020 }
9021 }
developer06a01d92022-09-07 16:32:39 +08009022
9023 return RETURN_OK;
9024}
9025
9026INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9027{
9028 FILE *fp = NULL;
9029 char str[MAX_BUF_SIZE] = {0};
9030 int wificlientindex = 0 ;
9031 int count = 0;
9032 int signalstrength = 0;
9033 int arr[MACADDRESS_SIZE] = {0};
9034 unsigned char mac[MACADDRESS_SIZE] = {0};
9035 UINT wifi_count = 0;
9036 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9037 char pipeCmd[MAX_CMD_SIZE] = {0};
9038
9039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9040 *output_array_size = 0;
9041 *associated_dev_array = NULL;
9042 char interface_name[50] = {0};
9043
9044 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9045 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9046 return RETURN_ERR;
9047 }
9048
9049 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9050 fp = popen(pipeCmd, "r");
9051 if (fp == NULL)
9052 {
9053 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9054 return RETURN_ERR;
9055 }
9056
9057 /* Read the output a line at a time - output it. */
9058 fgets(str, sizeof(str)-1, fp);
9059 wifi_count = (unsigned int) atoi ( str );
9060 *output_array_size = wifi_count;
9061 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9062 pclose(fp);
9063
9064 if(wifi_count == 0)
9065 {
9066 return RETURN_OK;
9067 }
9068 else
9069 {
9070 wifi_associated_dev2_t* temp = NULL;
9071 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9072 *associated_dev_array = temp;
9073 if(temp == NULL)
9074 {
9075 printf("Error Statement. Insufficient memory \n");
9076 return RETURN_ERR;
9077 }
9078
9079 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9080 system(pipeCmd);
9081
9082 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9083 if(fp == NULL)
9084 {
9085 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9086 return RETURN_ERR;
9087 }
9088 fclose(fp);
9089
developer30423732022-12-01 16:17:49 +08009090 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009091 fp = popen(pipeCmd, "r");
9092 if(fp)
9093 {
9094 for(count =0 ; count < wifi_count; count++)
9095 {
9096 fgets(str, MAX_BUF_SIZE, fp);
9097 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9098 {
9099 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9100 {
9101 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9102
9103 }
9104 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9105 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]);
9106 }
9107 temp[count].cli_AuthenticationState = 1; //TODO
9108 temp[count].cli_Active = 1; //TODO
9109 }
9110 pclose(fp);
9111 }
9112
9113 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009114 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 +08009115 fp = popen(pipeCmd, "r");
9116 if(fp)
9117 {
9118 pclose(fp);
9119 }
9120 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9121 if(fp)
9122 {
9123 for(count =0 ; count < wifi_count ;count++)
9124 {
9125 fgets(str, MAX_BUF_SIZE, fp);
9126 signalstrength = atoi(str);
9127 temp[count].cli_RSSI = signalstrength;
9128 }
9129 pclose(fp);
9130 }
9131
9132
9133 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009134 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 +08009135 fp = popen(pipeCmd, "r");
9136 if (fp)
9137 {
9138 pclose(fp);
9139 }
9140 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9141 if (fp)
9142 {
9143 for (count = 0; count < wifi_count; count++)
9144 {
9145 fgets(str, MAX_BUF_SIZE, fp);
9146 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9147 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9148 }
9149 pclose(fp);
9150 }
9151
9152 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009153 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 +08009154 fp = popen(pipeCmd, "r");
9155 if (fp)
9156 {
9157 pclose(fp);
9158 }
9159 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9160 if (fp)
9161 {
9162 for (count = 0; count < wifi_count; count++)
9163 {
9164 fgets(str, MAX_BUF_SIZE, fp);
9165 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9166 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9167 }
9168 pclose(fp);
9169 }
9170 }
9171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9172 return RETURN_OK;
9173
9174}
9175
9176INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9177{
9178#if 0
9179 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009180 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009181 _syscmd(cmd, buf, sizeof(buf));*/
9182
9183 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9184 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9185 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9186 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9187
9188 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.
9189 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].
9190 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].
9191 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].
9192 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9193 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9194
9195 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9196 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9197 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9198 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.
9199 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.
9200 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.
9201 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.
9202 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.
9203 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.
9204 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.
9205 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9206#endif
9207
9208 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009209 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009210 char pipeCmd[128] = {0};
9211 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009212 wifi_ssidTrafficStats2_t *out = output_struct;
9213
developerce736392022-09-13 15:24:34 +08009214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009215 if (!output_struct)
9216 return RETURN_ERR;
9217
developerce736392022-09-13 15:24:34 +08009218 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerd946fd62022-12-08 18:03:28 +08009219 GetInterfaceName(ssidIndex, interface_name);
developerce736392022-09-13 15:24:34 +08009220 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009221
developer06a01d92022-09-07 16:32:39 +08009222 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009223 if (fp == NULL) {
9224 fprintf(stderr, "%s: popen failed\n", __func__);
9225 return RETURN_ERR;
9226 }
9227 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009228 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009229
developerce736392022-09-13 15:24:34 +08009230 if (strlen(str) == 0) // interface not exist
9231 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009232
developerce736392022-09-13 15:24:34 +08009233 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9234 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009235
developerce736392022-09-13 15:24:34 +08009236 memset(str, 0, sizeof(str));
9237 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009238 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009239 if (fp == NULL) {
9240 fprintf(stderr, "%s: popen failed\n", __func__);
9241 return RETURN_ERR;
9242 }
9243 fgets(str, sizeof(str), fp);
9244
9245 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9246 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009247 pclose(fp);
developerce736392022-09-13 15:24:34 +08009248
9249 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9250 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9251
9252 // Not supported
9253 output_struct->ssid_RetransCount = 0;
9254 output_struct->ssid_FailedRetransCount = 0;
9255 output_struct->ssid_RetryCount = 0;
9256 output_struct->ssid_MultipleRetryCount = 0;
9257 output_struct->ssid_ACKFailureCount = 0;
9258 output_struct->ssid_AggregatedPacketCount = 0;
9259
developer06a01d92022-09-07 16:32:39 +08009260 return RETURN_OK;
9261}
9262
9263//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).
9264INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9265{
9266 char output_val[16]={'\0'};
9267 char config_file[MAX_BUF_SIZE] = {0};
9268
9269 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9270 if (!output)
9271 return RETURN_ERR;
9272 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9273 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9274
9275 if( strcmp(output_val,"1") == 0 )
9276 *output = TRUE;
9277 else
9278 *output = FALSE;
9279 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9280
9281 return RETURN_OK;
9282}
9283
9284INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9285{
9286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9287 char str[MAX_BUF_SIZE]={'\0'};
9288 char string[MAX_BUF_SIZE]={'\0'};
9289 char cmd[MAX_CMD_SIZE]={'\0'};
9290 char *ch;
9291 char config_file[MAX_BUF_SIZE] = {0};
9292 struct params params;
9293
9294 if(enable == TRUE)
9295 strcpy(string,"1");
9296 else
9297 strcpy(string,"0");
9298
9299 params.name = "ap_isolate";
9300 params.value = string;
9301
9302 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9303 wifi_hostapdWrite(config_file,&params,1);
9304 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9305
9306 return RETURN_OK;
9307}
9308
9309INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9310{
9311 if (NULL == output_dBm)
9312 return RETURN_ERR;
9313
9314 *output_dBm = 0;
9315 return RETURN_OK;
9316}
9317
9318INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9319{
9320 return RETURN_OK;
9321}
9322INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9323{
9324 return RETURN_OK;
9325}
9326INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9327{
9328 return RETURN_OK;
9329}
9330INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9331{
9332 return RETURN_OK;
9333}
9334INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9335{
9336 return RETURN_OK;
9337}
9338INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9339{
9340 char config_file[MAX_BUF_SIZE] = {0};
9341 struct params list;
9342
9343 list.name = "bss_transition";
9344 list.value = activate?"1":"0";
9345 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9346 wifi_hostapdWrite(config_file, &list, 1);
9347
9348 return RETURN_OK;
9349}
9350wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9351
9352void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9353{
9354 return;
9355}
9356
9357INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9358{
9359 // TODO Implement me!
9360 return RETURN_OK;
9361}
9362
9363INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9364{
developera3c68b92022-09-13 15:27:29 +08009365 char file_name[128] = {0};
9366 char buf[128] = {0};
9367 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009368 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009369
9370 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9371
developer804c64f2022-10-19 13:54:40 +08009372 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009373 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009374 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009375 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9376 f = fopen(file_name, "w");
9377 if (f == NULL)
9378 return RETURN_ERR;
9379 // For mode == 0 is to disable filter, just don't write to the file.
9380 if (mode)
9381 fprintf(f, "%s", essid);
9382
9383 fclose(f);
9384 }
9385 } else { // special case, need to set AP's SSID as filter for each radio.
9386 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9387 f = fopen(file_name, "w");
9388 if (f == NULL)
9389 return RETURN_ERR;
9390
9391 // For mode == 0 is to disable filter, just don't write to the file.
9392 if (mode)
9393 fprintf(f, "%s", essid);
9394
9395 fclose(f);
9396 }
9397
9398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009399 return RETURN_OK;
9400}
9401
9402INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9403{
9404 // TODO Implement me!
9405 //Apply wifi_pushRadioChannel() instantly
9406 return RETURN_ERR;
9407}
9408
9409INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9410{
9411 // TODO Implement me!
9412 return RETURN_OK;
9413}
9414
9415#ifdef HAL_NETLINK_IMPL
9416static int tidStats_callback(struct nl_msg *msg, void *arg) {
9417 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9418 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9419 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9420 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9421 int rem , tid_index = 0;
9422
9423 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9424 wifi_associated_dev_tid_entry_t *stats_entry;
9425
9426 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9427 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9428 };
9429 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9430 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9431 };
9432
9433 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9434 genlmsg_attrlen(gnlh, 0), NULL);
9435
9436
9437 if (!tb[NL80211_ATTR_STA_INFO]) {
9438 fprintf(stderr, "station stats missing!\n");
9439 return NL_SKIP;
9440 }
9441
9442 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9443 tb[NL80211_ATTR_STA_INFO],
9444 stats_policy)) {
9445 fprintf(stderr, "failed to parse nested attributes!\n");
9446 return NL_SKIP;
9447 }
9448
9449 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9450 {
9451 stats_entry = &out->tid_array[tid_index];
9452
9453 stats_entry->tid = tid_index;
9454 stats_entry->ac = _tid_ac_index_get[tid_index];
9455
9456 if(sinfo[NL80211_STA_INFO_TID_STATS])
9457 {
9458 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9459 printf("failed to parse nested stats attributes!");
9460 return NL_SKIP;
9461 }
9462 }
9463 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9464 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9465
9466 if(tid_index < (PS_MAX_TID - 1))
9467 tid_index++;
9468 }
9469 //ToDo: sum_time_ms, ewma_time_ms
9470 return NL_SKIP;
9471}
9472#endif
9473
9474INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9475{
9476#ifdef HAL_NETLINK_IMPL
9477 Netlink nl;
9478 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009479 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009480
developerd946fd62022-12-08 18:03:28 +08009481 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9482 return RETURN_ERR;
9483
9484 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009485
9486 nl.id = initSock80211(&nl);
9487
9488 if (nl.id < 0) {
9489 fprintf(stderr, "Error initializing netlink \n");
9490 return -1;
9491 }
9492
9493 struct nl_msg* msg = nlmsg_alloc();
9494
9495 if (!msg) {
9496 fprintf(stderr, "Failed to allocate netlink message.\n");
9497 nlfree(&nl);
9498 return -2;
9499 }
9500
9501 genlmsg_put(msg,
9502 NL_AUTO_PORT,
9503 NL_AUTO_SEQ,
9504 nl.id,
9505 0,
9506 0,
9507 NL80211_CMD_GET_STATION,
9508 0);
9509
9510 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9511 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9512 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9513 nl_send_auto(nl.socket, msg);
9514 nl_recvmsgs(nl.socket, nl.cb);
9515 nlmsg_free(msg);
9516 nlfree(&nl);
9517 return RETURN_OK;
9518#else
9519//iw implementation
9520#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9521#define TOTAL_MAX_LINES 50
9522
9523 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009524 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009525 FILE *fp=NULL;
9526 char pipeCmd[1024]= {'\0'};
9527 int lines,tid_index=0;
9528 char mac_addr[20] = {'\0'};
9529
developerd946fd62022-12-08 18:03:28 +08009530 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9531 return RETURN_ERR;
9532
developer06a01d92022-09-07 16:32:39 +08009533 wifi_associated_dev_tid_entry_t *stats_entry;
9534
developer06a01d92022-09-07 16:32:39 +08009535 strcpy(mac_addr,clientMacAddress);
9536
9537 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9538 fp= popen(pipeCmd,"r");
9539 if(fp == NULL)
9540 {
9541 perror("popen for station dump failed\n");
9542 return RETURN_ERR;
9543 }
9544 pclose(fp);
9545
9546 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9547 fp=popen(pipeCmd,"r");
9548 if(fp == NULL)
9549 {
9550 perror("popen for grep station failed\n");
9551 return RETURN_ERR;
9552 }
9553 else if(fgets(buf,sizeof(buf),fp) != NULL)
9554 lines=atoi(buf);
9555 else
9556 {
9557 pclose(fp);
9558 fprintf(stderr,"No devices are connected \n");
9559 return RETURN_ERR;
9560 }
9561 pclose(fp);
9562
9563 if(lines == 1)
9564 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9565
9566 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9567 {
9568 stats_entry = &tid_stats->tid_array[tid_index];
9569 stats_entry->tid = tid_index;
9570
9571 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);
9572
9573 fp=popen(pipeCmd,"r");
9574 if(fp ==NULL)
9575 {
9576 perror("Failed to read from tid file \n");
9577 return RETURN_ERR;
9578 }
9579 else if(fgets(buf,sizeof(buf),fp) != NULL)
9580 stats_entry->num_msdus = atol(buf);
9581
9582 pclose(fp);
9583 stats_entry->ac = _tid_ac_index_get[tid_index];
9584// TODO:
9585// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9586// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9587 }
9588 return RETURN_OK;
9589#endif
9590}
9591
9592
9593INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9594{
developerd946fd62022-12-08 18:03:28 +08009595 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009596 char cmd[128]={0};
9597 char buf[128]={0};
9598 int freq = 0;
9599
9600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9601
9602 // full mode is used to scan all channels.
9603 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9604 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9605 ieee80211_channel_to_frequency(chan_list[0], &freq);
9606
developerd946fd62022-12-08 18:03:28 +08009607 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9608 return RETURN_ERR;
9609
developer615510b2022-09-27 10:14:35 +08009610 if (freq)
developerd946fd62022-12-08 18:03:28 +08009611 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009612 else
developerd946fd62022-12-08 18:03:28 +08009613 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009614
9615 _syscmd(cmd, buf, sizeof(buf));
9616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9617
developer06a01d92022-09-07 16:32:39 +08009618 return RETURN_OK;
9619}
9620
9621
9622INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9623{
9624 // TODO Implement me!
9625 return RETURN_ERR;
9626}
9627
9628INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9629{
9630 // TODO Implement me!
9631 return RETURN_ERR;
9632}
9633
9634INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9635{
9636 // TODO Implement me!
9637 return RETURN_ERR;
9638}
9639
9640INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9641{
9642 // TODO Implement me!
9643 return RETURN_ERR;
9644}
9645
9646INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9647{
9648 // TODO Implement me!
9649 return RETURN_ERR;
9650}
9651
9652INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9653{
9654 // TODO Implement me!
9655 return RETURN_ERR;
9656}
9657
9658INT wifi_steering_eventUnregister(void)
9659{
9660 // TODO Implement me!
9661 return RETURN_ERR;
9662}
9663
9664INT wifi_delApAclDevices(INT apIndex)
9665{
9666#if 0
9667 char cmd[MAX_BUF_SIZE] = {0};
9668 char buf[MAX_BUF_SIZE] = {0};
9669
9670 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +08009671 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +08009672 if(_syscmd(cmd,buf,sizeof(buf)))
9673 return RETURN_ERR;
9674#endif
developere6aafda2022-09-13 14:59:28 +08009675 char cmd[MAX_CMD_SIZE]={0};
9676 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009677
developere6aafda2022-09-13 14:59:28 +08009678 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9679 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9680 if(_syscmd(cmd, buf, sizeof(buf)))
9681 return RETURN_ERR;
9682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009683
9684 return RETURN_OK;
9685}
9686
9687#ifdef HAL_NETLINK_IMPL
9688static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9689 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9690 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9691 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9692 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9693 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9694 char mac_addr[20],dev[20];
9695
9696 nla_parse(tb,
9697 NL80211_ATTR_MAX,
9698 genlmsg_attrdata(gnlh, 0),
9699 genlmsg_attrlen(gnlh, 0),
9700 NULL);
9701
9702 if(!tb[NL80211_ATTR_STA_INFO]) {
9703 fprintf(stderr, "sta stats missing!\n");
9704 return NL_SKIP;
9705 }
9706
9707 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9708 fprintf(stderr, "failed to parse nested attributes!\n");
9709 return NL_SKIP;
9710 }
9711 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9712
9713 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9714
9715 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9716 fprintf(stderr, "failed to parse nested rate attributes!");
9717 return NL_SKIP;
9718 }
9719
9720 if(sinfo[NL80211_STA_INFO_TID_STATS])
9721 {
9722 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9723 printf("failed to parse nested stats attributes!");
9724 return NL_SKIP;
9725 }
9726 }
9727
9728 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9729 {
9730 printf("Type is VHT\n");
9731 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9732 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9733
9734 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9735 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9736 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9737 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9738 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9739 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9740 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9741 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9742 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9743 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9744 }
9745 else
9746 {
9747 printf(" OFDM or CCK \n");
9748 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9749 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9750 }
9751
9752 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9753 if(rinfo[NL80211_RATE_INFO_MCS])
9754 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9755 }
9756 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9757 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9758 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9759 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9760
9761 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9762 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9763
9764 if (sinfo[NL80211_STA_INFO_SIGNAL])
9765 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9766 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9767 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9768 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9769 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9770 //rssi_array need to be filled
9771 return NL_SKIP;
9772}
9773#endif
9774
9775INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9776{
9777#ifdef HAL_NETLINK_IMPL
9778 Netlink nl;
developerd946fd62022-12-08 18:03:28 +08009779 char if_name[32];
9780 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9781 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009782
9783 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9784
9785 if (*output_array_size <= 0)
9786 return RETURN_OK;
9787
developer06a01d92022-09-07 16:32:39 +08009788 nl.id = initSock80211(&nl);
9789
9790 if (nl.id < 0) {
9791 fprintf(stderr, "Error initializing netlink \n");
9792 return 0;
9793 }
9794
9795 struct nl_msg* msg = nlmsg_alloc();
9796
9797 if (!msg) {
9798 fprintf(stderr, "Failed to allocate netlink message.\n");
9799 nlfree(&nl);
9800 return 0;
9801 }
9802
9803 genlmsg_put(msg,
9804 NL_AUTO_PORT,
9805 NL_AUTO_SEQ,
9806 nl.id,
9807 0,
9808 0,
9809 NL80211_CMD_GET_STATION,
9810 0);
9811
9812 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9813 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9814 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9815 nl_send_auto(nl.socket, msg);
9816 nl_recvmsgs(nl.socket, nl.cb);
9817 nlmsg_free(msg);
9818 nlfree(&nl);
9819 return RETURN_OK;
9820#else
9821 //TODO Implement me
9822 return RETURN_OK;
9823#endif
9824}
9825
9826#ifdef HAL_NETLINK_IMPL
9827static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9828 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9829 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9830 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9831 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9832 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9833 char mac_addr[20],dev[20];
9834
9835 nla_parse(tb,
9836 NL80211_ATTR_MAX,
9837 genlmsg_attrdata(gnlh, 0),
9838 genlmsg_attrlen(gnlh, 0),
9839 NULL);
9840
9841 if(!tb[NL80211_ATTR_STA_INFO]) {
9842 fprintf(stderr, "sta stats missing!\n");
9843 return NL_SKIP;
9844 }
9845
9846 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9847 fprintf(stderr, "failed to parse nested attributes!\n");
9848 return NL_SKIP;
9849 }
9850
9851 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9852
9853 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9854
9855 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9856 fprintf(stderr, "failed to parse nested rate attributes!");
9857 return NL_SKIP;
9858 }
9859
9860 if(sinfo[NL80211_STA_INFO_TID_STATS])
9861 {
9862 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9863 printf("failed to parse nested stats attributes!");
9864 return NL_SKIP;
9865 }
9866 }
9867 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9868 {
9869 printf("Type is VHT\n");
9870 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9871 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9872
9873 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9874 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9875 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9876 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9877 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9878 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9879 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9880 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9881 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9882 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9883 }
9884 else
9885 {
9886 printf(" OFDM or CCK \n");
9887 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9888 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9889 }
9890
9891 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9892 if(rinfo[NL80211_RATE_INFO_MCS])
9893 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9894 }
9895
9896 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9897 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9898 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9899 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9900
9901 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9902 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9903 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9904
9905 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9906 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9907
9908 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9909 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9910
9911 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9912 ((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]);
9913
9914 return NL_SKIP;
9915}
9916#endif
9917
9918INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9919{
9920#ifdef HAL_NETLINK_IMPL
9921 Netlink nl;
9922 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009923 char interface_name[16] = {0};
9924 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9925 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009926
9927 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9928
9929 if (*output_array_size <= 0)
9930 return RETURN_OK;
9931
developerd946fd62022-12-08 18:03:28 +08009932 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009933
9934 nl.id = initSock80211(&nl);
9935
9936 if(nl.id < 0) {
9937 fprintf(stderr, "Error initializing netlink \n");
9938 return 0;
9939 }
9940
9941 struct nl_msg* msg = nlmsg_alloc();
9942
9943 if(!msg) {
9944 fprintf(stderr, "Failed to allocate netlink message.\n");
9945 nlfree(&nl);
9946 return 0;
9947 }
9948
9949 genlmsg_put(msg,
9950 NL_AUTO_PORT,
9951 NL_AUTO_SEQ,
9952 nl.id,
9953 0,
9954 0,
9955 NL80211_CMD_GET_STATION,
9956 0);
9957
9958 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9959 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9960 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9961 nl_send_auto(nl.socket, msg);
9962 nl_recvmsgs(nl.socket, nl.cb);
9963 nlmsg_free(msg);
9964 nlfree(&nl);
9965 return RETURN_OK;
9966#else
9967 //TODO Implement me
9968 return RETURN_OK;
9969#endif
9970}
9971
9972INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9973{
9974 // TODO Implement me!
9975 char buf[MAX_BUF_SIZE] = {0};
9976 char config_file[MAX_BUF_SIZE] = {0};
9977
9978 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9979 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9980 *activate = (strncmp("1",buf,1) == 0);
9981
9982 return RETURN_OK;
9983}
9984
9985INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9986{
9987 char config_file[MAX_BUF_SIZE] = {0};
9988 struct params list;
9989
9990 list.name = "rrm_neighbor_report";
9991 list.value = activate?"1":"0";
9992 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9993 wifi_hostapdWrite(config_file, &list, 1);
9994
9995 return RETURN_OK;
9996}
9997
9998INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9999{
10000 char buf[32] = {0};
10001 char config_file[MAX_BUF_SIZE] = {0};
10002
10003 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10004 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10005 *activate = (strncmp("1",buf,1) == 0);
10006
10007 return RETURN_OK;
10008}
10009#undef HAL_NETLINK_IMPL
10010#ifdef HAL_NETLINK_IMPL
10011static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10012 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10013 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10014 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10015 char dev[20];
10016 int freq =0 ;
10017 static int i=0;
10018
10019 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10020
10021 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10022 };
10023
10024 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10025
10026 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10027
10028 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10029 fprintf(stderr, "survey data missing!\n");
10030 return NL_SKIP;
10031 }
10032
10033 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10034 {
10035 fprintf(stderr, "failed to parse nested attributes!\n");
10036 return NL_SKIP;
10037 }
10038
10039
10040 if(out[0].array_size == 1 )
10041 {
10042 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10043 {
10044 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10045 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10046 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10047
10048 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10049 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10050 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10051 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10052 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10053 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10054 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10055 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10056 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10057 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10058 if (sinfo[NL80211_SURVEY_INFO_TIME])
10059 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10060 return NL_STOP;
10061 }
10062 }
10063 else
10064 {
10065 if ( i <= out[0].array_size )
10066 {
10067 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10068 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10069 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10070
10071 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10072 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10073 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10074 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10075 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10076 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10077 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10078 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10079 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10080 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10081 if (sinfo[NL80211_SURVEY_INFO_TIME])
10082 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10083 }
10084 }
10085
10086 i++;
10087 return NL_SKIP;
10088}
10089#endif
10090
10091static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10092{
10093 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10094 FILE *fp;
10095
10096 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10097 {
10098 printf("Creating Frequency-Channel Map\n");
10099 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10100 }
10101 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10102 if((fp = popen(command, "r")))
10103 {
10104 fgets(output, sizeof(output), fp);
10105 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010106 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010107 }
10108
10109 return 0;
10110}
10111
10112static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10113{
10114 int freqMHz = -1;
10115 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +080010116 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080010117
10118 ieee80211_channel_to_frequency(channel, &freqMHz);
10119 if (freqMHz == -1) {
10120 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10121 return -1;
10122 }
10123
developer033b37b2022-10-18 11:27:46 +080010124 phyId = radio_index_to_phy(radioIndex);
10125 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 +080010126 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10127 radioIndex, freqMHz);
10128 return -1;
10129 }
10130
10131 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10132 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10133 return -1;
10134 }
10135
10136 return 0;
10137}
10138
10139static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10140{
10141 const char *ptr = buf;
10142 char *key = NULL;
10143 char *val = NULL;
10144 char line[256] = { '\0' };
10145
10146 while (ptr = get_line_from_str_buf(ptr, line)) {
10147 if (strstr(line, "Frequency")) continue;
10148
10149 key = strtok(line, ":");
10150 val = strtok(NULL, " ");
10151 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10152
10153 if (!strcmp(key, "noise")) {
10154 sscanf(val, "%d", &stats->ch_noise);
10155 if (stats->ch_noise == 0) {
10156 // Workaround for missing noise information.
10157 // Assume -95 for 2.4G and -103 for 5G
10158 if (radioIndex == 0) stats->ch_noise = -95;
10159 if (radioIndex == 1) stats->ch_noise = -103;
10160 }
10161 }
10162 else if (!strcmp(key, "channel active time")) {
10163 sscanf(val, "%llu", &stats->ch_utilization_total);
10164 }
10165 else if (!strcmp(key, "channel busy time")) {
10166 sscanf(val, "%llu", &stats->ch_utilization_busy);
10167 }
10168 else if (!strcmp(key, "channel receive time")) {
10169 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10170 }
10171 else if (!strcmp(key, "channel transmit time")) {
10172 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10173 }
10174 };
10175
10176 return 0;
10177}
10178
10179INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10180{
10181 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10182#ifdef HAL_NETLINK_IMPL
10183 Netlink nl;
10184 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010185 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010186
10187 local[0].array_size = array_size;
10188
developerd946fd62022-12-08 18:03:28 +080010189 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10190 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010191
10192 nl.id = initSock80211(&nl);
10193
10194 if (nl.id < 0) {
10195 fprintf(stderr, "Error initializing netlink \n");
10196 return -1;
10197 }
10198
10199 struct nl_msg* msg = nlmsg_alloc();
10200
10201 if (!msg) {
10202 fprintf(stderr, "Failed to allocate netlink message.\n");
10203 nlfree(&nl);
10204 return -2;
10205 }
10206
10207 genlmsg_put(msg,
10208 NL_AUTO_PORT,
10209 NL_AUTO_SEQ,
10210 nl.id,
10211 0,
10212 NLM_F_DUMP,
10213 NL80211_CMD_GET_SURVEY,
10214 0);
10215
10216 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10217 nl_send_auto(nl.socket, msg);
10218 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10219 nl_recvmsgs(nl.socket, nl.cb);
10220 nlmsg_free(msg);
10221 nlfree(&nl);
10222 //Copying the Values
10223 for(int i=0;i<array_size;i++)
10224 {
10225 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10226 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10227 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10228 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10229 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10230 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10231 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10232 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10233 }
10234#else
10235 ULONG channel = 0;
10236 int i;
10237 int number_of_channels = array_size;
10238 char buf[512];
10239 INT ret;
10240 wifi_channelStats_t tmp_stats;
10241
10242 if (number_of_channels == 0) {
10243 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10244 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10245 return RETURN_ERR;
10246 }
10247 number_of_channels = 1;
10248 input_output_channelStats_array[0].ch_number = channel;
10249 }
10250
10251 for (i = 0; i < number_of_channels; i++) {
10252
10253 input_output_channelStats_array[i].ch_noise = 0;
10254 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10255 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10256 input_output_channelStats_array[i].ch_utilization_busy = 0;
10257 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10258 input_output_channelStats_array[i].ch_utilization_total = 0;
10259
10260 memset(buf, 0, sizeof(buf));
10261 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10262 return RETURN_ERR;
10263 }
10264 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10265 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10266 return RETURN_ERR;
10267 }
10268
10269 // XXX: fake missing 'self' counter which is not available in iw survey output
10270 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10271 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10272
10273 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10274 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10275 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10276 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10277 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10278
10279 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",
10280 __func__,
10281 input_output_channelStats_array[i].ch_number,
10282 input_output_channelStats_array[i].ch_noise,
10283 input_output_channelStats_array[i].ch_utilization_total,
10284 input_output_channelStats_array[i].ch_utilization_busy,
10285 input_output_channelStats_array[i].ch_utilization_busy_rx,
10286 input_output_channelStats_array[i].ch_utilization_busy_tx,
10287 input_output_channelStats_array[i].ch_utilization_busy_self,
10288 input_output_channelStats_array[i].ch_utilization_busy_ext);
10289 }
10290#endif
10291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10292 return RETURN_OK;
10293}
10294#define HAL_NETLINK_IMPL
10295
10296/* Hostapd events */
10297
10298#ifndef container_of
10299#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10300#define container_of(ptr, type, member) \
10301 ((type *)((char *)ptr - offset_of(type, member)))
10302#endif /* container_of */
10303
10304struct ctrl {
10305 char sockpath[128];
10306 char sockdir[128];
10307 char bss[IFNAMSIZ];
10308 char reply[4096];
10309 int ssid_index;
10310 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10311 void (*overrun)(struct ctrl *ctrl);
10312 struct wpa_ctrl *wpa;
10313 unsigned int ovfl;
10314 size_t reply_len;
10315 int initialized;
10316 ev_timer retry;
10317 ev_timer watchdog;
10318 ev_stat stat;
10319 ev_io io;
10320};
10321static wifi_newApAssociatedDevice_callback clients_connect_cb;
10322static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10323static struct ctrl wpa_ctrl[MAX_APS];
10324static int initialized;
10325
10326static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10327{
10328 char cbuf[256] = {};
10329 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10330 struct cmsghdr *cmsg;
10331 unsigned int ovfl = ctrl->ovfl;
10332 unsigned int drop;
10333
10334 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10335 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10336 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10337 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10338
10339 drop = ovfl - ctrl->ovfl;
10340 ctrl->ovfl = ovfl;
10341
10342 return drop;
10343}
10344
10345static void ctrl_close(struct ctrl *ctrl)
10346{
10347 if (ctrl->io.cb)
10348 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10349 if (ctrl->retry.cb)
10350 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10351 if (!ctrl->wpa)
10352 return;
10353
10354 wpa_ctrl_detach(ctrl->wpa);
10355 wpa_ctrl_close(ctrl->wpa);
10356 ctrl->wpa = NULL;
10357 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10358}
10359
10360static void ctrl_process(struct ctrl *ctrl)
10361{
10362 const char *str;
10363 int drops;
10364 int level;
10365 int err;
10366
10367 /* Example events:
10368 *
10369 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10370 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10371 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10372 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10373 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10374 */
10375 if (!(str = index(ctrl->reply, '>')))
10376 return;
10377 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10378 return;
10379
10380 str++;
10381
10382 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10383 if (!(str = index(ctrl->reply, ' ')))
10384 return;
10385 wifi_associated_dev_t sta;
10386 memset(&sta, 0, sizeof(sta));
10387
10388 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10389 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10390 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10391
10392 sta.cli_Active=true;
10393
10394 (clients_connect_cb)(ctrl->ssid_index, &sta);
10395 goto handled;
10396 }
10397
10398 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10399 if (!(str = index(ctrl->reply, ' ')))
10400 return;
10401
10402 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10403 goto handled;
10404 }
10405
10406 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10407 printf("CTRL_WPA: handle TERMINATING event\n");
10408 goto retry;
10409 }
10410
10411 if (strncmp("AP-DISABLED", str, 11) == 0) {
10412 printf("CTRL_WPA: handle AP-DISABLED\n");
10413 goto retry;
10414 }
10415
10416 printf("Event not supported!!\n");
10417
10418handled:
10419
10420 if ((drops = ctrl_get_drops(ctrl))) {
10421 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10422 if (ctrl->overrun)
10423 ctrl->overrun(ctrl);
10424 }
10425
10426 return;
10427
10428retry:
10429 printf("WPA_CTRL: closing\n");
10430 ctrl_close(ctrl);
10431 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10432 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10433}
10434
10435static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10436{
10437 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10438 int err;
10439
10440 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10441 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10442 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10443 ctrl->reply[ctrl->reply_len] = 0;
10444 if (err < 0) {
10445 if (errno == EAGAIN || errno == EWOULDBLOCK)
10446 return;
10447 ctrl_close(ctrl);
10448 ev_timer_again(EV_A_ &ctrl->retry);
10449 return;
10450 }
10451
10452 ctrl_process(ctrl);
10453}
10454
10455static int ctrl_open(struct ctrl *ctrl)
10456{
10457 int fd;
10458
10459 if (ctrl->wpa)
10460 return 0;
10461
10462 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10463 if (!ctrl->wpa)
10464 goto err;
10465
10466 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10467 goto err_close;
10468
10469 fd = wpa_ctrl_get_fd(ctrl->wpa);
10470 if (fd < 0)
10471 goto err_detach;
10472
10473 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10474 goto err_detach;
10475
10476 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10477 ev_io_start(EV_DEFAULT_ &ctrl->io);
10478
10479 return 0;
10480
10481err_detach:
10482 wpa_ctrl_detach(ctrl->wpa);
10483err_close:
10484 wpa_ctrl_close(ctrl->wpa);
10485err:
10486 ctrl->wpa = NULL;
10487 return -1;
10488}
10489
10490static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10491{
10492 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10493
10494 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10495 ctrl_open(ctrl);
10496}
10497
10498static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10499{
10500 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10501
10502 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10503 if (ctrl_open(ctrl) == 0) {
10504 printf("WPA_CTRL: retry successful\n");
10505 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10506 }
10507}
10508
10509int ctrl_enable(struct ctrl *ctrl)
10510{
10511 if (ctrl->wpa)
10512 return 0;
10513
10514 if (!ctrl->stat.cb) {
10515 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10516 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10517 }
10518
10519 if (!ctrl->retry.cb) {
10520 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10521 }
10522
10523 return ctrl_open(ctrl);
10524}
10525
10526static void
10527ctrl_msg_cb(char *buf, size_t len)
10528{
10529 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10530
10531 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10532 ctrl_process(ctrl);
10533}
10534
10535static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10536{
10537 int err;
10538
10539 if (!ctrl->wpa)
10540 return -1;
10541 if (*reply_len < 2)
10542 return -1;
10543
10544 (*reply_len)--;
10545 ctrl->reply_len = sizeof(ctrl->reply);
10546 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10547 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10548 if (err < 0)
10549 return err;
10550
10551 if (ctrl->reply_len > *reply_len)
10552 ctrl->reply_len = *reply_len;
10553
10554 *reply_len = ctrl->reply_len;
10555 memcpy(reply, ctrl->reply, *reply_len);
10556 reply[*reply_len - 1] = 0;
10557 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10558 return 0;
10559}
10560
10561static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10562{
10563 const char *pong = "PONG";
10564 const char *ping = "PING";
10565 char reply[1024];
10566 size_t len = sizeof(reply);
10567 int err;
10568 ULONG s, snum;
10569 INT ret;
10570 BOOL status;
10571
10572 printf("WPA_CTRL: watchdog cb\n");
10573
10574 ret = wifi_getSSIDNumberOfEntries(&snum);
10575 if (ret != RETURN_OK) {
10576 printf("%s: failed to get SSID count", __func__);
10577 return;
10578 }
10579
10580 if (snum > MAX_APS) {
10581 printf("more ssid than supported! %lu\n", snum);
10582 return;
10583 }
10584
10585 for (s = 0; s < snum; s++) {
10586 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010587 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010588 continue;
10589 }
10590 if (status == false) continue;
10591
10592 memset(reply, 0, sizeof(reply));
10593 len = sizeof(reply);
10594 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10595 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10596 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10597 continue;
10598
10599 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10600 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010601 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010602 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10603 }
10604}
10605
10606static int init_wpa()
10607{
10608 int ret = 0, i = 0;
10609 ULONG s, snum;
10610
10611 ret = wifi_getSSIDNumberOfEntries(&snum);
10612 if (ret != RETURN_OK) {
10613 printf("%s: failed to get SSID count", __func__);
10614 return RETURN_ERR;
10615 }
10616
10617 if (snum > MAX_APS) {
10618 printf("more ssid than supported! %lu\n", snum);
10619 return RETURN_ERR;
10620 }
10621
10622 for (s = 0; s < snum; s++) {
10623 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10624 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10625 wpa_ctrl[s].ssid_index = s;
10626 ctrl_enable(&wpa_ctrl[s]);
10627 }
10628
10629 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10630 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10631
10632 initialized = 1;
10633 printf("WPA_CTRL: initialized\n");
10634
10635 return RETURN_OK;
10636}
10637
10638void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10639{
10640 clients_connect_cb = callback_proc;
10641 if (!initialized)
10642 init_wpa();
10643}
10644
10645void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10646{
10647 clients_disconnect_cb = callback_proc;
10648 if (!initialized)
10649 init_wpa();
10650}
10651
10652INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10653{
10654 // TODO Implement me!
10655 return RETURN_ERR;
10656}
10657
10658INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10659{
10660 // TODO Implement me!
10661 return RETURN_ERR;
10662}
10663
10664INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10665{
10666 int i;
10667 char cmd[256];
10668 char channel_numbers_buf[256];
10669 char dfs_state_buf[256];
10670 char line[256];
10671 const char *ptr;
10672
10673 memset(cmd, 0, sizeof(cmd));
10674 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10675 memset(line, 0, sizeof(line));
10676 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10677 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10678
10679 if (radioIndex == 0) { // 2.4G - all allowed
10680 if (outputMapSize < 11) {
10681 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10682 return RETURN_ERR;
10683 }
10684
10685 for (i = 0; i < 11; i++) {
10686 outputMap[i].ch_number = i + 1;
10687 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10688 }
10689
10690 return RETURN_OK;
10691 }
10692
10693 if (radioIndex == 1) { // 5G
10694// Example output of iw list:
10695//
10696// Frequencies:
10697// * 5180 MHz [36] (17.0 dBm)
10698// * 5200 MHz [40] (17.0 dBm)
10699// * 5220 MHz [44] (17.0 dBm)
10700// * 5240 MHz [48] (17.0 dBm)
10701// * 5260 MHz [52] (23.0 dBm) (radar detection)
10702// DFS state: usable (for 78930 sec)
10703// DFS CAC time: 60000 ms
10704// * 5280 MHz [56] (23.0 dBm) (radar detection)
10705// DFS state: usable (for 78930 sec)
10706// DFS CAC time: 60000 ms
10707// * 5300 MHz [60] (23.0 dBm) (radar detection)
10708// DFS state: usable (for 78930 sec)
10709// DFS CAC time: 60000 ms
10710// * 5320 MHz [64] (23.0 dBm) (radar detection)
10711// DFS state: usable (for 78930 sec)
10712// DFS CAC time: 60000 ms
10713// * 5500 MHz [100] (disabled)
10714// * 5520 MHz [104] (disabled)
10715// * 5540 MHz [108] (disabled)
10716// * 5560 MHz [112] (disabled)
10717//
10718// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10719 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10720 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10721 return RETURN_ERR;
10722 }
10723
10724 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10725 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10726 return RETURN_ERR;
10727 }
10728
10729 ptr = channel_numbers_buf;
10730 i = 0;
10731 while (ptr = get_line_from_str_buf(ptr, line)) {
10732 if (i >= outputMapSize) {
10733 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10734 return RETURN_ERR;
10735 }
10736 sscanf(line, "%d", &outputMap[i].ch_number);
10737
10738 memset(cmd, 0, sizeof(cmd));
10739 // Below command should fetch string for DFS state (usable, available or unavailable)
10740 // Example line: "DFS state: usable (for 78930 sec)"
10741 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) {
10742 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10743 return RETURN_ERR;
10744 }
10745
10746 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10747 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10748 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10749 return RETURN_ERR;
10750 }
10751
10752 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10753
10754 if (!strcmp(dfs_state_buf, "usable")) {
10755 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10756 } else if (!strcmp(dfs_state_buf, "available")) {
10757 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10758 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10759 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10760 } else {
10761 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10762 }
10763 i++;
10764 }
10765
10766 return RETURN_OK;
10767 }
10768
10769 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10770 return RETURN_ERR;
10771}
10772
10773INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10774{
10775 // TODO Implement me!
10776 return RETURN_ERR;
10777}
10778
10779INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10780{
10781 return RETURN_OK;
10782}
10783
10784INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10785{
10786 // TODO Implement me!
10787 return RETURN_ERR;
10788}
10789
10790INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10791{
10792 // TODO API refrence Implementaion is present on RPI hal
10793 return RETURN_ERR;
10794}
10795
10796INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10797{
developerd946fd62022-12-08 18:03:28 +080010798 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080010799 char cmd[128]={'\0'};
10800 char buf[128]={'\0'};
10801 char *support;
10802 int maximum_tx = 0, current_tx = 0;
10803
10804 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10805 if(txpwr_pcntg == NULL)
10806 return RETURN_ERR;
10807
developerd946fd62022-12-08 18:03:28 +080010808 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10809 return RETURN_ERR;
10810
developera5005b62022-09-13 15:43:35 +080010811 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080010812 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 +080010813 _syscmd(cmd, buf, sizeof(buf));
10814 maximum_tx = strtol(buf, NULL, 10);
10815
10816 // Get the current tx power
10817 memset(cmd, 0, sizeof(cmd));
10818 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080010819 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 +080010820 _syscmd(cmd, buf, sizeof(buf));
10821 current_tx = strtol(buf, NULL, 10);
10822
10823 // Get the power supported list and find the current power percentage in supported list
10824 memset(buf, 0, sizeof(buf));
10825 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10826 support = strtok(buf, ",");
10827 while(true)
10828 {
10829 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 +080010830 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010831 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010832 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010833 }
10834 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10835 if (tmp == current_tx) {
10836 *txpwr_pcntg = strtol(support, NULL, 10);
10837 break;
10838 }
10839 support = strtok(NULL, ",");
10840 }
10841 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010842 return RETURN_OK;
10843}
10844
10845INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10846{
developer58599c22022-09-13 16:40:34 +080010847 // TODO precac feature.
10848 struct params params = {0};
10849 char config_file[128] = {0};
10850
10851 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10852
10853 params.name = "enable_background_radar";
10854 params.value = enable?"1":"0";
10855 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10856 wifi_hostapdWrite(config_file, &params, 1);
10857 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10858
10859 /* TODO precac feature */
10860
10861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10862 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010863}
10864
10865INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10866{
developer58599c22022-09-13 16:40:34 +080010867 char config_file[128] = {0};
10868 char buf[64] = {0};
10869
10870 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10871 if (NULL == enable || NULL == precac)
10872 return RETURN_ERR;
10873
10874 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10875 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10876 if (strncmp(enable, "1", 1) == 0)
10877 *enable = true;
10878 else
10879 *enable = false;
10880
10881 /* TODO precac feature */
10882
10883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10884 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010885}
10886
10887INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10888{
developer58599c22022-09-13 16:40:34 +080010889 *supported = TRUE;
10890 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010891}
10892
developer3e6b1692022-09-30 18:04:05 +080010893INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10894{
10895 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10896 struct params params = {0};
10897 char config_file[64] = {0};
10898 char buf[64] = {0};
10899 unsigned int set_mu_type = 0;
10900 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10901
10902 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10903 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10904
10905 if (strlen(buf) > 0)
10906 set_mu_type = strtol(buf, NULL, 10);
10907
10908 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10909 set_mu_type &= ~0x05; // unset bit 0, 2
10910 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10911 set_mu_type |= 0x01;
10912 set_mu_type &= ~0x04;
10913 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10914 set_mu_type &= ~0x01;
10915 set_mu_type |= 0x04;
10916 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10917 set_mu_type |= 0x05; // set bit 0, 2
10918 }
10919
10920 params.name = "hemu_onoff";
10921 sprintf(buf, "%u", set_mu_type);
10922 params.value = buf;
10923 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10924 wifi_hostapdWrite(config_file, &params, 1);
10925 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10926
10927 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10928 return RETURN_OK;
10929}
10930
10931INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10932{
10933 struct params params={0};
10934 char config_file[64] = {0};
10935 char buf[64] = {0};
10936 unsigned int get_mu_type = 0;
10937
10938 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10939
10940 if (mu_type == NULL)
10941 return RETURN_ERR;
10942
10943 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10944 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10945 get_mu_type = strtol(buf, NULL, 10);
10946
10947 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10948 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10949 else if (get_mu_type & 0x04)
10950 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10951 else if (get_mu_type & 0x01)
10952 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10953 else
10954 *mu_type = WIFI_DL_MU_TYPE_NONE;
10955
10956 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10957 return RETURN_OK;
10958}
10959
10960INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10961{
10962 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10963 struct params params={0};
10964 char config_file[64] = {0};
10965 char buf[64] = {0};
10966 unsigned int set_mu_type = 0;
10967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10968
10969 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10970 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10971
10972 if (strlen(buf) > 0)
10973 set_mu_type = strtol(buf, NULL, 10);
10974
10975 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10976 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10977 set_mu_type &= ~0x0a;
10978 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10979 set_mu_type |= 0x02;
10980 set_mu_type &= ~0x08;
10981 }
10982
10983 params.name = "hemu_onoff";
10984 sprintf(buf, "%u", set_mu_type);
10985 params.value = buf;
10986 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10987 wifi_hostapdWrite(config_file, &params, 1);
10988 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10989
10990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10991 return RETURN_OK;
10992}
10993
10994INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10995{
10996 struct params params={0};
10997 char config_file[64] = {0};
10998 char buf[64] = {0};
10999 unsigned int get_mu_type = 0;
11000
11001 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11002
11003 if (mu_type == NULL)
11004 return RETURN_ERR;
11005
11006 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11007 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11008
11009 get_mu_type = strtol(buf, NULL, 10);
11010 if (get_mu_type & 0x02)
11011 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11012 else
11013 *mu_type = WIFI_DL_MU_TYPE_NONE;
11014
11015 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11016 return RETURN_OK;
11017}
11018
11019
developer454b9462022-09-13 15:29:16 +080011020INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11021{
11022 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011023 char buf[256] = {0};
11024 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011025 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011026 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011027 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011028 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011029
11030 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11031
developer254882b2022-09-30 17:12:31 +080011032 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011033 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11034 return RETURN_ERR;
11035 }
developer454b9462022-09-13 15:29:16 +080011036
developer254882b2022-09-30 17:12:31 +080011037 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011038 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011039
developer254882b2022-09-30 17:12:31 +080011040 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11041 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011042 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011043 _syscmd(cmd, buf, sizeof(buf));
11044 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11045 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11046 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011047 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 +080011048 _syscmd(cmd, buf, sizeof(buf));
11049 }
11050 if (band == band_5) {
11051 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11052 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011053 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 +080011054 _syscmd(cmd, buf, sizeof(buf));
11055 }
11056 }
11057 }
11058 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011059
developer254882b2022-09-30 17:12:31 +080011060 if (guard_interval == wifi_guard_interval_400)
11061 strcpy(GI, "0.4");
11062 else if (guard_interval == wifi_guard_interval_800)
11063 strcpy(GI, "0.8");
11064 else if (guard_interval == wifi_guard_interval_1600)
11065 strcpy(GI, "1.6");
11066 else if (guard_interval == wifi_guard_interval_3200)
11067 strcpy(GI, "3.2");
11068 else if (guard_interval == wifi_guard_interval_auto)
11069 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011070 // Record GI for get GI function
11071 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11072 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011073 if (f == NULL)
11074 return RETURN_ERR;
11075 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011076 fclose(f);
11077 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11078 return RETURN_OK;
11079}
11080
11081INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11082{
11083 char buf[32] = {0};
11084 char cmd[64] = {0};
11085
11086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11087
11088 if (guard_interval == NULL)
11089 return RETURN_ERR;
11090
11091 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11092 _syscmd(cmd, buf, sizeof(buf));
11093
11094 if (strncmp(buf, "0.4", 3) == 0)
11095 *guard_interval = wifi_guard_interval_400;
11096 else if (strncmp(buf, "0.8", 3) == 0)
11097 *guard_interval = wifi_guard_interval_800;
11098 else if (strncmp(buf, "1.6", 3) == 0)
11099 *guard_interval = wifi_guard_interval_1600;
11100 else if (strncmp(buf, "3.2", 3) == 0)
11101 *guard_interval = wifi_guard_interval_3200;
11102 else
11103 *guard_interval = wifi_guard_interval_auto;
11104
11105 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11106 return RETURN_OK;
11107}
11108
developer3cc61d12022-09-13 16:36:05 +080011109INT wifi_setBSSColor(INT radio_index, UCHAR color)
11110{
11111 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11112 struct params params = {0};
11113 char config_file[128] = {0};
11114 char bss_color[4] ={0};
11115
11116 params.name = "he_bss_color";
11117 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11118 params.value = bss_color;
11119 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11120 wifi_hostapdWrite(config_file, &params, 1);
11121 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11122
11123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11124 return RETURN_OK;
11125}
11126
11127INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11128{
11129 char config_file[128] = {0};
11130 char buf[64] = {0};
11131 char temp_output[128] = {'\0'};
11132
11133 wifi_dbg_printf("\nFunc=%s\n", __func__);
11134 if (NULL == color)
11135 return RETURN_ERR;
11136
11137 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11138 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11139
11140 if(strlen(buf) > 0) {
11141 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11142 } else {
11143 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11144 }
11145
11146 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11147 wifi_dbg_printf("\noutput_string=%s\n", color);
11148
11149 return RETURN_OK;
11150}
11151
developer06a01d92022-09-07 16:32:39 +080011152/* multi-psk support */
11153INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11154{
11155 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011156 char interface_name[16] = {0};
11157
11158 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11159 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011160
developerd946fd62022-12-08 18:03:28 +080011161 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11162 interface_name,
developer06a01d92022-09-07 16:32:39 +080011163 mac[0],
11164 mac[1],
11165 mac[2],
11166 mac[3],
11167 mac[4],
11168 mac[5]
11169 );
11170 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11171 _syscmd(cmd, key->wifi_keyId, 64);
11172
11173
11174 return RETURN_OK;
11175}
11176
11177INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11178{
developerd946fd62022-12-08 18:03:28 +080011179 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011180 FILE *fd = NULL;
11181 char fname[100];
11182 char cmd[128] = {0};
11183 char out[64] = {0};
11184 wifi_key_multi_psk_t * key = NULL;
11185 if(keysNumber < 0)
11186 return RETURN_ERR;
11187
11188 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11189 fd = fopen(fname, "w");
11190 if (!fd) {
11191 return RETURN_ERR;
11192 }
11193 key= (wifi_key_multi_psk_t *) keys;
11194 for(int i=0; i<keysNumber; ++i, key++) {
11195 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11196 }
11197 fclose(fd);
11198
11199 //reload file
developerd946fd62022-12-08 18:03:28 +080011200 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11201 return RETURN_ERR;
11202 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011203 _syscmd(cmd, out, 64);
11204 return RETURN_OK;
11205}
11206
11207INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11208{
11209 FILE *fd = NULL;
11210 char fname[100];
11211 char * line = NULL;
11212 char * pos = NULL;
11213 size_t len = 0;
11214 ssize_t read = 0;
11215 INT ret = RETURN_OK;
11216 wifi_key_multi_psk_t *keys_it = NULL;
11217
11218 if (keysNumber < 1) {
11219 return RETURN_ERR;
11220 }
11221
11222 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11223 fd = fopen(fname, "r");
11224 if (!fd) {
11225 return RETURN_ERR;
11226 }
11227
11228 if (keys == NULL) {
11229 ret = RETURN_ERR;
11230 goto close;
11231 }
11232
11233 keys_it = keys;
11234 while ((read = getline(&line, &len, fd)) != -1) {
11235 //Strip trailing new line if present
11236 if (read > 0 && line[read-1] == '\n') {
11237 line[read-1] = '\0';
11238 }
11239
11240 if(strcmp(line,"keyid=")) {
11241 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11242 if (!(pos = index(line, ' '))) {
11243 ret = RETURN_ERR;
11244 goto close;
11245 }
11246 pos++;
11247 //Here should be 00:00:00:00:00:00
11248 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11249 printf("Not supported MAC: %s\n", pos);
11250 }
11251 if (!(pos = index(pos, ' '))) {
11252 ret = RETURN_ERR;
11253 goto close;
11254 }
11255 pos++;
11256
11257 //The rest is PSK
11258 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11259 keys_it++;
11260
11261 if(--keysNumber <= 0)
11262 break;
11263 }
11264 }
11265
11266close:
11267 free(line);
11268 fclose(fd);
11269 return ret;
11270}
11271/* end of multi-psk support */
11272
11273INT wifi_setNeighborReports(UINT apIndex,
11274 UINT numNeighborReports,
11275 wifi_NeighborReport_t *neighborReports)
11276{
11277 char cmd[256] = { 0 };
11278 char hex_bssid[13] = { 0 };
11279 char bssid[18] = { 0 };
11280 char nr[256] = { 0 };
11281 char ssid[256];
11282 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011283 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011284 INT ret;
11285
11286 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011287 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11288 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11289 return RETURN_ERR;
11290 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 +080011291 system(cmd);
11292
11293 for(unsigned int i = 0; i < numNeighborReports; i++)
11294 {
11295 memset(ssid, 0, sizeof(ssid));
11296 ret = wifi_getSSIDName(apIndex, ssid);
11297 if (ret != RETURN_OK)
11298 return RETURN_ERR;
11299
11300 memset(hex_ssid, 0, sizeof(hex_ssid));
11301 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11302 sprintf(hex_ssid + k,"%02x", ssid[j]);
11303
11304 snprintf(hex_bssid, sizeof(hex_bssid),
11305 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11306 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11307 snprintf(bssid, sizeof(bssid),
11308 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11309 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11310
11311 snprintf(nr, sizeof(nr),
11312 "%s" // bssid
11313 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11314 "%02hhx" // operclass
11315 "%02hhx" // channel
11316 "%02hhx", // phy_mode
11317 hex_bssid,
11318 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11319 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11320 neighborReports[i].opClass,
11321 neighborReports[i].channel,
11322 neighborReports[i].phyTable);
11323
11324 snprintf(cmd, sizeof(cmd),
11325 "hostapd_cli set_neighbor "
11326 "%s " // bssid
11327 "ssid=%s " // ssid
11328 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011329 "-i %s",
11330 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011331
11332 if (WEXITSTATUS(system(cmd)) != 0)
11333 {
11334 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11335 }
11336 }
11337
11338 return RETURN_OK;
11339}
11340
11341INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11342{
11343 return RETURN_OK;
11344}
11345
11346#ifdef _WIFI_HAL_TEST_
11347int main(int argc,char **argv)
11348{
11349 int index;
11350 INT ret=0;
11351 char buf[1024]="";
11352
11353 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11354 if(argc<3)
11355 {
11356 if(argc==2)
11357 {
11358 if(!strcmp(argv[1], "init"))
11359 return wifi_init();
11360 if(!strcmp(argv[1], "reset"))
11361 return wifi_reset();
11362 if(!strcmp(argv[1], "wifi_getHalVersion"))
11363 {
11364 char buffer[64];
11365 if(wifi_getHalVersion(buffer)==RETURN_OK)
11366 printf("Version: %s\n", buffer);
11367 else
11368 printf("Error in wifi_getHalVersion\n");
11369 return RETURN_OK;
11370 }
11371 }
11372 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11373 exit(-1);
11374 }
11375
11376 index = atoi(argv[2]);
11377 if(strstr(argv[1], "wifi_getApName")!=NULL)
11378 {
11379 wifi_getApName(index,buf);
11380 printf("Ap name is %s \n",buf);
11381 return 0;
11382 }
11383 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11384 {
11385 BOOL b = FALSE;
11386 BOOL *output_bool = &b;
11387 wifi_getRadioAutoChannelEnable(index,output_bool);
11388 printf("Channel enabled = %d \n",b);
11389 return 0;
11390 }
11391 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11392 {
11393 wifi_getApWpaEncryptionMode(index,buf);
11394 printf("encryption enabled = %s\n",buf);
11395 return 0;
11396 }
11397 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11398 {
11399 BOOL b = FALSE;
11400 BOOL *output_bool = &b;
11401 wifi_getApSsidAdvertisementEnable(index,output_bool);
11402 printf("advertisment enabled = %d\n",b);
11403 return 0;
11404 }
11405 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11406 {
11407 if(argc <= 3 )
11408 {
11409 printf("Insufficient arguments \n");
11410 exit(-1);
11411 }
11412
11413 char sta[20] = {'\0'};
11414 ULLONG handle= 0;
11415 strcpy(sta,argv[3]);
11416 mac_address_t st;
11417 mac_addr_aton(st,sta);
11418
11419 wifi_associated_dev_tid_stats_t tid_stats;
11420 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11421 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11422 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);
11423 }
11424
11425 if(strstr(argv[1], "getApEnable")!=NULL) {
11426 BOOL enable;
11427 ret=wifi_getApEnable(index, &enable);
11428 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11429 }
11430 else if(strstr(argv[1], "setApEnable")!=NULL) {
11431 BOOL enable = atoi(argv[3]);
11432 ret=wifi_setApEnable(index, enable);
11433 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11434 }
11435 else if(strstr(argv[1], "getApStatus")!=NULL) {
11436 char status[64];
11437 ret=wifi_getApStatus(index, status);
11438 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11439 }
11440 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11441 {
11442 wifi_getSSIDNameStatus(index,buf);
11443 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11444 return 0;
11445 }
11446 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11447 wifi_ssidTrafficStats2_t stats={0};
11448 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11449 printf("%s %d: returns %d\n", argv[1], index, ret);
11450 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11451 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11452 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11453 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11454 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11455 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11456 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11457 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11458 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11459 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11460 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11461 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11462 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11463 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11464 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11465 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11466 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11467 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11468 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11469 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11470 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11471 }
11472 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11473 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11474 UINT array_size=0;
11475 UINT i=0;
11476 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11477 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11478 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11479 printf(" neighbor %d:\n", i);
11480 printf(" ap_SSID =%s\n", pt->ap_SSID);
11481 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11482 printf(" ap_Mode =%s\n", pt->ap_Mode);
11483 printf(" ap_Channel =%d\n", pt->ap_Channel);
11484 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11485 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11486 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11487 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11488 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11489 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11490 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11491 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11492 printf(" ap_Noise =%d\n", pt->ap_Noise);
11493 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11494 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11495 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11496 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11497 }
11498 if(neighbor_ap_array)
11499 free(neighbor_ap_array); //make sure to free the list
11500 }
11501 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11502 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11503 UINT array_size=0;
11504 UINT i=0;
11505 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11506 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11507 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11508 printf(" associated_dev %d:\n", i);
11509 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11510 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11511 printf(" cli_SNR =%d\n", pt->cli_SNR);
11512 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11513 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11514 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11515 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11516 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11517 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11518 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11519 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11520 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11521 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11522 }
11523 if(associated_dev_array)
11524 free(associated_dev_array); //make sure to free the list
11525 }
11526
11527 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11528 {
11529#define MAX_ARRAY_SIZE 64
11530 int i, array_size;
11531 char *p, *ch_str;
11532 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11533
11534 if(argc != 5)
11535 {
11536 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11537 exit(-1);
11538 }
11539 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11540
11541 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11542 {
11543 strtok_r(ch_str, ",", &p);
11544 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11545 }
11546 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11547 if(!array_size)
11548 array_size=1;//Need to print current channel statistics
11549 for(i=0; i<array_size; i++)
11550 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11551 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11552 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11553 input_output_channelStats_array[i].ch_number,\
11554 input_output_channelStats_array[i].ch_noise,\
11555 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11556 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11557 input_output_channelStats_array[i].ch_utilization_busy,\
11558 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11559 input_output_channelStats_array[i].ch_utilization_total);
11560 }
11561
11562 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11563 {
11564 if(argc <= 3 )
11565 {
11566 printf("Insufficient arguments \n");
11567 exit(-1);
11568 }
11569 char mac_addr[20] = {'\0'};
11570 wifi_device_t output_struct;
11571 int dev_index = atoi(argv[3]);
11572
11573 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11574 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11575 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);
11576 }
11577
11578 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11579 {
11580 if (argc <= 3)
11581 {
11582 printf("Insufficient arguments\n");
11583 exit(-1);
11584 }
11585 char args[256];
11586 wifi_NeighborReport_t *neighborReports;
11587
11588 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11589 if (!neighborReports)
11590 {
11591 printf("Failed to allocate memory");
11592 exit(-1);
11593 }
11594
11595 for (int i = 3; i < argc; ++i)
11596 {
11597 char *val;
11598 int j = 0;
11599 memset(args, 0, sizeof(args));
11600 strncpy(args, argv[i], sizeof(args));
11601 val = strtok(args, ";");
11602 while (val != NULL)
11603 {
11604 if (j == 0)
11605 {
11606 mac_addr_aton(neighborReports[i - 3].bssid, val);
11607 } else if (j == 1)
11608 {
11609 neighborReports[i - 3].info = strtol(val, NULL, 16);
11610 } else if (j == 2)
11611 {
11612 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11613 } else if (j == 3)
11614 {
11615 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11616 } else if (j == 4)
11617 {
11618 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11619 } else {
11620 printf("Insufficient arguments]n\n");
11621 exit(-1);
11622 }
11623 val = strtok(NULL, ";");
11624 j++;
11625 }
11626 }
11627
11628 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11629 if (ret != RETURN_OK)
11630 {
11631 printf("wifi_setNeighborReports ret = %d", ret);
11632 exit(-1);
11633 }
11634 }
11635 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11636 {
11637 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11638 printf("%s.\n", buf);
11639 else
11640 printf("Error returned\n");
11641 }
11642 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11643 {
11644 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11645 printf("%s.\n", buf);
11646 else
11647 printf("Error returned\n");
11648 }
11649 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11650 {
11651 if (argc <= 2)
11652 {
11653 printf("Insufficient arguments\n");
11654 exit(-1);
11655 }
11656 char buf[64]= {'\0'};
11657 wifi_getRadioOperatingChannelBandwidth(index,buf);
11658 printf("Current bandwidth is %s \n",buf);
11659 return 0;
11660 }
11661 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11662 {
11663 if (argc <= 5)
11664 {
11665 printf("Insufficient arguments\n");
11666 exit(-1);
11667 }
11668 UINT channel = atoi(argv[3]);
11669 UINT width = atoi(argv[4]);
11670 UINT beacon = atoi(argv[5]);
11671 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11672 printf("Result = %d", ret);
11673 }
11674
11675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11676 return 0;
11677}
11678
11679#endif
11680
11681#ifdef WIFI_HAL_VERSION_3
11682
developer1e5aa162022-09-13 16:06:24 +080011683INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11684{
11685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11686 if (bitMap & WIFI_BITRATE_1MBPS)
11687 strcat(BasicRate, "1,");
11688 if (bitMap & WIFI_BITRATE_2MBPS)
11689 strcat(BasicRate, "2,");
11690 if (bitMap & WIFI_BITRATE_5_5MBPS)
11691 strcat(BasicRate, "5.5,");
11692 if (bitMap & WIFI_BITRATE_6MBPS)
11693 strcat(BasicRate, "6,");
11694 if (bitMap & WIFI_BITRATE_9MBPS)
11695 strcat(BasicRate, "9,");
11696 if (bitMap & WIFI_BITRATE_11MBPS)
11697 strcat(BasicRate, "11,");
11698 if (bitMap & WIFI_BITRATE_12MBPS)
11699 strcat(BasicRate, "12,");
11700 if (bitMap & WIFI_BITRATE_18MBPS)
11701 strcat(BasicRate, "18,");
11702 if (bitMap & WIFI_BITRATE_24MBPS)
11703 strcat(BasicRate, "24,");
11704 if (bitMap & WIFI_BITRATE_36MBPS)
11705 strcat(BasicRate, "36,");
11706 if (bitMap & WIFI_BITRATE_48MBPS)
11707 strcat(BasicRate, "48,");
11708 if (bitMap & WIFI_BITRATE_54MBPS)
11709 strcat(BasicRate, "54,");
11710 if (strlen(BasicRate) != 0) // remove last comma
11711 BasicRate[strlen(BasicRate) - 1] = '\0';
11712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11713 return RETURN_OK;
11714}
11715
11716INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11717{
11718 UINT BitMap = 0;
11719 char *rate;
11720
11721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11722 rate = strtok(BasicRatesList, ",");
11723 while(rate != NULL)
11724 {
11725 if (strcmp(rate, "1") == 0)
11726 BitMap |= WIFI_BITRATE_1MBPS;
11727 else if (strcmp(rate, "2") == 0)
11728 BitMap |= WIFI_BITRATE_2MBPS;
11729 else if (strcmp(rate, "5.5") == 0)
11730 BitMap |= WIFI_BITRATE_5_5MBPS;
11731 else if (strcmp(rate, "6") == 0)
11732 BitMap |= WIFI_BITRATE_6MBPS;
11733 else if (strcmp(rate, "9") == 0)
11734 BitMap |= WIFI_BITRATE_9MBPS;
11735 else if (strcmp(rate, "11") == 0)
11736 BitMap |= WIFI_BITRATE_11MBPS;
11737 else if (strcmp(rate, "12") == 0)
11738 BitMap |= WIFI_BITRATE_12MBPS;
11739 else if (strcmp(rate, "18") == 0)
11740 BitMap |= WIFI_BITRATE_18MBPS;
11741 else if (strcmp(rate, "24") == 0)
11742 BitMap |= WIFI_BITRATE_24MBPS;
11743 else if (strcmp(rate, "36") == 0)
11744 BitMap |= WIFI_BITRATE_36MBPS;
11745 else if (strcmp(rate, "48") == 0)
11746 BitMap |= WIFI_BITRATE_48MBPS;
11747 else if (strcmp(rate, "54") == 0)
11748 BitMap |= WIFI_BITRATE_54MBPS;
11749 rate = strtok(NULL, ",");
11750 }
11751 *basicRateBitMap = BitMap;
11752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11753 return RETURN_OK;
11754}
11755
11756// 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 +080011757INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11758{
developer1e5aa162022-09-13 16:06:24 +080011759 char buf[128] = {0};
11760 char cmd[128] = {0};
11761 char config_file[64] = {0};
11762 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011763 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011764 wifi_radio_operationParam_t current_param;
11765
11766 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11767
11768 multiple_set = TRUE;
11769 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11770 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11771 return RETURN_ERR;
11772 }
11773 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11774 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11775 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11776 return RETURN_ERR;
11777 }
11778 }
developer5884e982022-10-06 10:52:50 +080011779
11780 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11781 bandwidth = 20;
11782 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11783 bandwidth = 40;
11784 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11785 bandwidth = 80;
11786 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11787 bandwidth = 160;
11788 if (operationParam->autoChannelEnabled){
11789 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11790 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11791 return RETURN_ERR;
11792 }
11793 }else{
developer1e5aa162022-09-13 16:06:24 +080011794 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11795 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11796 return RETURN_ERR;
11797 }
11798 }
developer5884e982022-10-06 10:52:50 +080011799
developer1e5aa162022-09-13 16:06:24 +080011800 if (current_param.variant != operationParam->variant) {
11801 // Two different definition bit map, so need to check every bit.
11802 if (operationParam->variant & WIFI_80211_VARIANT_A)
11803 set_mode |= WIFI_MODE_A;
11804 if (operationParam->variant & WIFI_80211_VARIANT_B)
11805 set_mode |= WIFI_MODE_B;
11806 if (operationParam->variant & WIFI_80211_VARIANT_G)
11807 set_mode |= WIFI_MODE_G;
11808 if (operationParam->variant & WIFI_80211_VARIANT_N)
11809 set_mode |= WIFI_MODE_N;
11810 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11811 set_mode |= WIFI_MODE_AC;
11812 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11813 set_mode |= WIFI_MODE_AX;
11814 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11815 memset(buf, 0, sizeof(buf));
11816 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11817 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11818 return RETURN_ERR;
11819 }
11820 }
11821 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11822 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11823 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11824 return RETURN_ERR;
11825 }
11826 }
11827 if (current_param.beaconInterval != operationParam->beaconInterval) {
11828 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11829 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11830 return RETURN_ERR;
11831 }
11832 }
11833 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11834 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11835 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11836 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11837 return RETURN_ERR;
11838 }
11839 }
11840 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11841 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11842 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11843 return RETURN_ERR;
11844 }
11845 }
11846 if (current_param.guardInterval != operationParam->guardInterval) {
11847 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11848 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11849 return RETURN_ERR;
11850 }
11851 }
11852 if (current_param.transmitPower != operationParam->transmitPower) {
11853 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11854 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11855 return RETURN_ERR;
11856 }
11857 }
11858 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11859 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11860 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11861 return RETURN_ERR;
11862 }
11863 }
11864 if (current_param.obssCoex != operationParam->obssCoex) {
11865 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11866 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11867 return RETURN_ERR;
11868 }
11869 }
11870 if (current_param.stbcEnable != operationParam->stbcEnable) {
11871 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11872 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11873 return RETURN_ERR;
11874 }
11875 }
11876 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11877 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11878 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11879 return RETURN_ERR;
11880 }
11881 }
11882
11883 // if enable is true, then restart the radio
11884 wifi_setRadioEnable(index, FALSE);
11885 if (operationParam->enable == TRUE)
11886 wifi_setRadioEnable(index, TRUE);
11887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11888
developer06a01d92022-09-07 16:32:39 +080011889 return RETURN_OK;
11890}
11891
11892INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11893{
developer1e5aa162022-09-13 16:06:24 +080011894 char band[64] = {0};
11895 char buf[256] = {0};
11896 char config_file[64] = {0};
11897 char cmd[128] = {0};
11898 int ret = RETURN_ERR;
11899 int mode = 0;
11900 ULONG channel = 0;
11901 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011902
11903 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11904 printf("Entering %s index = %d\n", __func__, (int)index);
11905
developer1e5aa162022-09-13 16:06:24 +080011906 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11907 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11908 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011909 {
developer1e5aa162022-09-13 16:06:24 +080011910 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011911 return RETURN_ERR;
11912 }
11913 operationParam->enable = enabled;
11914
11915 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011916 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011917 {
developer1e5aa162022-09-13 16:06:24 +080011918 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011919 return RETURN_ERR;
11920 }
11921
11922 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011923 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011924 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011925 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011926 else if (!strcmp(band, "6GHz"))
11927 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011928 else
11929 {
developer1e5aa162022-09-13 16:06:24 +080011930 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011931 band);
11932 }
11933
developer1e5aa162022-09-13 16:06:24 +080011934 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11935 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11936 operationParam->channel = 0;
11937 operationParam->autoChannelEnabled = TRUE;
11938 } else {
11939 operationParam->channel = strtol(buf, NULL, 10);
11940 operationParam->autoChannelEnabled = FALSE;
11941 }
11942
developer06a01d92022-09-07 16:32:39 +080011943 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011944 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11945 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11946 return RETURN_ERR;
11947 }
developer06a01d92022-09-07 16:32:39 +080011948 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11949 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11950 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011951 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11952 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011953 else
11954 {
developer1e5aa162022-09-13 16:06:24 +080011955 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11956 return false;
developer06a01d92022-09-07 16:32:39 +080011957 }
11958
developer1e5aa162022-09-13 16:06:24 +080011959 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11960 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11961 return RETURN_ERR;
11962 }
11963 // Two different definition bit map, so need to check every bit.
11964 if (mode & WIFI_MODE_A)
11965 operationParam->variant |= WIFI_80211_VARIANT_A;
11966 if (mode & WIFI_MODE_B)
11967 operationParam->variant |= WIFI_80211_VARIANT_B;
11968 if (mode & WIFI_MODE_G)
11969 operationParam->variant |= WIFI_80211_VARIANT_G;
11970 if (mode & WIFI_MODE_N)
11971 operationParam->variant |= WIFI_80211_VARIANT_N;
11972 if (mode & WIFI_MODE_AC)
11973 operationParam->variant |= WIFI_80211_VARIANT_AC;
11974 if (mode & WIFI_MODE_AX)
11975 operationParam->variant |= WIFI_80211_VARIANT_AX;
11976 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11977 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11978 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011979 }
developer1e5aa162022-09-13 16:06:24 +080011980 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11981 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11982 return RETURN_ERR;
11983 }
11984 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11985 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11986 return RETURN_ERR;
11987 }
developer06a01d92022-09-07 16:32:39 +080011988
developer1e5aa162022-09-13 16:06:24 +080011989 memset(buf, 0, sizeof(buf));
11990 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11991 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11992 return RETURN_ERR;
11993 }
11994 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11995
11996 memset(buf, 0, sizeof(buf));
11997 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11998 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11999 return RETURN_ERR;
12000 }
12001 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12002
12003 memset(buf, 0, sizeof(buf));
12004 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12005 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12006
12007 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12008 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12009 return RETURN_ERR;
12010 }
12011 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12012 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12013 return RETURN_ERR;
12014 }
12015
12016 memset(buf, 0, sizeof(buf));
12017 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12018 if (strcmp(buf, "-1") == 0) {
12019 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12020 operationParam->ctsProtection = FALSE;
12021 } else {
12022 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12023 operationParam->ctsProtection = TRUE;
12024 }
12025
12026 memset(buf, 0, sizeof(buf));
12027 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12028 if (strcmp(buf, "0") == 0)
12029 operationParam->obssCoex = FALSE;
12030 else
12031 operationParam->obssCoex = TRUE;
12032
12033 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12034 _syscmd(cmd, buf, sizeof(buf));
12035 if (strlen(buf) != 0)
12036 operationParam->stbcEnable = TRUE;
12037 else
12038 operationParam->stbcEnable = FALSE;
12039
12040 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12041 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12042 return RETURN_ERR;
12043 }
12044
12045 // Below value is hardcoded
12046
12047 operationParam->numSecondaryChannels = 0;
12048 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12049 operationParam->channelSecondary[i] = 0;
12050 }
12051 operationParam->csa_beacon_count = 15;
12052 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012053
12054 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12055 return RETURN_OK;
12056}
12057
12058static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12059{
developerc086fb72022-10-04 10:18:22 +080012060 int max_radio_num = 0;
12061
12062 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012063 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012064 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12065 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012066 }
12067
developerc086fb72022-10-04 10:18:22 +080012068 return (arrayIndex * max_radio_num) + radioIndex;
12069}
developer06a01d92022-09-07 16:32:39 +080012070
developerc086fb72022-10-04 10:18:22 +080012071wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12072 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12073 return WIFI_BITRATE_1MBPS;
12074 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12075 return WIFI_BITRATE_2MBPS;
12076 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12077 return WIFI_BITRATE_5_5MBPS;
12078 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12079 return WIFI_BITRATE_6MBPS;
12080 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12081 return WIFI_BITRATE_9MBPS;
12082 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12083 return WIFI_BITRATE_11MBPS;
12084 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12085 return WIFI_BITRATE_12MBPS;
12086 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12087 return WIFI_BITRATE_18MBPS;
12088 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12089 return WIFI_BITRATE_24MBPS;
12090 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12091 return WIFI_BITRATE_36MBPS;
12092 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12093 return WIFI_BITRATE_48MBPS;
12094 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12095 return WIFI_BITRATE_54MBPS;
12096 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012097}
12098
developer1d57d002022-10-12 18:03:15 +080012099INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12100{
12101 if (beacon == WIFI_BITRATE_1MBPS)
12102 strcpy(beacon_str, "1Mbps");
12103 else if (beacon == WIFI_BITRATE_2MBPS)
12104 strcpy(beacon_str, "2Mbps");
12105 else if (beacon == WIFI_BITRATE_5_5MBPS)
12106 strcpy(beacon_str, "5.5Mbps");
12107 else if (beacon == WIFI_BITRATE_6MBPS)
12108 strcpy(beacon_str, "6Mbps");
12109 else if (beacon == WIFI_BITRATE_9MBPS)
12110 strcpy(beacon_str, "9Mbps");
12111 else if (beacon == WIFI_BITRATE_11MBPS)
12112 strcpy(beacon_str, "11Mbps");
12113 else if (beacon == WIFI_BITRATE_12MBPS)
12114 strcpy(beacon_str, "12Mbps");
12115 else if (beacon == WIFI_BITRATE_18MBPS)
12116 strcpy(beacon_str, "18Mbps");
12117 else if (beacon == WIFI_BITRATE_24MBPS)
12118 strcpy(beacon_str, "24Mbps");
12119 else if (beacon == WIFI_BITRATE_36MBPS)
12120 strcpy(beacon_str, "36Mbps");
12121 else if (beacon == WIFI_BITRATE_48MBPS)
12122 strcpy(beacon_str, "48Mbps");
12123 else if (beacon == WIFI_BITRATE_54MBPS)
12124 strcpy(beacon_str, "54Mbps");
12125 return RETURN_OK;
12126}
12127
developer06a01d92022-09-07 16:32:39 +080012128INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12129{
developerc086fb72022-10-04 10:18:22 +080012130 INT mode = 0;
12131 INT ret = -1;
12132 INT output = 0;
12133 int i = 0;
12134 int vap_index = 0;
12135 BOOL enabled = FALSE;
12136 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012137 wifi_vap_security_t security = {0};
developerc086fb72022-10-04 10:18:22 +080012138 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080012139
12140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12141 printf("Entering %s index = %d\n", __func__, (int)index);
12142
developer06a01d92022-09-07 16:32:39 +080012143 for (i = 0; i < 5; i++)
12144 {
developerc086fb72022-10-04 10:18:22 +080012145 map->vap_array[i].radio_index = index;
12146
developer06a01d92022-09-07 16:32:39 +080012147 vap_index = array_index_to_vap_index(index, i);
12148 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012149 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012150
developerc086fb72022-10-04 10:18:22 +080012151 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012152
12153 map->vap_array[i].vap_index = vap_index;
12154
12155 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012156 ret = wifi_getApName(vap_index, buf);
12157 if (ret != RETURN_OK) {
12158 printf("%s: wifi_getApName return error\n", __func__);
12159 return RETURN_ERR;
12160 }
12161 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12162
12163 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012164 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012165 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012166 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012167 return RETURN_ERR;
12168 }
12169 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 +080012170
12171 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012172 if (ret != RETURN_OK) {
12173 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012174 return RETURN_ERR;
12175 }
12176 map->vap_array[i].u.bss_info.enabled = enabled;
12177
developerc086fb72022-10-04 10:18:22 +080012178 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12179 if (ret != RETURN_OK) {
12180 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12181 return RETURN_ERR;
12182 }
developer06a01d92022-09-07 16:32:39 +080012183 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012184
12185 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12186 if (ret != RETURN_OK) {
12187 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12188 return RETURN_ERR;
12189 }
12190 map->vap_array[i].u.bss_info.isolation = enabled;
12191
12192 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12193 if (ret != RETURN_OK) {
12194 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12195 return RETURN_ERR;
12196 }
12197 map->vap_array[i].u.bss_info.bssMaxSta = output;
12198
12199 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12200 if (ret != RETURN_OK) {
12201 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12202 return RETURN_ERR;
12203 }
12204 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012205
developerc086fb72022-10-04 10:18:22 +080012206 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12207 if (ret != RETURN_OK) {
12208 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12209 return RETURN_ERR;
12210 }
12211 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012212
developerc086fb72022-10-04 10:18:22 +080012213 ret = wifi_getApSecurity(vap_index, &security);
12214 if (ret != RETURN_OK) {
12215 printf("%s: wifi_getApSecurity return error\n", __func__);
12216 return RETURN_ERR;
12217 }
12218 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012219
developerc086fb72022-10-04 10:18:22 +080012220 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12221 if (ret != RETURN_OK) {
12222 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12223 return RETURN_ERR;
12224 }
12225 if (mode == 0)
12226 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12227 else
12228 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12229 if (mode == 1)
12230 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12231 else if (mode == 2)
12232 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012233
developerc086fb72022-10-04 10:18:22 +080012234 ret = wifi_getApWmmEnable(vap_index, &enabled);
12235 if (ret != RETURN_OK) {
12236 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12237 return RETURN_ERR;
12238 }
12239 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012240
developerc086fb72022-10-04 10:18:22 +080012241 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12242 if (ret != RETURN_OK) {
12243 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012244 return RETURN_ERR;
12245 }
developerc086fb72022-10-04 10:18:22 +080012246 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012247
12248 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012249 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012250 if (ret != RETURN_OK) {
12251 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12252 return RETURN_ERR;
12253 }
12254 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012255
developerc086fb72022-10-04 10:18:22 +080012256 memset(buf, 0, sizeof(buf));
12257 ret = wifi_getBaseBSSID(vap_index, buf);
12258 if (ret != RETURN_OK) {
12259 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12260 return RETURN_ERR;
12261 }
12262 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12263 &map->vap_array[i].u.bss_info.bssid[0],
12264 &map->vap_array[i].u.bss_info.bssid[1],
12265 &map->vap_array[i].u.bss_info.bssid[2],
12266 &map->vap_array[i].u.bss_info.bssid[3],
12267 &map->vap_array[i].u.bss_info.bssid[4],
12268 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012269 // 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]);
12270
12271 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12272 if (ret != RETURN_OK) {
12273 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12274 return RETURN_ERR;
12275 }
12276 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012277
developerc086fb72022-10-04 10:18:22 +080012278 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012279 }
12280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12281 return RETURN_OK;
12282}
12283
developerd946fd62022-12-08 18:03:28 +080012284static int prepareInterface(UINT apIndex, char *new_interface)
12285{
12286 char cur_interface[16] = {0};
12287 char config_file[128] = {0};
12288 char cmd[128] = {0};
12289 char buf[16] = {0};
12290 int max_radio_num = 0;
12291 int radioIndex = -1;
12292 int phyIndex = -1;
12293
12294 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12295 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12296
12297 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12298 wifi_getMaxRadioNumber(&max_radio_num);
12299 radioIndex = apIndex % max_radio_num;
12300 phyIndex = radio_index_to_phy(radioIndex);
12301 // disable and del old interface, then add new interface
12302 wifi_setApEnable(apIndex, FALSE);
12303 snprintf(cmd, sizeof(cmd), "iw %s del && iw %s%d interface add %s type __ap", cur_interface, RADIO_PREFIX, phyIndex, new_interface);
12304 _syscmd(cmd, buf, sizeof(buf));
12305 // modify vap status file, replace old interface with the new one
12306 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12307 _syscmd(cmd, buf, sizeof(buf));
12308 }
12309 return RETURN_OK;
12310}
12311
developer06a01d92022-09-07 16:32:39 +080012312INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12313{
developerd946fd62022-12-08 18:03:28 +080012314 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012315 unsigned int i;
12316 wifi_vap_info_t *vap_info = NULL;
12317 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012318 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012319 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012320 char buf[256] = {0};
12321 char cmd[128] = {0};
12322 char config_file[64] = {0};
12323 char bssid[32] = {0};
12324 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012325
12326 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12327 printf("Entering %s index = %d\n", __func__, (int)index);
12328 for (i = 0; i < map->num_vaps; i++)
12329 {
developer1d57d002022-10-12 18:03:15 +080012330 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012331 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012332 if (vap_info->u.bss_info.enabled == FALSE)
12333 continue;
developer06a01d92022-09-07 16:32:39 +080012334
developer1d57d002022-10-12 18:03:15 +080012335 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12336
12337 // multi-ap need to copy current radio config
12338 if (vap_info->radio_index != vap_info->vap_index) {
12339 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12340 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012341 }
developer06a01d92022-09-07 16:32:39 +080012342
developer1d57d002022-10-12 18:03:15 +080012343 struct params params[3];
developerd946fd62022-12-08 18:03:28 +080012344 // Check whether the interface name is used by other ap.
12345 int apIndex = -1;
12346 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12347 if (apIndex != -1 && apIndex != vap_info->vap_index)
12348 continue;
12349 prepareInterface(vap_info->vap_index, vap_info->vap_name);
12350
developer1d57d002022-10-12 18:03:15 +080012351 params[0].name = "interface";
12352 params[0].value = vap_info->vap_name;
12353 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12354 params[1].name = "bssid";
12355 params[1].value = bssid;
12356 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12357 params[2].name = "wpa_psk_file";
12358 params[2].value = psk_file;
12359
12360 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12361 wifi_hostapdWrite(config_file, params, 3);
12362
12363 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12364 _syscmd(cmd, buf, sizeof(buf));
12365
12366 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12367 if (ret != RETURN_OK) {
12368 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12369 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012370 }
developer1d57d002022-10-12 18:03:15 +080012371
12372 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12373 if (ret != RETURN_OK) {
12374 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12375 return RETURN_ERR;
12376 }
12377
12378 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12379 if (ret != RETURN_OK) {
12380 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12381 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012382 }
12383
developer1d57d002022-10-12 18:03:15 +080012384 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12385 if (ret != RETURN_OK) {
12386 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12387 return RETURN_ERR;
12388 }
developer06a01d92022-09-07 16:32:39 +080012389
developer1d57d002022-10-12 18:03:15 +080012390 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12391 if (ret != RETURN_OK) {
12392 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12393 return RETURN_ERR;
12394 }
developer06a01d92022-09-07 16:32:39 +080012395
developer1d57d002022-10-12 18:03:15 +080012396 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12397 if (ret != RETURN_OK) {
12398 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12399 return RETURN_ERR;
12400 }
12401
developer804c64f2022-10-19 13:54:40 +080012402 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012403 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012404 }else {
12405 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012406 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012407 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12408 _syscmd(cmd, buf, sizeof(buf));
12409 }else{
developer1d57d002022-10-12 18:03:15 +080012410 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012411 }
developer1d57d002022-10-12 18:03:15 +080012412 }
12413
12414 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12415 if (ret != RETURN_OK) {
12416 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12417 return RETURN_ERR;
12418 }
12419
12420 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12421 if (ret != RETURN_OK) {
12422 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12423 return RETURN_ERR;
12424 }
12425
12426 memset(buf, 0, sizeof(buf));
12427 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12428 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12429 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12430 if (ret != RETURN_OK) {
12431 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12432 return RETURN_ERR;
12433 }
12434
12435 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12436 if (ret != RETURN_OK) {
12437 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12438 return RETURN_ERR;
12439 }
12440
12441 wifi_setApEnable(vap_info->vap_index, TRUE);
12442 multiple_set = FALSE;
12443
12444 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12445 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12446 if (ret != RETURN_OK) {
12447 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12448 return RETURN_ERR;
12449 }
12450
12451 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12452 if (ret != RETURN_OK) {
12453 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12454 return RETURN_ERR;
12455 }
developer06a01d92022-09-07 16:32:39 +080012456
developer1d57d002022-10-12 18:03:15 +080012457 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012458 }
12459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12460 return RETURN_OK;
12461}
12462
12463int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12464{
12465 char *token, *next;
12466 const char s[2] = ",";
12467 int count =0;
12468
12469 /* get the first token */
12470 token = strtok_r(pchannels, s, &next);
12471
12472 /* walk through other tokens */
12473 while( token != NULL && count < MAX_CHANNELS) {
12474 chlistptr->channels_list[count++] = atoi(token);
12475 token = strtok_r(NULL, s, &next);
12476 }
12477
12478 return count;
12479}
12480
12481static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12482{
12483 INT status;
12484 wifi_channels_list_t *chlistp;
12485 CHAR output_string[64];
12486 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012487 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012488 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012489
12490 if(rcap == NULL)
12491 {
12492 return RETURN_ERR;
12493 }
12494
12495 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012496 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012497
developer1e5aa162022-09-13 16:06:24 +080012498 if (band == band_2_4)
12499 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12500 else if (band == band_5)
12501 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12502 else if (band == band_6)
12503 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012504
12505 chlistp = &(rcap->channel_list[0]);
12506 memset(pchannels, 0, sizeof(pchannels));
12507
12508 /* possible number of radio channels */
12509 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12510 {
12511 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12512 }
12513 /* Number of channels and list*/
12514 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12515
12516 /* autoChannelSupported */
12517 /* always ON with wifi_getRadioAutoChannelSupported */
12518 rcap->autoChannelSupported = TRUE;
12519
12520 /* DCSSupported */
12521 /* always ON with wifi_getRadioDCSSupported */
12522 rcap->DCSSupported = TRUE;
12523
12524 /* zeroDFSSupported - TBD */
12525 rcap->zeroDFSSupported = FALSE;
12526
12527 /* Supported Country List*/
12528 memset(output_string, 0, sizeof(output_string));
12529 status = wifi_getRadioCountryCode(radioIndex, output_string);
12530 if( status != 0 ) {
12531 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12532 return RETURN_ERR;
12533 } else {
12534 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12535 }
12536 if(!strcmp(output_string,"US")){
12537 rcap->countrySupported[0] = wifi_countrycode_US;
12538 rcap->countrySupported[1] = wifi_countrycode_CA;
12539 } else if (!strcmp(output_string,"CA")) {
12540 rcap->countrySupported[0] = wifi_countrycode_CA;
12541 rcap->countrySupported[1] = wifi_countrycode_US;
12542 } else {
12543 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12544 }
12545
12546 rcap->numcountrySupported = 2;
12547
12548 /* csi */
12549 rcap->csi.maxDevices = 8;
12550 rcap->csi.soudingFrameSupported = TRUE;
12551
developer033b37b2022-10-18 11:27:46 +080012552 phyId = radio_index_to_phy(radioIndex);
12553 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012554
12555 /* channelWidth - all supported bandwidths */
12556 int i=0;
12557 rcap->channelWidth[i] = 0;
12558 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12559 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12560 WIFI_CHANNELBANDWIDTH_40MHZ);
12561
12562 }
developer1e5aa162022-09-13 16:06:24 +080012563 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012564 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12565 WIFI_CHANNELBANDWIDTH_40MHZ |
12566 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12567 }
12568
12569
12570 /* mode - all supported variants */
12571 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12572 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012573 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 +080012574 }
12575 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012576 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12577 }
12578 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12579 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012580 }
12581 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12582 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12583
12584 /* supportedBitRate - all supported bitrates */
12585 rcap->supportedBitRate[i] = 0;
12586 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12587 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12588 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12589 }
developer1e5aa162022-09-13 16:06:24 +080012590 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012591 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12592 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12593 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12594 }
12595
12596
12597 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12598 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12599 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12600 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12601 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12602 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12603 rcap->cipherSupported = 0;
12604 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12605 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12606
12607 return RETURN_OK;
12608}
12609
12610INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12611{
developer30423732022-12-01 16:17:49 +080012612 INT status = 0, radioIndex = 0;
12613 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080012614 int iter = 0;
developer30423732022-12-01 16:17:49 +080012615 unsigned int j = 0;
12616 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080012617
12618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12619
12620 memset(cap, 0, sizeof(wifi_hal_capability_t));
12621
12622 /* version */
12623 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12624 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12625
12626 /* number of radios platform property */
12627 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12628 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012629 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012630
12631 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12632 {
12633 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12634 if (status != 0) {
12635 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12636 return RETURN_ERR;
12637 }
12638
12639 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12640 {
developer804c64f2022-10-19 13:54:40 +080012641 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012642 {
12643 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12644 return RETURN_ERR;
12645 }
12646 iface_info = &cap->wifi_prop.interface_map[iter];
12647 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12648 iface_info->rdk_radio_index = radioIndex;
12649 memset(output, 0, sizeof(output));
12650 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12651 {
12652 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12653 }
12654 // TODO: bridge name
12655 // TODO: vlan id
12656 // TODO: primary
12657 iface_info->index = array_index_to_vap_index(radioIndex, j);
12658 memset(output, 0, sizeof(output));
developer30423732022-12-01 16:17:49 +080012659 if (iface_info->index >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012660 {
12661 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12662 }
12663 iter++;
12664 }
12665 }
12666
12667 cap->BandSteeringSupported = FALSE;
12668 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12669 return RETURN_OK;
12670}
12671
developer9df4e652022-10-11 11:27:38 +080012672INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12673{
12674 struct params h_config={0};
12675 char config_file[64] = {0};
12676
12677 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12678
12679 h_config.name = "okc";
12680 h_config.value = okc_enable?"1":"0";
12681
12682 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12683 wifi_hostapdWrite(config_file, &h_config, 1);
12684 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12685
12686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12687 return RETURN_OK;
12688}
12689
12690INT wifi_setSAEMFP(int ap_index, BOOL enable)
12691{
12692 struct params h_config={0};
12693 char config_file[64] = {0};
12694 char buf[128] = {0};
12695
12696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12697
12698 h_config.name = "sae_require_mfp";
12699 h_config.value = enable?"1":"0";
12700
12701 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12702 wifi_hostapdWrite(config_file, &h_config, 1);
12703 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12704
12705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12706 return RETURN_OK;
12707}
12708
12709INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12710{
12711 struct params h_config={0};
12712 char config_file[64] = {0};
12713 char buf[128] = {0};
12714
12715 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12716
12717 h_config.name = "sae_pwe";
12718 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12719 h_config.value = buf;
12720
12721 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12722 wifi_hostapdWrite(config_file, &h_config, 1);
12723 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12724
12725 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12726 return RETURN_OK;
12727}
12728
12729INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12730{
12731 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12732 struct params h_config={0};
12733 char config_file[64] = {0};
12734
12735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12736
12737 h_config.name = "wpa_disable_eapol_key_retries";
12738 h_config.value = disable_EAPOL_retries?"1":"0";
12739
12740 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12741 wifi_hostapdWrite(config_file, &h_config, 1);
12742 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12743
12744 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12745 return RETURN_OK;
12746}
12747
developer06a01d92022-09-07 16:32:39 +080012748INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12749{
developer587c1b62022-09-27 15:58:59 +080012750 char buf[128] = {0};
12751 char config_file[128] = {0};
12752 char password[64] = {0};
12753 char mfp[32] = {0};
12754 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012755 BOOL okc_enable = FALSE;
12756 BOOL sae_MFP = FALSE;
12757 BOOL disable_EAPOL_retries = TRUE;
12758 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012759 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012760 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012761
12762 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12763
12764 multiple_set = TRUE;
12765 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12766 if (security->mode == wifi_security_mode_none) {
12767 strcpy(wpa_mode, "None");
12768 } else if (security->mode == wifi_security_mode_wpa_personal)
12769 strcpy(wpa_mode, "WPA-Personal");
12770 else if (security->mode == wifi_security_mode_wpa2_personal)
12771 strcpy(wpa_mode, "WPA2-Personal");
12772 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12773 strcpy(wpa_mode, "WPA-WPA2-Personal");
12774 else if (security->mode == wifi_security_mode_wpa_enterprise)
12775 strcpy(wpa_mode, "WPA-Enterprise");
12776 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12777 strcpy(wpa_mode, "WPA2-Enterprise");
12778 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12779 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012780 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012781 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012782 okc_enable = TRUE;
12783 sae_MFP = TRUE;
12784 sae_pwe = 2;
12785 disable_EAPOL_retries = FALSE;
12786 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012787 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012788 okc_enable = TRUE;
12789 sae_MFP = TRUE;
12790 sae_pwe = 2;
12791 disable_EAPOL_retries = FALSE;
12792 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012793 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012794 sae_MFP = TRUE;
12795 sae_pwe = 2;
12796 disable_EAPOL_retries = FALSE;
12797 }
12798
12799 band = wifi_index_to_band(ap_index);
12800 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12801 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12802 return RETURN_ERR;
12803 }
developer587c1b62022-09-27 15:58:59 +080012804
12805 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012806 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012807 wifi_setSAEMFP(ap_index, sae_MFP);
12808 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012809 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012810
developer9df4e652022-10-11 11:27:38 +080012811 if (security->mode != wifi_security_mode_none) {
12812 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12813 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12814 password[63] = '\0';
12815 wifi_setApSecurityKeyPassphrase(ap_index, password);
12816 }
12817 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12818 params.name = "sae_password";
12819 params.value = security->u.key.key;
12820 wifi_hostapdWrite(config_file, &params, 1);
12821 }
12822 }
developer587c1b62022-09-27 15:58:59 +080012823
12824 if (security->mode != wifi_security_mode_none) {
12825 memset(&params, 0, sizeof(params));
12826 params.name = "wpa_pairwise";
12827 if (security->encr == wifi_encryption_tkip)
12828 params.value = "TKIP";
12829 else if (security->encr == wifi_encryption_aes)
12830 params.value = "CCMP";
12831 else if (security->encr == wifi_encryption_aes_tkip)
12832 params.value = "TKIP CCMP";
12833 wifi_hostapdWrite(config_file, &params, 1);
12834 }
12835
12836 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012837 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012838 else if (security->mfp == wifi_mfp_cfg_optional)
12839 strcpy(mfp, "Optional");
12840 else if (security->mfp == wifi_mfp_cfg_required)
12841 strcpy(mfp, "Required");
12842 wifi_setApSecurityMFPConfig(ap_index, mfp);
12843
12844 memset(&params, 0, sizeof(params));
12845 params.name = "transition_disable";
12846 if (security->wpa3_transition_disable == TRUE)
12847 params.value = "0x01";
12848 else
12849 params.value = "0x00";
12850 wifi_hostapdWrite(config_file, &params, 1);
12851
12852 memset(&params, 0, sizeof(params));
12853 params.name = "wpa_group_rekey";
12854 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12855 params.value = buf;
12856 wifi_hostapdWrite(config_file, &params, 1);
12857
12858 memset(&params, 0, sizeof(params));
12859 params.name = "wpa_strict_rekey";
12860 params.value = security->strict_rekey?"1":"0";
12861 wifi_hostapdWrite(config_file, &params, 1);
12862
12863 memset(&params, 0, sizeof(params));
12864 params.name = "wpa_pairwise_update_count";
12865 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12866 params.value = buf;
12867 wifi_hostapdWrite(config_file, &params, 1);
12868
12869 memset(&params, 0, sizeof(params));
12870 params.name = "disable_pmksa_caching";
12871 params.value = security->disable_pmksa_caching?"1":"0";
12872 wifi_hostapdWrite(config_file, &params, 1);
12873
12874 wifi_setApEnable(ap_index, FALSE);
12875 wifi_setApEnable(ap_index, TRUE);
12876
12877 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12878
developer06a01d92022-09-07 16:32:39 +080012879 return RETURN_OK;
12880}
12881
12882INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12883{
developer9df4e652022-10-11 11:27:38 +080012884 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012885 char config_file[128] = {0};
12886 int disable = 0;
12887 // struct params params = {0};
12888
12889 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12890 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12891 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12892 security->mode = wifi_security_mode_none;
12893 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012894 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012895 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012896 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012897 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012898 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012899 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012900 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012901 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012902 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012903 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012904 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012905 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012906 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012907 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012908 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012909 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012910 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012911 security->mode = wifi_security_mode_wpa3_enterprise;
12912 }
12913
12914 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12915 if (security->mode == wifi_security_mode_none)
12916 security->encr = wifi_encryption_none;
12917 else {
12918 if (strcmp(buf, "TKIP") == 0)
12919 security->encr = wifi_encryption_tkip;
12920 else if (strcmp(buf, "CCMP") == 0)
12921 security->encr = wifi_encryption_aes;
12922 else
12923 security->encr = wifi_encryption_aes_tkip;
12924 }
12925
developer9df4e652022-10-11 11:27:38 +080012926 if (security->mode != wifi_encryption_none) {
12927 memset(buf, 0, sizeof(buf));
12928 // wpa3 can use one or both configs as password, so we check sae_password first.
12929 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12930 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12931 security->u.key.type = wifi_security_key_type_sae;
12932 } else {
12933 security->u.key.type = wifi_security_key_type_psk;
12934 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12935 }
12936 strncpy(security->u.key.key, buf, sizeof(buf));
12937 security->u.key.key[255] = '\0';
12938 }
12939
developer587c1b62022-09-27 15:58:59 +080012940 memset(buf, 0, sizeof(buf));
12941 wifi_getApSecurityMFPConfig(ap_index, buf);
12942 if (strcmp(buf, "Disabled") == 0)
12943 security->mfp = wifi_mfp_cfg_disabled;
12944 else if (strcmp(buf, "Optional") == 0)
12945 security->mfp = wifi_mfp_cfg_optional;
12946 else if (strcmp(buf, "Required") == 0)
12947 security->mfp = wifi_mfp_cfg_required;
12948
12949 memset(buf, 0, sizeof(buf));
12950 security->wpa3_transition_disable = FALSE;
12951 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12952 disable = strtol(buf, NULL, 16);
12953 if (disable != 0)
12954 security->wpa3_transition_disable = TRUE;
12955
12956 memset(buf, 0, sizeof(buf));
12957 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12958 if (strlen(buf) == 0)
12959 security->rekey_interval = 86400;
12960 else
12961 security->rekey_interval = strtol(buf, NULL, 10);
12962
12963 memset(buf, 0, sizeof(buf));
12964 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12965 if (strlen(buf) == 0)
12966 security->strict_rekey = 1;
12967 else
12968 security->strict_rekey = strtol(buf, NULL, 10);
12969
12970 memset(buf, 0, sizeof(buf));
12971 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12972 if (strlen(buf) == 0)
12973 security->eapol_key_retries = 4;
12974 else
12975 security->eapol_key_retries = strtol(buf, NULL, 10);
12976
12977 memset(buf, 0, sizeof(buf));
12978 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12979 if (strlen(buf) == 0)
12980 security->disable_pmksa_caching = FALSE;
12981 else
12982 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12983
12984 /* TODO
12985 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12986 */
12987 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12988 security->eap_identity_req_timeout = 0;
12989 security->eap_identity_req_retries = 0;
12990 security->eap_req_timeout = 0;
12991 security->eap_req_retries = 0;
12992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012993 return RETURN_OK;
12994}
12995
12996#endif /* WIFI_HAL_VERSION_3 */
12997
12998#ifdef WIFI_HAL_VERSION_3_PHASE2
12999INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13000{
developerd946fd62022-12-08 18:03:28 +080013001 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013002 char cmd[128] = {0};
13003 char buf[128] = {0};
13004 char *mac_addr = NULL;
13005 BOOL status = FALSE;
13006 size_t len = 0;
13007
13008 if(ap_index > MAX_APS)
13009 return RETURN_ERR;
13010
13011 *output_numDevices = 0;
13012 wifi_getApEnable(ap_index, &status);
13013 if (status == FALSE)
13014 return RETURN_OK;
13015
developerd946fd62022-12-08 18:03:28 +080013016 if (GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13017 return RETURN_ERR;
13018 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013019 _syscmd(cmd, buf, sizeof(buf));
13020
13021 mac_addr = strtok(buf, "\n");
13022 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13023 *output_numDevices = i + 1;
13024 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13025 addr_ptr = output_deviceMacAddressArray[i];
13026 mac_addr_aton(addr_ptr, mac_addr);
13027 mac_addr = strtok(NULL, "\n");
13028 }
13029
13030 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013031}
13032#else
13033INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13034{
developerd946fd62022-12-08 18:03:28 +080013035 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013036 char cmd[128];
13037 BOOL status = false;
13038
13039 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13040 return RETURN_ERR;
13041
13042 output_buf[0] = '\0';
13043
13044 wifi_getApEnable(ap_index,&status);
13045 if (!status)
13046 return RETURN_OK;
13047
developerd946fd62022-12-08 18:03:28 +080013048 if (GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13049 return RETURN_ERR;
13050 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013051 _syscmd(cmd, output_buf, output_buf_size);
13052
13053 return RETURN_OK;
13054}
13055#endif
developer2f513ab2022-09-13 14:26:06 +080013056
13057INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13058{
13059 char output[16]={'\0'};
13060 char config_file[MAX_BUF_SIZE] = {0};
13061
13062 if (!enable)
13063 return RETURN_ERR;
13064
13065 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13066 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13067
13068 if (strlen(output) == 0)
13069 *enable = FALSE;
13070 else if (strncmp(output, "1", 1) == 0)
13071 *enable = TRUE;
13072 else
13073 *enable = FALSE;
13074
13075 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13076 return RETURN_OK;
13077}
developer2d9c30f2022-09-13 15:06:14 +080013078
13079INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13080{
developer804c64f2022-10-19 13:54:40 +080013081 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013082 return RETURN_ERR;
13083 *output_enable=TRUE;
13084 return RETURN_OK;
13085}
developerfd7d2892022-09-13 16:44:53 +080013086
13087INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13088{
13089 char cmd[128] = {0};
13090 char buf[128] = {0};
13091 char line[128] = {0};
13092 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013093 FILE *f = NULL;
13094 int index = 0;
13095 int exp = 0;
13096 int mantissa = 0;
13097 int duration = 0;
13098 int radio_index = 0;
13099 int max_radio_num = 0;
13100 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013101 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013102 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13103
13104 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013105
developerfd7d2892022-09-13 16:44:53 +080013106 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013107
13108 phyId = radio_index_to_phy(radio_index);
13109 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013110 _syscmd(cmd, buf, sizeof(buf));
13111 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13112 if (*numSessionReturned > maxNumberSessions)
13113 *numSessionReturned = maxNumberSessions;
13114 else if (*numSessionReturned < 1) {
13115 *numSessionReturned = 0;
13116 return RETURN_OK;
13117 }
13118
developer033b37b2022-10-18 11:27:46 +080013119 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 +080013120 if ((f = popen(cmd, "r")) == NULL) {
13121 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13122 return RETURN_ERR;
13123 }
13124
13125 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013126 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013127 char *tmp = NULL;
13128 strcpy(buf, line);
13129 tmp = strtok(buf, " ");
13130 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13131 tmp = strtok(NULL, " ");
13132 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13133 tmp = strtok(NULL, " ");
13134 if (strstr(tmp, "t")) {
13135 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13136 }
13137 if (strstr(tmp, "a")) {
13138 twtSessions[index].twtParameters.operation.announced = TRUE;
13139 }
13140 tmp = strtok(NULL, " ");
13141 exp = strtol(tmp, NULL, 10);
13142 tmp = strtok(NULL, " ");
13143 mantissa = strtol(tmp, NULL, 10);
13144 tmp = strtok(NULL, " ");
13145 duration = strtol(tmp, NULL, 10);
13146
13147 // only implicit supported
13148 twtSessions[index].twtParameters.operation.implicit = TRUE;
13149 // only individual agreement supported
13150 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13151
13152 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13153 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013154 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013155 // Overflow handling
13156 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13157 } else {
13158 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13159 }
13160 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13161 index++;
13162 }
13163
13164 pclose(f);
13165 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13166 return RETURN_OK;
13167}