blob: 0737eea32e9392c77f6c3e77a15f32a4ad8d596d [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
511 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
512 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
540static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
541{
developer1e5aa162022-09-13 16:06:24 +0800542 if (multiple_set == TRUE)
543 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800544 char cmd[MAX_CMD_SIZE]="", output[32]="";
545 FILE *fp;
546 int i;
547 //NOTE RELOAD should be done in ApplySSIDSettings
548
549 for(i=0; i<item_count; i++, list++)
550 {
551 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
552 if((fp = popen(cmd, "r"))==NULL)
553 {
554 perror("popen failed");
555 return -1;
556 }
557 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
558 {
559 pclose(fp);
560 perror("fgets failed");
561 return -1;
562 }
563 pclose(fp);
564 }
565 return 0;
566}
567
568static int wifi_reloadAp(int apIndex)
569{
developer1e5aa162022-09-13 16:06:24 +0800570 if (multiple_set == TRUE)
571 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800572 char cmd[MAX_CMD_SIZE]="";
573 char buf[MAX_BUF_SIZE]="";
574
575 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
576 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
577 return RETURN_ERR;
578
579 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
580 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
581 return RETURN_ERR;
582
583 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
584 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
585 return RETURN_ERR;
586
587 return RETURN_OK;
588}
589
590
591//For Getting Current Interface Name from corresponding hostapd configuration
592void GetInterfaceName(char *interface_name, char *conf_file)
593{
594 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
595 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
596 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
597}
598
599INT File_Reading(CHAR *file, char *Value)
600{
601 FILE *fp = NULL;
602 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
603 int count = 0;
604
605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
606 fp = popen(file,"r");
607 if(fp == NULL)
608 return RETURN_ERR;
609
610 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
611 {
612 for(count=0;buf[count]!='\n';count++)
613 copy_buf[count]=buf[count];
614 copy_buf[count]='\0';
615 }
616 strcpy(Value,copy_buf);
617 pclose(fp);
618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
619
620 return RETURN_OK;
621}
622
623void wifi_RestartHostapd_2G()
624{
625 int Public2GApIndex = 4;
626
627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
628 wifi_setApEnable(Public2GApIndex, FALSE);
629 wifi_setApEnable(Public2GApIndex, TRUE);
630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
631}
632
633void wifi_RestartHostapd_5G()
634{
635 int Public5GApIndex = 5;
636
637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
638 wifi_setApEnable(Public5GApIndex, FALSE);
639 wifi_setApEnable(Public5GApIndex, TRUE);
640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
641}
642
643void wifi_RestartPrivateWifi_2G()
644{
645 int PrivateApIndex = 0;
646
647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
648 wifi_setApEnable(PrivateApIndex, FALSE);
649 wifi_setApEnable(PrivateApIndex, TRUE);
650 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
651}
652
653void wifi_RestartPrivateWifi_5G()
654{
655 int Private5GApIndex = 1;
656
657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
658 wifi_setApEnable(Private5GApIndex, FALSE);
659 wifi_setApEnable(Private5GApIndex, TRUE);
660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
661}
662
663static int writeBandWidth(int radioIndex,char *bw_value)
664{
665 char buf[MAX_BUF_SIZE];
666 char cmd[MAX_CMD_SIZE];
667
668 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
669 if(_syscmd(cmd, buf, sizeof(buf)))
670 {
671 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
672 _syscmd(cmd, buf, sizeof(buf));
673 return RETURN_OK;
674 }
675
676 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
677 _syscmd(cmd,buf,sizeof(buf));
678 return RETURN_OK;
679}
680
681static int readBandWidth(int radioIndex,char *bw_value)
682{
683 char buf[MAX_BUF_SIZE];
684 char cmd[MAX_CMD_SIZE];
685 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
686 _syscmd(cmd,buf,sizeof(buf));
687 if(NULL!=strstr(buf,"20MHz"))
688 {
689 strcpy(bw_value,"20MHz");
690 }
691 else if(NULL!=strstr(buf,"40MHz"))
692 {
693 strcpy(bw_value,"40MHz");
694 }
695 else if(NULL!=strstr(buf,"80MHz"))
696 {
697 strcpy(bw_value,"80MHz");
698 }
699 else
700 {
701 return RETURN_ERR;
702 }
703 return RETURN_OK;
704}
705
developer39a5efb2022-09-13 16:09:06 +0800706INT wifi_getMaxRadioNumber(INT *max_radio_num)
707{
708 char cmd[64] = {0};
709 char buf[4] = {0};
710
711 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
712
713 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
714 _syscmd(cmd, buf, sizeof(buf));
developer804c64f2022-10-19 13:54:40 +0800715 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
developer39a5efb2022-09-13 16:09:06 +0800716
717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
718
719 return RETURN_OK;
720}
721
developer264159b2022-11-02 09:41:35 +0800722// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800723INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
724{
developer5f222492022-09-13 15:21:52 +0800725 struct params params={'\0'};
726 char config_file[MAX_BUF_SIZE] = {0};
727 char buf[MAX_BUF_SIZE] = {'\0'};
728
729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800730 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800731 if (strlen (beaconRate) >= 5) {
732 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
733 buf[strlen(beaconRate) - 4] = '\0';
734 } else if (strlen(beaconRate) > 0)
735 strcpy(buf, beaconRate);
736 else
737 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800738
739 params.name = "beacon_rate";
740 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
741 if (strncmp(buf, "5.5", 3) == 0) {
742 snprintf(buf, sizeof(buf), "55");
743 params.value = buf;
744 } else {
745 strcat(buf, "0");
746 params.value = buf;
747 }
748
749 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
750 wifi_hostapdWrite(config_file, &params, 1);
751 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
753
754 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800755}
756
757INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
758{
developer1d57d002022-10-12 18:03:15 +0800759 char config_file[128] = {'\0'};
760 char temp_output[128] = {'\0'};
761 char buf[128] = {'\0'};
762 char cmd[128] = {'\0'};
763 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800764 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800765
766 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
767 if (NULL == beaconRate)
768 return RETURN_ERR;
769
770 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
771 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800772 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800773 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
774 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800775 if (strncmp(buf, "55", 2) == 0)
776 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
777 else {
778 rate = strtol(buf, NULL, 10)/10;
779 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
780 }
developer5f222492022-09-13 15:21:52 +0800781 } else {
developer1d57d002022-10-12 18:03:15 +0800782 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800783 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 +0800784 _syscmd(cmd, buf, sizeof(buf));
785 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800786 }
787 strncpy(beaconRate, temp_output, sizeof(temp_output));
788 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
789
790 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800791}
792
793INT wifi_setLED(INT radioIndex, BOOL enable)
794{
795 return 0;
796}
797INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
798{
799 return RETURN_OK;
800}
801/**********************************************************************************
802 *
803 * Wifi Subsystem level function prototypes
804 *
805**********************************************************************************/
806//---------------------------------------------------------------------------------------------------
807//Wifi system api
808//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
809INT wifi_getHalVersion(CHAR *output_string) //RDKB
810{
811 if(!output_string)
812 return RETURN_ERR;
813 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
814
815 return RETURN_OK;
816}
817
818
819/* wifi_factoryReset() function */
820/**
821* @description Clears internal variables to implement a factory reset of the Wi-Fi
822* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
823*
824* @param None
825*
826* @return The status of the operation.
827* @retval RETURN_OK if successful.
828* @retval RETURN_ERR if any error is detected
829*
830* @execution Synchronous
831* @sideeffect None
832*
833* @note This function must not suspend and must not invoke any blocking system
834* calls. It should probably just send a message to a driver event handler task.
835*
836*/
837INT wifi_factoryReset()
838{
839 char cmd[128];
840
841 /*delete running hostapd conf files*/
842 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
843 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
844 system(cmd);
845 system("systemctl restart hostapd.service");
846
847 return RETURN_OK;
848}
849
850/* wifi_factoryResetRadios() function */
851/**
852* @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.
853*
854* @param None
855* @return The status of the operation
856* @retval RETURN_OK if successful
857* @retval RETURN_ERR if any error is detected
858*
859* @execution Synchronous
860*
861* @sideeffect None
862*
863* @note This function must not suspend and must not invoke any blocking system
864* calls. It should probably just send a message to a driver event handler task.
865*
866*/
867INT wifi_factoryResetRadios()
868{
869 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
870 return RETURN_OK;
871
872 return RETURN_ERR;
873}
874
875
876/* wifi_factoryResetRadio() function */
877/**
878* @description Restore selected radio parameters without touching access point parameters
879*
880* @param radioIndex - Index of Wi-Fi Radio channel
881*
882* @return The status of the operation.
883* @retval RETURN_OK if successful.
884* @retval RETURN_ERR if any error is detected
885*
886* @execution Synchronous.
887* @sideeffect None.
888*
889* @note This function must not suspend and must not invoke any blocking system
890* calls. It should probably just send a message to a driver event handler task.
891*
892*/
893INT wifi_factoryResetRadio(int radioIndex) //RDKB
894{
developer5ff7f5f2022-09-13 15:12:16 +0800895 system("systemctl stop hostapd.service");
896
developer06a01d92022-09-07 16:32:39 +0800897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
898 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800899 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800900 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800901 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800902 else
903 return RETURN_ERR;
904
developer5ff7f5f2022-09-13 15:12:16 +0800905 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800906 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
907 return RETURN_OK;
908}
909
910/* wifi_initRadio() function */
911/**
912* Description: This function call initializes the specified radio.
913* Implementation specifics may dictate the functionality since
914* different hardware implementations may have different initilization requirements.
915* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
916*
917* @return The status of the operation.
918* @retval RETURN_OK if successful.
919* @retval RETURN_ERR if any error is detected
920*
921* @execution Synchronous.
922* @sideeffect None.
923*
924* @note This function must not suspend and must not invoke any blocking system
925* calls. It should probably just send a message to a driver event handler task.
926*
927*/
928INT wifi_initRadio(INT radioIndex)
929{
930 //TODO: Initializes the wifi subsystem (for specified radio)
931 return RETURN_OK;
932}
933void macfilter_init()
934{
935 char count[4]={'\0'};
936 char buf[253]={'\0'};
937 char tmp[19]={'\0'};
938 int dev_count,block,mac_entry=0;
939 char res[4]={'\0'};
940 char acl_file_path[64] = {'\0'};
941 FILE *fp = NULL;
942 int index=0;
943 char iface[10]={'\0'};
944 char config_file[MAX_BUF_SIZE] = {0};
945
946
947 sprintf(acl_file_path,"/tmp/mac_filter.sh");
948
949 fp=fopen(acl_file_path,"w+");
950 sprintf(buf,"#!/bin/sh \n");
951 fprintf(fp,"%s\n",buf);
952
953 system("chmod 0777 /tmp/mac_filter.sh");
954
955 for(index=0;index<=1;index++)
956 {
957 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
958 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
959 sprintf(buf,"syscfg get %dcountfilter",index);
960 _syscmd(buf,count,sizeof(count));
961 mac_entry=atoi(count);
962
963 sprintf(buf,"syscfg get %dblockall",index);
964 _syscmd(buf,res,sizeof(res));
965 block = atoi(res);
966
967 //Allow only those macs mentioned in ACL
968 if(block==1)
969 {
970 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
971 fprintf(fp,"%s\n",buf);
972 for(dev_count=1;dev_count<=mac_entry;dev_count++)
973 {
974 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
975 _syscmd(buf,tmp,sizeof(tmp));
976 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
977 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
978 fprintf(fp,"%s\n",buf);
979 }
980 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
981 fprintf(fp,"%s\n",buf);
982 }
983
984 //Block all the macs mentioned in ACL
985 else if(block==2)
986 {
987 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
988 fprintf(fp,"%s\n",buf);
989
990 for(dev_count=1;dev_count<=mac_entry;dev_count++)
991 {
992 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
993 _syscmd(buf,tmp,sizeof(tmp));
994 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
995 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
996 fprintf(fp,"%s\n",buf);
997 }
998 }
999 }
1000 fclose(fp);
1001}
1002
1003// Initializes the wifi subsystem (all radios)
1004INT wifi_init() //RDKB
1005{
1006 char interface[MAX_BUF_SIZE]={'\0'};
1007 char bridge_name[MAX_BUF_SIZE]={'\0'};
1008 INT len=0;
1009
1010 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1011 //Not intitializing macfilter for Turris-Omnia Platform for now
1012 //macfilter_init();
1013
1014 system("/usr/sbin/iw reg set US");
1015 system("systemctl start hostapd.service");
1016 sleep(2);//sleep to wait for hostapd to start
1017
1018 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1019
1020 return RETURN_OK;
1021}
1022
1023/* wifi_reset() function */
1024/**
1025* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1026* Implementation specifics may dictate what is actualy reset since
1027* different hardware implementations may have different requirements.
1028* Parameters : None
1029*
1030* @return The status of the operation.
1031* @retval RETURN_OK if successful.
1032* @retval RETURN_ERR if any error is detected
1033*
1034* @execution Synchronous.
1035* @sideeffect None.
1036*
1037* @note This function must not suspend and must not invoke any blocking system
1038* calls. It should probably just send a message to a driver event handler task.
1039*
1040*/
1041INT wifi_reset()
1042{
1043 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001044 system("systemctl stop hostapd.service");
1045 sleep(2);
1046 system("systemctl start hostapd.service");
1047 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001048 return RETURN_OK;
1049}
1050
1051/* wifi_down() function */
1052/**
1053* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1054* Implementation specifics may dictate some functionality since
1055* different hardware implementations may have different requirements.
1056*
1057* @param None
1058*
1059* @return The status of the operation
1060* @retval RETURN_OK if successful
1061* @retval RETURN_ERR if any error is detected
1062*
1063* @execution Synchronous
1064* @sideeffect None
1065*
1066* @note This function must not suspend and must not invoke any blocking system
1067* calls. It should probably just send a message to a driver event handler task.
1068*
1069*/
1070INT wifi_down()
1071{
1072 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001073 system("systemctl stop hostapd.service");
1074 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001075 return RETURN_OK;
1076}
1077
1078
1079/* wifi_createInitialConfigFiles() function */
1080/**
1081* @description This function creates wifi configuration files. The format
1082* and content of these files are implementation dependent. This function call is
1083* used to trigger this task if necessary. Some implementations may not need this
1084* function. If an implementation does not need to create config files the function call can
1085* do nothing and return RETURN_OK.
1086*
1087* @param None
1088*
1089* @return The status of the operation
1090* @retval RETURN_OK if successful
1091* @retval RETURN_ERR if any error is detected
1092*
1093* @execution Synchronous
1094* @sideeffect None
1095*
1096* @note This function must not suspend and must not invoke any blocking system
1097* calls. It should probably just send a message to a driver event handler task.
1098*
1099*/
1100INT wifi_createInitialConfigFiles()
1101{
1102 //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)
1103 return RETURN_OK;
1104}
1105
1106// outputs the country code to a max 64 character string
1107INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1108{
developer7543b3b2022-09-13 13:47:17 +08001109 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001110 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001111 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001112
1113 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1114 _syscmd(cmd, buf, sizeof(buf));
1115 if(strlen(buf) > 0)
1116 snprintf(output_string, 64, "%s", buf);
1117 else
1118 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001119
1120 return RETURN_OK;
1121}
1122
1123INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1124{
1125 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001126 char str[MAX_BUF_SIZE]={'\0'};
1127 char cmd[MAX_CMD_SIZE]={'\0'};
1128 struct params params;
1129 char config_file[MAX_BUF_SIZE] = {0};
1130
1131 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1132 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1133 return RETURN_ERR;
1134
developerb86c6f32022-10-07 14:34:58 +08001135 if (strlen(CountryCode) == 0)
1136 strcpy(CountryCode, "US");
1137
developer7543b3b2022-09-13 13:47:17 +08001138 params.name = "country_code";
1139 params.value = CountryCode;
1140 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1141 int ret = wifi_hostapdWrite(config_file, &params, 1);
1142 if (ret) {
1143 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1144 ,__func__, ret);
1145 }
1146
1147 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1148 if (ret) {
1149 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1150 ,__func__, ret);
1151 }
developer7543b3b2022-09-13 13:47:17 +08001152 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1153
developer06a01d92022-09-07 16:32:39 +08001154 return RETURN_OK;
1155}
1156
developera748dcf2022-09-13 15:56:48 +08001157INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1158{
1159 char channel_util_file[64] = {0};
1160 char cmd[128] = {0};
1161 char buf[128] = {0};
1162 char line[128] = {0};
1163 char *param = NULL, *value = NULL;
1164 int read = 0;
1165 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1166 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1167 size_t len = 0;
1168 FILE *f = NULL;
1169
1170 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1171
1172 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1173 _syscmd(cmd, buf, sizeof(buf));
1174 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1175
1176 memset(cmd, 0, sizeof(cmd));
1177 memset(buf, 0, sizeof(buf));
1178 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1179 if ((f = popen(cmd, "r")) == NULL) {
1180 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1181 return RETURN_ERR;
1182 }
1183
1184 read = getline(&line, &len, f);
1185 while (read != -1) {
1186 param = strtok(line, ":\t");
1187 value = strtok(NULL, " ");
1188 if(strstr(param, "frequency") != NULL) {
1189 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1190 }
1191 if(strstr(param, "noise") != NULL) {
1192 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1193 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1194 }
1195 if(strstr(param, "channel active time") != NULL) {
1196 ActiveTime = strtol(value, NULL, 10);
1197 }
1198 if(strstr(param, "channel busy time") != NULL) {
1199 BusyTime = strtol(value, NULL, 10);
1200 }
1201 if(strstr(param, "channel transmit time") != NULL) {
1202 TransmitTime = strtol(value, NULL, 10);
1203 }
1204 read = getline(&line, &len, f);
1205 }
1206 pclose(f);
1207
1208 // The file should store the last active, busy and transmit time
1209 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1210 f = fopen(channel_util_file, "r");
1211 if (f != NULL) {
1212 read = getline(&line, &len, f);
1213 preActiveTime = strtol(line, NULL, 10);
1214 read = getline(&line, &len, f);
1215 preBusyTime = strtol(line, NULL, 10);
1216 read = getline(&line, &len, f);
1217 preTransmitTime = strtol(line, NULL, 10);
1218 fclose(f);
1219 }
1220
1221 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1222 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1223
1224 f = fopen(channel_util_file, "w");
1225 if (f != NULL) {
1226 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1227 fclose(f);
1228 }
1229 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1230 return RETURN_OK;
1231}
1232
developer06a01d92022-09-07 16:32:39 +08001233/**********************************************************************************
1234 *
1235 * Wifi radio level function prototypes
1236 *
1237**********************************************************************************/
1238
1239//Get the total number of radios in this wifi subsystem
1240INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1241{
1242 if (NULL == output)
1243 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001244 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001245
1246 return RETURN_OK;
1247}
1248
1249//Get the total number of SSID entries in this wifi subsystem
1250INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1251{
1252 if (NULL == output)
1253 return RETURN_ERR;
1254 *output = MAX_APS;
1255
1256 return RETURN_OK;
1257}
1258
1259//Get the Radio enable config parameter
1260INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1261{
1262 char interface_path[MAX_CMD_SIZE] = {0};
1263 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001264 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001265
1266 if (NULL == output_bool)
1267 return RETURN_ERR;
1268
1269 *output_bool = FALSE;
developer804c64f2022-10-19 13:54:40 +08001270 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001271 return RETURN_ERR;
1272
developer033b37b2022-10-18 11:27:46 +08001273 phyId = radio_index_to_phy(radioIndex);
1274
1275 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001276 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001277 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001278 {
developercf48e482022-09-13 14:49:50 +08001279 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001280 }
1281 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001282 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1283 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1284 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001285
developercf48e482022-09-13 14:49:50 +08001286 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1287 *output_bool = TRUE;
1288 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001289 return RETURN_OK;
1290}
1291
1292INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1293{
1294 char cmd[MAX_CMD_SIZE] = {0};
1295 char buf[MAX_CMD_SIZE] = {0};
1296 int apIndex, ret;
1297 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001298 int max_radio_num = 0;
1299 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001300
1301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001302
1303 phyId = radio_index_to_phy(radioIndex);
1304
1305 wifi_getMaxRadioNumber(&max_radio_num);
1306
developer06a01d92022-09-07 16:32:39 +08001307 if(enable==FALSE)
1308 {
developer033b37b2022-10-18 11:27:46 +08001309 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001310 {
1311 //Detaching %s%d from hostapd daemon
1312 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1313 _syscmd(cmd, buf, sizeof(buf));
1314 if(strncmp(buf, "OK", 2))
1315 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1316 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1317 _syscmd(cmd, buf, sizeof(buf));
1318 }
developer033b37b2022-10-18 11:27:46 +08001319 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001320 _syscmd(cmd, buf, sizeof(buf));
1321 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001322 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001323 }
1324 else
1325 {
developer033b37b2022-10-18 11:27:46 +08001326 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001327 _syscmd(cmd, buf, sizeof(buf));
1328 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001329 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001330 sleep(1);
developer033b37b2022-10-18 11:27:46 +08001331
1332 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001333 {
developer033b37b2022-10-18 11:27:46 +08001334 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, phyId, AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08001335 ret = _syscmd(cmd, buf, sizeof(buf));
1336 if ( ret == RETURN_ERR)
1337 {
1338 fprintf(stderr, "VAP interface creation failed\n");
1339 continue;
1340 }
1341 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1342 _syscmd(cmd, buf, sizeof(buf));
1343 if(*buf == '1')
1344 {
1345 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001346 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001347 _syscmd(cmd, buf, sizeof(buf));
1348 if(strncmp(buf, "OK", 2))
1349 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1350 }
1351 }
1352 }
1353
1354 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1355 return RETURN_OK;
1356}
1357
1358//Get the Radio enable status
1359INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1360{
1361 if (NULL == output_bool)
1362 return RETURN_ERR;
1363
1364 return wifi_getRadioEnable(radioIndex, output_bool);
1365}
1366
1367//Get the Radio Interface name from platform, eg "wlan0"
1368INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1369{
developer033b37b2022-10-18 11:27:46 +08001370 int phyId = 0;
developer804c64f2022-10-19 13:54:40 +08001371 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001372 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08001373 phyId = radio_index_to_phy(radioIndex);
1374 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001375
1376 return RETURN_OK;
1377}
1378
1379//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1380//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.
1381INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1382{
developerbcc556a2022-09-22 20:02:45 +08001383 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1384 // For max bit rate, we should always choose the best MCS
1385 char mode[64] = {0};
1386 char channel_bandwidth_str[16] = {0};
1387 char *tmp = NULL;
1388 UINT mode_map = 0;
1389 UINT num_subcarrier = 0;
1390 UINT code_bits = 0;
1391 float code_rate = 0; // use max code rate
1392 int NSS = 0;
1393 UINT Symbol_duration = 0;
1394 UINT GI_duration = 0;
1395 wifi_band band = band_invalid;
1396 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1397 BOOL enable = FALSE;
1398 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001399
1400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1401 if (NULL == output_string)
1402 return RETURN_ERR;
1403
developerbcc556a2022-09-22 20:02:45 +08001404 wifi_getRadioEnable(radioIndex, &enable);
1405 if (enable == FALSE) {
1406 snprintf(output_string, 64, "0 Mb/s");
1407 return RETURN_OK;
1408 }
1409
1410 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1411 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1412 return RETURN_ERR;
1413 }
1414
1415 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1416 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1417 return RETURN_ERR;
1418 }
1419
1420 if (gi == wifi_guard_interval_3200)
1421 GI_duration = 32;
1422 else if (gi == wifi_guard_interval_1600)
1423 GI_duration = 16;
1424 else if (gi == wifi_guard_interval_800)
1425 GI_duration = 8;
1426 else // auto, 400
1427 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001428
developerbcc556a2022-09-22 20:02:45 +08001429 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1430 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1431 return RETURN_ERR;
1432 }
1433
1434 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1435 strcpy(channel_bandwidth_str, "160");
1436
1437 if (mode_map & WIFI_MODE_AX) {
1438 if (strstr(channel_bandwidth_str, "160") != NULL)
1439 num_subcarrier = 1960;
1440 else if (strstr(channel_bandwidth_str, "80") != NULL)
1441 num_subcarrier = 980;
1442 else if (strstr(channel_bandwidth_str, "40") != NULL)
1443 num_subcarrier = 468;
1444 else if (strstr(channel_bandwidth_str, "20") != NULL)
1445 num_subcarrier = 234;
1446 code_bits = 10;
1447 code_rate = (float)5/6;
1448 Symbol_duration = 128;
1449 } else if (mode_map & WIFI_MODE_AC) {
1450 if (strstr(channel_bandwidth_str, "160") != NULL)
1451 num_subcarrier = 468;
1452 else if (strstr(channel_bandwidth_str, "80") != NULL)
1453 num_subcarrier = 234;
1454 else if (strstr(channel_bandwidth_str, "40") != NULL)
1455 num_subcarrier = 108;
1456 else if (strstr(channel_bandwidth_str, "20") != NULL)
1457 num_subcarrier = 52;
1458 code_bits = 8;
1459 code_rate = (float)5/6;
1460 Symbol_duration = 32;
1461 } else if (mode_map & WIFI_MODE_N) {
1462 if (strstr(channel_bandwidth_str, "160") != NULL)
1463 num_subcarrier = 468;
1464 else if (strstr(channel_bandwidth_str, "80") != NULL)
1465 num_subcarrier = 234;
1466 else if (strstr(channel_bandwidth_str, "40") != NULL)
1467 num_subcarrier = 108;
1468 else if (strstr(channel_bandwidth_str, "20") != NULL)
1469 num_subcarrier = 52;
1470 code_bits = 6;
1471 code_rate = (float)3/4;
1472 Symbol_duration = 32;
1473 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1474 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1475 snprintf(output_string, 64, "65 Mb/s");
1476 return RETURN_OK;
1477 } else {
1478 snprintf(output_string, 64, "0 Mb/s");
1479 return RETURN_OK;
1480 }
developer06a01d92022-09-07 16:32:39 +08001481
developerbcc556a2022-09-22 20:02:45 +08001482 // Spatial streams
1483 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1484 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1485 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001486 }
developerbcc556a2022-09-22 20:02:45 +08001487
1488 // multiple 10 is to align duration unit (0.1 us)
1489 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1490 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1491
developer06a01d92022-09-07 16:32:39 +08001492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1493
1494 return RETURN_OK;
1495}
1496#if 0
1497INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1498{
1499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1500 char cmd[64];
1501 char buf[1024];
1502 int apIndex;
1503
1504 if (NULL == output_string)
1505 return RETURN_ERR;
1506
1507 apIndex=(radioIndex==0)?0:1;
1508
1509 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1510 _syscmd(cmd,buf, sizeof(buf));
1511
1512 snprintf(output_string, 64, "%s", buf);
1513 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1514 return RETURN_OK;
1515}
1516#endif
1517
1518
1519//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1520//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.
1521INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1522{
developer963da0c2022-09-13 15:58:27 +08001523 wifi_band band = band_invalid;
1524
developer06a01d92022-09-07 16:32:39 +08001525 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1526 if (NULL == output_string)
1527 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001528
1529 band = wifi_index_to_band(radioIndex);
1530
1531 memset(output_string, 0, 10);
1532 if (band == band_2_4)
1533 strcpy(output_string, "2.4GHz");
1534 else if (band == band_5)
1535 strcpy(output_string, "5GHz");
1536 else if (band == band_6)
1537 strcpy(output_string, "6GHz");
1538 else
1539 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001540 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1541
1542 return RETURN_OK;
1543#if 0
1544 char buf[MAX_BUF_SIZE]={'\0'};
1545 char str[MAX_BUF_SIZE]={'\0'};
1546 char cmd[MAX_CMD_SIZE]={'\0'};
1547 char *ch=NULL;
1548 char *ch2=NULL;
1549
1550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1551 if (NULL == output_string)
1552 return RETURN_ERR;
1553
1554
1555 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1556
1557 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1558 {
1559 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1560 return RETURN_ERR;
1561 }
1562 ch=strchr(buf,'\n');
1563 *ch='\0';
1564 ch=strchr(buf,'=');
1565 if(ch==NULL)
1566 return RETURN_ERR;
1567
1568
1569 ch++;
1570
1571 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1572 strcpy(buf,"0");
1573 if(strlen(ch) == 1)
1574 ch=strcat(buf,ch);
1575
1576
1577 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1578
1579 if(_syscmd(cmd,str,64) == RETURN_ERR)
1580 {
1581 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1582 return RETURN_ERR;
1583 }
1584
1585
1586 ch2=strchr(str,'\n');
1587 //replace \n with \0
1588 *ch2='\0';
1589 ch2=strchr(str,'=');
1590 if(ch2==NULL)
1591 {
1592 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1593 return RETURN_ERR;
1594 }
1595 else
1596 wifi_dbg_printf("%s",ch2+1);
1597
1598
1599 ch2++;
1600
1601
1602 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1603
1604 memset(buf,'\0',sizeof(buf));
1605 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1606 {
1607 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1608 return RETURN_ERR;
1609 }
1610 if (strstr(buf,"2.4") != NULL )
1611 strcpy(output_string,"2.4GHz");
1612 else if(strstr(buf,"5.") != NULL )
1613 strcpy(output_string,"5GHz");
1614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1615
1616 return RETURN_OK;
1617#endif
1618}
1619
1620//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1621//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.
1622INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1623{
developerb7593de2022-10-18 09:51:57 +08001624 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1626 if (NULL == output_string)
1627 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001628 band = wifi_index_to_band(radioIndex);
1629
1630 if (band == band_2_4)
1631 snprintf(output_string, 64, "2.4GHz");
1632 else if (band == band_5)
1633 snprintf(output_string, 64, "5GHz");
1634 else if (band == band_6)
1635 snprintf(output_string, 64, "6GHz");
1636
developer06a01d92022-09-07 16:32:39 +08001637 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1638
1639 return RETURN_OK;
1640#if 0
1641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1642 char buf[MAX_BUF_SIZE]={'\0'};
1643 char str[MAX_BUF_SIZE]={'\0'};
1644 char cmd[MAX_CMD_SIZE]={'\0'};
1645 char *ch=NULL;
1646 char *ch2=NULL;
1647 char ch1[5]="0";
1648
1649 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1650
1651 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1652 {
1653 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1654 return RETURN_ERR;
1655 }
1656
1657 ch=strchr(buf,'\n');
1658 *ch='\0';
1659 ch=strchr(buf,'=');
1660 if(ch==NULL)
1661 return RETURN_ERR;
1662 ch++;
1663
1664 if(strlen(ch)==1)
1665 {
1666 strcat(ch1,ch);
1667
1668 }
1669 else
1670 {
1671 strcpy(ch1,ch);
1672 }
1673
1674
1675
1676 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1677 if(_syscmd(cmd,str,64) == RETURN_ERR)
1678 {
1679 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1680 return RETURN_ERR;
1681 }
1682
1683
1684 ch2=strchr(str,'\n');
1685 //replace \n with \0
1686 *ch2='\0';
1687 ch2=strchr(str,'=');
1688 if(ch2==NULL)
1689 {
1690 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1691 return RETURN_ERR;
1692 }
1693 else
1694 wifi_dbg_printf("%s",ch2+1);
1695 ch2++;
1696
1697
1698 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1699 memset(buf,'\0',sizeof(buf));
1700 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1701 {
1702 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1703 return RETURN_ERR;
1704 }
1705
1706
1707 if(strstr(buf,"2.4")!=NULL)
1708 {
1709 strcpy(output_string,"2.4GHz");
1710 }
1711 if(strstr(buf,"5.")!=NULL)
1712 {
1713 strcpy(output_string,"5GHz");
1714 }
1715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1716 return RETURN_OK;
1717#endif
1718}
1719
1720//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1721//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.
1722INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1723{
developer963da0c2022-09-13 15:58:27 +08001724 char cmd[128]={0};
1725 char buf[128]={0};
1726 char temp_output[128] = {0};
1727 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001728 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001729
1730 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001731 if (NULL == output_string)
1732 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001733
1734 band = wifi_index_to_band(radioIndex);
1735 if (band == band_2_4) {
1736 strcat(temp_output, "b,g,");
1737 } else if (band == band_5) {
1738 strcat(temp_output, "a,");
1739 }
developer033b37b2022-10-18 11:27:46 +08001740 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001741 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001742 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 +08001743 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001744 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001745 strcat(temp_output, "n,");
1746 }
developer06a01d92022-09-07 16:32:39 +08001747
developer963da0c2022-09-13 15:58:27 +08001748 // vht capabilities
1749 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001750 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 +08001751 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001752 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001753 strcat(temp_output, "ac,");
1754 }
1755 }
1756
1757 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001758 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 +08001759 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001760 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001761 strcat(temp_output, "ax,");
1762 }
1763
1764 // Remove the last comma
1765 if (strlen(temp_output) != 0)
1766 temp_output[strlen(temp_output)-1] = '\0';
1767 strncpy(output_string, temp_output, strlen(temp_output));
1768 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001769 return RETURN_OK;
1770}
1771
1772//Get the radio operating mode, and pure mode flag. eg: "ac"
1773//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1774INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1775{
1776 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1777 if (NULL == output_string)
1778 return RETURN_ERR;
1779
1780 if (radioIndex == 0) {
1781 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1782 *gOnly = FALSE;
1783 *nOnly = TRUE;
1784 *acOnly = FALSE;
1785 } else {
1786 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1787 *gOnly = FALSE;
1788 *nOnly = FALSE;
1789 *acOnly = FALSE;
1790 }
1791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1792
1793 return RETURN_OK;
1794#if 0
1795 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1796 char buf[64] = {0};
1797 char config_file[MAX_BUF_SIZE] = {0};
1798
1799 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1800 return RETURN_ERR;
1801
1802 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1803 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1804
1805 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1806 if (strlen(buf) == 0)
1807 {
1808 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1809 return RETURN_ERR;
1810 }
1811 if(strcmp(buf,"g")==0)
1812 {
1813 wifi_dbg_printf("\nG\n");
1814 *gOnly=TRUE;
1815 *nOnly=FALSE;
1816 *acOnly=FALSE;
1817 }
1818 else if(strcmp(buf,"n")==0)
1819 {
1820 wifi_dbg_printf("\nN\n");
1821 *gOnly=FALSE;
1822 *nOnly=TRUE;
1823 *acOnly=FALSE;
1824 }
1825 else if(strcmp(buf,"ac")==0)
1826 {
1827 wifi_dbg_printf("\nac\n");
1828 *gOnly=FALSE;
1829 *nOnly=FALSE;
1830 *acOnly=TRUE;
1831 }
1832 /* hostapd-5G.conf has "a" as hw_mode */
1833 else if(strcmp(buf,"a")==0)
1834 {
1835 wifi_dbg_printf("\na\n");
1836 *gOnly=FALSE;
1837 *nOnly=FALSE;
1838 *acOnly=FALSE;
1839 }
1840 else
1841 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1842
1843 //for a,n mode
1844 if(radioIndex == 1)
1845 {
1846 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1847 if(strcmp(buf,"1")==0)
1848 {
1849 strncpy(output_string, "n", 1);
1850 *nOnly=FALSE;
1851 }
1852 }
1853
1854 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1856 return RETURN_OK;
1857#endif
1858}
1859
developerdb744382022-09-13 15:34:54 +08001860INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1861{
1862 char cmd[128] = {0};
1863 char buf[64] = {0};
1864 char config_file[64] = {0};
1865 wifi_band band;
1866
1867 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1868 if(NULL == output_string || NULL == pureMode)
1869 return RETURN_ERR;
1870
1871 // grep all of the ieee80211 protocol config set to 1
1872 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1873 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1874 _syscmd(cmd, buf, sizeof(buf));
1875
1876 band = wifi_index_to_band(radioIndex);
1877 // puremode is a bit map
1878 *pureMode = 0;
1879 if (band == band_2_4) {
1880 strcat(output_string, "b,g");
1881 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1882 if (strstr(buf, "n") != NULL) {
1883 strcat(output_string, ",n");
1884 *pureMode |= WIFI_MODE_N;
1885 }
1886 if (strstr(buf, "ax") != NULL) {
1887 strcat(output_string, ",ax");
1888 *pureMode |= WIFI_MODE_AX;
1889 }
1890 } else if (band == band_5) {
1891 strcat(output_string, "a");
1892 *pureMode |= WIFI_MODE_A;
1893 if (strstr(buf, "n") != NULL) {
1894 strcat(output_string, ",n");
1895 *pureMode |= WIFI_MODE_N;
1896 }
1897 if (strstr(buf, "ac") != NULL) {
1898 strcat(output_string, ",ac");
1899 *pureMode |= WIFI_MODE_AC;
1900 }
1901 if (strstr(buf, "ax") != NULL) {
1902 strcat(output_string, ",ax");
1903 *pureMode |= WIFI_MODE_AX;
1904 }
1905 } else if (band == band_6) {
1906 if (strstr(buf, "ax") != NULL) {
1907 strcat(output_string, "ax");
1908 *pureMode |= WIFI_MODE_AX;
1909 }
1910 }
1911
1912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1913 return RETURN_OK;
1914}
1915
1916// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001917INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1918{
1919 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1920 if (strcmp (channelMode,"11A") == 0)
1921 {
1922 writeBandWidth(radioIndex,"20MHz");
1923 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1924 printf("\nChannel Mode is 802.11a (5GHz)\n");
1925 }
1926 else if (strcmp (channelMode,"11NAHT20") == 0)
1927 {
1928 writeBandWidth(radioIndex,"20MHz");
1929 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1930 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1931 }
1932 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1933 {
1934 writeBandWidth(radioIndex,"40MHz");
1935 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1936 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1937 }
1938 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1939 {
1940 writeBandWidth(radioIndex,"40MHz");
1941 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1942 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1943 }
1944 else if (strcmp (channelMode,"11ACVHT20") == 0)
1945 {
1946 writeBandWidth(radioIndex,"20MHz");
1947 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1948 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1949 }
1950 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1951 {
1952 writeBandWidth(radioIndex,"40MHz");
1953 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1954 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1955 }
1956 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1957 {
1958 writeBandWidth(radioIndex,"40MHz");
1959 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1960 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1961 }
1962 else if (strcmp (channelMode,"11ACVHT80") == 0)
1963 {
1964 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1965 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1966 }
1967 else if (strcmp (channelMode,"11ACVHT160") == 0)
1968 {
1969 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1970 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1971 }
1972 else if (strcmp (channelMode,"11B") == 0)
1973 {
1974 writeBandWidth(radioIndex,"20MHz");
1975 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1976 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1977 }
1978 else if (strcmp (channelMode,"11G") == 0)
1979 {
1980 writeBandWidth(radioIndex,"20MHz");
1981 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1982 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1983 }
1984 else if (strcmp (channelMode,"11NGHT20") == 0)
1985 {
1986 writeBandWidth(radioIndex,"20MHz");
1987 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1988 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1989 }
1990 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1991 {
1992 writeBandWidth(radioIndex,"40MHz");
1993 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1994 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1995 }
1996 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1997 {
1998 writeBandWidth(radioIndex,"40MHz");
1999 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2000 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2001 }
2002 else
2003 {
2004 return RETURN_ERR;
2005 }
2006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2007
2008 return RETURN_OK;
2009}
2010
developerdb744382022-09-13 15:34:54 +08002011// Set the radio operating mode, and pure mode flag.
2012INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2013{
2014 int num_hostapd_support_mode = 3; // n, ac, ax
2015 struct params list[num_hostapd_support_mode];
2016 char config_file[64] = {0};
2017 char bandwidth[16] = {0};
2018 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002019
developerdb744382022-09-13 15:34:54 +08002020
2021 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2022 // Set radio mode
2023 list[0].name = "ieee80211n";
2024 list[1].name = "ieee80211ac";
2025 list[2].name = "ieee80211ax";
2026 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2027
2028 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002029 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002030 list[0].value = "1";
2031 else
2032 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002033 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002034 list[1].value = "1";
2035 else
2036 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002037 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002038 list[2].value = "1";
2039 else
2040 list[2].value = "0";
2041 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2042
2043 if (channelMode == NULL || strlen(channelMode) == 0)
2044 return RETURN_OK;
2045 // Set bandwidth
2046 if (strstr(channelMode, "40") != NULL)
2047 strcpy(bandwidth, "40MHz");
2048 else if (strstr(channelMode, "80") != NULL)
2049 strcpy(bandwidth, "80MHz");
2050 else if (strstr(channelMode, "160") != NULL)
2051 strcpy(bandwidth, "160MHz");
2052 else // 11A, 11B, 11G....
2053 strcpy(bandwidth, "20MHz");
2054
2055 writeBandWidth(radioIndex, bandwidth);
2056 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2057
2058 wifi_reloadAp(radioIndex);
2059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2060
2061 return RETURN_OK;
2062}
2063
developer1d12ebf2022-10-04 15:13:38 +08002064INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2065
2066 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002067 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002068 struct params params = {0};
2069 wifi_band band = band_invalid;
2070
2071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2072
2073 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002074
2075 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002076 return RETURN_ERR;
2077 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2078 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002079 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2080 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002081
2082 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2083 params.name = "hw_mode";
2084 params.value = hw_mode;
2085 wifi_hostapdWrite(config_file, &params, 1);
2086 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2087
developeref938762022-10-19 17:21:01 +08002088 if (band == band_2_4) {
2089 if (strncmp(hw_mode, "b", 1) == 0) {
2090 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2091 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2092 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2093 snprintf(buf, sizeof(buf), "%s", "1,2");
2094 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2095 } else {
2096 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2097
2098 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2099 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2100 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2101 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2102 }
2103 }
2104
developer1d12ebf2022-10-04 15:13:38 +08002105 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2106 return RETURN_OK;
2107}
2108
developere8988ba2022-10-18 17:42:30 +08002109INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2110{
2111 char config_file[64] = {0};
2112 struct params params = {0};
2113 wifi_band band = band_invalid;
2114
2115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2116
2117 band = wifi_index_to_band(radioIndex);
2118
2119 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2120 params.name = "noscan";
2121 params.value = noscan;
2122 wifi_hostapdWrite(config_file, &params, 1);
2123 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2124
2125 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2126 return RETURN_OK;
2127}
2128
developer06a01d92022-09-07 16:32:39 +08002129//Get the list of supported channel. eg: "1-11"
2130//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.
2131INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2132{
developer6318ed52022-09-13 15:17:58 +08002133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002134 if (NULL == output_string)
2135 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002136 char cmd[256] = {0};
2137 char buf[128] = {0};
2138 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002139 int phyId = 0;
2140
developer6318ed52022-09-13 15:17:58 +08002141 // Parse possible channel number and separate them with commas.
2142 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002143 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002144 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002145 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002146 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 +08002147 else
developer033b37b2022-10-18 11:27:46 +08002148 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 +08002149
2150 _syscmd(cmd,buf,sizeof(buf));
2151 strncpy(output_string, buf, sizeof(buf));
2152
2153 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2154 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002155}
2156
2157//Get the list for used channel. eg: "1,6,9,11"
2158//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.
2159INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2160{
developerf5745ee2022-10-05 16:09:53 +08002161 char cmd[128] = {0};
2162 char buf[128] = {0};
2163 char config_file[64] = {0};
2164 int channel = 0;
2165 int freq = 0;
2166 int bandwidth = 0;
2167 int center_freq = 0;
2168 int center_channel = 0;
2169 int channel_delta = 0;
2170 wifi_band band = band_invalid;
2171
2172 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2173
developer06a01d92022-09-07 16:32:39 +08002174 if (NULL == output_string)
2175 return RETURN_ERR;
2176
developerf5745ee2022-10-05 16:09:53 +08002177 sprintf(cmd, "iw %s%d info | grep channel | sed -e 's/[^0-9 ]//g'", AP_PREFIX, radioIndex);
2178 _syscmd(cmd, buf, sizeof(buf));
2179 if (strlen(buf) == 0) {
2180 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2181 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002182 }
developerf5745ee2022-10-05 16:09:53 +08002183 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2184
2185 if (bandwidth == 20) {
2186 snprintf(output_string, 256, "%d", channel);
2187 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002188 }
developerf5745ee2022-10-05 16:09:53 +08002189
2190 center_channel = ieee80211_frequency_to_channel(center_freq);
2191
2192 band = wifi_index_to_band(radioIndex);
2193 if (band == band_2_4 && bandwidth == 40) {
2194 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2195 memset(buf, 0, sizeof(buf));
2196 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2197
2198 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2199 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2200 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2201 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2202 } else {
2203 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2204 return RETURN_ERR;
2205 }
2206 } else if (band == band_5 || band == band_6){
2207 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2208 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2209 channel_delta = (bandwidth-20)/10;
2210 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2211 } else
2212 return RETURN_ERR;
2213
2214 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002215 return RETURN_OK;
2216}
2217
2218//Get the running channel number
2219INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2220{
developer5b398df2022-11-17 20:39:48 +08002221 char channel_str[16] = {0};
2222 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002223
developer5b398df2022-11-17 20:39:48 +08002224 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002225 return RETURN_ERR;
2226
developer5b398df2022-11-17 20:39:48 +08002227 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2228 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002229
developer5b398df2022-11-17 20:39:48 +08002230 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002231
developer06a01d92022-09-07 16:32:39 +08002232 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002233}
2234
2235
2236INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2237{
2238 char cmd[1024] = {0}, buf[5] = {0};
2239 char interface_name[50] = {0};
2240
2241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2242 if (NULL == output_ulong)
2243 return RETURN_ERR;
2244
2245 wifi_getApName(apIndex,interface_name);
2246 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2247 _syscmd(cmd,buf,sizeof(buf));
2248 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2249 if (*output_ulong == 0) {
2250 return RETURN_ERR;
2251 }
2252
2253 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2254 return RETURN_OK;
2255}
2256
2257//Storing the previous channel value
2258INT wifi_storeprevchanval(INT radioIndex)
2259{
2260 char buf[256] = {0};
2261 char output[4]={'\0'};
2262 char config_file[MAX_BUF_SIZE] = {0};
2263 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2264 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2265 if(radioIndex == 0)
2266 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2267 else if(radioIndex == 1)
2268 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2269 system(buf);
2270 Radio_flag = FALSE;
2271 return RETURN_OK;
2272}
2273
2274//Set the running channel number
2275INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2276{
developer76989232022-10-04 14:13:19 +08002277 // We only write hostapd config here
2278 char str_channel[8]={0};
2279 char *list_channel;
2280 char config_file[128] = {0};
2281 char possible_channels[256] = {0};
2282 int max_radio_num = 0;
2283 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002284
developer76989232022-10-04 14:13:19 +08002285 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002286
developer76989232022-10-04 14:13:19 +08002287 // Check valid
2288 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002289
developer76989232022-10-04 14:13:19 +08002290 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2291 list_channel = strtok(possible_channels, ",");
2292 while(true)
developer06a01d92022-09-07 16:32:39 +08002293 {
developer76989232022-10-04 14:13:19 +08002294 if(list_channel == NULL) { // input not in the list
2295 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2296 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002297 }
developer76989232022-10-04 14:13:19 +08002298 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2299 break;
2300 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002301 }
2302
developer76989232022-10-04 14:13:19 +08002303 list.name = "channel";
2304 list.value = str_channel;
2305 wifi_getMaxRadioNumber(&max_radio_num);
2306 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002307 {
developer76989232022-10-04 14:13:19 +08002308 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2309 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002310 }
2311
developer76989232022-10-04 14:13:19 +08002312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002313 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002314}
developer06a01d92022-09-07 16:32:39 +08002315
2316INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2317{
developer76989232022-10-04 14:13:19 +08002318 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002319 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002320 char config_file[64];
2321 int max_num_radios = 0;
2322 wifi_band band = band_invalid;
2323
2324 band = wifi_index_to_band(radioIndex);
2325 if (band == band_2_4)
2326 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002327
developer06a01d92022-09-07 16:32:39 +08002328 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002329 list[0].name = "vht_oper_centr_freq_seg0_idx";
2330 list[0].value = str_idx;
2331 list[1].name = "he_oper_centr_freq_seg0_idx";
2332 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002333
developer76989232022-10-04 14:13:19 +08002334 wifi_getMaxRadioNumber(&max_num_radios);
2335 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002336 {
developer76989232022-10-04 14:13:19 +08002337 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2338 if (band == band_6)
2339 wifi_hostapdWrite(config_file, &list[1], 1);
2340 else
2341 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002342 }
2343
2344 return RETURN_OK;
2345}
2346
2347//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2348//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2349INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2350{
2351 //Set to wifi config only. Wait for wifi reset to apply.
2352 char buf[256] = {0};
2353 char str_channel[256] = {0};
2354 int count = 0;
2355 ULONG Value = 0;
2356 FILE *fp = NULL;
2357 if(enable == TRUE)
2358 {
developer06a01d92022-09-07 16:32:39 +08002359 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002360 }
developer5884e982022-10-06 10:52:50 +08002361 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002362}
2363
developer0b246d12022-09-30 15:24:20 +08002364INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2365{
2366 if (output_bool == NULL)
2367 return RETURN_ERR;
2368
2369 *output_bool = TRUE;
2370
2371 return RETURN_OK;
2372}
2373
developer06a01d92022-09-07 16:32:39 +08002374INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2375{
2376 if (NULL == output_bool)
2377 return RETURN_ERR;
2378 *output_bool=FALSE;
2379 return RETURN_OK;
2380}
2381
2382INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2383{
2384 if (NULL == output_bool)
2385 return RETURN_ERR;
2386 *output_bool=FALSE;
2387 return RETURN_OK;
2388}
2389
2390INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2391{
2392 //Set to wifi config only. Wait for wifi reset to apply.
2393 return RETURN_OK;
2394}
2395
2396INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2397{
2398 return RETURN_OK;
2399}
2400
2401INT wifi_factoryResetAP(int apIndex)
2402{
developer838cca92022-10-03 13:19:57 +08002403 char ap_config_file[64] = {0};
2404 char cmd[128] = {0};
2405
developer06a01d92022-09-07 16:32:39 +08002406 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002407
2408 wifi_setApEnable(apIndex, FALSE);
2409 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2410 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2411 wifi_setApEnable(apIndex, TRUE);
2412
developer06a01d92022-09-07 16:32:39 +08002413 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002414
developer06a01d92022-09-07 16:32:39 +08002415 return RETURN_OK;
2416}
2417
2418//To set Band Steering AP group
2419//To-do
2420INT wifi_setBandSteeringApGroup(char *ApGroup)
2421{
2422 return RETURN_OK;
2423}
2424
developer1e5aa162022-09-13 16:06:24 +08002425INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2426{
2427 char config_file[128] = {'\0'};
2428 char buf[128] = {'\0'};
2429
2430 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2431 if (dtimInterval == NULL)
2432 return RETURN_ERR;
2433
2434 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2435 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2436
2437 if (strlen(buf) == 0) {
2438 *dtimInterval = 2;
2439 } else {
2440 *dtimInterval = strtoul(buf, NULL, 10);
2441 }
2442
2443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2444 return RETURN_OK;
2445}
2446
developer06a01d92022-09-07 16:32:39 +08002447INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2448{
developer5f222492022-09-13 15:21:52 +08002449 struct params params={0};
2450 char config_file[MAX_BUF_SIZE] = {'\0'};
2451 char buf[MAX_BUF_SIZE] = {'\0'};
2452
2453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2454 if (dtimInterval < 1 || dtimInterval > 255) {
2455 return RETURN_ERR;
2456 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2457 }
2458
2459 params.name = "dtim_period";
2460 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2461 params.value = buf;
2462
2463 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2464 wifi_hostapdWrite(config_file, &params, 1);
2465 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2466
2467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2468 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002469}
2470
2471//Check if the driver support the Dfs
2472INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2473{
developer78a15382022-11-02 10:57:40 +08002474 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002475 if (NULL == output_bool)
2476 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002477 *output_bool=FALSE;
2478
2479 band = wifi_index_to_band(radioIndex);
2480 if (band == band_5)
2481 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002482 return RETURN_OK;
2483}
2484
2485//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.
2486//The value of this parameter is a comma seperated list of channel number
2487INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2488{
2489 if (NULL == output_pool)
2490 return RETURN_ERR;
2491 if (radioIndex==1)
2492 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2493 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2494
2495 return RETURN_OK;
2496}
2497
2498INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2499{
2500 //Set to wifi config. And apply instantly.
2501 return RETURN_OK;
2502}
2503
2504INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2505{
2506 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2507 return RETURN_ERR;
2508 *output_interval_seconds=1800;
2509 *output_dwell_milliseconds=40;
2510
2511 return RETURN_OK;
2512}
2513
2514INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2515{
2516 //Set to wifi config. And apply instantly.
2517 return RETURN_OK;
2518}
2519
developerbfc18512022-10-05 17:54:28 +08002520INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2521{
2522 if (output_bool == NULL)
2523 return RETURN_ERR;
2524 *output_bool = true;
2525 return RETURN_OK;
2526}
2527
2528INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2529{
2530 return RETURN_OK;
2531}
2532
developer06a01d92022-09-07 16:32:39 +08002533//Get the Dfs enable status
2534INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2535{
developer9964b5b2022-09-13 15:59:34 +08002536 char buf[16] = {0};
2537 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002538
2539 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2540
2541 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002542 if (NULL == output_bool)
2543 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002544
developer9964b5b2022-09-13 15:59:34 +08002545 f = fopen(DFS_ENABLE_FILE, "r");
2546 if (f != NULL) {
2547 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002548 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002549 *output_bool = FALSE;
2550 fclose(f);
2551 }
2552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002553 return RETURN_OK;
2554}
2555
2556//Set the Dfs enable status
2557INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2558{
developer9964b5b2022-09-13 15:59:34 +08002559 char config_file[128] = {0};
2560 FILE *f = NULL;
2561 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002562
2563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2564
developer9964b5b2022-09-13 15:59:34 +08002565 f = fopen(DFS_ENABLE_FILE, "w");
2566 if (f == NULL)
2567 return RETURN_ERR;
2568 fprintf(f, "%d", enable);
2569 fclose(f);
2570
2571 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002572 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002573 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2574 wifi_hostapdWrite(config_file, &params, 1);
2575 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2576
2577 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2578
developer9964b5b2022-09-13 15:59:34 +08002579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002580 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002581}
2582
2583//Check if the driver support the AutoChannelRefreshPeriod
2584INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2585{
2586 if (NULL == output_bool)
2587 return RETURN_ERR;
2588 *output_bool=FALSE; //not support
2589
2590 return RETURN_OK;
2591}
2592
2593//Get the ACS refresh period in seconds
2594INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2595{
2596 if (NULL == output_ulong)
2597 return RETURN_ERR;
2598 *output_ulong=300;
2599
2600 return RETURN_OK;
2601}
2602
2603//Set the ACS refresh period in seconds
2604INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2605{
2606 return RETURN_ERR;
2607}
2608
2609//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2610//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.
2611INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2612{
developer70490032022-09-13 15:45:20 +08002613 char cmd[128] = {0}, buf[64] = {0};
2614 char interface_name[64] = {0};
2615 int ret = 0, len=0;
2616 BOOL radio_enable = FALSE;
2617
2618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2619
developer06a01d92022-09-07 16:32:39 +08002620 if (NULL == output_string)
2621 return RETURN_ERR;
2622
developer70490032022-09-13 15:45:20 +08002623 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2624 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002625
developer70490032022-09-13 15:45:20 +08002626 if (radio_enable != TRUE)
2627 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002628
developer70490032022-09-13 15:45:20 +08002629 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002630 ret = _syscmd(cmd, buf, sizeof(buf));
2631 len = strlen(buf);
2632 if((ret != 0) || (len == 0))
2633 {
2634 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2635 return RETURN_ERR;
2636 }
2637
2638 buf[len-1] = '\0';
2639 snprintf(output_string, 64, "%sMHz", buf);
2640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2641
2642#if 0
2643 //TODO: revisit below implementation
2644 char output_buf[8]={0};
2645 char bw_value[10];
2646 char config_file[MAX_BUF_SIZE] = {0};
2647
2648 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2649 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2650 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2651 readBandWidth(radioIndex,bw_value);
2652
2653 if(strstr (output_buf,"0") != NULL )
2654 {
2655 strcpy(output_string,bw_value);
2656 }
2657 else if (strstr (output_buf,"1") != NULL)
2658 {
2659 strcpy(output_string,"80MHz");
2660 }
2661 else if (strstr (output_buf,"2") != NULL)
2662 {
2663 strcpy(output_string,"160MHz");
2664 }
2665 else if (strstr (output_buf,"3") != NULL)
2666 {
2667 strcpy(output_string,"80+80");
2668 }
2669 else
2670 {
2671 strcpy(output_string,"Auto");
2672 }
2673 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2674#endif
2675
2676 return RETURN_OK;
2677}
2678
2679//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002680INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002681{
developerf7a466e2022-09-29 11:55:56 +08002682 char config_file[128];
2683 char set_value[16];
2684 struct params params[2];
2685 int max_radio_num = 0;
2686
developer06a01d92022-09-07 16:32:39 +08002687 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002688
developerf7a466e2022-09-29 11:55:56 +08002689 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002690 return RETURN_ERR;
2691
developerf7a466e2022-09-29 11:55:56 +08002692 if(strstr(bandwidth,"80+80") != NULL)
2693 strcpy(set_value, "3");
2694 else if(strstr(bandwidth,"160") != NULL)
2695 strcpy(set_value, "2");
2696 else if(strstr(bandwidth,"80") != NULL)
2697 strcpy(set_value, "1");
2698 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2699 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002700 else
2701 {
developerf7a466e2022-09-29 11:55:56 +08002702 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002703 return RETURN_ERR;
2704 }
2705
developerf7a466e2022-09-29 11:55:56 +08002706 params[0].name = "vht_oper_chwidth";
2707 params[0].value = set_value;
2708 params[1].name = "he_oper_chwidth";
2709 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002710
developerf7a466e2022-09-29 11:55:56 +08002711 wifi_getMaxRadioNumber(&max_radio_num);
2712 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002713 {
developerf7a466e2022-09-29 11:55:56 +08002714 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2715 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002716 }
2717
2718 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2719 return RETURN_OK;
2720}
2721
2722//Getting current radio extension channel
2723INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2724{
2725 CHAR buf[150] = {0};
2726 CHAR cmd[150] = {0};
2727 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2728 _syscmd(cmd, buf, sizeof(buf));
2729 if(NULL != strstr(buf,"HT40+"))
2730 strcpy(Value,"AboveControlChannel");
2731 else if(NULL != strstr(buf,"HT40-"))
2732 strcpy(Value,"BelowControlChannel");
2733 return RETURN_OK;
2734}
2735
2736//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2737//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.
2738INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2739{
2740 if (NULL == output_string)
2741 return RETURN_ERR;
2742
2743 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2744#if 0
2745 CHAR Value[100] = {0};
2746 if (NULL == output_string)
2747 return RETURN_ERR;
2748 if(radioIndex == 0)
2749 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2750 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2751 {
2752 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2753 if(strcmp(Value,"40MHz") == 0)
2754 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2755 else
2756 strcpy(Value,"Auto");
2757 }
2758 strcpy(output_string,Value);
2759#endif
2760
2761 return RETURN_OK;
2762}
2763
2764//Set the extension channel.
2765INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2766{
2767 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2768 struct params params={'\0'};
2769 char config_file[MAX_BUF_SIZE] = {0};
2770 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002771 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002772 params.name = "ht_capab";
2773
developer033b37b2022-10-18 11:27:46 +08002774 if(NULL!= strstr(string,"Above"))
2775 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2776 else if(NULL!= strstr(string,"Below"))
2777 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2778 else
2779 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2780
developer06a01d92022-09-07 16:32:39 +08002781
2782 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002783
2784 wifi_getMaxRadioNumber(&max_radio_num);
2785 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002786 {
developer033b37b2022-10-18 11:27:46 +08002787 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002788 wifi_hostapdWrite(config_file, &params, 1);
2789 }
2790
2791 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2793 return RETURN_OK;
2794}
2795
2796//Get the guard interval value. eg "400nsec" or "800nsec"
2797//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.
2798INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2799{
developer454b9462022-09-13 15:29:16 +08002800 wifi_guard_interval_t GI;
2801
2802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2803
2804 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002805 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002806
2807 if (GI == wifi_guard_interval_400)
2808 strcpy(output_string, "400nsec");
2809 else if (GI == wifi_guard_interval_800)
2810 strcpy(output_string, "800nsec");
2811 else if (GI == wifi_guard_interval_1600)
2812 strcpy(output_string, "1600nsec");
2813 else if (GI == wifi_guard_interval_3200)
2814 strcpy(output_string, "3200nsec");
2815 else
developer78a15382022-11-02 10:57:40 +08002816 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002817
developer454b9462022-09-13 15:29:16 +08002818 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002819 return RETURN_OK;
2820}
2821
2822//Set the guard interval value.
2823INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2824{
developer454b9462022-09-13 15:29:16 +08002825 wifi_guard_interval_t GI;
2826 int ret = 0;
2827
2828 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2829
2830 if (strcmp(string, "400nsec") == 0)
2831 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002832 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002833 GI = wifi_guard_interval_800;
2834 else if (strcmp(string , "1600nsec") == 0)
2835 GI = wifi_guard_interval_1600;
2836 else if (strcmp(string , "3200nsec") == 0)
2837 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002838 else
2839 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002840
2841 ret = wifi_setGuardInterval(radioIndex, GI);
2842
2843 if (ret == RETURN_ERR) {
2844 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2845 return RETURN_ERR;
2846 }
2847
2848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2849 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002850}
2851
2852//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2853INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2854{
developerf49437e2022-09-29 19:58:21 +08002855 char buf[32]={0};
2856 char mcs_file[64] = {0};
2857 char cmd[64] = {0};
2858 int mode_bitmap = 0;
2859
2860 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2861 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002862 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002863 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2864
2865 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2866 _syscmd(cmd, buf, sizeof(buf));
2867 if (strlen(buf) > 0)
2868 *output_int = strtol(buf, NULL, 10);
2869 else {
2870 // output the max MCS for the current radio mode
2871 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2872 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2873 return RETURN_ERR;
2874 }
2875 if (mode_bitmap & WIFI_MODE_AX) {
2876 *output_int = 11;
2877 } else if (mode_bitmap & WIFI_MODE_AC) {
2878 *output_int = 9;
2879 } else if (mode_bitmap & WIFI_MODE_N) {
2880 *output_int = 7;
2881 }
2882 }
2883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002884
2885 return RETURN_OK;
2886}
2887
2888//Set the Modulation Coding Scheme index
2889INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2890{
developerf49437e2022-09-29 19:58:21 +08002891 // 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).
2892 char config_file[64] = {0};
2893 char set_value[16] = {0};
2894 char mcs_file[32] = {0};
2895 wifi_band band = band_invalid;
2896 struct params set_config = {0};
2897 FILE *f = NULL;
2898
2899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2900
2901 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2902
developer78a15382022-11-02 10:57:40 +08002903 // -1 means auto
2904 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08002905 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2906 return RETURN_ERR;
2907 }
2908
developer78a15382022-11-02 10:57:40 +08002909 if (MCS > 9 || MCS == -1)
2910 strcpy(set_value, "2");
2911 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08002912 strcpy(set_value, "1");
2913 else
developer78a15382022-11-02 10:57:40 +08002914 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08002915
2916 set_config.name = "he_basic_mcs_nss_set";
2917 set_config.value = set_value;
2918
2919 wifi_hostapdWrite(config_file, &set_config, 1);
2920 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2921
2922 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2923 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2924 f = fopen(mcs_file, "w");
2925 if (f == NULL) {
2926 fprintf(stderr, "%s: fopen failed\n", __func__);
2927 return RETURN_ERR;
2928 }
2929 fprintf(f, "%d", MCS);
2930 fclose(f);
2931
2932 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2933 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002934}
2935
2936//Get supported Transmit Power list, eg : "0,25,50,75,100"
2937//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.
2938INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2939{
2940 if (NULL == output_list)
2941 return RETURN_ERR;
2942 snprintf(output_list, 64,"0,25,50,75,100");
2943 return RETURN_OK;
2944}
2945
developera5005b62022-09-13 15:43:35 +08002946//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002947//The transmite power level is in units of full power for this radio.
2948INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2949{
2950 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002951 char buf[16]={0};
2952 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002953
developera5005b62022-09-13 15:43:35 +08002954 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002955 return RETURN_ERR;
2956
developera5005b62022-09-13 15:43:35 +08002957 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002958 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002959
developera5005b62022-09-13 15:43:35 +08002960 *output_ulong = strtol(buf, NULL, 10);
2961
2962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002963 return RETURN_OK;
2964}
2965
2966//Set Transmit Power
2967//The transmite power level is in units of full power for this radio.
2968INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2969{
developera5005b62022-09-13 15:43:35 +08002970 char *support;
developer06a01d92022-09-07 16:32:39 +08002971 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002972 char buf[128]={0};
2973 char txpower_str[64] = {0};
2974 int txpower = 0;
2975 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08002976 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08002977
2978 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002979
developera5005b62022-09-13 15:43:35 +08002980 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002981 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002982 maximum_tx = strtol(buf, NULL, 10);
2983
2984 // Get the Tx power supported list and check that is the input in the list
2985 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2986 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2987 support = strtok(buf, ",");
2988 while(true)
2989 {
2990 if(support == NULL) { // input not in the list
2991 wifi_dbg_printf("Input value is invalid.\n");
2992 return RETURN_ERR;
2993 }
2994 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2995 break;
2996 }
2997 support = strtok(NULL, ",");
2998 }
2999 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003000 phyId = radio_index_to_phy(radioIndex);
3001 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003002 _syscmd(cmd, buf, sizeof(buf));
3003 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003004
3005 return RETURN_OK;
3006}
3007
3008//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3009INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3010{
3011 if (NULL == Supported)
3012 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003013 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003014
3015 return RETURN_OK;
3016}
3017
3018//Get 80211h feature enable
3019INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3020{
developer3885fec2022-09-13 15:13:47 +08003021 char buf[64]={'\0'};
3022 char config_file[64] = {'\0'};
3023
3024 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3025 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003026 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003027
3028 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3029 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003030
developer3885fec2022-09-13 15:13:47 +08003031 if (strncmp(buf, "1", 1) == 0)
3032 *enable = TRUE;
3033 else
3034 *enable = FALSE;
3035
3036 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003037 return RETURN_OK;
3038}
3039
3040//Set 80211h feature enable
3041INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3042{
developer3885fec2022-09-13 15:13:47 +08003043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3044 struct params params={'\0'};
3045 char config_file[MAX_BUF_SIZE] = {0};
3046
3047 params.name = "ieee80211h";
3048
3049 if (enable) {
3050 params.value = "1";
3051 } else {
3052 params.value = "0";
3053 }
3054
3055 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3056 wifi_hostapdWrite(config_file, &params, 1);
3057
3058 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3060 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003061}
3062
3063//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.
3064INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3065{
3066 if (NULL == output)
3067 return RETURN_ERR;
3068 *output=100;
3069
3070 return RETURN_OK;
3071}
3072
3073//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.
3074INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3075{
3076 if (NULL == output)
3077 return RETURN_ERR;
3078 *output = -99;
3079
3080 return RETURN_OK;
3081}
3082
3083INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3084{
3085 return RETURN_ERR;
3086}
3087
3088
3089//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3090INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3091{
developer5f222492022-09-13 15:21:52 +08003092 char cmd[MAX_BUF_SIZE]={'\0'};
3093 char buf[MAX_CMD_SIZE]={'\0'};
3094
3095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3096 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003097 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003098
3099 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3100 _syscmd(cmd, buf, sizeof(buf));
3101 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003102
developer5f222492022-09-13 15:21:52 +08003103 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003104 return RETURN_OK;
3105}
3106
3107INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3108{
developer5f222492022-09-13 15:21:52 +08003109 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3110 struct params params={'\0'};
3111 char buf[MAX_BUF_SIZE] = {'\0'};
3112 char config_file[MAX_BUF_SIZE] = {'\0'};
3113
developer5b398df2022-11-17 20:39:48 +08003114 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3115 return RETURN_ERR;
3116
developer5f222492022-09-13 15:21:52 +08003117 params.name = "beacon_int";
3118 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3119 params.value = buf;
3120
3121 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3122 wifi_hostapdWrite(config_file, &params, 1);
3123
3124 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3125 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3126 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003127}
3128
3129//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.
3130INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3131{
developer06a01d92022-09-07 16:32:39 +08003132 //TODO: need to revisit below implementation
3133 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003134 char temp_output[128] = {0};
3135 char temp_TransmitRates[64] = {0};
3136 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003137
3138 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3139 if (NULL == output)
3140 return RETURN_ERR;
3141 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003142 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3143
3144 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3145 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3146 } else {
3147 temp = strtok(temp_TransmitRates," ");
3148 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003149 {
developere9d0abd2022-09-13 15:40:57 +08003150 // Convert 100 kbps to Mbps
3151 temp[strlen(temp)-1]=0;
3152 if((temp[0]=='5') && (temp[1]=='\0'))
3153 {
3154 temp="5.5";
3155 }
3156 strcat(temp_output,temp);
3157 temp = strtok(NULL," ");
3158 if(temp!=NULL)
3159 {
3160 strcat(temp_output,",");
3161 }
developer06a01d92022-09-07 16:32:39 +08003162 }
developere9d0abd2022-09-13 15:40:57 +08003163 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003164 }
developer06a01d92022-09-07 16:32:39 +08003165 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003166 return RETURN_OK;
3167}
3168
3169INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3170{
3171 char *temp;
3172 char temp1[128];
3173 char temp_output[128];
3174 char temp_TransmitRates[128];
3175 char set[128];
3176 char sub_set[128];
3177 int set_count=0,subset_count=0;
3178 int set_index=0,subset_index=0;
3179 char *token;
3180 int flag=0, i=0;
3181 struct params params={'\0'};
3182 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003183 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003184
3185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3186 if(NULL == TransmitRates)
3187 return RETURN_ERR;
3188 strcpy(sub_set,TransmitRates);
3189
3190 //Allow only supported Data transmit rate to be set
3191 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3192 token = strtok(sub_set,",");
3193 while( token != NULL ) /* split the basic rate to be set, by comma */
3194 {
3195 sub_set[subset_count]=atoi(token);
3196 subset_count++;
3197 token=strtok(NULL,",");
3198 }
3199 token=strtok(set,",");
3200 while(token!=NULL) /* split the supported rate by comma */
3201 {
3202 set[set_count]=atoi(token);
3203 set_count++;
3204 token=strtok(NULL,",");
3205 }
3206 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3207 {
3208 for(set_index=0;set_index < set_count;set_index++)
3209 {
3210 flag=0;
3211 if(sub_set[subset_index]==set[set_index])
3212 break;
3213 else
3214 flag=1; /* No match found */
3215 }
3216 if(flag==1)
3217 return RETURN_ERR; //If value not found return Error
3218 }
3219 strcpy(temp_TransmitRates,TransmitRates);
3220
3221 for(i=0;i<strlen(temp_TransmitRates);i++)
3222 {
3223 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003224 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003225 {
3226 continue;
3227 }
3228 else
3229 {
3230 return RETURN_ERR;
3231 }
3232 }
3233 strcpy(temp_output,"");
3234 temp = strtok(temp_TransmitRates,",");
3235 while(temp!=NULL)
3236 {
3237 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003238 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003239 {
developeref938762022-10-19 17:21:01 +08003240 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003241 {
3242 return RETURN_ERR;
3243 }
3244 }
3245
3246 if(strcmp(temp,"5.5")==0)
3247 {
3248 strcpy(temp1,"55");
3249 }
3250 else
3251 {
3252 strcat(temp1,"0");
3253 }
3254 strcat(temp_output,temp1);
3255 temp = strtok(NULL,",");
3256 if(temp!=NULL)
3257 {
3258 strcat(temp_output," ");
3259 }
3260 }
3261 strcpy(TransmitRates,temp_output);
3262
3263 params.name= "basic_rates";
3264 params.value =TransmitRates;
3265
3266 wifi_dbg_printf("\n%s:",__func__);
3267 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3268 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3269 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3270 wifi_hostapdWrite(config_file,&params,1);
3271 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3272 return RETURN_OK;
3273}
3274
3275//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3276INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3277{
3278 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3279 FILE *fp = NULL;
3280 char path[256] = {0}, output_string[256] = {0};
3281 int count = 0;
3282 char *interface = NULL;
3283
3284 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3285 if (fp == NULL)
3286 {
3287 printf("Failed to run command in Function %s\n", __FUNCTION__);
3288 return RETURN_ERR;
3289 }
3290 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3291 {
3292 interface = strchr(path, '=');
3293
3294 if (interface != NULL)
3295 {
3296 strcpy(output_string, interface + 1);
3297 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3298 interface_name[count] = output_string[count];
3299
3300 interface_name[count] = '\0';
3301 }
3302 }
3303 pclose(fp);
3304 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3305 return RETURN_OK;
3306}
3307
3308INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3309{
3310 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3311 output_struct->radio_BytesSent = 0;
3312 output_struct->radio_BytesReceived = 0;
3313 output_struct->radio_PacketsSent = 0;
3314 output_struct->radio_PacketsReceived = 0;
3315 output_struct->radio_ErrorsSent = 0;
3316 output_struct->radio_ErrorsReceived = 0;
3317 output_struct->radio_DiscardPacketsSent = 0;
3318 output_struct->radio_DiscardPacketsReceived = 0;
3319 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3320 return RETURN_OK;
3321}
3322
3323
3324INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3325{
3326 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3327 CHAR buf[MAX_CMD_SIZE] = {0};
3328 CHAR Value[MAX_BUF_SIZE] = {0};
3329 FILE *fp = NULL;
3330
3331 if (ifname == NULL || strlen(ifname) <= 1)
3332 return RETURN_OK;
3333
3334 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3335 system(buf);
3336
3337 fp = fopen("/tmp/Radio_Stats.txt", "r");
3338 if(fp == NULL)
3339 {
3340 printf("/tmp/Radio_Stats.txt not exists \n");
3341 return RETURN_ERR;
3342 }
3343 fclose(fp);
3344
3345 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3346 File_Reading(buf, Value);
3347 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3348
3349 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3350 File_Reading(buf, Value);
3351 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3352
3353 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3354 File_Reading(buf, Value);
3355 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3356
3357 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3358 File_Reading(buf, Value);
3359 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3360
3361 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3362 File_Reading(buf, Value);
3363 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3364
3365 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3366 File_Reading(buf, Value);
3367 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3368
3369 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3370 File_Reading(buf, Value);
3371 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3372
3373 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3374 File_Reading(buf, Value);
3375 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3376
3377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3378 return RETURN_OK;
3379}
3380
3381INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3382{
3383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3384 CHAR buf[MAX_CMD_SIZE] = {0};
3385 FILE *fp = NULL;
3386 INT count = 0;
3387
3388 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3389 {
3390 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3391 File_Reading(buf, status);
3392 }
3393 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3394 return RETURN_OK;
3395}
3396
3397//Get detail radio traffic static info
3398INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3399{
3400
3401#if 0
3402 //ifconfig radio_x
3403 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3404 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3405 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3406 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3407
3408 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3409 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3410 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.
3411 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.
3412
3413 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3414 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].
3415 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3416 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.
3417 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
3418 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
3419 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
3420 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
3421 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
3422
3423 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
3424 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
3425 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
3426 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.
3427
3428 return RETURN_OK;
3429#endif
3430
developera91d99f2022-09-29 15:59:10 +08003431 CHAR interface_name[64] = {0};
3432 CHAR config_path[64] = {0};
3433 BOOL iface_status = FALSE;
3434 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003435
3436 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3437 if (NULL == output_struct)
3438 return RETURN_ERR;
3439
developera91d99f2022-09-29 15:59:10 +08003440 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3441 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003442
developera91d99f2022-09-29 15:59:10 +08003443 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003444
developera91d99f2022-09-29 15:59:10 +08003445 if (iface_status == TRUE)
3446 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3447 else
3448 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003449
developera91d99f2022-09-29 15:59:10 +08003450 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3451 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3452 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3453 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3454 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3455 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3456 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3457 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003458
3459 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3460 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].
3461 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3462 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.
3463 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
3464 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
3465 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
3466 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
3467 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
3468
3469 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
3470 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
3471 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
3472 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.
3473
3474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3475
3476 return RETURN_OK;
3477}
3478
3479//Set radio traffic static Measureing rules
3480INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3481{
3482 //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
3483 // Else, save the MeasuringRate and MeasuringInterval for future usage
3484
3485 return RETURN_OK;
3486}
3487
3488//To start or stop RadioTrafficStats
3489INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3490{
3491 //zqiu: If the RadioTrafficStats process running
3492 // if(enable)
3493 // return RETURN_OK.
3494 // else
3495 // Stop RadioTrafficStats process
3496 // Else
3497 // if(enable)
3498 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3499 // else
3500 // return RETURN_OK.
3501
3502 return RETURN_OK;
3503}
3504
3505//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
3506INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3507{
3508 //zqiu: Please ignor signalIndex.
3509 if (NULL == SignalLevel)
3510 return RETURN_ERR;
3511 *SignalLevel=(radioIndex==0)?-19:-19;
3512
3513 return RETURN_OK;
3514}
3515
3516//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3517INT wifi_applyRadioSettings(INT radioIndex)
3518{
3519 return RETURN_OK;
3520}
3521
3522//Get the radio index assocated with this SSID entry
3523INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3524{
developer5b398df2022-11-17 20:39:48 +08003525 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003526 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003527 int max_radio_num = 0;
3528 wifi_getMaxRadioNumber(&max_radio_num);
3529 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003530 return RETURN_OK;
3531}
3532
3533//Device.WiFi.SSID.{i}.Enable
3534//Get SSID enable configuration parameters (not the SSID enable status)
3535INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3536{
3537 if (NULL == output_bool)
3538 return RETURN_ERR;
3539
developer06a01d92022-09-07 16:32:39 +08003540 return wifi_getApEnable(ssidIndex, output_bool);
3541}
3542
3543//Device.WiFi.SSID.{i}.Enable
3544//Set SSID enable configuration parameters
3545INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3546{
developer06a01d92022-09-07 16:32:39 +08003547 return wifi_setApEnable(ssidIndex, enable);
3548}
3549
3550//Device.WiFi.SSID.{i}.Status
3551//Get the SSID enable status
3552INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3553{
3554 char cmd[MAX_CMD_SIZE]={0};
3555 char buf[MAX_BUF_SIZE]={0};
3556 BOOL output_bool;
3557
3558 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3559 if (NULL == output_string)
3560 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003561
developer06a01d92022-09-07 16:32:39 +08003562 wifi_getApEnable(ssidIndex,&output_bool);
3563 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3564
3565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3566 return RETURN_OK;
3567}
3568
3569// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3570INT wifi_getSSIDName(INT apIndex, CHAR *output)
3571{
3572 char config_file[MAX_BUF_SIZE] = {0};
3573
3574 if (NULL == output)
3575 return RETURN_ERR;
3576
3577 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3578 wifi_hostapdRead(config_file,"ssid",output,32);
3579
3580 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3581 return RETURN_OK;
3582}
3583
3584// Set a max 32 byte string and sets an internal variable to the SSID name
3585INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3586{
3587 char str[MAX_BUF_SIZE]={'\0'};
3588 char cmd[MAX_CMD_SIZE]={'\0'};
3589 struct params params;
3590 char config_file[MAX_BUF_SIZE] = {0};
3591
3592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3593 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3594 return RETURN_ERR;
3595
3596 params.name = "ssid";
3597 params.value = ssid_string;
3598 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3599 wifi_hostapdWrite(config_file, &params, 1);
3600 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3602
3603 return RETURN_OK;
3604}
3605
3606//Get the BSSID
3607INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3608{
3609 char cmd[MAX_CMD_SIZE]="";
3610
3611 if (NULL == output_string)
3612 return RETURN_ERR;
3613
3614 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3615 {
developer1d57d002022-10-12 18:03:15 +08003616 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 +08003617 _syscmd(cmd, output_string, 64);
3618 return RETURN_OK;
3619 }
3620 strncpy(output_string, "\0", 1);
3621
3622 return RETURN_ERR;
3623}
3624
3625//Get the MAC address associated with this Wifi SSID
3626INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3627{
3628 wifi_getBaseBSSID(ssidIndex,output_string);
3629 return RETURN_OK;
3630}
3631
3632//Get the basic SSID traffic static info
3633//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3634//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3635INT wifi_applySSIDSettings(INT ssidIndex)
3636{
3637 BOOL status = false;
3638 char cmd[MAX_CMD_SIZE] = {0};
3639 char buf[MAX_CMD_SIZE] = {0};
3640 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003641 int max_radio_num = 0;
3642 int radioIndex = 0;
3643
3644 wifi_getMaxRadioNumber(&max_radio_num);
3645
3646 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003647
3648 wifi_getApEnable(ssidIndex,&status);
3649 // Do not apply when ssid index is disabled
3650 if (status == false)
3651 return RETURN_OK;
3652
3653 /* Doing full remove and add for ssid Index
3654 * Not all hostapd options are supported with reload
3655 * for example macaddr_acl
3656 */
3657 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3658 return RETURN_ERR;
3659
3660 ret = wifi_setApEnable(ssidIndex,true);
3661
3662 /* Workaround for hostapd issue with multiple bss definitions
3663 * when first created interface will be removed
3664 * then all vaps other vaps on same phy are removed
3665 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003666 for(int i=0; i < MAX_APS/max_radio_num; i++) {
3667 apIndex = max_radio_num*i+radioIndex;
developer06a01d92022-09-07 16:32:39 +08003668 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3669 _syscmd(cmd, buf, sizeof(buf));
3670 if(*buf == '1')
3671 wifi_setApEnable(apIndex, true);
3672 }
3673
3674 return ret;
3675}
3676
developera3c68b92022-09-13 15:27:29 +08003677struct channels_noise {
3678 int channel;
3679 int noise;
3680};
3681
3682// Return noise array for each channel
3683int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3684{
3685 FILE *f = NULL;
3686 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003687 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003688 size_t len = 0;
3689 ssize_t read = 0;
3690 int tmp = 0, arr_index = -1;
3691
3692 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3693
3694 if ((f = popen(cmd, "r")) == NULL) {
3695 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3696 return RETURN_ERR;
3697 }
developer5550e242022-09-30 09:59:32 +08003698
3699 while(fgets(line, sizeof(line), f) != NULL) {
3700 if(arr_index < channels_num){
3701 sscanf(line, "%d", &tmp);
3702 if (tmp > 0) { // channel frequency, the first line must be frequency
3703 arr_index++;
3704 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3705 } else { // noise
3706 channels_noise_arr[arr_index].noise = tmp;
3707 }
3708 }else{
3709 break;
developera3c68b92022-09-13 15:27:29 +08003710 }
3711 }
developera3c68b92022-09-13 15:27:29 +08003712 pclose(f);
3713 return RETURN_OK;
3714}
3715
developer06a01d92022-09-07 16:32:39 +08003716//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3717//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3718INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3719{
developera3c68b92022-09-13 15:27:29 +08003720 int index = -1;
3721 wifi_neighbor_ap2_t *scan_array = NULL;
3722 char cmd[256]={0};
3723 char buf[128]={0};
3724 char file_name[32] = {0};
3725 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003726 char line[256] = {0};
3727 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003728 int freq=0;
3729 FILE *f = NULL;
3730 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003731 int channels_num = 0;
3732 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003733 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003734 bool filter_enable = false;
3735 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003736 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003737
developer615510b2022-09-27 10:14:35 +08003738 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003739
3740 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3741 f = fopen(file_name, "r");
3742 if (f != NULL) {
3743 fgets(filter_SSID, sizeof(file_name), f);
3744 if (strlen(filter_SSID) != 0)
3745 filter_enable = true;
3746 fclose(f);
3747 }
3748
developer033b37b2022-10-18 11:27:46 +08003749 phyId = radio_index_to_phy(radioIndex);
3750 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003751 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003752 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003753
developer5550e242022-09-30 09:59:32 +08003754
developer06a01d92022-09-07 16:32:39 +08003755
developera3c68b92022-09-13 15:27:29 +08003756 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
developer615510b2022-09-27 10:14:35 +08003757 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
developera3c68b92022-09-13 15:27:29 +08003758 fprintf(stderr, "cmd: %s\n", cmd);
3759 if ((f = popen(cmd, "r")) == NULL) {
3760 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3761 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003762 }
developer5550e242022-09-30 09:59:32 +08003763
3764 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3765 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3766
developer615510b2022-09-27 10:14:35 +08003767 ret = fgets(line, sizeof(line), f);
3768 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003769 if(strstr(line, "BSS") != NULL) { // new neighbor info
3770 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3771 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3772 // 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 +08003773
developera3c68b92022-09-13 15:27:29 +08003774 if (!filter_BSS) {
3775 index++;
3776 wifi_neighbor_ap2_t *tmp;
3777 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3778 if (tmp == NULL) { // no more memory to use
3779 index--;
3780 wifi_dbg_printf("%s: realloc failed\n", __func__);
3781 break;
3782 }
3783 scan_array = tmp;
3784 }
3785 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3786
3787 filter_BSS = false;
3788 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3789 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3790 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3791 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3792 } else if (strstr(line, "freq") != NULL) {
3793 sscanf(line," freq: %d", &freq);
3794 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3795
3796 if (freq >= 2412 && freq <= 2484) {
3797 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3798 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3799 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3800 }
3801 else if (freq >= 5160 && freq <= 5805) {
3802 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3803 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3804 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3805 }
3806
3807 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003808 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003809 for (int i = 0; i < channels_num; i++) {
3810 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3811 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3812 break;
3813 }
3814 }
3815 }
3816 } else if (strstr(line, "beacon interval") != NULL) {
3817 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3818 } else if (strstr(line, "signal") != NULL) {
3819 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3820 } else if (strstr(line,"SSID") != NULL) {
3821 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3822 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3823 filter_BSS = true;
3824 }
3825 } else if (strstr(line, "Supported rates") != NULL) {
3826 char SRate[80] = {0}, *tmp = NULL;
3827 memset(buf, 0, sizeof(buf));
3828 strcpy(SRate, line);
3829 tmp = strtok(SRate, ":");
3830 tmp = strtok(NULL, ":");
3831 strcpy(buf, tmp);
3832 memset(SRate, 0, sizeof(SRate));
3833
3834 tmp = strtok(buf, " \n");
3835 while (tmp != NULL) {
3836 strcat(SRate, tmp);
3837 if (SRate[strlen(SRate) - 1] == '*') {
3838 SRate[strlen(SRate) - 1] = '\0';
3839 }
3840 strcat(SRate, ",");
3841
3842 tmp = strtok(NULL, " \n");
3843 }
3844 SRate[strlen(SRate) - 1] = '\0';
3845 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3846 } else if (strstr(line, "DTIM") != NULL) {
3847 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3848 } else if (strstr(line, "VHT capabilities") != NULL) {
3849 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3850 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3851 } else if (strstr(line, "HT capabilities") != NULL) {
3852 strcat(scan_array[index].ap_SupportedStandards, ",n");
3853 strcpy(scan_array[index].ap_OperatingStandards, "n");
3854 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003855 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003856 sscanf(line," * channel width: %d", &vht_channel_width);
3857 if(vht_channel_width == 1) {
3858 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3859 } else {
3860 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3861 }
3862 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3863 continue;
3864 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003865 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003866 sscanf(line," * secondary channel offset: %s", &buf);
3867 if (!strcmp(buf, "above")) {
3868 //40Mhz +
3869 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3870 }
3871 else if (!strcmp(buf, "below")) {
3872 //40Mhz -
3873 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3874 } else {
3875 //20Mhz
3876 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3877 }
3878 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3879 continue;
3880 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003881 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3882 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3883 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003884 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3885 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003886 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003887 else
developer615510b2022-09-27 10:14:35 +08003888 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003889 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003890 if (strstr(line, "HE80/5GHz") != NULL) {
3891 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3892 ret = fgets(line, sizeof(line), f);
3893 } else
3894 continue;
developera3c68b92022-09-13 15:27:29 +08003895 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003896 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003897 }
developer615510b2022-09-27 10:14:35 +08003898 continue;
developera3c68b92022-09-13 15:27:29 +08003899 } else if (strstr(line, "WPA") != NULL) {
3900 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3901 } else if (strstr(line, "RSN") != NULL) {
3902 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3903 } else if (strstr(line, "Group cipher") != NULL) {
3904 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3905 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3906 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3907 }
3908 }
developer615510b2022-09-27 10:14:35 +08003909 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003910 }
3911
3912 if (!filter_BSS) {
3913 *output_array_size = index + 1;
3914 } else {
3915 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3916 *output_array_size = index;
3917 }
3918 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003919 pclose(f);
developer5550e242022-09-30 09:59:32 +08003920 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003922 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003923}
3924
3925//>> Deprecated: used for old RDKB code.
3926INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3927{
3928 INT status = RETURN_ERR;
3929
3930 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3931 output_struct->wifi_PLCPErrorCount = 0;
3932 output_struct->wifi_FCSErrorCount = 0;
3933 output_struct->wifi_InvalidMACCount = 0;
3934 output_struct->wifi_PacketsOtherReceived = 0;
3935 output_struct->wifi_Noise = 0;
3936 status = RETURN_OK;
3937 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3938 return status;
3939}
3940
3941INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3942{
3943 char cmd[128];
3944 char buf[1280];
3945 char *pos = NULL;
3946
3947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3948 if (NULL == output_struct)
3949 return RETURN_ERR;
3950
3951 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3952
3953 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3954 _syscmd(cmd, buf, sizeof(buf));
3955
3956 pos = buf;
3957 if ((pos = strstr(pos, "RX packets:")) == NULL)
3958 return RETURN_ERR;
3959 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3960
3961 if ((pos = strstr(pos, "TX packets:")) == NULL)
3962 return RETURN_ERR;
3963 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3964
3965 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3966 return RETURN_ERR;
3967 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3968
3969 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3970 return RETURN_ERR;
3971 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3972
3973 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3974 _syscmd(cmd, buf, sizeof(buf));
3975 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3976
3977#if 0
3978 //TODO: need to revisit below implementation
3979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3980 char interface_name[MAX_BUF_SIZE] = {0};
3981 char interface_status[MAX_BUF_SIZE] = {0};
3982 char Value[MAX_BUF_SIZE] = {0};
3983 char buf[MAX_CMD_SIZE] = {0};
3984 char cmd[MAX_CMD_SIZE] = {0};
3985 FILE *fp = NULL;
3986
3987 if (NULL == output_struct) {
3988 return RETURN_ERR;
3989 }
3990
3991 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3992
3993 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3994 {
3995 if(apIndex == 0) //private_wifi for 2.4G
3996 {
3997 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3998 }
3999 else if(apIndex == 1) //private_wifi for 5G
4000 {
4001 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4002 }
4003 else if(apIndex == 4) //public_wifi for 2.4G
4004 {
4005 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4006 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4007 {
4008 return RETURN_ERR;
4009 }
4010 if(buf[0] == '#')//tp-link
4011 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4012 else//tenda
4013 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4014 }
4015 else if(apIndex == 5) //public_wifi for 5G
4016 {
4017 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4018 }
4019
4020 GetIfacestatus(interface_name, interface_status);
4021
4022 if(0 != strcmp(interface_status, "1"))
4023 return RETURN_ERR;
4024
4025 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4026 system(cmd);
4027
4028 fp = fopen("/tmp/SSID_Stats.txt", "r");
4029 if(fp == NULL)
4030 {
4031 printf("/tmp/SSID_Stats.txt not exists \n");
4032 return RETURN_ERR;
4033 }
4034 fclose(fp);
4035
4036 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4037 File_Reading(buf, Value);
4038 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4039
4040 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4041 File_Reading(buf, Value);
4042 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4043
4044 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4045 File_Reading(buf, Value);
4046 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4047
4048 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4049 File_Reading(buf, Value);
4050 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4051
4052 /* There is no specific parameter from caller to associate the value wifi_Associations */
4053 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4054 //_syscmd(cmd, buf, sizeof(buf));
4055 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4056 }
4057#endif
4058 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4059 return RETURN_OK;
4060}
4061
4062INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4063{
4064 char interface_name[MAX_BUF_SIZE] = {0};
4065 char interface_status[MAX_BUF_SIZE] = {0};
4066 char Value[MAX_BUF_SIZE] = {0};
4067 char buf[MAX_CMD_SIZE] = {0};
4068 char cmd[MAX_CMD_SIZE] = {0};
4069 FILE *fp = NULL;
4070
4071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4072 if (NULL == output_struct)
4073 return RETURN_ERR;
4074
4075 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4076
4077 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4078 {
4079 if(apIndex == 0) //private_wifi for 2.4G
4080 {
4081 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4082 }
4083 else if(apIndex == 1) //private_wifi for 5G
4084 {
4085 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4086 }
4087 else if(apIndex == 4) //public_wifi for 2.4G
4088 {
4089 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4090 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4091 {
4092 return RETURN_ERR;
4093 }
4094 if(buf[0] == '#')
4095 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4096 else
4097 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4098 }
4099 else if(apIndex == 5) //public_wifi for 5G
4100 {
4101 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4102 }
4103
4104 GetIfacestatus(interface_name, interface_status);
4105
4106 if(0 != strcmp(interface_status, "1"))
4107 return RETURN_ERR;
4108
4109 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4110 system(cmd);
4111
4112 fp = fopen("/tmp/SSID_Stats.txt", "r");
4113 if(fp == NULL)
4114 {
4115 printf("/tmp/SSID_Stats.txt not exists \n");
4116 return RETURN_ERR;
4117 }
4118 fclose(fp);
4119
4120 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4121 File_Reading(buf, Value);
4122 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4123
4124 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4125 File_Reading(buf, Value);
4126 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4127
4128 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4129 File_Reading(buf, Value);
4130 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4131
4132 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4133 File_Reading(buf, Value);
4134 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4135 }
4136
4137 output_struct->wifi_UnicastPacketsSent = 0;
4138 output_struct->wifi_UnicastPacketsReceived = 0;
4139 output_struct->wifi_MulticastPacketsSent = 0;
4140 output_struct->wifi_MulticastPacketsReceived = 0;
4141 output_struct->wifi_BroadcastPacketsSent = 0;
4142 output_struct->wifi_BroadcastPacketsRecevied = 0;
4143 output_struct->wifi_UnknownPacketsReceived = 0;
4144
4145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4146 return RETURN_OK;
4147}
4148
4149INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4150{
4151 INT status = RETURN_ERR;
4152
4153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4154 //Below values should get updated from hal
4155 output_struct->wifi_RetransCount=0;
4156 output_struct->wifi_FailedRetransCount=0;
4157 output_struct->wifi_RetryCount=0;
4158 output_struct->wifi_MultipleRetryCount=0;
4159 output_struct->wifi_ACKFailureCount=0;
4160 output_struct->wifi_AggregatedPacketCount=0;
4161
4162 status = RETURN_OK;
4163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4164
4165 return status;
4166}
4167
4168INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4169{
4170 INT status = RETURN_ERR;
4171 UINT index;
4172 wifi_neighbor_ap_t *pt=NULL;
4173
4174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4175 *output_array_size=2;
4176 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4177 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4178 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4179 strcpy(pt->ap_Radio,"");
4180 strcpy(pt->ap_SSID,"");
4181 strcpy(pt->ap_BSSID,"");
4182 strcpy(pt->ap_Mode,"");
4183 pt->ap_Channel=1;
4184 pt->ap_SignalStrength=0;
4185 strcpy(pt->ap_SecurityModeEnabled,"");
4186 strcpy(pt->ap_EncryptionMode,"");
4187 strcpy(pt->ap_OperatingFrequencyBand,"");
4188 strcpy(pt->ap_SupportedStandards,"");
4189 strcpy(pt->ap_OperatingStandards,"");
4190 strcpy(pt->ap_OperatingChannelBandwidth,"");
4191 pt->ap_BeaconPeriod=1;
4192 pt->ap_Noise=0;
4193 strcpy(pt->ap_BasicDataTransferRates,"");
4194 strcpy(pt->ap_SupportedDataTransferRates,"");
4195 pt->ap_DTIMPeriod=1;
4196 pt->ap_ChannelUtilization = 1;
4197 }
4198
4199 status = RETURN_OK;
4200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4201
4202 return status;
4203}
4204
4205//----------------- AP HAL -------------------------------
4206
4207//>> Deprecated: used for old RDKB code.
4208INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4209{
4210 if (NULL == output_ulong || NULL == output_struct)
4211 return RETURN_ERR;
4212 *output_ulong = 0;
4213 *output_struct = NULL;
4214 return RETURN_OK;
4215}
4216
4217#ifdef HAL_NETLINK_IMPL
4218static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4219 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4220 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4221 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4222 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4223 char mac_addr[20];
4224 static int count=0;
4225 int rate=0;
4226
4227 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4228
4229 nla_parse(tb,
4230 NL80211_ATTR_MAX,
4231 genlmsg_attrdata(gnlh, 0),
4232 genlmsg_attrlen(gnlh, 0),
4233 NULL);
4234
4235 if(!tb[NL80211_ATTR_STA_INFO]) {
4236 fprintf(stderr, "sta stats missing!\n");
4237 return NL_SKIP;
4238 }
4239
4240
4241 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4242 fprintf(stderr, "failed to parse nested attributes!\n");
4243 return NL_SKIP;
4244 }
4245
4246 //devIndex starts from 1
4247 if( ++count == out->wifi_devIndex )
4248 {
4249 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4250 //Getting the mac addrress
4251 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4252
4253 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4254 fprintf(stderr, "failed to parse nested rate attributes!");
4255 return NL_SKIP;
4256 }
4257
4258 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4259 if(rinfo[NL80211_RATE_INFO_BITRATE])
4260 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4261 out->wifi_devTxRate = rate/10;
4262 }
4263
4264 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4265 fprintf(stderr, "failed to parse nested rate attributes!");
4266 return NL_SKIP;
4267 }
4268
4269 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4270 if(rinfo[NL80211_RATE_INFO_BITRATE])
4271 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4272 out->wifi_devRxRate = rate/10;
4273 }
4274 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4275 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4276
4277 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4278 count = 0; //starts the count for next cycle
4279 return NL_STOP;
4280 }
4281
4282 return NL_SKIP;
4283
4284}
4285#endif
4286
4287INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4288{
4289#ifdef HAL_NETLINK_IMPL
4290 Netlink nl;
4291 char if_name[10];
4292
4293 wifi_device_info_t info;
4294 info.wifi_devIndex = devIndex;
4295
4296 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4297
4298 nl.id = initSock80211(&nl);
4299
4300 if (nl.id < 0) {
4301 fprintf(stderr, "Error initializing netlink \n");
4302 return -1;
4303 }
4304
4305 struct nl_msg* msg = nlmsg_alloc();
4306
4307 if (!msg) {
4308 fprintf(stderr, "Failed to allocate netlink message.\n");
4309 nlfree(&nl);
4310 return -2;
4311 }
4312
4313 genlmsg_put(msg,
4314 NL_AUTO_PORT,
4315 NL_AUTO_SEQ,
4316 nl.id,
4317 0,
4318 NLM_F_DUMP,
4319 NL80211_CMD_GET_STATION,
4320 0);
4321
4322 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4323 nl_send_auto(nl.socket, msg);
4324 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4325 nl_recvmsgs(nl.socket, nl.cb);
4326 nlmsg_free(msg);
4327 nlfree(&nl);
4328
4329 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4330 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4331 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4332 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4333 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4334 return RETURN_OK;
4335#else
4336 //iw utility to retrieve station information
4337#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4338#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4339#define MACFILE "/tmp/wifi_AssoMac.txt"
4340#define TXRATEFILE "/tmp/wifi_txrate.txt"
4341#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4342 FILE *file = NULL;
4343 char if_name[10] = {'\0'};
4344 char pipeCmd[256] = {'\0'};
4345 char line[256];
4346 int count,device = 0;
4347
4348 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4349
4350 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4351 file = popen(pipeCmd, "r");
4352
4353 if(file == NULL)
4354 return RETURN_ERR; //popen failed
4355
4356 fgets(line, sizeof line, file);
4357 device = atoi(line);
4358 pclose(file);
4359
4360 if(device == 0)
4361 return RETURN_ERR; //No devices are connected
4362
4363 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4364 system(pipeCmd);
4365
4366 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4367
4368 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4369
4370 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4371
4372 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4373
4374 //devIndex starts from 1, ++count
4375 if((file = fopen(SIGNALFILE, "r")) != NULL )
4376 {
4377 for(count =0;fgets(line, sizeof line, file) != NULL;)
4378 {
4379 if (++count == devIndex)
4380 {
4381 output_struct->wifi_devSignalStrength = atoi(line);
4382 break;
4383 }
4384 }
4385 fclose(file);
4386 }
4387 else
4388 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4389
4390 if((file = fopen(MACFILE, "r")) != NULL )
4391 {
4392 for(count =0;fgets(line, sizeof line, file) != NULL;)
4393 {
4394 if (++count == devIndex)
4395 {
4396 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]);
4397 break;
4398 }
4399 }
4400 fclose(file);
4401 }
4402 else
4403 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4404
4405 if((file = fopen(TXRATEFILE, "r")) != NULL )
4406 {
4407 for(count =0;fgets(line, sizeof line, file) != NULL;)
4408 {
4409 if (++count == devIndex)
4410 {
4411 output_struct->wifi_devTxRate = atoi(line);
4412 break;
4413 }
4414 }
4415 fclose(file);
4416 }
4417 else
4418 fprintf(stderr,"fopen wifi_txrate.txt failed");
4419
4420 if((file = fopen(RXRATEFILE, "r")) != NULL)
4421 {
4422 for(count =0;fgets(line, sizeof line, file) != NULL;)
4423 {
4424 if (++count == devIndex)
4425 {
4426 output_struct->wifi_devRxRate = atoi(line);
4427 break;
4428 }
4429 }
4430 fclose(file);
4431 }
4432 else
4433 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4434
4435 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4436
4437 return RETURN_OK;
4438#endif
4439}
4440
4441INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4442{
4443 if (NULL == device)
4444 return RETURN_ERR;
4445 return RETURN_OK;
4446}
4447//<<
4448
4449
4450//--------------wifi_ap_hal-----------------------------
4451//enables CTS protection for the radio used by this AP
4452INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4453{
4454 //save config and Apply instantly
4455 return RETURN_ERR;
4456}
4457
4458// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4459INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4460{
developer463d39a2022-09-13 15:32:51 +08004461 char config_file[64] = {'\0'};
4462 char buf[64] = {'\0'};
4463 struct params list;
4464
4465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4466 list.name = "ht_coex";
4467 snprintf(buf, sizeof(buf), "%d", enable);
4468 list.value = buf;
4469
4470 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4471 wifi_hostapdWrite(config_file, &list, 1);
4472 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4473
4474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4475
4476 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004477}
4478
4479//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4480INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4481{
developerea4bcce2022-09-13 15:26:13 +08004482 char config_file[MAX_BUF_SIZE] = {'\0'};
4483 char buf[MAX_BUF_SIZE] = {'\0'};
4484 struct params list;
4485
4486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4487 if (threshold < 256 || threshold > 2346 )
4488 return RETURN_ERR;
4489 list.name = "fragm_threshold";
4490 snprintf(buf, sizeof(buf), "%d", threshold);
4491 list.value = buf;
4492
4493 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4494 wifi_hostapdWrite(config_file, &list, 1);
4495 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004496
developerea4bcce2022-09-13 15:26:13 +08004497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004498
4499 return RETURN_OK;
4500}
4501
4502// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4503INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4504{
developer51a927d2022-09-13 15:42:22 +08004505 char config_file[64] = {'\0'};
4506 char cmd[128] = {'\0'};
4507 char buf[64] = {'\0'};
4508 char stbc_config[16] = {'\0'};
4509 wifi_band band;
4510 int iterator = 0;
4511 BOOL current_stbc = FALSE;
4512
4513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4514
4515 band = wifi_index_to_band(radioIndex);
4516 if (band == band_invalid)
4517 return RETURN_ERR;
4518
4519 if (band == band_2_4)
4520 iterator = 1;
4521 else if (band == band_5)
4522 iterator = 2;
4523 else
4524 return RETURN_OK;
4525
4526 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4527
4528 // set ht and vht config
4529 for (int i = 0; i < iterator; i++) {
4530 memset(stbc_config, 0, sizeof(stbc_config));
4531 memset(cmd, 0, sizeof(cmd));
4532 memset(buf, 0, sizeof(buf));
4533 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4534 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4535 _syscmd(cmd, buf, sizeof(buf));
4536 if (strlen(buf) != 0)
4537 current_stbc = TRUE;
4538 if (current_stbc == STBC_Enable)
4539 continue;
4540
4541 if (STBC_Enable == TRUE) {
4542 // Append the STBC flags in capab config
4543 memset(cmd, 0, sizeof(cmd));
4544 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004545 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004546 else
developer6372c2b2022-10-27 17:39:51 +08004547 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 +08004548 _syscmd(cmd, buf, sizeof(buf));
4549 } else if (STBC_Enable == FALSE) {
4550 // Remove the STBC flags and remain other flags in capab
4551 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004552 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004553 _syscmd(cmd, buf, sizeof(buf));
4554 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004555 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004556 _syscmd(cmd, buf, sizeof(buf));
4557 }
4558 }
4559
4560 wifi_reloadAp(radioIndex);
4561
4562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4563 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004564}
4565
4566// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4567INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4568{
developer54e6b9f2022-09-28 14:41:20 +08004569 char AMSDU_file_path[64] = {0};
4570
4571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4572
4573 if(output_bool == NULL)
4574 return RETURN_ERR;
4575
4576 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4577
4578 if (access(AMSDU_file_path, F_OK) == 0)
4579 *output_bool = TRUE;
4580 else
4581 *output_bool = FALSE;
4582
4583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4584 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004585}
4586
4587// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4588INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4589{
developer54e6b9f2022-09-28 14:41:20 +08004590 char cmd[64]={0};
4591 char buf[64]={0};
4592 char AMSDU_file_path[64] = {0};
4593
4594 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4595
4596 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4597 _syscmd(cmd, buf, sizeof(buf));
4598
4599 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4600 memset(cmd, 0, sizeof(cmd));
4601 if (amsduEnable == TRUE)
4602 sprintf(cmd, "touch %s", AMSDU_file_path);
4603 else
4604 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4605 _syscmd(cmd, buf, sizeof(buf));
4606
4607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4608 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004609}
4610
4611//P2 // outputs the number of Tx streams
4612INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4613{
developer2de97692022-09-26 14:00:03 +08004614 char buf[8] = {0};
4615 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004616 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004617
4618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4619
4620 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4621 _syscmd(cmd, buf, sizeof(buf));
4622
developer033b37b2022-10-18 11:27:46 +08004623 phyId = radio_index_to_phy(radioIndex);
developer2de97692022-09-26 14:00:03 +08004624 // if there is no record, output the max number of spatial streams
4625 if (strlen(buf) == 0) {
developer033b37b2022-10-18 11:27:46 +08004626 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 +08004627 _syscmd(cmd, buf, sizeof(buf));
4628 }
4629
4630 *output_int = (INT)strtol(buf, NULL, 10);
4631
4632 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4633
4634 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004635}
4636
4637//P2 // sets the number of Tx streams to an enviornment variable
4638INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4639{
developer2de97692022-09-26 14:00:03 +08004640 char cmd[128] = {0};
4641 char buf[128] = {0};
4642 char chain_mask_file[128] = {0};
4643 FILE *f = NULL;
developer033b37b2022-10-18 11:27:46 +08004644 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004645
4646 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4647
4648 if (numStreams == 0) {
4649 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4650 return RETURN_ERR;
4651 }
4652 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004653
4654 phyId = radio_index_to_phy(radioIndex);
4655 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004656 _syscmd(cmd, buf, sizeof(buf));
4657
4658 if (strlen(buf) > 0) {
4659 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4660 return RETURN_ERR;
4661 }
4662 wifi_setRadioEnable(radioIndex, TRUE);
4663
4664 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4665 f = fopen(chain_mask_file, "w");
4666 if (f == NULL) {
4667 fprintf(stderr, "%s: fopen failed.\n", __func__);
4668 return RETURN_ERR;
4669 }
4670 fprintf(f, "%d", numStreams);
4671 fclose(f);
4672 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4673 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004674}
4675
4676//P2 // outputs the number of Rx streams
4677INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4678{
developer2de97692022-09-26 14:00:03 +08004679 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4680 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4681 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004682 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004683 }
4684 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004685 return RETURN_OK;
4686}
4687
4688//P2 // sets the number of Rx streams to an enviornment variable
4689INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4690{
developer2de97692022-09-26 14:00:03 +08004691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4692 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4693 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4694 return RETURN_ERR;
4695 }
4696 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004697 return RETURN_ERR;
4698}
4699
4700//Get radio RDG enable setting
4701INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4702{
4703 if (NULL == output_bool)
4704 return RETURN_ERR;
4705 *output_bool = TRUE;
4706 return RETURN_OK;
4707}
4708
4709//Get radio RDG enable setting
4710INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4711{
4712 if (NULL == output_bool)
4713 return RETURN_ERR;
4714 *output_bool = TRUE;
4715 return RETURN_OK;
4716}
4717
4718//Set radio RDG enable setting
4719INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4720{
4721 return RETURN_ERR;
4722}
4723
4724//Get radio ADDBA enable setting
4725INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4726{
4727 if (NULL == output_bool)
4728 return RETURN_ERR;
4729 *output_bool = TRUE;
4730 return RETURN_OK;
4731}
4732
4733//Set radio ADDBA enable setting
4734INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4735{
4736 return RETURN_ERR;
4737}
4738
4739//Get radio auto block ack enable setting
4740INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4741{
4742 if (NULL == output_bool)
4743 return RETURN_ERR;
4744 *output_bool = TRUE;
4745 return RETURN_OK;
4746}
4747
4748//Set radio auto block ack enable setting
4749INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4750{
4751 return RETURN_ERR;
4752}
4753
4754//Get radio 11n pure mode enable support
4755INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4756{
4757 if (NULL == output_bool)
4758 return RETURN_ERR;
4759 *output_bool = TRUE;
4760 return RETURN_OK;
4761}
4762
4763//Get radio 11n pure mode enable setting
4764INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4765{
4766 if (NULL == output_bool)
4767 return RETURN_ERR;
4768 *output_bool = TRUE;
4769 return RETURN_OK;
4770}
4771
4772//Set radio 11n pure mode enable setting
4773INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4774{
4775 return RETURN_ERR;
4776}
4777
4778//Get radio IGMP snooping enable setting
4779INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4780{
developer81bf2ed2022-09-13 15:31:14 +08004781 char cmd[128]={0};
4782 char buf[4]={0};
4783 bool bridge = FALSE, mac80211 = FALSE;
4784 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4785
4786 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004787 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004788
4789 *output_bool = FALSE;
4790
4791 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4792 _syscmd(cmd, buf, sizeof(buf));
4793 if (strncmp(buf, "1", 1) == 0)
4794 bridge = TRUE;
4795
4796 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4797 _syscmd(cmd, buf, sizeof(buf));
4798 if (strncmp(buf, "1", 1) == 0)
4799 mac80211 = TRUE;
4800
4801 if (bridge && mac80211)
4802 *output_bool = TRUE;
4803
4804 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004805 return RETURN_OK;
4806}
4807
4808//Set radio IGMP snooping enable setting
4809INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4810{
developer81bf2ed2022-09-13 15:31:14 +08004811 char cmd[128]={0};
4812 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004813 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4815
4816 // bridge
4817 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4818 _syscmd(cmd, buf, sizeof(buf));
4819
developer804c64f2022-10-19 13:54:40 +08004820 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004821 // mac80211
developer804c64f2022-10-19 13:54:40 +08004822 for (int i = 0; i < max_num_radios; i++) {
developer81bf2ed2022-09-13 15:31:14 +08004823 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4824 _syscmd(cmd, buf, sizeof(buf));
4825 }
4826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4827 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004828}
4829
4830//Get the Reset count of radio
4831INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4832{
4833 if (NULL == output_int)
4834 return RETURN_ERR;
4835 *output_int = (radioIndex==0)? 1: 3;
4836
4837 return RETURN_OK;
4838}
4839
4840
4841//---------------------------------------------------------------------------------------------------
4842//
4843// Additional Wifi AP level APIs used for Access Point devices
4844//
4845//---------------------------------------------------------------------------------------------------
4846
4847// creates a new ap and pushes these parameters to the hardware
4848INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4849{
4850 char buf[1024];
4851 char cmd[128];
developer033b37b2022-10-18 11:27:46 +08004852 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004853
4854 if (NULL == essid)
4855 return RETURN_ERR;
4856
developer033b37b2022-10-18 11:27:46 +08004857 phyId = radio_index_to_phy(radioIndex);
4858 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08004859 _syscmd(cmd, buf, sizeof(buf));
4860
4861 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4862 _syscmd(cmd, buf, sizeof(buf));
4863
4864 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4865
4866 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4867 _syscmd(cmd, buf, sizeof(buf));
4868
4869 return RETURN_OK;
4870}
4871
4872// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4873INT wifi_deleteAp(INT apIndex)
4874{
4875 char buf[1024];
4876 char cmd[128];
4877
4878 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4879 _syscmd(cmd, buf, sizeof(buf));
4880
4881 wifi_removeApSecVaribles(apIndex);
4882
4883 return RETURN_OK;
4884}
4885
4886// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4887INT wifi_getApName(INT apIndex, CHAR *output_string)
4888{
4889 if(NULL == output_string)
4890 return RETURN_ERR;
4891
4892 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4893 return RETURN_OK;
4894}
4895
4896// Outputs the index number in that corresponds to the SSID string
4897INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4898{
4899 CHAR *pos = NULL;
4900
4901 *output_int = -1;
4902 pos = strstr(inputSsidString, AP_PREFIX);
4903 if(pos)
4904 {
4905 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4906 return RETURN_OK;
4907 }
4908 return RETURN_ERR;
4909}
4910
4911INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4912{
4913 return wifi_getIndexFromName(inputSsidString, output_int);
4914}
4915
4916// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4917INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4918{
4919 char buf[MAX_BUF_SIZE] = {0};
4920 char cmd[MAX_CMD_SIZE] = {0};
4921 char config_file[MAX_BUF_SIZE] = {0};
4922
4923 if(NULL == output_string)
4924 return RETURN_ERR;
4925
4926 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4927 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4928 if((strcmp(buf,"3")==0))
4929 snprintf(output_string, 32, "WPAand11i");
4930 else if((strcmp(buf,"2")==0))
4931 snprintf(output_string, 32, "11i");
4932 else if((strcmp(buf,"1")==0))
4933 snprintf(output_string, 32, "WPA");
4934 else
4935 snprintf(output_string, 32, "None");
4936
4937 return RETURN_OK;
4938}
4939
4940// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4941INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4942{
4943 char config_file[MAX_BUF_SIZE] = {0};
4944 struct params list;
4945
4946 if (NULL == beaconTypeString)
4947 return RETURN_ERR;
4948 list.name = "wpa";
4949 list.value = "0";
4950
4951 if((strcmp(beaconTypeString,"WPAand11i")==0))
4952 list.value="3";
4953 else if((strcmp(beaconTypeString,"11i")==0))
4954 list.value="2";
4955 else if((strcmp(beaconTypeString,"WPA")==0))
4956 list.value="1";
4957
4958 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4959 wifi_hostapdWrite(config_file, &list, 1);
4960 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4961 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4962 return RETURN_OK;
4963}
4964
4965// sets the beacon interval on the hardware for this AP
4966INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4967{
developer5f222492022-09-13 15:21:52 +08004968 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4969 struct params params={'\0'};
4970 char buf[MAX_BUF_SIZE] = {'\0'};
4971 char config_file[MAX_BUF_SIZE] = {'\0'};
4972
4973 params.name = "beacon_int";
4974 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4975 params.value = buf;
4976
4977 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4978 wifi_hostapdWrite(config_file, &params, 1);
4979
4980 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4982 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004983}
4984
4985INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4986{
developer5b398df2022-11-17 20:39:48 +08004987 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
4988 return RETURN_ERR;
4989 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004990}
4991
4992// Get the packet size threshold supported.
4993INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4994{
4995 //save config and apply instantly
4996 if (NULL == output_bool)
4997 return RETURN_ERR;
4998 *output_bool = FALSE;
4999 return RETURN_OK;
5000}
5001
5002// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5003INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5004{
5005 char cmd[128];
5006 char buf[512];
5007
5008 if (threshold > 0)
5009 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
5010 else
5011 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
5012 _syscmd(cmd, buf, sizeof(buf));
5013
5014 return RETURN_OK;
5015}
5016
5017// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5018INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5019{
5020 if (NULL == output_string)
5021 return RETURN_ERR;
5022 snprintf(output_string, 32, "TKIPandAESEncryption");
5023 return RETURN_OK;
5024
5025}
5026
5027// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5028INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5029{
5030 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5031 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
5032
5033 if(NULL == output_string)
5034 return RETURN_ERR;
5035
5036 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5037 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5038
5039 if(strcmp(buf,"0")==0)
5040 {
5041 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5042 snprintf(output_string, 32, "None");
5043 return RETURN_OK;
5044 }
5045 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5046 param_name = "rsn_pairwise";
5047 else if((strcmp(buf,"1")==0))
5048 param_name = "wpa_pairwise";
5049 else
5050 return RETURN_ERR;
5051 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005052 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005053 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5054 param_name = "wpa_pairwise";
5055 memset(output_string, '\0', 32);
5056 wifi_hostapdRead(config_file, param_name, output_string, 32);
5057 }
developer06a01d92022-09-07 16:32:39 +08005058 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5059
5060 if(strcmp(output_string,"TKIP") == 0)
5061 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5062 else if(strcmp(output_string,"CCMP") == 0)
5063 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5064 else if(strcmp(output_string,"TKIP CCMP") == 0)
5065 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5066
5067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5068 return RETURN_OK;
5069}
5070
5071// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5072INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5073{
5074 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5075 struct params params={'\0'};
5076 char output_string[32];
5077 char config_file[MAX_BUF_SIZE] = {0};
5078
5079 memset(output_string,'\0',32);
5080 wifi_getApWpaEncryptionMode(apIndex,output_string);
5081
5082 if(strcmp(encMode, "TKIPEncryption") == 0)
5083 params.value = "TKIP";
5084 else if(strcmp(encMode,"AESEncryption") == 0)
5085 params.value = "CCMP";
5086 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5087 params.value = "TKIP CCMP";
5088
5089 if((strcmp(output_string,"WPAand11i")==0))
5090 {
5091 params.name = "wpa_pairwise";
5092 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5093 wifi_hostapdWrite(config_file, &params, 1);
5094 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5095
5096 params.name,"rsn_pairwise";
5097 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5098 wifi_hostapdWrite(config_file, &params, 1);
5099 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5100
5101 return RETURN_OK;
5102 }
5103 else if((strcmp(output_string,"11i")==0))
5104 {
5105 params.name = "rsn_pairwise";
5106 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5107 wifi_hostapdWrite(config_file, &params, 1);
5108 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5109 return RETURN_OK;
5110 }
5111 else if((strcmp(output_string,"WPA")==0))
5112 {
5113 params.name = "wpa_pairwise";
5114 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5115 wifi_hostapdWrite(config_file, &params, 1);
5116 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5117 return RETURN_OK;
5118 }
5119
5120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5121 return RETURN_OK;
5122}
5123
5124// deletes internal security varable settings for this ap
5125INT wifi_removeApSecVaribles(INT apIndex)
5126{
5127 //TODO: remove the entry in hostapd config file
5128 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5129 //_syscmd(cmd, buf, sizeof(buf));
5130
5131 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5132 //_syscmd(cmd, buf, sizeof(buf));
5133 return RETURN_ERR;
5134}
5135
5136// changes the hardware settings to disable encryption on this ap
5137INT wifi_disableApEncryption(INT apIndex)
5138{
5139 //Apply instantly
5140 return RETURN_ERR;
5141}
5142
5143// set the authorization mode on this ap
5144// mode mapping as: 1: open, 2: shared, 4:auto
5145INT wifi_setApAuthMode(INT apIndex, INT mode)
5146{
developeraf95c502022-09-13 16:18:22 +08005147 struct params params={0};
5148 char config_file[64] = {0};
5149 int ret;
5150
5151 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5152
5153 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5154 params.name = "auth_algs";
5155
5156 if (mode & 1 && mode & 2)
5157 params.value = "3";
5158 else if (mode & 2)
5159 params.value = "2";
5160 else if (mode & 1)
5161 params.value = "1";
5162 else
5163 params.value = "0";
5164
5165 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5166 wifi_hostapdWrite(config_file, &params, 1);
5167 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5168 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5169
5170 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005171}
5172
5173// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5174INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5175{
5176 //save to wifi config, and wait for wifi restart to apply
5177 struct params params={'\0'};
5178 char config_file[MAX_BUF_SIZE] = {0};
5179 int ret;
5180
5181 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5182 if(authMode == NULL)
5183 return RETURN_ERR;
5184
5185 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5186 params.name = "wpa_key_mgmt";
5187
5188 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5189 params.value = "WPA-PSK";
5190 else if(strcmp(authMode,"EAPAuthentication") == 0)
5191 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005192 else if (strcmp(authMode, "SAEAuthentication") == 0)
5193 params.value = "SAE";
5194 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5195 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005196 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5197 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005198 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5199 return RETURN_OK; //This is taken careof in beaconType
5200
5201 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5202 ret=wifi_hostapdWrite(config_file,&params,1);
5203 if(!ret)
5204 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5205 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5206
5207 return ret;
5208}
5209
5210// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5211INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5212{
5213 //save to wifi config, and wait for wifi restart to apply
5214 char BeaconType[50] = {0};
5215 char config_file[MAX_BUF_SIZE] = {0};
5216
5217 *authMode = 0;
5218 wifi_getApBeaconType(apIndex,BeaconType);
5219 printf("%s____%s \n",__FUNCTION__,BeaconType);
5220
5221 if(strcmp(BeaconType,"None") == 0)
5222 strcpy(authMode,"None");
5223 else
5224 {
5225 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5226 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5227 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5228 if(strcmp(authMode,"WPA-PSK") == 0)
5229 strcpy(authMode,"SharedAuthentication");
5230 else if(strcmp(authMode,"WPA-EAP") == 0)
5231 strcpy(authMode,"EAPAuthentication");
5232 }
5233
5234 return RETURN_OK;
5235}
5236
5237// Outputs the number of stations associated per AP
5238INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5239{
5240 char cmd[128]={0};
5241 char buf[128]={0};
5242 BOOL status = false;
5243
5244 if(apIndex > MAX_APS)
5245 return RETURN_ERR;
5246
5247 wifi_getApEnable(apIndex,&status);
5248 if (!status)
5249 return RETURN_OK;
5250
5251 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5252 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5253 _syscmd(cmd, buf, sizeof(buf));
5254 sscanf(buf,"%lu", output_ulong);
5255
5256 return RETURN_OK;
5257}
5258
5259// manually removes any active wi-fi association with the device specified on this ap
5260INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5261{
5262 char buf[126]={'\0'};
5263
5264 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5265 system(buf);
5266
5267 return RETURN_OK;
5268}
5269
5270// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5271INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5272{
5273 if(NULL == output_int)
5274 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005275 int max_radio_num = 0;
5276 wifi_getMaxRadioNumber(&max_radio_num);
5277 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005278 return RETURN_OK;
5279}
5280
5281// sets the radio index for the specific ap
5282INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5283{
5284 //set to config only and wait for wifi reset to apply settings
5285 return RETURN_ERR;
5286}
5287
5288// Get the ACL MAC list per AP
5289INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5290{
5291 char cmd[MAX_CMD_SIZE]={'\0'};
5292 int ret = 0;
5293
5294 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5295 ret = _syscmd(cmd,macArray,buf_size);
5296 if (ret != 0)
5297 return RETURN_ERR;
5298
5299 return RETURN_OK;
5300}
5301
developere6aafda2022-09-13 14:59:28 +08005302INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5303{
5304 char cmd[MAX_CMD_SIZE]={'\0'};
5305 int ret = 0;
5306
5307 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5308 ret = _syscmd(cmd,macArray,buf_size);
5309 if (ret != 0)
5310 return RETURN_ERR;
5311
5312 return RETURN_OK;
5313}
5314
5315
developer06a01d92022-09-07 16:32:39 +08005316// Get the list of stations associated per AP
5317INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5318{
5319 char cmd[128];
5320
5321 if(apIndex > 3) //Currently supporting apIndex upto 3
5322 return RETURN_ERR;
5323 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5324 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5325 _syscmd(cmd, macArray, buf_size);
5326
5327 return RETURN_OK;
5328}
5329
5330// adds the mac address to the filter list
5331//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5332INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5333{
5334 char cmd[MAX_CMD_SIZE]={'\0'};
5335 char buf[MAX_BUF_SIZE]={'\0'};
5336
5337#if 0
5338 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5339 if(_syscmd(cmd,buf,sizeof(buf)))
5340 return RETURN_ERR;
5341#endif
5342 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5343 if(_syscmd(cmd,buf,sizeof(buf)))
5344 return RETURN_ERR;
5345
5346 return RETURN_OK;
5347}
5348
5349// deletes the mac address from the filter list
5350//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5351INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5352{
5353 char cmd[MAX_CMD_SIZE]={'\0'};
5354 char buf[MAX_BUF_SIZE]={'\0'};
5355
5356#if 0
5357 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5358 if(_syscmd(cmd,buf,sizeof(buf)))
5359 return RETURN_ERR;
5360
5361#endif
5362 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5363 if(_syscmd(cmd,buf,sizeof(buf)))
5364 return RETURN_ERR;
5365
5366 return RETURN_OK;
5367}
5368
5369// outputs the number of devices in the filter list
5370INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5371{
developere6aafda2022-09-13 14:59:28 +08005372 char cmd[MAX_BUF_SIZE]={0};
5373 char buf[MAX_CMD_SIZE]={0};
5374
5375 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5376 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005377 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005378
5379 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5380 _syscmd(cmd, buf, sizeof(buf));
5381
5382 *output_uint = atoi(buf);
5383
5384 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5385 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005386}
5387
5388INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5389{
5390 char cmd[128]={'\0'};
5391 char buf[128]={'\0'};
5392
5393 if(strcmp(action,"DENY")==0)
5394 {
5395 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5396 system(buf);
5397 return RETURN_OK;
5398 }
5399
5400 if(strcmp(action,"ALLOW")==0)
5401 {
5402 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5403 system(buf);
5404 return RETURN_OK;
5405 }
5406
5407 return RETURN_ERR;
5408
5409}
5410
5411// enable kick for devices on acl black list
5412INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5413{
5414 char aclArray[512] = {0}, *acl = NULL;
5415 char assocArray[512] = {0}, *asso = NULL;
5416
developere6aafda2022-09-13 14:59:28 +08005417 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005418 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5419
5420 // if there are no devices connected there is nothing to do
5421 if (strlen(assocArray) < 17)
5422 return RETURN_OK;
5423
5424 if (enable == TRUE)
5425 {
5426 //kick off the MAC which is in ACL array (deny list)
5427 acl = strtok(aclArray, "\r\n");
5428 while (acl != NULL) {
5429 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5430 wifi_kickApAssociatedDevice(apIndex, acl);
5431
5432 acl = strtok(NULL, "\r\n");
5433 }
developere6aafda2022-09-13 14:59:28 +08005434 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005435 }
5436 else
5437 {
developere6aafda2022-09-13 14:59:28 +08005438 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005439 }
5440
5441#if 0
5442 //TODO: need to revisit below implementation
5443 char aclArray[512]={0}, *acl=NULL;
5444 char assocArray[512]={0}, *asso=NULL;
5445 char buf[256]={'\0'};
5446 char action[10]={'\0'};
5447 FILE *fr=NULL;
5448 char interface[10]={'\0'};
5449 char config_file[MAX_BUF_SIZE] = {0};
5450
5451 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5452 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5453 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5454 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5455
5456 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5457 system(buf);
5458 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5459 system(buf);
5460 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5461 system(buf);
5462 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5463 system(buf);
5464 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5465 system(buf);
5466
5467 if ( enable == TRUE )
5468 {
5469 int device_count=0;
5470 strcpy(action,"DENY");
5471 //kick off the MAC which is in ACL array (deny list)
5472 acl = strtok (aclArray,",");
5473 while (acl != NULL) {
5474 if(strlen(acl)>=17)
5475 {
5476 apply_rules(apIndex, acl,action,interface);
5477 device_count++;
5478 //Register mac to be blocked ,in syscfg.db persistent storage
5479 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5480 system(buf);
5481 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5482 system(buf);
5483 system("syscfg commit");
5484
5485 wifi_kickApAssociatedDevice(apIndex, acl);
5486 }
5487 acl = strtok (NULL, ",");
5488 }
5489 }
5490 else
5491 {
5492 int device_count=0;
5493 char cmdmac[20]={'\0'};
5494 strcpy(action,"ALLOW");
5495 //kick off the MAC which is not in ACL array (allow list)
5496 acl = strtok (aclArray,",");
5497 while (acl != NULL) {
5498 if(strlen(acl)>=17)
5499 {
5500 apply_rules(apIndex, acl,action,interface);
5501 device_count++;
5502 //Register mac to be Allowed ,in syscfg.db persistent storage
5503 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5504 system(buf);
5505 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5506 system(buf);
5507 sprintf(cmdmac,"%s",acl);
5508 }
5509 acl = strtok (NULL, ",");
5510 }
5511 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5512 system(buf);
5513
5514 //Disconnect the mac which is not in ACL
5515 asso = strtok (assocArray,",");
5516 while (asso != NULL) {
5517 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5518 wifi_kickApAssociatedDevice(apIndex, asso);
5519 asso = strtok (NULL, ",");
5520 }
5521 }
5522#endif
5523 return RETURN_OK;
5524}
5525
5526INT wifi_setPreferPrivateConnection(BOOL enable)
5527{
5528 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5529 char buf[1024] = {0};
5530
5531 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5532 if(enable == TRUE)
5533 {
5534 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5535 sprintf(buf,"ifconfig %s down" ,interface_name);
5536 system(buf);
5537 memset(buf,0,sizeof(buf));
5538 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5539 sprintf(buf,"ifconfig %s down" ,interface_name);
5540 system(buf);
5541 }
5542 else
5543 {
5544 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5545 if(strcmp(ssid_cur_value,"1") == 0)
5546 wifi_RestartPrivateWifi_5G();
5547 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5548 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5549 if(strcmp(ssid_cur_value,"1") == 0)
5550 wifi_RestartHostapd_2G();
5551 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5552 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5553 if(strcmp(ssid_cur_value,"1") == 0)
5554 wifi_RestartHostapd_5G();
5555 }
5556 return RETURN_OK;
5557}
5558
5559// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5560INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5561{
5562 int items = 1;
5563 struct params list[2];
5564 char buf[MAX_BUF_SIZE] = {0};
5565 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005566 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005567
5568 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005569
developer10adcc12022-09-13 14:39:17 +08005570 if (filterMode == 0) {
5571 sprintf(buf, "%d", 0);
5572 list[0].value = buf;
5573
5574 char cmd[128], rtn[128];
5575 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5576 _syscmd(cmd, rtn, sizeof(rtn));
5577 memset(cmd,0,sizeof(cmd));
5578 // Delete deny_mac_file in hostapd configuration
5579 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5580 _syscmd(cmd, rtn, sizeof(rtn));
5581 }
5582 else if (filterMode == 1) {
5583 sprintf(buf, "%d", filterMode);
5584 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005585 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5586 list[1].name = "accept_mac_file";
5587 list[1].value = acl_file;
5588 items = 2;
developer10adcc12022-09-13 14:39:17 +08005589 } else if (filterMode == 2) {
5590 //TODO: deny_mac_file
5591 sprintf(buf, "%d", 0);
5592 list[0].value = buf;
5593 list[1].name = "deny_mac_file";
5594 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5595 list[1].value = deny_file;
5596 items = 2;
5597 } else {
5598 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005599 }
developer10adcc12022-09-13 14:39:17 +08005600
developer06a01d92022-09-07 16:32:39 +08005601 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5602 wifi_hostapdWrite(config_file, list, items);
5603
5604 return RETURN_OK;
5605
5606#if 0
5607 if(apIndex==0 || apIndex==1)
5608 {
5609 //set the filtermode
5610 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5611 system(buf);
5612 system("syscfg commit");
5613
5614 if(filterMode==0)
5615 {
5616 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5617 system(buf);
5618 return RETURN_OK;
5619 }
5620 }
5621 return RETURN_OK;
5622#endif
5623}
5624
5625// 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.
5626INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5627{
5628 return RETURN_ERR;
5629}
5630
5631// gets the vlan ID for this ap from an internal enviornment variable
5632INT wifi_getApVlanID(INT apIndex, INT *output_int)
5633{
5634 if(apIndex=0)
5635 {
5636 *output_int=100;
5637 return RETURN_OK;
5638 }
5639
5640 return RETURN_ERR;
5641}
5642
5643// sets the vlan ID for this ap to an internal enviornment variable
5644INT wifi_setApVlanID(INT apIndex, INT vlanId)
5645{
5646 //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)
5647 return RETURN_ERR;
5648}
5649
5650// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5651INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5652{
5653 snprintf(bridgeName, 32, "brlan0");
5654 snprintf(IP, 32, "10.0.0.1");
5655 snprintf(subnet, 32, "255.255.255.0");
5656
5657 return RETURN_OK;
5658}
5659
5660//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5661INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5662{
5663 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5664 return RETURN_ERR;
5665}
5666
5667// reset the vlan configuration for this ap
5668INT wifi_resetApVlanCfg(INT apIndex)
5669{
developerf5fef612022-09-20 19:38:26 +08005670 char original_config_file[64] = {0};
5671 char current_config_file[64] = {0};
5672 char buf[64] = {0};
5673 char cmd[64] = {0};
5674 char vlan_file[64] = {0};
5675 char vlan_tagged_interface[16] = {0};
5676 char vlan_bridge[16] = {0};
5677 char vlan_naming[16] = {0};
5678 struct params list[4] = {0};
5679 wifi_band band;
5680
5681 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5682
5683 band = wifi_index_to_band(apIndex);
5684 if (band == band_2_4)
5685 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5686 else if (band = band_5)
5687 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5688 else if (band = band_6)
5689 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5690
5691 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5692
5693 if (strlen(vlan_file) == 0)
5694 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005695
developerf5fef612022-09-20 19:38:26 +08005696 // The file should exist or this vap would not work.
5697 if (access(vlan_file, F_OK) != 0) {
5698 sprintf(cmd, "touch %s", vlan_file);
5699 _syscmd(cmd, buf, sizeof(buf));
5700 }
5701 list[0].name = "vlan_file";
5702 list[0].value = vlan_file;
5703
5704 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5705 list[1].name = "vlan_tagged_interface";
5706 list[1].value = vlan_tagged_interface;
5707
5708 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5709 list[2].name = "vlan_bridge";
5710 list[2].value = vlan_bridge;
5711
5712 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5713 list[3].name = "vlan_naming";
5714 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005715
developerf5fef612022-09-20 19:38:26 +08005716 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5717 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005718 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005719 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005720
developerf5fef612022-09-20 19:38:26 +08005721 // restart this ap
5722 wifi_setApEnable(apIndex, FALSE);
5723 wifi_setApEnable(apIndex, TRUE);
5724
5725 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5726
5727 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005728}
5729
5730// 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.
5731INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5732{
5733 return RETURN_ERR;
5734}
5735
5736// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5737INT wifi_startHostApd()
5738{
5739 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5740 system("systemctl start hostapd.service");
5741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5742 return RETURN_OK;
5743 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5744}
5745
5746// stops hostapd
5747INT wifi_stopHostApd()
5748{
5749 char cmd[128] = {0};
5750 char buf[128] = {0};
5751
5752 sprintf(cmd,"systemctl stop hostapd");
5753 _syscmd(cmd, buf, sizeof(buf));
5754
5755 return RETURN_OK;
5756}
5757
5758// restart hostapd dummy function
5759INT wifi_restartHostApd()
5760{
5761 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5762 system("systemctl restart hostapd-global");
5763 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5764
5765 return RETURN_OK;
5766}
5767
5768static int align_hostapd_config(int index)
5769{
5770 ULONG lval;
5771 wifi_getRadioChannel(index%2, &lval);
5772 wifi_setRadioChannel(index%2, lval);
5773}
5774
5775// sets the AP enable status variable for the specified ap.
5776INT wifi_setApEnable(INT apIndex, BOOL enable)
5777{
5778 char config_file[MAX_BUF_SIZE] = {0};
5779 char cmd[MAX_CMD_SIZE] = {0};
5780 char buf[MAX_BUF_SIZE] = {0};
5781 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005782 int max_radio_num = 0;
5783 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005784
5785 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005786
5787 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005788 if (enable == status)
5789 return RETURN_OK;
5790
5791 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005792 int radioIndex = apIndex % max_radio_num;
5793 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005794 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5795 //Hostapd will bring up this interface
5796 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5797 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005798 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005799 _syscmd(cmd, buf, sizeof(buf));
5800 }
5801 else {
5802 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5803 _syscmd(cmd, buf, sizeof(buf));
5804 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5805 _syscmd(cmd, buf, sizeof(buf));
5806 }
5807 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5808 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5809 _syscmd(cmd, buf, sizeof(buf));
5810 //Wait for wifi up/down to apply
5811 return RETURN_OK;
5812}
5813
5814// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5815INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5816{
5817 char cmd[MAX_CMD_SIZE] = {'\0'};
5818 char buf[MAX_BUF_SIZE] = {'\0'};
5819
5820 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5821 return RETURN_ERR;
5822
5823 *output_bool = 0;
5824
5825 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5826 {
developer70490032022-09-13 15:45:20 +08005827 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005828 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5829 }
5830
5831 return RETURN_OK;
5832}
5833
5834// Outputs the AP "Enabled" "Disabled" status from driver
5835INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5836{
5837 char cmd[128] = {0};
5838 char buf[128] = {0};
5839 BOOL output_bool;
5840
5841 if ( NULL == output_string)
5842 return RETURN_ERR;
5843 wifi_getApEnable(apIndex,&output_bool);
5844
5845 if(output_bool == 1)
5846 snprintf(output_string, 32, "Up");
5847 else
5848 snprintf(output_string, 32, "Disable");
5849
5850 return RETURN_OK;
5851}
5852
5853//Indicates whether or not beacons include the SSID name.
5854// outputs a 1 if SSID on the AP is enabled, else outputs 0
5855INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5856{
5857 //get the running status
5858 char config_file[MAX_BUF_SIZE] = {0};
5859 char buf[16] = {0};
5860
5861 if (!output)
5862 return RETURN_ERR;
5863
5864 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5865 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005866 // default is enable
5867 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5868 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005869
5870 return RETURN_OK;
5871}
5872
5873// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5874INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5875{
5876 //store the config, apply instantly
5877 char config_file[MAX_BUF_SIZE] = {0};
5878 struct params list;
5879
5880 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5881 list.name = "ignore_broadcast_ssid";
5882 list.value = enable?"0":"1";
5883
5884 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5885 wifi_hostapdWrite(config_file, &list, 1);
5886 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5887 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005888 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005889 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5890
5891 return RETURN_OK;
5892}
5893
5894//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5895INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5896{
5897 //get the running status
5898 if(!output_uint)
5899 return RETURN_ERR;
5900 *output_uint=16;
5901 return RETURN_OK;
5902}
5903
5904INT wifi_setApRetryLimit(INT apIndex, UINT number)
5905{
5906 //apply instantly
5907 return RETURN_ERR;
5908}
5909
5910//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5911INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5912{
5913 if(!output)
5914 return RETURN_ERR;
5915 *output=TRUE;
5916 return RETURN_OK;
5917}
5918
5919//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5920INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5921{
5922 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005923 char cmd[128] = {0};
5924 char buf[128] = {0};
5925 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08005926 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08005927
developer0b246d12022-09-30 15:24:20 +08005928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005929
developer0b246d12022-09-30 15:24:20 +08005930 wifi_getMaxRadioNumber(&max_radio_num);
5931 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08005932 phyId = radio_index_to_phy(radioIndex);
5933 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08005934 _syscmd(cmd,buf, sizeof(buf));
5935
5936 if (strlen(buf) > 0)
5937 *output = true;
5938
5939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005940
developer06a01d92022-09-07 16:32:39 +08005941 return RETURN_OK;
5942}
5943
5944//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5945INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5946{
5947 //get the running status from driver
5948 if(!output)
5949 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005950
5951 char config_file[MAX_BUF_SIZE] = {0};
5952 char buf[16] = {0};
5953
5954 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5955 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005956 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08005957 *output = TRUE;
5958 else
5959 *output = FALSE;
5960
developer06a01d92022-09-07 16:32:39 +08005961 return RETURN_OK;
5962}
5963
5964// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5965INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5966{
5967 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005968 char config_file[MAX_BUF_SIZE] = {0};
5969 struct params list;
5970
5971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5972 list.name = "wmm_enabled";
5973 list.value = enable?"1":"0";
5974
5975 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5976 wifi_hostapdWrite(config_file, &list, 1);
5977 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5978 wifi_reloadAp(apIndex);
5979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5980
5981 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005982}
5983
5984//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.
5985INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5986{
5987 //get the running status from driver
5988 if(!output)
5989 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08005990
5991 char config_file[128] = {0};
5992 char buf[16] = {0};
5993
5994 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5995 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5996 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
5997 *output = TRUE;
5998 else
5999 *output = FALSE;
6000
developer06a01d92022-09-07 16:32:39 +08006001 return RETURN_OK;
6002}
6003
6004// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6005INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6006{
6007 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006008 char config_file[MAX_BUF_SIZE] = {0};
6009 struct params list;
6010
6011 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6012 list.name = "uapsd_advertisement_enabled";
6013 list.value = enable?"1":"0";
6014
6015 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6016 wifi_hostapdWrite(config_file, &list, 1);
6017 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6018 wifi_reloadAp(apIndex);
6019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6020
6021 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006022}
6023
developer6daeb3f2022-09-30 13:36:39 +08006024// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006025INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6026{
developer6daeb3f2022-09-30 13:36:39 +08006027 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6028 char cmd[128] = {0};
6029 char buf[128] = {0};
6030 char ack_filepath[128] = {0};
6031 uint16_t bitmap = 0;
6032 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6033 FILE *f = NULL;
6034
6035 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6036
6037 // Get current setting
6038 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6039 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6040 _syscmd(cmd, buf, sizeof(buf));
6041 if (strlen(buf) > 0)
6042 bitmap = strtoul(buf, NULL, 10);
6043
6044 bitmap = strtoul(buf, NULL, 10);
6045
6046 if (ackPolicy == TRUE) { // True, unset this class
6047 bitmap &= ~class_map[class];
6048 } else { // False, set this class
6049 bitmap |= class_map[class];
6050 }
6051
6052 f = fopen(ack_filepath, "w");
6053 if (f == NULL) {
6054 fprintf(stderr, "%s: fopen failed\n", __func__);
6055 return RETURN_ERR;
6056 }
6057 fprintf(f, "%hu", bitmap);
6058 fclose(f);
6059
6060 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
6061 _syscmd(cmd, buf, sizeof(buf));
6062
6063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6064 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006065}
6066
6067//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.
6068INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6069{
6070 //get the running status from driver
6071 if(!output_uint)
6072 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006073
6074 char output[16]={'\0'};
6075 char config_file[MAX_BUF_SIZE] = {0};
6076
6077 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6078 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6079 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6080 else {
6081 int device_num = atoi(output);
6082 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6083 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6084 return RETURN_ERR;
6085 }
6086 else {
6087 *output_uint = device_num;
6088 }
6089 }
6090
developer06a01d92022-09-07 16:32:39 +08006091 return RETURN_OK;
6092}
6093
6094INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6095{
6096 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006097 char str[MAX_BUF_SIZE]={'\0'};
6098 char cmd[MAX_CMD_SIZE]={'\0'};
6099 struct params params;
6100 char config_file[MAX_BUF_SIZE] = {0};
6101
6102 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6103 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6104 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6105 return RETURN_ERR;
6106 }
6107 sprintf(str, "%d", number);
6108 params.name = "max_num_sta";
6109 params.value = str;
6110
6111 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6112 int ret = wifi_hostapdWrite(config_file, &params, 1);
6113 if (ret) {
6114 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6115 ,__func__, ret);
6116 }
6117
6118 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6119 if (ret) {
6120 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6121 ,__func__, ret);
6122 }
6123 wifi_reloadAp(apIndex);
6124 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6125
6126 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006127}
6128
6129//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.
6130INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6131{
6132 //get the current threshold
6133 if(!output_uint)
6134 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006135 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6136 if (*output_uint == 0)
6137 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006138 return RETURN_OK;
6139}
6140
6141INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6142{
6143 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006144 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6145 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006146 return RETURN_ERR;
6147}
6148
6149//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.
6150INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6151{
6152 if(!output_uint)
6153 return RETURN_ERR;
6154 *output_uint = 3;
6155 return RETURN_OK;
6156}
6157
6158//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6159INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6160{
6161 if(!output_uint)
6162 return RETURN_ERR;
6163 *output_uint = 3;
6164 return RETURN_OK;
6165}
6166
6167//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.
6168INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6169{
6170 if(!output_in_seconds)
6171 return RETURN_ERR;
6172 *output_in_seconds = 0;
6173 return RETURN_OK;
6174}
6175
6176//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
6177INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6178{
6179 if(!output || apIndex>=MAX_APS)
6180 return RETURN_ERR;
6181 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006182 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006183 return RETURN_OK;
6184}
6185
6186//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6187INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6188{
developer587c1b62022-09-27 15:58:59 +08006189 char config_file[128] = {0};
6190 char wpa[16] = {0};
6191 char key_mgmt[64] = {0};
6192 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006193 if (!output)
6194 return RETURN_ERR;
6195
6196 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006197 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006198
developer587c1b62022-09-27 15:58:59 +08006199 strcpy(output, "None");//Copying "None" to output string for default case
6200 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006201 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006202 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006203 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006204 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006205 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006206 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006207 snprintf(output, 32, "WPA-WPA2-Personal");
6208
6209 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006210 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006211 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006212 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006213 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006214 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006215 snprintf(output, 32, "WPA-WPA2-Enterprise");
6216 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006217 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006218 snprintf(output, 32, "WPA3-Personal");
6219 else
developer4a359672022-10-13 15:30:46 +08006220 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006221 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6222 snprintf(output, 32, "WPA3-Enterprise");
6223 }
developer06a01d92022-09-07 16:32:39 +08006224
6225 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6226 return RETURN_OK;
6227#if 0
6228 //TODO: need to revisit below implementation
6229 char securityType[32], authMode[32];
6230 int enterpriseMode=0;
6231
6232 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6233 if(!output)
6234 return RETURN_ERR;
6235
6236 wifi_getApBeaconType(apIndex, securityType);
6237 strcpy(output,"None");//By default, copying "None" to output string
6238 if (strncmp(securityType,"None", strlen("None")) == 0)
6239 return RETURN_OK;
6240
6241 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6242 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6243
6244 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6245 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6246 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6247 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6248 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6249 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6250 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6251
6252 return RETURN_OK;
6253#endif
6254}
6255
6256INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6257{
6258 char securityType[32];
6259 char authMode[32];
6260
6261 //store settings and wait for wifi up to apply
6262 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6263 if(!encMode)
6264 return RETURN_ERR;
6265
developer06a01d92022-09-07 16:32:39 +08006266 if (strcmp(encMode, "None")==0)
6267 {
6268 strcpy(securityType,"None");
6269 strcpy(authMode,"None");
6270 }
6271 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6272 {
6273 strcpy(securityType,"WPAand11i");
6274 strcpy(authMode,"PSKAuthentication");
6275 }
6276 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6277 {
6278 strcpy(securityType,"WPAand11i");
6279 strcpy(authMode,"EAPAuthentication");
6280 }
6281 else if (strcmp(encMode, "WPA-Personal")==0)
6282 {
6283 strcpy(securityType,"WPA");
6284 strcpy(authMode,"PSKAuthentication");
6285 }
6286 else if (strcmp(encMode, "WPA-Enterprise")==0)
6287 {
6288 strcpy(securityType,"WPA");
6289 strcpy(authMode,"EAPAuthentication");
6290 }
6291 else if (strcmp(encMode, "WPA2-Personal")==0)
6292 {
6293 strcpy(securityType,"11i");
6294 strcpy(authMode,"PSKAuthentication");
6295 }
6296 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6297 {
6298 strcpy(securityType,"11i");
6299 strcpy(authMode,"EAPAuthentication");
6300 }
developer587c1b62022-09-27 15:58:59 +08006301 else if (strcmp(encMode, "WPA3-Personal") == 0)
6302 {
6303 strcpy(securityType,"11i");
6304 strcpy(authMode,"SAEAuthentication");
6305 }
developer4a359672022-10-13 15:30:46 +08006306 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006307 {
6308 strcpy(securityType, "11i");
6309 strcpy(authMode, "PSK-SAEAuthentication");
6310 }
developer587c1b62022-09-27 15:58:59 +08006311 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6312 {
6313 strcpy(securityType,"11i");
6314 strcpy(authMode,"EAP_192-bit_Authentication");
6315 }
developer06a01d92022-09-07 16:32:39 +08006316 else
6317 {
6318 strcpy(securityType,"None");
6319 strcpy(authMode,"None");
6320 }
6321 wifi_setApBeaconType(apIndex, securityType);
6322 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6324
6325 return RETURN_OK;
6326}
6327
6328
6329//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6330// output_string must be pre-allocated as 64 character string by caller
6331// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6332INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6333{
6334 char buf[16];
6335 char config_file[MAX_BUF_SIZE] = {0};
6336
6337 if(output_string==NULL)
6338 return RETURN_ERR;
6339
6340 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6341 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6342
6343 if(strcmp(buf,"0")==0)
6344 {
6345 printf("wpa_mode is %s ......... \n",buf);
6346 return RETURN_ERR;
6347 }
6348
6349 wifi_dbg_printf("\nFunc=%s\n",__func__);
6350 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6351 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6352 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6353
6354 return RETURN_OK;
6355}
6356
6357// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6358// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6359INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6360{
6361 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6362 struct params params={'\0'};
6363 int ret;
6364 char config_file[MAX_BUF_SIZE] = {0};
6365
6366 if(NULL == preSharedKey)
6367 return RETURN_ERR;
6368
6369 params.name = "wpa_passphrase";
6370
6371 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6372 {
6373 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6374 return RETURN_ERR;
6375 }
6376 params.value = preSharedKey;
6377 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6378 ret = wifi_hostapdWrite(config_file, &params, 1);
6379 if(!ret)
6380 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6381 return ret;
6382 //TODO: call hostapd_cli for dynamic_config_control
6383}
6384
6385//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6386// outputs the passphrase, maximum 63 characters
6387INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6388{
6389 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6390
6391 wifi_dbg_printf("\nFunc=%s\n",__func__);
6392 if (NULL == output_string)
6393 return RETURN_ERR;
6394
6395 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6396 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6397 if(strcmp(buf,"0")==0)
6398 {
6399 printf("wpa_mode is %s ......... \n",buf);
6400 return RETURN_ERR;
6401 }
6402
6403 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6404 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6405
6406 return RETURN_OK;
6407}
6408
6409// sets the passphrase enviornment variable, max 63 characters
6410INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6411{
6412 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6413 struct params params={'\0'};
6414 char config_file[MAX_BUF_SIZE] = {0};
6415 int ret;
6416
6417 if(NULL == passPhrase)
6418 return RETURN_ERR;
6419
6420 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6421 {
6422 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6423 return RETURN_ERR;
6424 }
6425 params.name = "wpa_passphrase";
6426 params.value = passPhrase;
6427 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6428 ret=wifi_hostapdWrite(config_file,&params,1);
6429 if(!ret)
6430 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6431
6432 return ret;
6433}
6434
6435//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.
6436INT wifi_setApSecurityReset(INT apIndex)
6437{
developer8d583982022-09-20 11:28:22 +08006438 char original_config_file[64] = {0};
6439 char current_config_file[64] = {0};
6440 char buf[64] = {0};
6441 char cmd[64] = {0};
6442 char wpa[4] = {0};
6443 char wpa_psk[64] = {0};
6444 char wpa_passphrase[64] = {0};
6445 char wpa_psk_file[128] = {0};
6446 char wpa_key_mgmt[64] = {0};
6447 char wpa_pairwise[32] = {0};
6448 wifi_band band;
6449 struct params list[6];
6450
6451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6452
6453 band = wifi_index_to_band(apIndex);
6454 if (band == band_2_4)
6455 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6456 else if (band = band_5)
6457 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6458 else if (band = band_6)
6459 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6460 else
6461 return RETURN_ERR;
6462
6463 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6464 list[0].name = "wpa";
6465 list[0].value = wpa;
6466
6467 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6468 list[1].name = "wpa_psk";
6469 list[1].value = wpa_psk;
6470
6471 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6472 list[2].name = "wpa_passphrase";
6473 list[2].value = wpa_passphrase;
6474
6475 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6476
6477 if (strlen(wpa_psk_file) == 0)
6478 strcpy(wpa_psk_file, PSK_FILE);
6479
6480 if (access(wpa_psk_file, F_OK) != 0) {
6481 sprintf(cmd, "touch %s", wpa_psk_file);
6482 _syscmd(cmd, buf, sizeof(buf));
6483 }
6484 list[3].name = "wpa_psk_file";
6485 list[3].value = wpa_psk_file;
6486
6487 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6488 list[4].name = "wpa_key_mgmt";
6489 list[4].value = wpa_key_mgmt;
6490
6491 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6492 list[5].name = "wpa_pairwise";
6493 list[5].value = wpa_pairwise;
6494
6495 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6496 wifi_hostapdWrite(current_config_file, list, 6);
6497
6498 wifi_setApEnable(apIndex, FALSE);
6499 wifi_setApEnable(apIndex, TRUE);
6500
6501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6502 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006503}
6504
6505//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).
6506INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6507{
developer8f2ddd52022-09-13 15:39:24 +08006508 char config_file[64] = {0};
6509 char buf[64] = {0};
6510 char cmd[256] = {0};
6511
6512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6513
developer06a01d92022-09-07 16:32:39 +08006514 if(!IP_output || !Port_output || !RadiusSecret_output)
6515 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006516
developer8f2ddd52022-09-13 15:39:24 +08006517 // Read the first matched config
6518 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6519 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6520 _syscmd(cmd, buf, sizeof(buf));
6521 strncpy(IP_output, buf, 64);
6522
6523 memset(buf, 0, sizeof(buf));
6524 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6525 _syscmd(cmd, buf, sizeof(buf));
6526 *Port_output = atoi(buf);
6527
6528 memset(buf, 0, sizeof(buf));
6529 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6530 _syscmd(cmd, buf, sizeof(buf));
6531 strncpy(RadiusSecret_output, buf, 64);
6532
6533 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006534 return RETURN_OK;
6535}
6536
6537INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6538{
developer8f2ddd52022-09-13 15:39:24 +08006539 char config_file[64] = {0};
6540 char port_str[8] = {0};
6541 char cmd[256] = {0};
6542 char buf[128] = {0};
6543
6544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6545
6546 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6547
6548 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6549 _syscmd(cmd, buf, sizeof(buf));
6550 memset(cmd, 0, sizeof(cmd));
6551
6552 snprintf(port_str, sizeof(port_str), "%d", port);
6553 if (strlen(buf) == 0)
6554 // Append
6555 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6556 "auth_server_addr=%s\\n"
6557 "auth_server_port=%s\\n"
6558 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6559 else {
6560 // Delete the three lines setting after the "# radius 1" comment
6561 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6562 _syscmd(cmd, buf, sizeof(buf));
6563 memset(cmd, 0, sizeof(cmd));
6564 // Use "# radius 1" comment to find the location to insert the radius setting
6565 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6566 "# radius 1\\n"
6567 "auth_server_addr=%s\\n"
6568 "auth_server_port=%s\\n"
6569 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6570 }
6571 if(_syscmd(cmd, buf, sizeof(buf))) {
6572 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6573 return RETURN_ERR;
6574 }
6575
6576 wifi_reloadAp(apIndex);
6577 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6578 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006579}
6580
6581INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6582{
developer8f2ddd52022-09-13 15:39:24 +08006583 char config_file[64] = {0};
6584 char buf[64] = {0};
6585 char cmd[256] = {0};
6586
6587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6588
developer06a01d92022-09-07 16:32:39 +08006589 if(!IP_output || !Port_output || !RadiusSecret_output)
6590 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006591
6592 // Read the second matched config
6593 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6594 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6595 _syscmd(cmd, buf, sizeof(buf));
6596 strncpy(IP_output, buf, 64);
6597
6598 memset(buf, 0, sizeof(buf));
6599 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6600 _syscmd(cmd, buf, sizeof(buf));
6601 *Port_output = atoi(buf);
6602
6603 memset(buf, 0, sizeof(buf));
6604 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6605 _syscmd(cmd, buf, sizeof(buf));
6606 strncpy(RadiusSecret_output, buf, 64);
6607
6608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006609 return RETURN_OK;
6610}
6611
6612INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6613{
developer8f2ddd52022-09-13 15:39:24 +08006614 char config_file[64] = {0};
6615 char port_str[8] = {0};
6616 char cmd[256] = {0};
6617 char buf[128] = {0};
6618
6619 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6620
6621 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6622
6623 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6624 _syscmd(cmd, buf, sizeof(buf));
6625 memset(cmd, 0, sizeof(cmd));
6626
6627 snprintf(port_str, sizeof(port_str), "%d", port);
6628 if (strlen(buf) == 0)
6629 // Append
6630 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6631 "auth_server_addr=%s\\n"
6632 "auth_server_port=%s\\n"
6633 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6634 else {
6635 // Delete the three lines setting after the "# radius 2" comment
6636 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6637 _syscmd(cmd, buf, sizeof(buf));
6638 memset(cmd, 0, sizeof(cmd));
6639 // Use "# radius 2" comment to find the location to insert the radius setting
6640 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6641 "# radius 2\\n"
6642 "auth_server_addr=%s\\n"
6643 "auth_server_port=%s\\n"
6644 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6645 }
6646 if(_syscmd(cmd, buf, sizeof(buf))) {
6647 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6648 return RETURN_ERR;
6649 }
6650
6651 wifi_reloadAp(apIndex);
6652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6653 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006654}
6655
6656//RadiusSettings
6657INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6658{
6659 if(!output)
6660 return RETURN_ERR;
6661
6662 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6663 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6664 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6665 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6666 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6667 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.
6668 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6669 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6670 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6671 //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.
6672
6673 return RETURN_OK;
6674}
6675
6676INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6677{
6678 //store the paramters, and apply instantly
6679 return RETURN_ERR;
6680}
6681
6682//Device.WiFi.AccessPoint.{i}.WPS.Enable
6683//Enables or disables WPS functionality for this access point.
6684// outputs the WPS enable state of this ap in output_bool
6685INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6686{
6687 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006688 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006689 return RETURN_ERR;
6690 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6691 _syscmd(cmd, buf, sizeof(buf));
6692 if(strstr(buf, "configured"))
6693 *output_bool=TRUE;
6694 else
6695 *output_bool=FALSE;
6696
6697 return RETURN_OK;
6698}
6699
6700//Device.WiFi.AccessPoint.{i}.WPS.Enable
6701// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6702INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6703{
6704 char config_file[MAX_BUF_SIZE] = {0};
6705 struct params params;
6706
developer06a01d92022-09-07 16:32:39 +08006707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6708 //store the paramters, and wait for wifi up to apply
6709 params.name = "wps_state";
6710 params.value = enable ? "2":"0";
6711
6712 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6713 wifi_hostapdWrite(config_file, &params, 1);
6714 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6715 wifi_reloadAp(apIndex);
6716
6717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6718 return RETURN_OK;
6719}
6720
6721//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
6722INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6723{
6724 if(!output)
6725 return RETURN_ERR;
6726 snprintf(output, 128, "PushButton,PIN");
6727 return RETURN_OK;
6728}
6729
6730//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6731//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.
6732// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6733INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6734{
6735 if(!output)
6736 return RETURN_ERR;
6737 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6738
6739 return RETURN_OK;
6740}
6741
6742//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6743// 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
6744INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6745{
6746 //apply instantly. No setting need to be stored.
6747 char methods[MAX_BUF_SIZE], *token, *next_token;
6748 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6749 struct params params;
6750
developer5b398df2022-11-17 20:39:48 +08006751 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006752 return RETURN_ERR;
6753 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6754 //store the paramters, and wait for wifi up to apply
6755
6756 snprintf(methods, sizeof(methods), "%s", methodString);
6757 for(token=methods; *token; token=next_token)
6758 {
6759 strtok_r(token, ",", &next_token);
6760 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6761 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6762 else if(*token=='E')
6763 {
6764 if(!strcmp(methods, "Ethernet"))
6765 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6766 else if(!strcmp(methods, "ExternalNFCToken"))
6767 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6768 else
6769 printf("%s: Unknown WpsConfigMethod\n", __func__);
6770 }
6771 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6772 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6773 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6774 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6775 else if(*token=='P' )
6776 {
6777 if(!strcmp(token, "PushButton"))
6778 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6779 else if(!strcmp(token, "PIN"))
6780 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6781 else
6782 printf("%s: Unknown WpsConfigMethod\n", __func__);
6783 }
6784 else
6785 printf("%s: Unknown WpsConfigMethod\n", __func__);
6786 }
6787 params.name = "config_methods";
6788 params.value = config_methods;
6789 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6790 wifi_hostapdWrite(config_file, &params, 1);
6791 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6793
6794 return RETURN_OK;
6795}
6796
6797// outputs the pin value, ulong_pin must be allocated by the caller
6798INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6799{
6800 char buf[MAX_BUF_SIZE] = {0};
6801 char cmd[MAX_CMD_SIZE] = {0};
6802
developer5b398df2022-11-17 20:39:48 +08006803 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08006804 return RETURN_ERR;
6805 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6806 _syscmd(cmd, buf, sizeof(buf));
6807 if(strlen(buf) > 0)
6808 *output_ulong=strtoul(buf, NULL, 10);
6809
6810 return RETURN_OK;
6811}
6812
6813// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6814INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6815{
6816 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6817 char ap_pin[16] = {0};
6818 char buf[MAX_BUF_SIZE] = {0};
6819 char config_file[MAX_BUF_SIZE] = {0};
6820 ULONG prev_pin = 0;
6821 struct params params;
6822
developer06a01d92022-09-07 16:32:39 +08006823 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6824 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6825 params.name = "ap_pin";
6826 params.value = ap_pin;
6827 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6828 wifi_hostapdWrite(config_file, &params, 1);
6829 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6831
6832 return RETURN_OK;
6833}
6834
6835// Output string is either Not configured or Configured, max 32 characters
6836INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6837{
6838 char cmd[MAX_CMD_SIZE];
6839 char buf[MAX_BUF_SIZE]={0};
6840
developer5b398df2022-11-17 20:39:48 +08006841 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08006842 return RETURN_ERR;
6843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6844 snprintf(output_string, 32, "Not configured");
6845 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6846 _syscmd(cmd, buf, sizeof(buf));
6847
developer348e3d92022-09-13 14:48:41 +08006848 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006849 snprintf(output_string, 32, "Configured");
6850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6851
6852 return RETURN_OK;
6853}
6854
6855// sets the WPS pin for this AP
6856INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6857{
6858 char cmd[MAX_CMD_SIZE];
6859 char buf[MAX_BUF_SIZE]={0};
6860 BOOL enable;
6861
developer06a01d92022-09-07 16:32:39 +08006862 wifi_getApEnable(apIndex, &enable);
6863 if (!enable)
6864 return RETURN_ERR;
6865 wifi_getApWpsEnable(apIndex, &enable);
6866 if (!enable)
6867 return RETURN_ERR;
6868
6869 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6870 _syscmd(cmd, buf, sizeof(buf));
6871 if((strstr(buf, "OK"))!=NULL)
6872 return RETURN_OK;
6873
6874 return RETURN_ERR;
6875}
6876
6877// This function is called when the WPS push button has been pressed for this AP
6878INT wifi_setApWpsButtonPush(INT apIndex)
6879{
6880 char cmd[MAX_CMD_SIZE];
6881 char buf[MAX_BUF_SIZE]={0};
6882 BOOL enable=FALSE;
6883
developer06a01d92022-09-07 16:32:39 +08006884 wifi_getApEnable(apIndex, &enable);
6885 if (!enable)
6886 return RETURN_ERR;
6887
6888 wifi_getApWpsEnable(apIndex, &enable);
6889 if (!enable)
6890 return RETURN_ERR;
6891
6892 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6893 _syscmd(cmd, buf, sizeof(buf));
6894
6895 if((strstr(buf, "OK"))!=NULL)
6896 return RETURN_OK;
6897 return RETURN_ERR;
6898}
6899
6900// cancels WPS mode for this AP
6901INT wifi_cancelApWPS(INT apIndex)
6902{
6903 char cmd[MAX_CMD_SIZE];
6904 char buf[MAX_BUF_SIZE]={0};
6905
developer06a01d92022-09-07 16:32:39 +08006906 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6907 _syscmd(cmd,buf, sizeof(buf));
6908
6909 if((strstr(buf, "OK"))!=NULL)
6910 return RETURN_OK;
6911 return RETURN_ERR;
6912}
6913
6914//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6915//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6916INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6917{
6918 FILE *f;
6919 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6920 char cmd[256], buf[2048];
6921 char *param , *value, *line=NULL;
6922 size_t len = 0;
6923 ssize_t nread;
6924 wifi_associated_dev_t *dev=NULL;
6925
6926 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6927 *associated_dev_array = NULL;
6928 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6929 _syscmd(cmd,buf,sizeof(buf));
6930 *output_array_size = atoi(buf);
6931
6932 if (*output_array_size <= 0)
6933 return RETURN_OK;
6934
6935 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6936 *associated_dev_array = dev;
6937 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6938 _syscmd(cmd,buf,sizeof(buf));
6939 f = fopen("/tmp/connected_devices.txt", "r");
6940 if (f==NULL)
6941 {
6942 *output_array_size=0;
6943 return RETURN_ERR;
6944 }
6945 while ((nread = getline(&line, &len, f)) != -1)
6946 {
6947 param = strtok(line,"=");
6948 value = strtok(NULL,"=");
6949
6950 if( strcmp("flags",param) == 0 )
6951 {
6952 value[strlen(value)-1]='\0';
6953 if(strstr (value,"AUTHORIZED") != NULL )
6954 {
6955 dev[auth_temp].cli_AuthenticationState = 1;
6956 dev[auth_temp].cli_Active = 1;
6957 auth_temp++;
6958 read_flag=1;
6959 }
6960 }
6961 if(read_flag==1)
6962 {
6963 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6964 {
6965 value[strlen(value)-1]='\0';
6966 sscanf(value, "%x:%x:%x:%x:%x:%x",
6967 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6968 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6969 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6970 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6971 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6972 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6973 mac_temp++;
6974 read_flag=0;
6975 }
6976 }
6977 }
6978 *output_array_size = auth_temp;
6979 auth_temp=0;
6980 mac_temp=0;
6981 free(line);
6982 fclose(f);
6983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6984 return RETURN_OK;
6985}
6986
6987#define MACADDRESS_SIZE 6
6988
6989INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6990{
6991 FILE *fp = NULL;
6992 char str[MAX_BUF_SIZE] = {0};
6993 int wificlientindex = 0 ;
6994 int count = 0;
6995 int signalstrength = 0;
6996 int arr[MACADDRESS_SIZE] = {0};
6997 unsigned char mac[MACADDRESS_SIZE] = {0};
6998 UINT wifi_count = 0;
6999 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7000 char pipeCmd[MAX_CMD_SIZE] = {0};
7001
7002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7003 *output_array_size = 0;
7004 *associated_dev_array = NULL;
7005
7006 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7007 fp = popen(pipeCmd, "r");
7008 if (fp == NULL)
7009 {
7010 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7011 return RETURN_ERR;
7012 }
7013
7014 /* Read the output a line at a time - output it. */
7015 fgets(str, sizeof(str)-1, fp);
7016 wifi_count = (unsigned int) atoi ( str );
7017 *output_array_size = wifi_count;
7018 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7019 pclose(fp);
7020
7021 if(wifi_count == 0)
7022 {
7023 return RETURN_OK;
7024 }
7025 else
7026 {
7027 wifi_associated_dev3_t* temp = NULL;
7028 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7029 if(temp == NULL)
7030 {
7031 printf("Error Statement. Insufficient memory \n");
7032 return RETURN_ERR;
7033 }
7034
7035 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7036 system(pipeCmd);
7037 memset(pipeCmd,0,sizeof(pipeCmd));
7038 if(apIndex == 0)
7039 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7040 else if(apIndex == 1)
7041 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7042 system(pipeCmd);
7043
7044 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7045 if(fp == NULL)
7046 {
7047 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7048 return RETURN_ERR;
7049 }
7050 fclose(fp);
7051
7052 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7053 fp = popen(pipeCmd, "r");
7054 if(fp)
7055 {
7056 for(count =0 ; count < wifi_count; count++)
7057 {
7058 fgets(str, MAX_BUF_SIZE, fp);
7059 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7060 {
7061 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7062 {
7063 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7064
7065 }
7066 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7067 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]);
7068 }
7069 temp[count].cli_AuthenticationState = 1; //TODO
7070 temp[count].cli_Active = 1; //TODO
7071 }
7072 pclose(fp);
7073 }
7074
7075 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7076 fp = popen(pipeCmd, "r");
7077 if(fp)
7078 {
7079 pclose(fp);
7080 }
7081 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7082 if(fp)
7083 {
7084 for(count =0 ; count < wifi_count ;count++)
7085 {
7086 fgets(str, MAX_BUF_SIZE, fp);
7087 signalstrength = atoi(str);
7088 temp[count].cli_SignalStrength = signalstrength;
7089 temp[count].cli_RSSI = signalstrength;
7090 temp[count].cli_SNR = signalstrength + 95;
7091 }
7092 pclose(fp);
7093 }
7094
7095
7096 if((apIndex == 0) || (apIndex == 4))
7097 {
7098 for(count =0 ; count < wifi_count ;count++)
7099 {
7100 strcpy(temp[count].cli_OperatingStandard,"g");
7101 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7102 }
7103
7104 //BytesSent
7105 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7106 fp = popen(pipeCmd, "r");
7107 if(fp)
7108 {
7109 pclose(fp);
7110 }
7111 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7112 if(fp)
7113 {
7114 for (count = 0; count < wifi_count; count++)
7115 {
7116 fgets(str, MAX_BUF_SIZE, fp);
7117 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7118 }
7119 pclose(fp);
7120 }
7121
7122 //BytesReceived
7123 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7124 fp = popen(pipeCmd, "r");
7125 if (fp)
7126 {
7127 pclose(fp);
7128 }
7129 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7130 if (fp)
7131 {
7132 for (count = 0; count < wifi_count; count++)
7133 {
7134 fgets(str, MAX_BUF_SIZE, fp);
7135 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7136 }
7137 pclose(fp);
7138 }
7139
7140 //PacketsSent
7141 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7142 fp = popen(pipeCmd, "r");
7143 if (fp)
7144 {
7145 pclose(fp);
7146 }
7147
7148 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7149 if (fp)
7150 {
7151 for (count = 0; count < wifi_count; count++)
7152 {
7153 fgets(str, MAX_BUF_SIZE, fp);
7154 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7155 }
7156 pclose(fp);
7157 }
7158
7159 //PacketsReceived
7160 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7161 fp = popen(pipeCmd, "r");
7162 if (fp)
7163 {
7164 pclose(fp);
7165 }
7166 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7167 if (fp)
7168 {
7169 for (count = 0; count < wifi_count; count++)
7170 {
7171 fgets(str, MAX_BUF_SIZE, fp);
7172 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7173 }
7174 pclose(fp);
7175 }
7176
7177 //ErrorsSent
7178 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7179 fp = popen(pipeCmd, "r");
7180 if (fp)
7181 {
7182 pclose(fp);
7183 }
7184 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7185 if (fp)
7186 {
7187 for (count = 0; count < wifi_count; count++)
7188 {
7189 fgets(str, MAX_BUF_SIZE, fp);
7190 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7191 }
7192 pclose(fp);
7193 }
7194
7195 //ErrorsSent
7196 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7197 fp = popen(pipeCmd, "r");
7198 if (fp)
7199 {
7200 pclose(fp);
7201 }
7202 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7203 if (fp)
7204 {
7205 for (count = 0; count < wifi_count; count++)
7206 {
7207 fgets(str, MAX_BUF_SIZE, fp);
7208 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7209 }
7210 pclose(fp);
7211 }
7212
7213 //LastDataDownlinkRate
7214 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7215 fp = popen(pipeCmd, "r");
7216 if (fp)
7217 {
7218 pclose(fp);
7219 }
7220 fp = popen("cat /tmp/Ass_Bitrate_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_LastDataDownlinkRate = strtoul(str, NULL, 10);
7227 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7228 }
7229 pclose(fp);
7230 }
7231
7232 //LastDataUplinkRate
7233 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7234 fp = popen(pipeCmd, "r");
7235 if (fp)
7236 {
7237 pclose(fp);
7238 }
7239 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7240 if (fp)
7241 {
7242 for (count = 0; count < wifi_count; count++)
7243 {
7244 fgets(str, MAX_BUF_SIZE, fp);
7245 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7246 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7247 }
7248 pclose(fp);
7249 }
7250
7251 }
7252 else if ((apIndex == 1) || (apIndex == 5))
7253 {
7254 for (count = 0; count < wifi_count; count++)
7255 {
7256 strcpy(temp[count].cli_OperatingStandard, "a");
7257 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7258 temp[count].cli_BytesSent = 0;
7259 temp[count].cli_BytesReceived = 0;
7260 temp[count].cli_LastDataUplinkRate = 0;
7261 temp[count].cli_LastDataDownlinkRate = 0;
7262 temp[count].cli_PacketsSent = 0;
7263 temp[count].cli_PacketsReceived = 0;
7264 temp[count].cli_ErrorsSent = 0;
7265 }
7266 }
7267
7268 for (count = 0; count < wifi_count; count++)
7269 {
7270 temp[count].cli_Retransmissions = 0;
7271 temp[count].cli_DataFramesSentAck = 0;
7272 temp[count].cli_DataFramesSentNoAck = 0;
7273 temp[count].cli_MinRSSI = 0;
7274 temp[count].cli_MaxRSSI = 0;
7275 strncpy(temp[count].cli_InterferenceSources, "", 64);
7276 memset(temp[count].cli_IPAddress, 0, 64);
7277 temp[count].cli_RetransCount = 0;
7278 temp[count].cli_FailedRetransCount = 0;
7279 temp[count].cli_RetryCount = 0;
7280 temp[count].cli_MultipleRetryCount = 0;
7281 }
7282 *associated_dev_array = temp;
7283 }
7284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7285 return RETURN_OK;
7286}
7287
7288int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7289{
7290 FILE *fp = NULL;
7291 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7292 char cmd[MAX_CMD_SIZE];
7293 int count = 0;
7294
7295 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7296 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7297 fp = popen(cmd,"r");
7298 if(fp == NULL)
7299 {
7300 printf("Failed to run command in Function %s\n",__FUNCTION__);
7301 return 0;
7302 }
7303 if(fgets(path, sizeof(path)-1, fp) != NULL)
7304 {
7305 for(count=0;path[count]!='\n';count++)
7306 status[count]=path[count];
7307 status[count]='\0';
7308 }
7309 strcpy(wifi_status,status);
7310 pclose(fp);
7311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7312 return RETURN_OK;
7313}
7314
7315/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7316struct hostapd_sta_param {
7317 char key[50];
7318 char value[100];
7319}
7320
7321static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7322 int i = 0;
7323
7324 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7325 if (strncmp(params[i].key,key,50) == 0){
7326 return &params[i].value;
7327 }
7328 i++;
7329 }
7330 return NULL;
7331
7332} */
7333
7334static unsigned int count_occurences(const char *buf, const char *word)
7335{
7336 unsigned int n = 0;
7337 char *ptr = strstr(buf, word);
7338
7339 while (ptr++) {
7340 n++;
7341 ptr = strstr(ptr, word);
7342 }
7343
7344 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7345 return n;
7346}
7347
7348static const char *get_line_from_str_buf(const char *buf, char *line)
7349{
7350 int i;
7351 int n = strlen(buf);
7352
7353 for (i = 0; i < n; i++) {
7354 line[i] = buf[i];
7355 if (buf[i] == '\n') {
7356 line[i] = '\0';
7357 return &buf[i + 1];
7358 }
7359 }
7360
7361 return NULL;
7362}
7363
7364INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7365{
7366 unsigned int assoc_cnt = 0;
7367 char interface_name[50] = {0};
7368 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7369 char cmd[MAX_CMD_SIZE] = {'\0'};
7370 char line[256] = {'\0'};
7371 int i = 0;
7372 int ret = 0;
7373 const char *ptr = NULL;
7374 char *key = NULL;
7375 char *val = NULL;
7376 wifi_associated_dev3_t *temp = NULL;
7377 int rssi;
7378
7379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7380
7381 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7382 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7383 return RETURN_ERR;
7384 }
7385
7386 // Example filtered output of 'iw dev' command:
7387 // Station 0a:69:72:10:d2:fa (on wifi0)
7388 // signal avg:-67 [-71, -71] dBm
7389 // Station 28:c2:1f:25:5f:99 (on wifi0)
7390 // signal avg:-67 [-71, -70] dBm
7391 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7392 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7393 return RETURN_ERR;
7394 }
7395
7396 ret = _syscmd(cmd, buf, sizeof(buf));
7397 if (ret == RETURN_ERR) {
7398 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7399 return RETURN_ERR;
7400 }
7401
7402 *output_array_size = count_occurences(buf, "Station");
7403 if (*output_array_size == 0) return RETURN_OK;
7404
7405 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7406 if (temp == NULL) {
7407 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7408 return RETURN_ERR;
7409 }
7410 *associated_dev_array = temp;
7411
7412 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7413 ptr = get_line_from_str_buf(buf, line);
7414 i = -1;
7415 while (ptr) {
7416 if (strstr(line, "Station")) {
7417 i++;
7418 key = strtok(line, " ");
7419 val = strtok(NULL, " ");
7420 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7421 &temp[i].cli_MACAddress[0],
7422 &temp[i].cli_MACAddress[1],
7423 &temp[i].cli_MACAddress[2],
7424 &temp[i].cli_MACAddress[3],
7425 &temp[i].cli_MACAddress[4],
7426 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7427 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7428 free(*associated_dev_array);
7429 return RETURN_ERR;
7430 }
7431 }
7432 else if (i < 0) {
7433 ptr = get_line_from_str_buf(ptr, line);
7434 continue; // We didn't detect 'station' entry yet
7435 }
7436 else if (strstr(line, "signal avg")) {
7437 key = strtok(line, ":");
7438 val = strtok(NULL, " ");
7439 if (sscanf(val, "%d", &rssi) <= 0 ) {
7440 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7441 free(*associated_dev_array);
7442 return RETURN_ERR;
7443 }
7444 temp[i].cli_RSSI = rssi;
7445 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7446 }
7447 // Here other fields can be parsed if added to filter of 'iw dev' command
7448
7449 ptr = get_line_from_str_buf(ptr, line);
7450 };
7451
7452 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7453
7454 return RETURN_OK;
7455}
7456
7457#if 0
7458//To-do
7459INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7460{
7461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7462
7463 //Using different approach to get required WiFi Parameters from system available commands
7464#if 0
7465 FILE *f;
7466 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7467 char cmd[256], buf[2048];
7468 char *param , *value, *line=NULL;
7469 size_t len = 0;
7470 ssize_t nread;
7471 wifi_associated_dev3_t *dev=NULL;
7472 *associated_dev_array = NULL;
7473 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7474 _syscmd(cmd,buf,sizeof(buf));
7475 *output_array_size = atoi(buf);
7476
7477 if (*output_array_size <= 0)
7478 return RETURN_OK;
7479
7480 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7481 *associated_dev_array = dev;
7482 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7483 _syscmd(cmd,buf,sizeof(buf));
7484 f = fopen("/tmp/connected_devices.txt", "r");
7485 if (f==NULL)
7486 {
7487 *output_array_size=0;
7488 return RETURN_ERR;
7489 }
7490 while ((nread = getline(&line, &len, f)) != -1)
7491 {
7492 param = strtok(line,"=");
7493 value = strtok(NULL,"=");
7494
7495 if( strcmp("flags",param) == 0 )
7496 {
7497 value[strlen(value)-1]='\0';
7498 if(strstr (value,"AUTHORIZED") != NULL )
7499 {
7500 dev[auth_temp].cli_AuthenticationState = 1;
7501 dev[auth_temp].cli_Active = 1;
7502 auth_temp++;
7503 read_flag=1;
7504 }
7505 }
7506 if(read_flag==1)
7507 {
7508 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7509 {
7510 value[strlen(value)-1]='\0';
7511 sscanf(value, "%x:%x:%x:%x:%x:%x",
7512 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7513 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7514 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7515 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7516 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7517 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7518
7519 }
7520 else if( strcmp("rx_packets",param) == 0 )
7521 {
7522 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7523 }
7524
7525 else if( strcmp("tx_packets",param) == 0 )
7526 {
7527 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7528 }
7529
7530 else if( strcmp("rx_bytes",param) == 0 )
7531 {
7532 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7533 }
7534
7535 else if( strcmp("tx_bytes",param) == 0 )
7536 {
7537 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7538 mac_temp++;
7539 read_flag=0;
7540 }
7541 }
7542 }
7543
7544 *output_array_size = auth_temp;
7545 auth_temp=0;
7546 mac_temp=0;
7547 free(line);
7548 fclose(f);
7549#endif
7550 char interface_name[MAX_BUF_SIZE] = {0};
7551 char wifi_status[MAX_BUF_SIZE] = {0};
7552 char hostapdconf[MAX_BUF_SIZE] = {0};
7553
7554 wifi_associated_dev3_t *dev_array = NULL;
7555 ULONG wifi_count = 0;
7556
7557 *associated_dev_array = NULL;
7558 *output_array_size = 0;
7559
7560 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7561 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7562 {
7563 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7564
7565 GetInterfaceName(interface_name, hostapdconf);
7566
7567 if(strlen(interface_name) > 1)
7568 {
7569 wifihal_interfacestatus(wifi_status,interface_name);
7570 if(strcmp(wifi_status,"RUNNING") == 0)
7571 {
7572 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7573
7574 *associated_dev_array = dev_array;
7575 *output_array_size = wifi_count;
7576 }
7577 else
7578 {
7579 *associated_dev_array = NULL;
7580 }
7581 }
7582 }
7583
7584 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7585 return RETURN_OK;
7586}
7587#endif
7588
7589/* getIPAddress function */
7590/**
7591* @description Returning IpAddress of the Matched String
7592*
7593* @param
7594* @str Having MacAddress
7595* @ipaddr Having ipaddr
7596* @return The status of the operation
7597* @retval RETURN_OK if successful
7598* @retval RETURN_ERR if any error is detected
7599*
7600*/
7601
7602INT getIPAddress(char *str,char *ipaddr)
7603{
7604 FILE *fp = NULL;
7605 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7606 int LeaseTime = 0,ret = 0;
7607 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7608 {
7609 return RETURN_ERR;
7610 }
7611
7612 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7613 {
7614 /*
7615 Sample:sss
7616 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7617 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7618 */
7619 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7620 &(LeaseTime),
7621 phyAddr,
7622 ipAddr,
7623 hostName
7624 );
7625 if(ret != 4)
7626 continue;
7627 if(strcmp(str,phyAddr) == 0)
7628 strcpy(ipaddr,ipAddr);
7629 }
7630 return RETURN_OK;
7631}
7632
7633/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7634/**
7635* @description Returning Inactive wireless connected clients informations
7636*
7637* @param
7638* @filename Holding private_wifi 2g/5g content files
7639* @associated_dev_array Having inactiv wireless clients informations
7640* @output_array_size Returning Inactive wireless counts
7641* @return The status of the operation
7642* @retval RETURN_OK if successful
7643* @retval RETURN_ERR if any error is detected
7644*
7645*/
7646
7647INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7648{
7649 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7650 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7651 FILE *fp = NULL;
7652 int arr[MACADDRESS_SIZE] = {0};
7653 unsigned char mac[MACADDRESS_SIZE] = {0};
7654 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7655 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7656 fp = popen(buf,"r");
7657 if(fp == NULL)
7658 return RETURN_ERR;
7659 else
7660 {
7661 fgets(path,sizeof(path),fp);
7662 maccount = atoi(path);
7663 }
7664 pclose(fp);
7665 *output_array_size = maccount;
7666 wifi_associated_dev3_t* temp = NULL;
7667 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7668 *associated_dev_array = temp;
7669 if(temp == NULL)
7670 {
7671 printf("Error Statement. Insufficient memory \n");
7672 return RETURN_ERR;
7673 }
7674 memset(buf,0,sizeof(buf));
7675 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7676 fp = popen(buf,"r");
7677 for(count = 0; count < maccount ; count++)
7678 {
7679 fgets(path,sizeof(path),fp);
7680 for(i = 0; path[i]!='\n';i++)
7681 str[i]=path[i];
7682 str[i]='\0';
7683 getIPAddress(str,ipaddr);
7684 memset(buf,0,sizeof(buf));
7685 if(strlen(ipaddr) > 0)
7686 {
7687 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7688 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7689 {
7690 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7691 {
7692 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7693 {
7694 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7695
7696 }
7697 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7698 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]);
7699 }
7700 temp[count].cli_AuthenticationState = 0; //TODO
7701 temp[count].cli_Active = 0; //TODO
7702 temp[count].cli_SignalStrength = 0;
7703 }
7704 else //Active wireless clients info
7705 {
7706 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7707 {
7708 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7709 {
7710 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7711
7712 }
7713 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7714 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]);
7715 }
7716 temp[count].cli_Active = 1;
7717 }
7718 }
7719 memset(ipaddr,0,sizeof(ipaddr));
7720 }
7721 pclose(fp);
7722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7723 return RETURN_OK;
7724}
7725//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7726//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7727//To get Band Steering Capability
7728INT wifi_getBandSteeringCapability(BOOL *support)
7729{
7730 *support = FALSE;
7731 return RETURN_OK;
7732}
7733
7734
7735//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7736//To get Band Steering enable status
7737INT wifi_getBandSteeringEnable(BOOL *enable)
7738{
7739 *enable = FALSE;
7740 return RETURN_OK;
7741}
7742
7743//To turn on/off Band steering
7744INT wifi_setBandSteeringEnable(BOOL enable)
7745{
7746 return RETURN_OK;
7747}
7748
7749//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7750//To get Band Steering AP group
7751INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7752{
7753 if (NULL == output_ApGroup)
7754 return RETURN_ERR;
7755
7756 strcpy(output_ApGroup, "1,2");
7757 return RETURN_OK;
7758}
7759
7760//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7761//to set and read the band steering BandUtilizationThreshold parameters
7762INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7763{
7764 return RETURN_ERR;
7765}
7766
7767INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7768{
7769 return RETURN_ERR;
7770}
7771
7772//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7773//to set and read the band steering RSSIThreshold parameters
7774INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7775{
7776 return RETURN_ERR;
7777}
7778
7779INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7780{
7781 return RETURN_ERR;
7782}
7783
7784
7785//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7786//to set and read the band steering physical modulation rate threshold parameters
7787INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7788{
7789 //If chip is not support, return -1
7790 return RETURN_ERR;
7791}
7792
7793INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7794{
7795 //If chip is not support, return -1
7796 return RETURN_ERR;
7797}
7798
7799//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7800//to set and read the inactivity time (in seconds) for steering under overload condition
7801INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7802{
7803 return RETURN_ERR;
7804}
7805
7806INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7807{
7808 return RETURN_ERR;
7809}
7810
7811//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7812//to set and read the inactivity time (in seconds) for steering under Idle condition
7813INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7814{
7815 return RETURN_ERR;
7816}
7817
7818INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7819{
7820 return RETURN_ERR;
7821}
7822
7823//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7824//pClientMAC[64]
7825//pSourceSSIDIndex[64]
7826//pDestSSIDIndex[64]
7827//pSteeringReason[256]
7828INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7829{
7830 //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
7831 *pSteeringTime=time(NULL);
7832 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7833 return RETURN_OK;
7834}
7835
7836INT wifi_ifConfigDown(INT apIndex)
7837{
7838 INT status = RETURN_OK;
7839 char cmd[64];
7840
7841 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7842 printf("%s: %s\n", __func__, cmd);
7843 system(cmd);
7844
7845 return status;
7846}
7847
7848INT wifi_ifConfigUp(INT apIndex)
7849{
7850 char cmd[128];
7851 char buf[1024];
7852
7853 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7854 _syscmd(cmd, buf, sizeof(buf));
7855 return 0;
7856}
7857
7858//>> Deprecated. Replace with wifi_applyRadioSettings
7859INT wifi_pushBridgeInfo(INT apIndex)
7860{
7861 char ip[32];
7862 char subnet[32];
7863 char bridge[32];
7864 int vlanId;
7865 char cmd[128];
7866 char buf[1024];
7867
7868 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7869 wifi_getApVlanID(apIndex,&vlanId);
7870
7871 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7872 _syscmd(cmd,buf, sizeof(buf));
7873
7874 return 0;
7875}
7876
7877INT wifi_pushChannel(INT radioIndex, UINT channel)
7878{
7879 char cmd[128];
7880 char buf[1024];
7881 int apIndex;
7882
7883 apIndex=(radioIndex==0)?0:1;
7884 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7885 _syscmd(cmd,buf, sizeof(buf));
7886
7887 return 0;
7888}
7889
7890INT wifi_pushChannelMode(INT radioIndex)
7891{
7892 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7893 return RETURN_ERR;
7894}
7895
7896INT wifi_pushDefaultValues(INT radioIndex)
7897{
7898 //Apply Comcast specified default radio settings instantly
7899 //AMPDU=1
7900 //AMPDUFrames=32
7901 //AMPDULim=50000
7902 //txqueuelen=1000
7903
7904 return RETURN_ERR;
7905}
7906
7907INT wifi_pushTxChainMask(INT radioIndex)
7908{
7909 //Apply default TxChainMask instantly
7910 return RETURN_ERR;
7911}
7912
7913INT wifi_pushRxChainMask(INT radioIndex)
7914{
7915 //Apply default RxChainMask instantly
7916 return RETURN_ERR;
7917}
7918
7919INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7920{
7921 INT status;
7922
7923 status = wifi_setSSIDName(apIndex,ssid);
7924 wifi_setApEnable(apIndex,FALSE);
7925 wifi_setApEnable(apIndex,TRUE);
7926
7927 return status;
7928}
7929
7930INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7931{
7932 //Apply default Ssid Advertisement instantly
7933 return RETURN_ERR;
7934}
7935
7936INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7937{
7938 INT status = RETURN_ERR;
7939 *output = 0;
7940 return RETURN_ERR;
7941}
7942
7943INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7944{
7945 return RETURN_OK;
7946}
7947
7948INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7949{
7950 return RETURN_OK;
7951}
7952
7953//To-do
7954INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7955{
developereb199ae2022-09-13 14:04:27 +08007956 char output[16]={'\0'};
7957 char config_file[MAX_BUF_SIZE] = {0};
7958
7959 if (!output_string)
7960 return RETURN_ERR;
7961
7962 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7963 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7964
7965 if (strlen(output) == 0)
7966 snprintf(output_string, 64, "Disabled");
7967 else if (strncmp(output, "0", 1) == 0)
7968 snprintf(output_string, 64, "Disabled");
7969 else if (strncmp(output, "1", 1) == 0)
7970 snprintf(output_string, 64, "Optional");
7971 else if (strncmp(output, "2", 1) == 0)
7972 snprintf(output_string, 64, "Required");
7973 else {
7974 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7975 return RETURN_ERR;
7976 }
7977
7978 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007979 return RETURN_OK;
7980}
7981INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7982{
developereb199ae2022-09-13 14:04:27 +08007983 char str[MAX_BUF_SIZE]={'\0'};
7984 char cmd[MAX_CMD_SIZE]={'\0'};
7985 struct params params;
7986 char config_file[MAX_BUF_SIZE] = {0};
7987
7988 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7989 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7990 return RETURN_ERR;
7991
7992 params.name = "ieee80211w";
7993 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7994 params.value = "0";
7995 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7996 params.value = "1";
7997 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7998 params.value = "2";
7999 else{
8000 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8001 return RETURN_ERR;
8002 }
8003 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8004 wifi_hostapdWrite(config_file, &params, 1);
8005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008006 return RETURN_OK;
8007}
8008INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8009{
8010 char output[16]={'\0'};
8011 char config_file[MAX_BUF_SIZE] = {0};
8012
8013 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8014 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8015 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8016
8017 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8018 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8019
8020 return RETURN_OK;
8021}
8022
8023INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8024{
8025 return RETURN_OK;
8026}
8027
8028INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8029{
8030 return RETURN_OK;
8031}
8032
8033INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8034{
8035 return RETURN_OK;
8036}
8037
8038INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8039{
8040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8041 char config_file[MAX_BUF_SIZE] = {0};
8042
8043 if (NULL == output)
8044 return RETURN_ERR;
8045 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8046 wifi_hostapdRead(config_file,"hw_mode",output,64);
8047
8048 if(strcmp(output,"b")==0)
8049 sprintf(output, "%s", "1,2,5.5,11");
8050 else if (strcmp(output,"a")==0)
8051 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8052 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8053 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8054
8055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8056 return RETURN_OK;
8057}
8058
8059INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8060{
8061 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8062 char *temp;
8063 char temp_output[128];
8064 char temp_TransmitRates[128];
8065 char config_file[MAX_BUF_SIZE] = {0};
8066
8067 if (NULL == output)
8068 return RETURN_ERR;
8069
8070 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8071 wifi_hostapdRead(config_file,"supported_rates",output,64);
8072
developer5b398df2022-11-17 20:39:48 +08008073 if (strlen(output) == 0) {
8074 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8075 return RETURN_OK;
8076 }
developer06a01d92022-09-07 16:32:39 +08008077 strcpy(temp_TransmitRates,output);
8078 strcpy(temp_output,"");
8079 temp = strtok(temp_TransmitRates," ");
8080 while(temp!=NULL)
8081 {
8082 temp[strlen(temp)-1]=0;
8083 if((temp[0]=='5') && (temp[1]=='\0'))
8084 {
8085 temp="5.5";
8086 }
8087 strcat(temp_output,temp);
8088 temp = strtok(NULL," ");
8089 if(temp!=NULL)
8090 {
8091 strcat(temp_output,",");
8092 }
8093 }
8094 strcpy(output,temp_output);
8095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8096
8097 return RETURN_OK;
8098}
8099
8100INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8101{
8102 return RETURN_OK;
8103}
8104
8105
8106INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8107{
8108 int i=0;
8109 char *temp;
developeref938762022-10-19 17:21:01 +08008110 char temp1[128] = {0};
8111 char temp_output[128] = {0};
8112 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008113 struct params params={'\0'};
8114 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008115 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008116
8117 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8118 if(NULL == output)
8119 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008120 strcpy(temp_TransmitRates,output);
8121
8122 for(i=0;i<strlen(temp_TransmitRates);i++)
8123 {
developeref938762022-10-19 17:21:01 +08008124 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008125 {
8126 continue;
8127 }
8128 else
8129 {
8130 return RETURN_ERR;
8131 }
8132 }
8133 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008134 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008135 while(temp!=NULL)
8136 {
8137 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008138 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008139 {
developeref938762022-10-19 17:21:01 +08008140 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008141 {
8142 return RETURN_ERR;
8143 }
8144 }
8145
8146 if(strcmp(temp,"5.5")==0)
8147 {
8148 strcpy(temp1,"55");
8149 }
8150 else
8151 {
8152 strcat(temp1,"0");
8153 }
8154 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008155 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008156 if(temp!=NULL)
8157 {
8158 strcat(temp_output," ");
8159 }
8160 }
8161 strcpy(output,temp_output);
8162
developer06a01d92022-09-07 16:32:39 +08008163 params.name = "supported_rates";
8164 params.value = output;
8165
8166 wifi_dbg_printf("\n%s:",__func__);
8167 wifi_dbg_printf("params.value=%s\n",params.value);
8168 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8169 wifi_hostapdWrite(config_file,&params,1);
8170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8171
8172 return RETURN_OK;
8173}
8174
8175
8176static char *sncopy(char *dst, int dst_sz, const char *src)
8177{
8178 if (src && dst && dst_sz > 0) {
8179 strncpy(dst, src, dst_sz);
8180 dst[dst_sz - 1] = '\0';
8181 }
8182 return dst;
8183}
8184
8185static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8186{
8187 if (0 == strcmp(ht_mode, "HT40") ||
8188 0 == strcmp(ht_mode, "HT80") ||
8189 0 == strcmp(ht_mode, "HT160")) {
8190 switch (channel) {
8191 case 1 ... 7:
8192 case 36:
8193 case 44:
8194 case 52:
8195 case 60:
8196 case 100:
8197 case 108:
8198 case 116:
8199 case 124:
8200 case 132:
8201 case 140:
8202 case 149:
8203 case 157:
8204 return 1;
8205 case 8 ... 13:
8206 case 40:
8207 case 48:
8208 case 56:
8209 case 64:
8210 case 104:
8211 case 112:
8212 case 120:
8213 case 128:
8214 case 136:
8215 case 144:
8216 case 153:
8217 case 161:
8218 return -1;
8219 default:
8220 return -EINVAL;
8221 }
8222 }
8223
8224 return -EINVAL;
8225}
8226
developerb7593de2022-10-18 09:51:57 +08008227static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8228{
8229 int idx = channel%8;
8230 if (0 == strcmp(ht_mode, "HT40") ||
8231 0 == strcmp(ht_mode, "HT80") ||
8232 0 == strcmp(ht_mode, "HT160")) {
8233 switch (idx) {
8234 case 1:
8235 return 1;
8236 case 5:
8237 return -1;
8238 default:
8239 return -EINVAL;
8240 }
8241 }
8242
8243 return -EINVAL;
8244}
developer06a01d92022-09-07 16:32:39 +08008245static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8246{
8247 if (NULL == hw_mode) return;
8248
8249 if (0 == strcmp(hw_mode, "ac"))
8250 sncopy(bw_mode, bw_mode_len, "ht vht");
8251
8252 if (0 == strcmp(hw_mode, "n"))
8253 sncopy(bw_mode, bw_mode_len, "ht");
8254
8255 return;
8256}
8257
8258static int util_chan_to_freq(int chan)
8259{
8260 if (chan == 14)
8261 return 2484;
8262 else if (chan < 14)
8263 return 2407 + chan * 5;
8264 else if (chan >= 182 && chan <= 196)
8265 return 4000 + chan * 5;
8266 else
8267 return 5000 + chan * 5;
8268 return 0;
8269}
8270
developerb7593de2022-10-18 09:51:57 +08008271static int util_6G_chan_to_freq(int chan)
8272{
8273 if (chan)
8274 return 5950 + chan * 5;
8275 else
8276 return 0;
8277
8278}
developer06a01d92022-09-07 16:32:39 +08008279const int *util_unii_5g_chan2list(int chan, int width)
8280{
8281 static const int lists[] = {
8282 // <width>, <chan1>, <chan2>..., 0,
8283 20, 36, 0,
8284 20, 40, 0,
8285 20, 44, 0,
8286 20, 48, 0,
8287 20, 52, 0,
8288 20, 56, 0,
8289 20, 60, 0,
8290 20, 64, 0,
8291 20, 100, 0,
8292 20, 104, 0,
8293 20, 108, 0,
8294 20, 112, 0,
8295 20, 116, 0,
8296 20, 120, 0,
8297 20, 124, 0,
8298 20, 128, 0,
8299 20, 132, 0,
8300 20, 136, 0,
8301 20, 140, 0,
8302 20, 144, 0,
8303 20, 149, 0,
8304 20, 153, 0,
8305 20, 157, 0,
8306 20, 161, 0,
8307 20, 165, 0,
8308 40, 36, 40, 0,
8309 40, 44, 48, 0,
8310 40, 52, 56, 0,
8311 40, 60, 64, 0,
8312 40, 100, 104, 0,
8313 40, 108, 112, 0,
8314 40, 116, 120, 0,
8315 40, 124, 128, 0,
8316 40, 132, 136, 0,
8317 40, 140, 144, 0,
8318 40, 149, 153, 0,
8319 40, 157, 161, 0,
8320 80, 36, 40, 44, 48, 0,
8321 80, 52, 56, 60, 64, 0,
8322 80, 100, 104, 108, 112, 0,
8323 80, 116, 120, 124, 128, 0,
8324 80, 132, 136, 140, 144, 0,
8325 80, 149, 153, 157, 161, 0,
8326 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8327 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8328 -1 // final delimiter
8329 };
8330 const int *start;
8331 const int *p;
8332
8333 for (p = lists; *p != -1; p++) {
8334 if (*p == width) {
8335 for (start = ++p; *p != 0; p++) {
8336 if (*p == chan)
8337 return start;
8338 }
8339 }
8340 // move to the end of channel list of given width
8341 while (*p != 0) {
8342 p++;
8343 }
8344 }
8345
8346 return NULL;
8347}
8348
8349static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8350{
8351 if (NULL == ht_mode)
8352 return 0;
8353
8354 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8355 const int *chans = util_unii_5g_chan2list(channel, width);
8356 int sum = 0;
8357 int cnt = 0;
8358
8359 if (NULL == chans)
8360 return 0;
8361
8362 while (*chans) {
8363 sum += *chans;
8364 cnt++;
8365 chans++;
8366 }
8367 return sum / cnt;
8368}
8369
developerb7593de2022-10-18 09:51:57 +08008370static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8371{
8372 if (NULL == ht_mode)
8373 return 0;
8374
8375 int width = strtol((ht_mode + 2), NULL, 10);
8376
8377 int idx = 0 ;
8378 int centerchan = 0;
8379 int chan_ofs = 1;
8380
8381 if (width == 40){
8382 idx = ((channel/4) + chan_ofs)%2;
8383 switch (idx) {
8384 case 0:
8385 centerchan = (channel - 2);
8386 break;
8387 case 1:
8388 centerchan = (channel + 2);
8389 break;
8390 default:
8391 return -EINVAL;
8392 }
8393 }else if (width == 80){
8394 idx = ((channel/4) + chan_ofs)%4;
8395 switch (idx) {
8396 case 0:
8397 centerchan = (channel - 6);
8398 break;
8399 case 1:
8400 centerchan = (channel + 6);
8401 break;
8402 case 2:
8403 centerchan = (channel + 2);
8404 break;
8405 case 3:
8406 centerchan = (channel - 2);
8407 break;
8408 default:
8409 return -EINVAL;
8410 }
8411 }else if (width == 160){
8412 switch (channel) {
8413 case 1 ... 29:
8414 centerchan = 15;
8415 break;
8416 case 33 ... 61:
8417 centerchan = 47;
8418 break;
8419 case 65 ... 93:
8420 centerchan = 79;
8421 break;
8422 case 97 ... 125:
8423 centerchan = 111;
8424 break;
8425 case 129 ... 157:
8426 centerchan = 143;
8427 break;
8428 case 161 ... 189:
8429 centerchan = 175;
8430 break;
8431 case 193 ... 221:
8432 centerchan = 207;
8433 break;
8434 default:
8435 return -EINVAL;
8436 }
8437 }
8438 return centerchan;
8439}
developer06a01d92022-09-07 16:32:39 +08008440static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8441{
8442 BOOL onlyG, onlyN, onlyA;
8443 CHAR tmp[64];
8444 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8445 if (ret == RETURN_OK) {
8446 sncopy(hw_mode, hw_mode_size, tmp);
8447 }
8448 return ret;
8449}
8450
8451INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8452{
8453 // Sample commands:
8454 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8455 // hostapd_cli -i wifi0 chan_switch 30 2437
8456 char cmd[MAX_CMD_SIZE] = {0};
8457 char buf[MAX_BUF_SIZE] = {0};
8458 int freq = 0, ret = 0;
8459 char center_freq1_str[32] = ""; // center_freq1=%d
8460 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8461 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8462 char hw_mode[16] = ""; // n|ac
8463 char bw_mode[16] = ""; // ht|ht vht
8464 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8465 int sec_chan_offset;
8466 int width;
developer4fb0b922022-09-30 14:29:09 +08008467 char config_file[64] = {0};
8468 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008469 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008470 wifi_band band = band_invalid;
8471 int center_chan = 0;
8472 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008473
developer4fb0b922022-09-30 14:29:09 +08008474 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008475
8476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8477
developerb7593de2022-10-18 09:51:57 +08008478 band = wifi_index_to_band(radioIndex);
8479
developer5884e982022-10-06 10:52:50 +08008480 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008481
8482 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008483 if (channel){
developerb7593de2022-10-18 09:51:57 +08008484 if (band == band_6){
8485 freq = util_6G_chan_to_freq(channel);
8486 }else{
8487 freq = util_chan_to_freq(channel);
8488 }
developer5884e982022-10-06 10:52:50 +08008489 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008490
developer5884e982022-10-06 10:52:50 +08008491 // Provide bandwith if specified
8492 if (channel_width_MHz > 20) {
8493 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8494 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8495 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008496
developer5884e982022-10-06 10:52:50 +08008497 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8498 }else if (channel_width_MHz == 20){
8499 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8500 }
developer06a01d92022-09-07 16:32:39 +08008501
developerb7593de2022-10-18 09:51:57 +08008502
developer5884e982022-10-06 10:52:50 +08008503 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008504 if (band == band_6){
8505 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8506 if(center_chan){
8507 center_freq1 = util_6G_chan_to_freq(center_chan);
8508 }
8509 }else{
8510 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8511 if(center_chan){
8512 center_freq1 = util_chan_to_freq(center_chan);
8513 }
developer5884e982022-10-06 10:52:50 +08008514 }
developerb7593de2022-10-18 09:51:57 +08008515
8516 if (center_freq1)
8517 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8518
8519 }
8520
8521 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8522 if (band == band_6){
8523 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8524 }else{
8525 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008526 }
developerb7593de2022-10-18 09:51:57 +08008527 if (sec_chan_offset != -EINVAL)
8528 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008529
developer5884e982022-10-06 10:52:50 +08008530 // Only the first AP, other are hanging on the same radio
8531 int apIndex = radioIndex;
8532 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8533 AP_PREFIX, apIndex, csa_beacon_count, freq,
8534 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8535 wifi_dbg_printf("execute: '%s'\n", cmd);
8536 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008537
developer5884e982022-10-06 10:52:50 +08008538 ret = wifi_setRadioChannel(radioIndex, channel);
8539 if (ret != RETURN_OK) {
8540 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8541 return RETURN_ERR;
8542 }
8543
8544 if (sec_chan_offset == 1) ext_str = "Above";
8545 else if (sec_chan_offset == -1) ext_str = "Below";
8546
8547 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008548
developer5884e982022-10-06 10:52:50 +08008549 } else {
8550 if (channel_width_MHz > 20)
8551 ext_str = "Above";
8552 }
developer4fb0b922022-09-30 14:29:09 +08008553 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8554 _syscmd(cmd, buf, sizeof(buf));
8555 if (strlen(buf) != 0)
8556 stbcEnable = TRUE;
8557
developer06a01d92022-09-07 16:32:39 +08008558 wifi_setRadioExtChannel(radioIndex, ext_str);
8559
developer4fb0b922022-09-30 14:29:09 +08008560 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8561
developer06a01d92022-09-07 16:32:39 +08008562 char mhz_str[16];
8563 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8564 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8565
8566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8567
8568 return RETURN_OK;
8569}
8570
8571INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8572{
developer615510b2022-09-27 10:14:35 +08008573 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008574 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008575 char cmd[256]={0};
8576 char buf[128]={0};
8577 char file_name[32] = {0};
8578 char filter_SSID[32] = {0};
8579 char line[256] = {0};
8580 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008581 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008582 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008583 size_t len=0;
8584 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008585 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008586 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008587 bool filter_enable = false;
8588 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008589 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008590
developer615510b2022-09-27 10:14:35 +08008591 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008592
developer615510b2022-09-27 10:14:35 +08008593 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8594 f = fopen(file_name, "r");
8595 if (f != NULL) {
8596 fgets(filter_SSID, sizeof(file_name), f);
8597 if (strlen(filter_SSID) != 0)
8598 filter_enable = true;
8599 fclose(f);
8600 }
8601
developer033b37b2022-10-18 11:27:46 +08008602 phyId = radio_index_to_phy(radio_index);
8603
8604 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008605 _syscmd(cmd, buf, sizeof(buf));
8606 channels_num = strtol(buf, NULL, 10);
8607
developer615510b2022-09-27 10:14:35 +08008608 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8609 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radio_index, AP_PREFIX, radio_index);
8610 fprintf(stderr, "cmd: %s\n", cmd);
8611 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008612 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8613 return RETURN_ERR;
8614 }
developer5550e242022-09-30 09:59:32 +08008615
8616 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8617 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8618
developer615510b2022-09-27 10:14:35 +08008619 ret = fgets(line, sizeof(line), f);
8620 while (ret != NULL) {
8621 if(strstr(line, "BSS") != NULL) { // new neighbor info
8622 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8623 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8624 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8625
8626 if (!filter_BSS) {
8627 index++;
8628 wifi_neighbor_ap2_t *tmp;
8629 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8630 if (tmp == NULL) { // no more memory to use
8631 index--;
8632 wifi_dbg_printf("%s: realloc failed\n", __func__);
8633 break;
8634 }
8635 scan_array = tmp;
8636 }
8637 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008638
developer615510b2022-09-27 10:14:35 +08008639 filter_BSS = false;
8640 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8641 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8642 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8643 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8644 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008645 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008646 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008647
developer615510b2022-09-27 10:14:35 +08008648 if (freq >= 2412 && freq <= 2484) {
8649 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8650 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8651 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8652 }
8653 else if (freq >= 5160 && freq <= 5805) {
8654 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8655 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8656 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8657 }
developer06a01d92022-09-07 16:32:39 +08008658
developer615510b2022-09-27 10:14:35 +08008659 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008660 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008661 for (int i = 0; i < channels_num; i++) {
8662 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8663 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8664 break;
8665 }
8666 }
developer06a01d92022-09-07 16:32:39 +08008667 }
developer615510b2022-09-27 10:14:35 +08008668 } else if (strstr(line, "beacon interval") != NULL) {
8669 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8670 } else if (strstr(line, "signal") != NULL) {
8671 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8672 } else if (strstr(line,"SSID") != NULL) {
8673 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8674 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8675 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008676 }
developer615510b2022-09-27 10:14:35 +08008677 } else if (strstr(line, "Supported rates") != NULL) {
8678 char SRate[80] = {0}, *tmp = NULL;
8679 memset(buf, 0, sizeof(buf));
8680 strcpy(SRate, line);
8681 tmp = strtok(SRate, ":");
8682 tmp = strtok(NULL, ":");
8683 strcpy(buf, tmp);
8684 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008685
developer615510b2022-09-27 10:14:35 +08008686 tmp = strtok(buf, " \n");
8687 while (tmp != NULL) {
8688 strcat(SRate, tmp);
8689 if (SRate[strlen(SRate) - 1] == '*') {
8690 SRate[strlen(SRate) - 1] = '\0';
8691 }
8692 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008693
developer615510b2022-09-27 10:14:35 +08008694 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008695 }
developer615510b2022-09-27 10:14:35 +08008696 SRate[strlen(SRate) - 1] = '\0';
8697 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8698 } else if (strstr(line, "DTIM") != NULL) {
8699 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8700 } else if (strstr(line, "VHT capabilities") != NULL) {
8701 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8702 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8703 } else if (strstr(line, "HT capabilities") != NULL) {
8704 strcat(scan_array[index].ap_SupportedStandards, ",n");
8705 strcpy(scan_array[index].ap_OperatingStandards, "n");
8706 } else if (strstr(line, "VHT operation") != NULL) {
8707 ret = fgets(line, sizeof(line), f);
8708 sscanf(line," * channel width: %d", &vht_channel_width);
8709 if(vht_channel_width == 1) {
8710 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8711 } else {
8712 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8713 }
8714 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8715 continue;
8716 } else if (strstr(line, "HT operation") != NULL) {
8717 ret = fgets(line, sizeof(line), f);
8718 sscanf(line," * secondary channel offset: %s", &buf);
8719 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008720 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008721 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 +08008722 }
developer615510b2022-09-27 10:14:35 +08008723 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008724 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008725 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8726 } else {
8727 //20Mhz
8728 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 +08008729 }
developer615510b2022-09-27 10:14:35 +08008730 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008731 continue;
developer615510b2022-09-27 10:14:35 +08008732 } else if (strstr(line, "HE capabilities") != NULL) {
8733 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8734 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8735 ret = fgets(line, sizeof(line), f);
8736 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8737 if (strstr(line, "HE40/2.4GHz") != NULL)
8738 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8739 else
8740 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8741 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8742 if (strstr(line, "HE80/5GHz") != NULL) {
8743 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8744 ret = fgets(line, sizeof(line), f);
8745 } else
8746 continue;
8747 if (strstr(line, "HE160/5GHz") != NULL)
8748 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008749 }
developer615510b2022-09-27 10:14:35 +08008750 continue;
8751 } else if (strstr(line, "WPA") != NULL) {
8752 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8753 } else if (strstr(line, "RSN") != NULL) {
8754 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8755 } else if (strstr(line, "Group cipher") != NULL) {
8756 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8757 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8758 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008759 }
developer06a01d92022-09-07 16:32:39 +08008760 }
developer615510b2022-09-27 10:14:35 +08008761 ret = fgets(line, sizeof(line), f);
8762 }
8763
8764 if (!filter_BSS) {
8765 *output_array_size = index + 1;
8766 } else {
8767 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8768 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008769 }
developer06a01d92022-09-07 16:32:39 +08008770 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008771 pclose(f);
developer5550e242022-09-30 09:59:32 +08008772 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008774 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008775}
developer615510b2022-09-27 10:14:35 +08008776
developer06a01d92022-09-07 16:32:39 +08008777INT wifi_getApAssociatedDeviceStats(
8778 INT apIndex,
8779 mac_address_t *clientMacAddress,
8780 wifi_associated_dev_stats_t *associated_dev_stats,
8781 u64 *handle)
8782{
8783 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8784 char interface_name[50] = {0};
8785 char cmd[1024] = {0};
8786 char mac_str[18] = {0};
8787 char *key = NULL;
8788 char *val = NULL;
8789 FILE *f = NULL;
8790 char *line = NULL;
8791 size_t len = 0;
8792 ssize_t read = 0;
8793
8794 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8795 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8796 return RETURN_ERR;
8797 }
8798
8799 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8800 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8801 if((f = popen(cmd, "r")) == NULL) {
8802 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8803 return RETURN_ERR;
8804 }
8805
8806 while ((read = getline(&line, &len, f)) != -1) {
8807 key = strtok(line,":");
8808 val = strtok(NULL,":");
8809
8810 if(!strncmp(key,"rx bytes",8))
8811 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8812 if(!strncmp(key,"tx bytes",8))
8813 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8814 if(!strncmp(key,"rx packets",10))
8815 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8816 if(!strncmp(key,"tx packets",10))
8817 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8818 if(!strncmp(key,"tx retries",10))
8819 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8820 if(!strncmp(key,"tx failed",9))
8821 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8822 if(!strncmp(key,"rx drop misc",13))
8823 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8824 if(!strncmp(key,"rx bitrate",10)) {
8825 val = strtok(val, " ");
8826 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8827 }
8828 if(!strncmp(key,"tx bitrate",10)) {
8829 val = strtok(val, " ");
8830 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8831 }
8832 }
8833 free(line);
8834 pclose(f);
8835 return RETURN_OK;
8836}
8837
8838INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8839{
8840 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8841
8842 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8843 if (NULL == output_string)
8844 return RETURN_ERR;
8845
8846 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8847 _syscmd(cmd, buf, sizeof(buf));
8848
8849 //size of SSID name restricted to value less than 32 bytes
8850 snprintf(output_string, 32, "%s", buf);
8851 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8852
8853 return RETURN_OK;
8854}
8855
8856INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8857{
8858 //char cmd[MAX_CMD_SIZE] = {0};
8859 char config_file[MAX_BUF_SIZE] = {0};
8860 char buf[32] = {0};
8861
8862 if (!output_filterMode)
8863 return RETURN_ERR;
8864
8865 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8866 //_syscmd(cmd, buf, sizeof(buf));
8867 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8868 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008869 if(strlen(buf) == 0) {
8870 *output_filterMode = 0;
8871 }
8872 else {
8873 int macaddr_acl_mode = strtol(buf, NULL, 10);
8874 if (macaddr_acl_mode == 1) {
8875 *output_filterMode = 1;
8876 } else if (macaddr_acl_mode == 0) {
8877 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8878 if (strlen(buf) == 0) {
8879 *output_filterMode = 0;
8880 } else {
8881 *output_filterMode = 2;
8882 }
8883 } else {
8884 return RETURN_ERR;
8885 }
8886 }
developer06a01d92022-09-07 16:32:39 +08008887
8888 return RETURN_OK;
8889}
8890
8891INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8892{
8893 FILE *fp = NULL;
8894 char str[MAX_BUF_SIZE] = {0};
8895 int wificlientindex = 0 ;
8896 int count = 0;
8897 int signalstrength = 0;
8898 int arr[MACADDRESS_SIZE] = {0};
8899 unsigned char mac[MACADDRESS_SIZE] = {0};
8900 UINT wifi_count = 0;
8901 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8902 char pipeCmd[MAX_CMD_SIZE] = {0};
8903
8904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8905 *output_array_size = 0;
8906 *associated_dev_array = NULL;
8907 char interface_name[50] = {0};
8908
8909 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8910 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8911 return RETURN_ERR;
8912 }
8913
8914 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8915 fp = popen(pipeCmd, "r");
8916 if (fp == NULL)
8917 {
8918 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8919 return RETURN_ERR;
8920 }
8921
8922 /* Read the output a line at a time - output it. */
8923 fgets(str, sizeof(str)-1, fp);
8924 wifi_count = (unsigned int) atoi ( str );
8925 *output_array_size = wifi_count;
8926 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8927 pclose(fp);
8928
8929 if(wifi_count == 0)
8930 {
8931 return RETURN_OK;
8932 }
8933 else
8934 {
8935 wifi_associated_dev2_t* temp = NULL;
8936 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8937 *associated_dev_array = temp;
8938 if(temp == NULL)
8939 {
8940 printf("Error Statement. Insufficient memory \n");
8941 return RETURN_ERR;
8942 }
8943
8944 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8945 system(pipeCmd);
8946
8947 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8948 if(fp == NULL)
8949 {
8950 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8951 return RETURN_ERR;
8952 }
8953 fclose(fp);
8954
8955 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8956 fp = popen(pipeCmd, "r");
8957 if(fp)
8958 {
8959 for(count =0 ; count < wifi_count; count++)
8960 {
8961 fgets(str, MAX_BUF_SIZE, fp);
8962 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8963 {
8964 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8965 {
8966 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8967
8968 }
8969 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8970 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]);
8971 }
8972 temp[count].cli_AuthenticationState = 1; //TODO
8973 temp[count].cli_Active = 1; //TODO
8974 }
8975 pclose(fp);
8976 }
8977
8978 //Updating RSSI per client
8979 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8980 fp = popen(pipeCmd, "r");
8981 if(fp)
8982 {
8983 pclose(fp);
8984 }
8985 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8986 if(fp)
8987 {
8988 for(count =0 ; count < wifi_count ;count++)
8989 {
8990 fgets(str, MAX_BUF_SIZE, fp);
8991 signalstrength = atoi(str);
8992 temp[count].cli_RSSI = signalstrength;
8993 }
8994 pclose(fp);
8995 }
8996
8997
8998 //LastDataDownlinkRate
8999 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
9000 fp = popen(pipeCmd, "r");
9001 if (fp)
9002 {
9003 pclose(fp);
9004 }
9005 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9006 if (fp)
9007 {
9008 for (count = 0; count < wifi_count; count++)
9009 {
9010 fgets(str, MAX_BUF_SIZE, fp);
9011 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9012 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9013 }
9014 pclose(fp);
9015 }
9016
9017 //LastDataUplinkRate
9018 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
9019 fp = popen(pipeCmd, "r");
9020 if (fp)
9021 {
9022 pclose(fp);
9023 }
9024 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9025 if (fp)
9026 {
9027 for (count = 0; count < wifi_count; count++)
9028 {
9029 fgets(str, MAX_BUF_SIZE, fp);
9030 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9031 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9032 }
9033 pclose(fp);
9034 }
9035 }
9036 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9037 return RETURN_OK;
9038
9039}
9040
9041INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9042{
9043#if 0
9044 /*char buf[1024] = {0};
9045 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
9046 _syscmd(cmd, buf, sizeof(buf));*/
9047
9048 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9049 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9050 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9051 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9052
9053 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.
9054 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].
9055 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].
9056 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].
9057 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9058 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9059
9060 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9061 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9062 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9063 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.
9064 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.
9065 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.
9066 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.
9067 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.
9068 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.
9069 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.
9070 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9071#endif
9072
9073 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08009074 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08009075 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009076 char pipeCmd[128] = {0};
9077 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009078 wifi_ssidTrafficStats2_t *out = output_struct;
9079
developerce736392022-09-13 15:24:34 +08009080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009081 if (!output_struct)
9082 return RETURN_ERR;
9083
developerce736392022-09-13 15:24:34 +08009084 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9085 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
9086 GetInterfaceName(interface_name, HConf_file);
9087 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009088
developer06a01d92022-09-07 16:32:39 +08009089 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009090 if (fp == NULL) {
9091 fprintf(stderr, "%s: popen failed\n", __func__);
9092 return RETURN_ERR;
9093 }
9094 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08009095
developerce736392022-09-13 15:24:34 +08009096 if (strlen(str) == 0) // interface not exist
9097 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009098
developerce736392022-09-13 15:24:34 +08009099 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9100 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009101 pclose(fp);
9102
developerce736392022-09-13 15:24:34 +08009103 memset(str, 0, sizeof(str));
9104 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009105 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009106 if (fp == NULL) {
9107 fprintf(stderr, "%s: popen failed\n", __func__);
9108 return RETURN_ERR;
9109 }
9110 fgets(str, sizeof(str), fp);
9111
9112 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9113 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009114 pclose(fp);
developerce736392022-09-13 15:24:34 +08009115
9116 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9117 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9118
9119 // Not supported
9120 output_struct->ssid_RetransCount = 0;
9121 output_struct->ssid_FailedRetransCount = 0;
9122 output_struct->ssid_RetryCount = 0;
9123 output_struct->ssid_MultipleRetryCount = 0;
9124 output_struct->ssid_ACKFailureCount = 0;
9125 output_struct->ssid_AggregatedPacketCount = 0;
9126
developer06a01d92022-09-07 16:32:39 +08009127 return RETURN_OK;
9128}
9129
9130//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).
9131INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9132{
9133 char output_val[16]={'\0'};
9134 char config_file[MAX_BUF_SIZE] = {0};
9135
9136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9137 if (!output)
9138 return RETURN_ERR;
9139 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9140 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9141
9142 if( strcmp(output_val,"1") == 0 )
9143 *output = TRUE;
9144 else
9145 *output = FALSE;
9146 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9147
9148 return RETURN_OK;
9149}
9150
9151INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9152{
9153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9154 char str[MAX_BUF_SIZE]={'\0'};
9155 char string[MAX_BUF_SIZE]={'\0'};
9156 char cmd[MAX_CMD_SIZE]={'\0'};
9157 char *ch;
9158 char config_file[MAX_BUF_SIZE] = {0};
9159 struct params params;
9160
9161 if(enable == TRUE)
9162 strcpy(string,"1");
9163 else
9164 strcpy(string,"0");
9165
9166 params.name = "ap_isolate";
9167 params.value = string;
9168
9169 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9170 wifi_hostapdWrite(config_file,&params,1);
9171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9172
9173 return RETURN_OK;
9174}
9175
9176INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9177{
9178 if (NULL == output_dBm)
9179 return RETURN_ERR;
9180
9181 *output_dBm = 0;
9182 return RETURN_OK;
9183}
9184
9185INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9186{
9187 return RETURN_OK;
9188}
9189INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9190{
9191 return RETURN_OK;
9192}
9193INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9194{
9195 return RETURN_OK;
9196}
9197INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9198{
9199 return RETURN_OK;
9200}
9201INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9202{
9203 return RETURN_OK;
9204}
9205INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9206{
9207 char config_file[MAX_BUF_SIZE] = {0};
9208 struct params list;
9209
9210 list.name = "bss_transition";
9211 list.value = activate?"1":"0";
9212 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9213 wifi_hostapdWrite(config_file, &list, 1);
9214
9215 return RETURN_OK;
9216}
9217wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9218
9219void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9220{
9221 return;
9222}
9223
9224INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9225{
9226 // TODO Implement me!
9227 return RETURN_OK;
9228}
9229
9230INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9231{
developera3c68b92022-09-13 15:27:29 +08009232 char file_name[128] = {0};
9233 char buf[128] = {0};
9234 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009235 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009236
9237 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9238
developer804c64f2022-10-19 13:54:40 +08009239 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009240 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009241 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009242 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9243 f = fopen(file_name, "w");
9244 if (f == NULL)
9245 return RETURN_ERR;
9246 // For mode == 0 is to disable filter, just don't write to the file.
9247 if (mode)
9248 fprintf(f, "%s", essid);
9249
9250 fclose(f);
9251 }
9252 } else { // special case, need to set AP's SSID as filter for each radio.
9253 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9254 f = fopen(file_name, "w");
9255 if (f == NULL)
9256 return RETURN_ERR;
9257
9258 // For mode == 0 is to disable filter, just don't write to the file.
9259 if (mode)
9260 fprintf(f, "%s", essid);
9261
9262 fclose(f);
9263 }
9264
9265 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009266 return RETURN_OK;
9267}
9268
9269INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9270{
9271 // TODO Implement me!
9272 //Apply wifi_pushRadioChannel() instantly
9273 return RETURN_ERR;
9274}
9275
9276INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9277{
9278 // TODO Implement me!
9279 return RETURN_OK;
9280}
9281
9282#ifdef HAL_NETLINK_IMPL
9283static int tidStats_callback(struct nl_msg *msg, void *arg) {
9284 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9285 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9286 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9287 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9288 int rem , tid_index = 0;
9289
9290 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9291 wifi_associated_dev_tid_entry_t *stats_entry;
9292
9293 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9294 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9295 };
9296 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9297 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9298 };
9299
9300 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9301 genlmsg_attrlen(gnlh, 0), NULL);
9302
9303
9304 if (!tb[NL80211_ATTR_STA_INFO]) {
9305 fprintf(stderr, "station stats missing!\n");
9306 return NL_SKIP;
9307 }
9308
9309 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9310 tb[NL80211_ATTR_STA_INFO],
9311 stats_policy)) {
9312 fprintf(stderr, "failed to parse nested attributes!\n");
9313 return NL_SKIP;
9314 }
9315
9316 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9317 {
9318 stats_entry = &out->tid_array[tid_index];
9319
9320 stats_entry->tid = tid_index;
9321 stats_entry->ac = _tid_ac_index_get[tid_index];
9322
9323 if(sinfo[NL80211_STA_INFO_TID_STATS])
9324 {
9325 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9326 printf("failed to parse nested stats attributes!");
9327 return NL_SKIP;
9328 }
9329 }
9330 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9331 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9332
9333 if(tid_index < (PS_MAX_TID - 1))
9334 tid_index++;
9335 }
9336 //ToDo: sum_time_ms, ewma_time_ms
9337 return NL_SKIP;
9338}
9339#endif
9340
9341INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9342{
9343#ifdef HAL_NETLINK_IMPL
9344 Netlink nl;
9345 char if_name[10];
9346
9347 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9348
9349 nl.id = initSock80211(&nl);
9350
9351 if (nl.id < 0) {
9352 fprintf(stderr, "Error initializing netlink \n");
9353 return -1;
9354 }
9355
9356 struct nl_msg* msg = nlmsg_alloc();
9357
9358 if (!msg) {
9359 fprintf(stderr, "Failed to allocate netlink message.\n");
9360 nlfree(&nl);
9361 return -2;
9362 }
9363
9364 genlmsg_put(msg,
9365 NL_AUTO_PORT,
9366 NL_AUTO_SEQ,
9367 nl.id,
9368 0,
9369 0,
9370 NL80211_CMD_GET_STATION,
9371 0);
9372
9373 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9374 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9375 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9376 nl_send_auto(nl.socket, msg);
9377 nl_recvmsgs(nl.socket, nl.cb);
9378 nlmsg_free(msg);
9379 nlfree(&nl);
9380 return RETURN_OK;
9381#else
9382//iw implementation
9383#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9384#define TOTAL_MAX_LINES 50
9385
9386 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9387 char if_name[10];
9388 FILE *fp=NULL;
9389 char pipeCmd[1024]= {'\0'};
9390 int lines,tid_index=0;
9391 char mac_addr[20] = {'\0'};
9392
9393 wifi_associated_dev_tid_entry_t *stats_entry;
9394
9395 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9396 strcpy(mac_addr,clientMacAddress);
9397
9398 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9399 fp= popen(pipeCmd,"r");
9400 if(fp == NULL)
9401 {
9402 perror("popen for station dump failed\n");
9403 return RETURN_ERR;
9404 }
9405 pclose(fp);
9406
9407 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9408 fp=popen(pipeCmd,"r");
9409 if(fp == NULL)
9410 {
9411 perror("popen for grep station failed\n");
9412 return RETURN_ERR;
9413 }
9414 else if(fgets(buf,sizeof(buf),fp) != NULL)
9415 lines=atoi(buf);
9416 else
9417 {
9418 pclose(fp);
9419 fprintf(stderr,"No devices are connected \n");
9420 return RETURN_ERR;
9421 }
9422 pclose(fp);
9423
9424 if(lines == 1)
9425 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9426
9427 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9428 {
9429 stats_entry = &tid_stats->tid_array[tid_index];
9430 stats_entry->tid = tid_index;
9431
9432 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);
9433
9434 fp=popen(pipeCmd,"r");
9435 if(fp ==NULL)
9436 {
9437 perror("Failed to read from tid file \n");
9438 return RETURN_ERR;
9439 }
9440 else if(fgets(buf,sizeof(buf),fp) != NULL)
9441 stats_entry->num_msdus = atol(buf);
9442
9443 pclose(fp);
9444 stats_entry->ac = _tid_ac_index_get[tid_index];
9445// TODO:
9446// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9447// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9448 }
9449 return RETURN_OK;
9450#endif
9451}
9452
9453
9454INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9455{
developer615510b2022-09-27 10:14:35 +08009456 char cmd[128]={0};
9457 char buf[128]={0};
9458 int freq = 0;
9459
9460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9461
9462 // full mode is used to scan all channels.
9463 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9464 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9465 ieee80211_channel_to_frequency(chan_list[0], &freq);
9466
9467 if (freq)
9468 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9469 else
9470 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9471
9472 _syscmd(cmd, buf, sizeof(buf));
9473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9474
developer06a01d92022-09-07 16:32:39 +08009475 return RETURN_OK;
9476}
9477
9478
9479INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9480{
9481 // TODO Implement me!
9482 return RETURN_ERR;
9483}
9484
9485INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9486{
9487 // TODO Implement me!
9488 return RETURN_ERR;
9489}
9490
9491INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9492{
9493 // TODO Implement me!
9494 return RETURN_ERR;
9495}
9496
9497INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9498{
9499 // TODO Implement me!
9500 return RETURN_ERR;
9501}
9502
9503INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9504{
9505 // TODO Implement me!
9506 return RETURN_ERR;
9507}
9508
9509INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9510{
9511 // TODO Implement me!
9512 return RETURN_ERR;
9513}
9514
9515INT wifi_steering_eventUnregister(void)
9516{
9517 // TODO Implement me!
9518 return RETURN_ERR;
9519}
9520
9521INT wifi_delApAclDevices(INT apIndex)
9522{
9523#if 0
9524 char cmd[MAX_BUF_SIZE] = {0};
9525 char buf[MAX_BUF_SIZE] = {0};
9526
9527 /* Not reset proof solution */
9528 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9529 if(_syscmd(cmd,buf,sizeof(buf)))
9530 return RETURN_ERR;
9531#endif
developere6aafda2022-09-13 14:59:28 +08009532 char cmd[MAX_CMD_SIZE]={0};
9533 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009534
developere6aafda2022-09-13 14:59:28 +08009535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9536 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9537 if(_syscmd(cmd, buf, sizeof(buf)))
9538 return RETURN_ERR;
9539 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009540
9541 return RETURN_OK;
9542}
9543
9544#ifdef HAL_NETLINK_IMPL
9545static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9546 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9547 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9548 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9549 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9550 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9551 char mac_addr[20],dev[20];
9552
9553 nla_parse(tb,
9554 NL80211_ATTR_MAX,
9555 genlmsg_attrdata(gnlh, 0),
9556 genlmsg_attrlen(gnlh, 0),
9557 NULL);
9558
9559 if(!tb[NL80211_ATTR_STA_INFO]) {
9560 fprintf(stderr, "sta stats missing!\n");
9561 return NL_SKIP;
9562 }
9563
9564 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9565 fprintf(stderr, "failed to parse nested attributes!\n");
9566 return NL_SKIP;
9567 }
9568 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9569
9570 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9571
9572 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9573 fprintf(stderr, "failed to parse nested rate attributes!");
9574 return NL_SKIP;
9575 }
9576
9577 if(sinfo[NL80211_STA_INFO_TID_STATS])
9578 {
9579 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9580 printf("failed to parse nested stats attributes!");
9581 return NL_SKIP;
9582 }
9583 }
9584
9585 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9586 {
9587 printf("Type is VHT\n");
9588 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9589 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9590
9591 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9592 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9593 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9594 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9595 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9596 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9597 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9598 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9599 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9600 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9601 }
9602 else
9603 {
9604 printf(" OFDM or CCK \n");
9605 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9606 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9607 }
9608
9609 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9610 if(rinfo[NL80211_RATE_INFO_MCS])
9611 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9612 }
9613 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9614 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9615 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9616 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9617
9618 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9619 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9620
9621 if (sinfo[NL80211_STA_INFO_SIGNAL])
9622 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9623 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9624 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9625 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9626 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9627 //rssi_array need to be filled
9628 return NL_SKIP;
9629}
9630#endif
9631
9632INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9633{
9634#ifdef HAL_NETLINK_IMPL
9635 Netlink nl;
9636 char if_name[10];
9637
9638 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9639
9640 if (*output_array_size <= 0)
9641 return RETURN_OK;
9642
9643 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9644 nl.id = initSock80211(&nl);
9645
9646 if (nl.id < 0) {
9647 fprintf(stderr, "Error initializing netlink \n");
9648 return 0;
9649 }
9650
9651 struct nl_msg* msg = nlmsg_alloc();
9652
9653 if (!msg) {
9654 fprintf(stderr, "Failed to allocate netlink message.\n");
9655 nlfree(&nl);
9656 return 0;
9657 }
9658
9659 genlmsg_put(msg,
9660 NL_AUTO_PORT,
9661 NL_AUTO_SEQ,
9662 nl.id,
9663 0,
9664 0,
9665 NL80211_CMD_GET_STATION,
9666 0);
9667
9668 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9669 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9670 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9671 nl_send_auto(nl.socket, msg);
9672 nl_recvmsgs(nl.socket, nl.cb);
9673 nlmsg_free(msg);
9674 nlfree(&nl);
9675 return RETURN_OK;
9676#else
9677 //TODO Implement me
9678 return RETURN_OK;
9679#endif
9680}
9681
9682#ifdef HAL_NETLINK_IMPL
9683static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9684 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9685 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9686 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9687 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9688 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9689 char mac_addr[20],dev[20];
9690
9691 nla_parse(tb,
9692 NL80211_ATTR_MAX,
9693 genlmsg_attrdata(gnlh, 0),
9694 genlmsg_attrlen(gnlh, 0),
9695 NULL);
9696
9697 if(!tb[NL80211_ATTR_STA_INFO]) {
9698 fprintf(stderr, "sta stats missing!\n");
9699 return NL_SKIP;
9700 }
9701
9702 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9703 fprintf(stderr, "failed to parse nested attributes!\n");
9704 return NL_SKIP;
9705 }
9706
9707 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9708
9709 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9710
9711 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9712 fprintf(stderr, "failed to parse nested rate attributes!");
9713 return NL_SKIP;
9714 }
9715
9716 if(sinfo[NL80211_STA_INFO_TID_STATS])
9717 {
9718 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9719 printf("failed to parse nested stats attributes!");
9720 return NL_SKIP;
9721 }
9722 }
9723 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9724 {
9725 printf("Type is VHT\n");
9726 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9727 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9728
9729 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9730 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9731 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9732 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9733 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9734 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9735 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9736 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9737 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9738 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9739 }
9740 else
9741 {
9742 printf(" OFDM or CCK \n");
9743 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9744 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9745 }
9746
9747 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9748 if(rinfo[NL80211_RATE_INFO_MCS])
9749 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9750 }
9751
9752 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9753 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9754 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9755 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9756
9757 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9758 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9759 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9760
9761 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9762 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9763
9764 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9765 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9766
9767 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9768 ((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]);
9769
9770 return NL_SKIP;
9771}
9772#endif
9773
9774INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9775{
9776#ifdef HAL_NETLINK_IMPL
9777 Netlink nl;
9778 char if_name[10];
9779
9780 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9781
9782 if (*output_array_size <= 0)
9783 return RETURN_OK;
9784
9785 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9786
9787 nl.id = initSock80211(&nl);
9788
9789 if(nl.id < 0) {
9790 fprintf(stderr, "Error initializing netlink \n");
9791 return 0;
9792 }
9793
9794 struct nl_msg* msg = nlmsg_alloc();
9795
9796 if(!msg) {
9797 fprintf(stderr, "Failed to allocate netlink message.\n");
9798 nlfree(&nl);
9799 return 0;
9800 }
9801
9802 genlmsg_put(msg,
9803 NL_AUTO_PORT,
9804 NL_AUTO_SEQ,
9805 nl.id,
9806 0,
9807 0,
9808 NL80211_CMD_GET_STATION,
9809 0);
9810
9811 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9812 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9813 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9814 nl_send_auto(nl.socket, msg);
9815 nl_recvmsgs(nl.socket, nl.cb);
9816 nlmsg_free(msg);
9817 nlfree(&nl);
9818 return RETURN_OK;
9819#else
9820 //TODO Implement me
9821 return RETURN_OK;
9822#endif
9823}
9824
9825INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9826{
9827 // TODO Implement me!
9828 char buf[MAX_BUF_SIZE] = {0};
9829 char config_file[MAX_BUF_SIZE] = {0};
9830
9831 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9832 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9833 *activate = (strncmp("1",buf,1) == 0);
9834
9835 return RETURN_OK;
9836}
9837
9838INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9839{
9840 char config_file[MAX_BUF_SIZE] = {0};
9841 struct params list;
9842
9843 list.name = "rrm_neighbor_report";
9844 list.value = activate?"1":"0";
9845 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9846 wifi_hostapdWrite(config_file, &list, 1);
9847
9848 return RETURN_OK;
9849}
9850
9851INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9852{
9853 char buf[32] = {0};
9854 char config_file[MAX_BUF_SIZE] = {0};
9855
9856 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9857 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9858 *activate = (strncmp("1",buf,1) == 0);
9859
9860 return RETURN_OK;
9861}
9862#undef HAL_NETLINK_IMPL
9863#ifdef HAL_NETLINK_IMPL
9864static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9865 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9866 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9867 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9868 char dev[20];
9869 int freq =0 ;
9870 static int i=0;
9871
9872 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9873
9874 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9875 };
9876
9877 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9878
9879 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9880
9881 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9882 fprintf(stderr, "survey data missing!\n");
9883 return NL_SKIP;
9884 }
9885
9886 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9887 {
9888 fprintf(stderr, "failed to parse nested attributes!\n");
9889 return NL_SKIP;
9890 }
9891
9892
9893 if(out[0].array_size == 1 )
9894 {
9895 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9896 {
9897 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9898 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9899 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9900
9901 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9902 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9903 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9904 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9905 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9906 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9907 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9908 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9909 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9910 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9911 if (sinfo[NL80211_SURVEY_INFO_TIME])
9912 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9913 return NL_STOP;
9914 }
9915 }
9916 else
9917 {
9918 if ( i <= out[0].array_size )
9919 {
9920 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9921 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9922 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9923
9924 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9925 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9926 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9927 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9928 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9929 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9930 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9931 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9932 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9933 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9934 if (sinfo[NL80211_SURVEY_INFO_TIME])
9935 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9936 }
9937 }
9938
9939 i++;
9940 return NL_SKIP;
9941}
9942#endif
9943
9944static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9945{
9946 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9947 FILE *fp;
9948
9949 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9950 {
9951 printf("Creating Frequency-Channel Map\n");
9952 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9953 }
9954 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9955 if((fp = popen(command, "r")))
9956 {
9957 fgets(output, sizeof(output), fp);
9958 *freqMHz = atoi(output);
9959 fclose(fp);
9960 }
9961
9962 return 0;
9963}
9964
9965static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9966{
9967 int freqMHz = -1;
9968 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +08009969 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009970
9971 ieee80211_channel_to_frequency(channel, &freqMHz);
9972 if (freqMHz == -1) {
9973 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9974 return -1;
9975 }
9976
developer033b37b2022-10-18 11:27:46 +08009977 phyId = radio_index_to_phy(radioIndex);
9978 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 +08009979 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9980 radioIndex, freqMHz);
9981 return -1;
9982 }
9983
9984 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9985 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9986 return -1;
9987 }
9988
9989 return 0;
9990}
9991
9992static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9993{
9994 const char *ptr = buf;
9995 char *key = NULL;
9996 char *val = NULL;
9997 char line[256] = { '\0' };
9998
9999 while (ptr = get_line_from_str_buf(ptr, line)) {
10000 if (strstr(line, "Frequency")) continue;
10001
10002 key = strtok(line, ":");
10003 val = strtok(NULL, " ");
10004 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10005
10006 if (!strcmp(key, "noise")) {
10007 sscanf(val, "%d", &stats->ch_noise);
10008 if (stats->ch_noise == 0) {
10009 // Workaround for missing noise information.
10010 // Assume -95 for 2.4G and -103 for 5G
10011 if (radioIndex == 0) stats->ch_noise = -95;
10012 if (radioIndex == 1) stats->ch_noise = -103;
10013 }
10014 }
10015 else if (!strcmp(key, "channel active time")) {
10016 sscanf(val, "%llu", &stats->ch_utilization_total);
10017 }
10018 else if (!strcmp(key, "channel busy time")) {
10019 sscanf(val, "%llu", &stats->ch_utilization_busy);
10020 }
10021 else if (!strcmp(key, "channel receive time")) {
10022 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10023 }
10024 else if (!strcmp(key, "channel transmit time")) {
10025 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10026 }
10027 };
10028
10029 return 0;
10030}
10031
10032INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10033{
10034 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10035#ifdef HAL_NETLINK_IMPL
10036 Netlink nl;
10037 wifi_channelStats_t_loc local[array_size];
10038 char if_name[10];
10039
10040 local[0].array_size = array_size;
10041
10042 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
10043
10044 nl.id = initSock80211(&nl);
10045
10046 if (nl.id < 0) {
10047 fprintf(stderr, "Error initializing netlink \n");
10048 return -1;
10049 }
10050
10051 struct nl_msg* msg = nlmsg_alloc();
10052
10053 if (!msg) {
10054 fprintf(stderr, "Failed to allocate netlink message.\n");
10055 nlfree(&nl);
10056 return -2;
10057 }
10058
10059 genlmsg_put(msg,
10060 NL_AUTO_PORT,
10061 NL_AUTO_SEQ,
10062 nl.id,
10063 0,
10064 NLM_F_DUMP,
10065 NL80211_CMD_GET_SURVEY,
10066 0);
10067
10068 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10069 nl_send_auto(nl.socket, msg);
10070 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10071 nl_recvmsgs(nl.socket, nl.cb);
10072 nlmsg_free(msg);
10073 nlfree(&nl);
10074 //Copying the Values
10075 for(int i=0;i<array_size;i++)
10076 {
10077 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10078 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10079 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10080 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10081 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10082 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10083 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10084 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10085 }
10086#else
10087 ULONG channel = 0;
10088 int i;
10089 int number_of_channels = array_size;
10090 char buf[512];
10091 INT ret;
10092 wifi_channelStats_t tmp_stats;
10093
10094 if (number_of_channels == 0) {
10095 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10096 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10097 return RETURN_ERR;
10098 }
10099 number_of_channels = 1;
10100 input_output_channelStats_array[0].ch_number = channel;
10101 }
10102
10103 for (i = 0; i < number_of_channels; i++) {
10104
10105 input_output_channelStats_array[i].ch_noise = 0;
10106 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10107 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10108 input_output_channelStats_array[i].ch_utilization_busy = 0;
10109 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10110 input_output_channelStats_array[i].ch_utilization_total = 0;
10111
10112 memset(buf, 0, sizeof(buf));
10113 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10114 return RETURN_ERR;
10115 }
10116 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10117 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10118 return RETURN_ERR;
10119 }
10120
10121 // XXX: fake missing 'self' counter which is not available in iw survey output
10122 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10123 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10124
10125 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10126 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10127 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10128 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10129 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10130
10131 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",
10132 __func__,
10133 input_output_channelStats_array[i].ch_number,
10134 input_output_channelStats_array[i].ch_noise,
10135 input_output_channelStats_array[i].ch_utilization_total,
10136 input_output_channelStats_array[i].ch_utilization_busy,
10137 input_output_channelStats_array[i].ch_utilization_busy_rx,
10138 input_output_channelStats_array[i].ch_utilization_busy_tx,
10139 input_output_channelStats_array[i].ch_utilization_busy_self,
10140 input_output_channelStats_array[i].ch_utilization_busy_ext);
10141 }
10142#endif
10143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10144 return RETURN_OK;
10145}
10146#define HAL_NETLINK_IMPL
10147
10148/* Hostapd events */
10149
10150#ifndef container_of
10151#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10152#define container_of(ptr, type, member) \
10153 ((type *)((char *)ptr - offset_of(type, member)))
10154#endif /* container_of */
10155
10156struct ctrl {
10157 char sockpath[128];
10158 char sockdir[128];
10159 char bss[IFNAMSIZ];
10160 char reply[4096];
10161 int ssid_index;
10162 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10163 void (*overrun)(struct ctrl *ctrl);
10164 struct wpa_ctrl *wpa;
10165 unsigned int ovfl;
10166 size_t reply_len;
10167 int initialized;
10168 ev_timer retry;
10169 ev_timer watchdog;
10170 ev_stat stat;
10171 ev_io io;
10172};
10173static wifi_newApAssociatedDevice_callback clients_connect_cb;
10174static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10175static struct ctrl wpa_ctrl[MAX_APS];
10176static int initialized;
10177
10178static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10179{
10180 char cbuf[256] = {};
10181 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10182 struct cmsghdr *cmsg;
10183 unsigned int ovfl = ctrl->ovfl;
10184 unsigned int drop;
10185
10186 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10187 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10188 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10189 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10190
10191 drop = ovfl - ctrl->ovfl;
10192 ctrl->ovfl = ovfl;
10193
10194 return drop;
10195}
10196
10197static void ctrl_close(struct ctrl *ctrl)
10198{
10199 if (ctrl->io.cb)
10200 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10201 if (ctrl->retry.cb)
10202 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10203 if (!ctrl->wpa)
10204 return;
10205
10206 wpa_ctrl_detach(ctrl->wpa);
10207 wpa_ctrl_close(ctrl->wpa);
10208 ctrl->wpa = NULL;
10209 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10210}
10211
10212static void ctrl_process(struct ctrl *ctrl)
10213{
10214 const char *str;
10215 int drops;
10216 int level;
10217 int err;
10218
10219 /* Example events:
10220 *
10221 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10222 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10223 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10224 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10225 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10226 */
10227 if (!(str = index(ctrl->reply, '>')))
10228 return;
10229 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10230 return;
10231
10232 str++;
10233
10234 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10235 if (!(str = index(ctrl->reply, ' ')))
10236 return;
10237 wifi_associated_dev_t sta;
10238 memset(&sta, 0, sizeof(sta));
10239
10240 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10241 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10242 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10243
10244 sta.cli_Active=true;
10245
10246 (clients_connect_cb)(ctrl->ssid_index, &sta);
10247 goto handled;
10248 }
10249
10250 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10251 if (!(str = index(ctrl->reply, ' ')))
10252 return;
10253
10254 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10255 goto handled;
10256 }
10257
10258 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10259 printf("CTRL_WPA: handle TERMINATING event\n");
10260 goto retry;
10261 }
10262
10263 if (strncmp("AP-DISABLED", str, 11) == 0) {
10264 printf("CTRL_WPA: handle AP-DISABLED\n");
10265 goto retry;
10266 }
10267
10268 printf("Event not supported!!\n");
10269
10270handled:
10271
10272 if ((drops = ctrl_get_drops(ctrl))) {
10273 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10274 if (ctrl->overrun)
10275 ctrl->overrun(ctrl);
10276 }
10277
10278 return;
10279
10280retry:
10281 printf("WPA_CTRL: closing\n");
10282 ctrl_close(ctrl);
10283 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10284 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10285}
10286
10287static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10288{
10289 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10290 int err;
10291
10292 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10293 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10294 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10295 ctrl->reply[ctrl->reply_len] = 0;
10296 if (err < 0) {
10297 if (errno == EAGAIN || errno == EWOULDBLOCK)
10298 return;
10299 ctrl_close(ctrl);
10300 ev_timer_again(EV_A_ &ctrl->retry);
10301 return;
10302 }
10303
10304 ctrl_process(ctrl);
10305}
10306
10307static int ctrl_open(struct ctrl *ctrl)
10308{
10309 int fd;
10310
10311 if (ctrl->wpa)
10312 return 0;
10313
10314 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10315 if (!ctrl->wpa)
10316 goto err;
10317
10318 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10319 goto err_close;
10320
10321 fd = wpa_ctrl_get_fd(ctrl->wpa);
10322 if (fd < 0)
10323 goto err_detach;
10324
10325 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10326 goto err_detach;
10327
10328 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10329 ev_io_start(EV_DEFAULT_ &ctrl->io);
10330
10331 return 0;
10332
10333err_detach:
10334 wpa_ctrl_detach(ctrl->wpa);
10335err_close:
10336 wpa_ctrl_close(ctrl->wpa);
10337err:
10338 ctrl->wpa = NULL;
10339 return -1;
10340}
10341
10342static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10343{
10344 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10345
10346 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10347 ctrl_open(ctrl);
10348}
10349
10350static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10351{
10352 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10353
10354 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10355 if (ctrl_open(ctrl) == 0) {
10356 printf("WPA_CTRL: retry successful\n");
10357 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10358 }
10359}
10360
10361int ctrl_enable(struct ctrl *ctrl)
10362{
10363 if (ctrl->wpa)
10364 return 0;
10365
10366 if (!ctrl->stat.cb) {
10367 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10368 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10369 }
10370
10371 if (!ctrl->retry.cb) {
10372 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10373 }
10374
10375 return ctrl_open(ctrl);
10376}
10377
10378static void
10379ctrl_msg_cb(char *buf, size_t len)
10380{
10381 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10382
10383 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10384 ctrl_process(ctrl);
10385}
10386
10387static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10388{
10389 int err;
10390
10391 if (!ctrl->wpa)
10392 return -1;
10393 if (*reply_len < 2)
10394 return -1;
10395
10396 (*reply_len)--;
10397 ctrl->reply_len = sizeof(ctrl->reply);
10398 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10399 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10400 if (err < 0)
10401 return err;
10402
10403 if (ctrl->reply_len > *reply_len)
10404 ctrl->reply_len = *reply_len;
10405
10406 *reply_len = ctrl->reply_len;
10407 memcpy(reply, ctrl->reply, *reply_len);
10408 reply[*reply_len - 1] = 0;
10409 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10410 return 0;
10411}
10412
10413static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10414{
10415 const char *pong = "PONG";
10416 const char *ping = "PING";
10417 char reply[1024];
10418 size_t len = sizeof(reply);
10419 int err;
10420 ULONG s, snum;
10421 INT ret;
10422 BOOL status;
10423
10424 printf("WPA_CTRL: watchdog cb\n");
10425
10426 ret = wifi_getSSIDNumberOfEntries(&snum);
10427 if (ret != RETURN_OK) {
10428 printf("%s: failed to get SSID count", __func__);
10429 return;
10430 }
10431
10432 if (snum > MAX_APS) {
10433 printf("more ssid than supported! %lu\n", snum);
10434 return;
10435 }
10436
10437 for (s = 0; s < snum; s++) {
10438 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10439 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10440 continue;
10441 }
10442 if (status == false) continue;
10443
10444 memset(reply, 0, sizeof(reply));
10445 len = sizeof(reply);
10446 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10447 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10448 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10449 continue;
10450
10451 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10452 ctrl_close(&wpa_ctrl[s]);
10453 printf("WPA_CTRL: ev_timer_again %d\n", s);
10454 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10455 }
10456}
10457
10458static int init_wpa()
10459{
10460 int ret = 0, i = 0;
10461 ULONG s, snum;
10462
10463 ret = wifi_getSSIDNumberOfEntries(&snum);
10464 if (ret != RETURN_OK) {
10465 printf("%s: failed to get SSID count", __func__);
10466 return RETURN_ERR;
10467 }
10468
10469 if (snum > MAX_APS) {
10470 printf("more ssid than supported! %lu\n", snum);
10471 return RETURN_ERR;
10472 }
10473
10474 for (s = 0; s < snum; s++) {
10475 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10476 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10477 wpa_ctrl[s].ssid_index = s;
10478 ctrl_enable(&wpa_ctrl[s]);
10479 }
10480
10481 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10482 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10483
10484 initialized = 1;
10485 printf("WPA_CTRL: initialized\n");
10486
10487 return RETURN_OK;
10488}
10489
10490void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10491{
10492 clients_connect_cb = callback_proc;
10493 if (!initialized)
10494 init_wpa();
10495}
10496
10497void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10498{
10499 clients_disconnect_cb = callback_proc;
10500 if (!initialized)
10501 init_wpa();
10502}
10503
10504INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10505{
10506 // TODO Implement me!
10507 return RETURN_ERR;
10508}
10509
10510INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10511{
10512 // TODO Implement me!
10513 return RETURN_ERR;
10514}
10515
10516INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10517{
10518 int i;
10519 char cmd[256];
10520 char channel_numbers_buf[256];
10521 char dfs_state_buf[256];
10522 char line[256];
10523 const char *ptr;
10524
10525 memset(cmd, 0, sizeof(cmd));
10526 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10527 memset(line, 0, sizeof(line));
10528 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10529 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10530
10531 if (radioIndex == 0) { // 2.4G - all allowed
10532 if (outputMapSize < 11) {
10533 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10534 return RETURN_ERR;
10535 }
10536
10537 for (i = 0; i < 11; i++) {
10538 outputMap[i].ch_number = i + 1;
10539 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10540 }
10541
10542 return RETURN_OK;
10543 }
10544
10545 if (radioIndex == 1) { // 5G
10546// Example output of iw list:
10547//
10548// Frequencies:
10549// * 5180 MHz [36] (17.0 dBm)
10550// * 5200 MHz [40] (17.0 dBm)
10551// * 5220 MHz [44] (17.0 dBm)
10552// * 5240 MHz [48] (17.0 dBm)
10553// * 5260 MHz [52] (23.0 dBm) (radar detection)
10554// DFS state: usable (for 78930 sec)
10555// DFS CAC time: 60000 ms
10556// * 5280 MHz [56] (23.0 dBm) (radar detection)
10557// DFS state: usable (for 78930 sec)
10558// DFS CAC time: 60000 ms
10559// * 5300 MHz [60] (23.0 dBm) (radar detection)
10560// DFS state: usable (for 78930 sec)
10561// DFS CAC time: 60000 ms
10562// * 5320 MHz [64] (23.0 dBm) (radar detection)
10563// DFS state: usable (for 78930 sec)
10564// DFS CAC time: 60000 ms
10565// * 5500 MHz [100] (disabled)
10566// * 5520 MHz [104] (disabled)
10567// * 5540 MHz [108] (disabled)
10568// * 5560 MHz [112] (disabled)
10569//
10570// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10571 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10572 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10573 return RETURN_ERR;
10574 }
10575
10576 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10577 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10578 return RETURN_ERR;
10579 }
10580
10581 ptr = channel_numbers_buf;
10582 i = 0;
10583 while (ptr = get_line_from_str_buf(ptr, line)) {
10584 if (i >= outputMapSize) {
10585 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10586 return RETURN_ERR;
10587 }
10588 sscanf(line, "%d", &outputMap[i].ch_number);
10589
10590 memset(cmd, 0, sizeof(cmd));
10591 // Below command should fetch string for DFS state (usable, available or unavailable)
10592 // Example line: "DFS state: usable (for 78930 sec)"
10593 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) {
10594 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10595 return RETURN_ERR;
10596 }
10597
10598 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10599 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10600 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10601 return RETURN_ERR;
10602 }
10603
10604 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10605
10606 if (!strcmp(dfs_state_buf, "usable")) {
10607 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10608 } else if (!strcmp(dfs_state_buf, "available")) {
10609 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10610 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10611 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10612 } else {
10613 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10614 }
10615 i++;
10616 }
10617
10618 return RETURN_OK;
10619 }
10620
10621 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10622 return RETURN_ERR;
10623}
10624
10625INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10626{
10627 // TODO Implement me!
10628 return RETURN_ERR;
10629}
10630
10631INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10632{
10633 return RETURN_OK;
10634}
10635
10636INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10637{
10638 // TODO Implement me!
10639 return RETURN_ERR;
10640}
10641
10642INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10643{
10644 // TODO API refrence Implementaion is present on RPI hal
10645 return RETURN_ERR;
10646}
10647
10648INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10649{
developera5005b62022-09-13 15:43:35 +080010650 char cmd[128]={'\0'};
10651 char buf[128]={'\0'};
10652 char *support;
10653 int maximum_tx = 0, current_tx = 0;
10654
10655 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10656 if(txpwr_pcntg == NULL)
10657 return RETURN_ERR;
10658
10659 // Get the maximum tx power of the device
10660 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10661 _syscmd(cmd, buf, sizeof(buf));
10662 maximum_tx = strtol(buf, NULL, 10);
10663
10664 // Get the current tx power
10665 memset(cmd, 0, sizeof(cmd));
10666 memset(buf, 0, sizeof(buf));
10667 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10668 _syscmd(cmd, buf, sizeof(buf));
10669 current_tx = strtol(buf, NULL, 10);
10670
10671 // Get the power supported list and find the current power percentage in supported list
10672 memset(buf, 0, sizeof(buf));
10673 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10674 support = strtok(buf, ",");
10675 while(true)
10676 {
10677 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 +080010678 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010679 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010680 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010681 }
10682 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10683 if (tmp == current_tx) {
10684 *txpwr_pcntg = strtol(support, NULL, 10);
10685 break;
10686 }
10687 support = strtok(NULL, ",");
10688 }
10689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010690 return RETURN_OK;
10691}
10692
10693INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10694{
developer58599c22022-09-13 16:40:34 +080010695 // TODO precac feature.
10696 struct params params = {0};
10697 char config_file[128] = {0};
10698
10699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10700
10701 params.name = "enable_background_radar";
10702 params.value = enable?"1":"0";
10703 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10704 wifi_hostapdWrite(config_file, &params, 1);
10705 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10706
10707 /* TODO precac feature */
10708
10709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10710 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010711}
10712
10713INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10714{
developer58599c22022-09-13 16:40:34 +080010715 char config_file[128] = {0};
10716 char buf[64] = {0};
10717
10718 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10719 if (NULL == enable || NULL == precac)
10720 return RETURN_ERR;
10721
10722 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10723 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10724 if (strncmp(enable, "1", 1) == 0)
10725 *enable = true;
10726 else
10727 *enable = false;
10728
10729 /* TODO precac feature */
10730
10731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10732 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010733}
10734
10735INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10736{
developer58599c22022-09-13 16:40:34 +080010737 *supported = TRUE;
10738 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010739}
10740
developer3e6b1692022-09-30 18:04:05 +080010741INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10742{
10743 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10744 struct params params = {0};
10745 char config_file[64] = {0};
10746 char buf[64] = {0};
10747 unsigned int set_mu_type = 0;
10748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10749
10750 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10751 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10752
10753 if (strlen(buf) > 0)
10754 set_mu_type = strtol(buf, NULL, 10);
10755
10756 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10757 set_mu_type &= ~0x05; // unset bit 0, 2
10758 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10759 set_mu_type |= 0x01;
10760 set_mu_type &= ~0x04;
10761 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10762 set_mu_type &= ~0x01;
10763 set_mu_type |= 0x04;
10764 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10765 set_mu_type |= 0x05; // set bit 0, 2
10766 }
10767
10768 params.name = "hemu_onoff";
10769 sprintf(buf, "%u", set_mu_type);
10770 params.value = buf;
10771 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10772 wifi_hostapdWrite(config_file, &params, 1);
10773 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10774
10775 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10776 return RETURN_OK;
10777}
10778
10779INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10780{
10781 struct params params={0};
10782 char config_file[64] = {0};
10783 char buf[64] = {0};
10784 unsigned int get_mu_type = 0;
10785
10786 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10787
10788 if (mu_type == NULL)
10789 return RETURN_ERR;
10790
10791 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10792 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10793 get_mu_type = strtol(buf, NULL, 10);
10794
10795 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10796 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10797 else if (get_mu_type & 0x04)
10798 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10799 else if (get_mu_type & 0x01)
10800 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10801 else
10802 *mu_type = WIFI_DL_MU_TYPE_NONE;
10803
10804 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10805 return RETURN_OK;
10806}
10807
10808INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10809{
10810 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10811 struct params params={0};
10812 char config_file[64] = {0};
10813 char buf[64] = {0};
10814 unsigned int set_mu_type = 0;
10815 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10816
10817 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10818 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10819
10820 if (strlen(buf) > 0)
10821 set_mu_type = strtol(buf, NULL, 10);
10822
10823 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10824 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10825 set_mu_type &= ~0x0a;
10826 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10827 set_mu_type |= 0x02;
10828 set_mu_type &= ~0x08;
10829 }
10830
10831 params.name = "hemu_onoff";
10832 sprintf(buf, "%u", set_mu_type);
10833 params.value = buf;
10834 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10835 wifi_hostapdWrite(config_file, &params, 1);
10836 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10837
10838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10839 return RETURN_OK;
10840}
10841
10842INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10843{
10844 struct params params={0};
10845 char config_file[64] = {0};
10846 char buf[64] = {0};
10847 unsigned int get_mu_type = 0;
10848
10849 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10850
10851 if (mu_type == NULL)
10852 return RETURN_ERR;
10853
10854 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10855 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10856
10857 get_mu_type = strtol(buf, NULL, 10);
10858 if (get_mu_type & 0x02)
10859 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10860 else
10861 *mu_type = WIFI_DL_MU_TYPE_NONE;
10862
10863 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10864 return RETURN_OK;
10865}
10866
10867
developer454b9462022-09-13 15:29:16 +080010868INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10869{
10870 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010871 char buf[256] = {0};
10872 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010873 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010874 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010875 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010876 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010877
10878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10879
developer254882b2022-09-30 17:12:31 +080010880 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010881 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10882 return RETURN_ERR;
10883 }
developer454b9462022-09-13 15:29:16 +080010884
developer254882b2022-09-30 17:12:31 +080010885 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010886 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010887
developer254882b2022-09-30 17:12:31 +080010888 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10889 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080010890 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010891 _syscmd(cmd, buf, sizeof(buf));
10892 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10893 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10894 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010895 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 +080010896 _syscmd(cmd, buf, sizeof(buf));
10897 }
10898 if (band == band_5) {
10899 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10900 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010901 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 +080010902 _syscmd(cmd, buf, sizeof(buf));
10903 }
10904 }
10905 }
10906 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010907
developer254882b2022-09-30 17:12:31 +080010908 if (guard_interval == wifi_guard_interval_400)
10909 strcpy(GI, "0.4");
10910 else if (guard_interval == wifi_guard_interval_800)
10911 strcpy(GI, "0.8");
10912 else if (guard_interval == wifi_guard_interval_1600)
10913 strcpy(GI, "1.6");
10914 else if (guard_interval == wifi_guard_interval_3200)
10915 strcpy(GI, "3.2");
10916 else if (guard_interval == wifi_guard_interval_auto)
10917 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010918 // Record GI for get GI function
10919 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10920 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010921 if (f == NULL)
10922 return RETURN_ERR;
10923 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010924 fclose(f);
10925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10926 return RETURN_OK;
10927}
10928
10929INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10930{
10931 char buf[32] = {0};
10932 char cmd[64] = {0};
10933
10934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10935
10936 if (guard_interval == NULL)
10937 return RETURN_ERR;
10938
10939 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10940 _syscmd(cmd, buf, sizeof(buf));
10941
10942 if (strncmp(buf, "0.4", 3) == 0)
10943 *guard_interval = wifi_guard_interval_400;
10944 else if (strncmp(buf, "0.8", 3) == 0)
10945 *guard_interval = wifi_guard_interval_800;
10946 else if (strncmp(buf, "1.6", 3) == 0)
10947 *guard_interval = wifi_guard_interval_1600;
10948 else if (strncmp(buf, "3.2", 3) == 0)
10949 *guard_interval = wifi_guard_interval_3200;
10950 else
10951 *guard_interval = wifi_guard_interval_auto;
10952
10953 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10954 return RETURN_OK;
10955}
10956
developer3cc61d12022-09-13 16:36:05 +080010957INT wifi_setBSSColor(INT radio_index, UCHAR color)
10958{
10959 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10960 struct params params = {0};
10961 char config_file[128] = {0};
10962 char bss_color[4] ={0};
10963
10964 params.name = "he_bss_color";
10965 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10966 params.value = bss_color;
10967 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10968 wifi_hostapdWrite(config_file, &params, 1);
10969 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10970
10971 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10972 return RETURN_OK;
10973}
10974
10975INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10976{
10977 char config_file[128] = {0};
10978 char buf[64] = {0};
10979 char temp_output[128] = {'\0'};
10980
10981 wifi_dbg_printf("\nFunc=%s\n", __func__);
10982 if (NULL == color)
10983 return RETURN_ERR;
10984
10985 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10986 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10987
10988 if(strlen(buf) > 0) {
10989 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10990 } else {
10991 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10992 }
10993
10994 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10995 wifi_dbg_printf("\noutput_string=%s\n", color);
10996
10997 return RETURN_OK;
10998}
10999
developer06a01d92022-09-07 16:32:39 +080011000/* multi-psk support */
11001INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11002{
11003 char cmd[256];
11004
11005 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11006 AP_PREFIX,
11007 apIndex,
11008 mac[0],
11009 mac[1],
11010 mac[2],
11011 mac[3],
11012 mac[4],
11013 mac[5]
11014 );
11015 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11016 _syscmd(cmd, key->wifi_keyId, 64);
11017
11018
11019 return RETURN_OK;
11020}
11021
11022INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11023{
11024 FILE *fd = NULL;
11025 char fname[100];
11026 char cmd[128] = {0};
11027 char out[64] = {0};
11028 wifi_key_multi_psk_t * key = NULL;
11029 if(keysNumber < 0)
11030 return RETURN_ERR;
11031
11032 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11033 fd = fopen(fname, "w");
11034 if (!fd) {
11035 return RETURN_ERR;
11036 }
11037 key= (wifi_key_multi_psk_t *) keys;
11038 for(int i=0; i<keysNumber; ++i, key++) {
11039 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11040 }
11041 fclose(fd);
11042
11043 //reload file
11044 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
11045 _syscmd(cmd, out, 64);
11046 return RETURN_OK;
11047}
11048
11049INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11050{
11051 FILE *fd = NULL;
11052 char fname[100];
11053 char * line = NULL;
11054 char * pos = NULL;
11055 size_t len = 0;
11056 ssize_t read = 0;
11057 INT ret = RETURN_OK;
11058 wifi_key_multi_psk_t *keys_it = NULL;
11059
11060 if (keysNumber < 1) {
11061 return RETURN_ERR;
11062 }
11063
11064 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11065 fd = fopen(fname, "r");
11066 if (!fd) {
11067 return RETURN_ERR;
11068 }
11069
11070 if (keys == NULL) {
11071 ret = RETURN_ERR;
11072 goto close;
11073 }
11074
11075 keys_it = keys;
11076 while ((read = getline(&line, &len, fd)) != -1) {
11077 //Strip trailing new line if present
11078 if (read > 0 && line[read-1] == '\n') {
11079 line[read-1] = '\0';
11080 }
11081
11082 if(strcmp(line,"keyid=")) {
11083 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11084 if (!(pos = index(line, ' '))) {
11085 ret = RETURN_ERR;
11086 goto close;
11087 }
11088 pos++;
11089 //Here should be 00:00:00:00:00:00
11090 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11091 printf("Not supported MAC: %s\n", pos);
11092 }
11093 if (!(pos = index(pos, ' '))) {
11094 ret = RETURN_ERR;
11095 goto close;
11096 }
11097 pos++;
11098
11099 //The rest is PSK
11100 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11101 keys_it++;
11102
11103 if(--keysNumber <= 0)
11104 break;
11105 }
11106 }
11107
11108close:
11109 free(line);
11110 fclose(fd);
11111 return ret;
11112}
11113/* end of multi-psk support */
11114
11115INT wifi_setNeighborReports(UINT apIndex,
11116 UINT numNeighborReports,
11117 wifi_NeighborReport_t *neighborReports)
11118{
11119 char cmd[256] = { 0 };
11120 char hex_bssid[13] = { 0 };
11121 char bssid[18] = { 0 };
11122 char nr[256] = { 0 };
11123 char ssid[256];
11124 char hex_ssid[256];
11125 INT ret;
11126
11127 /*rmeove all neighbors*/
11128 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
11129 sprintf(cmd, "hostapd_cli show_neighbor -i %s%d | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s%d",AP_PREFIX,apIndex,AP_PREFIX,apIndex);
11130 system(cmd);
11131
11132 for(unsigned int i = 0; i < numNeighborReports; i++)
11133 {
11134 memset(ssid, 0, sizeof(ssid));
11135 ret = wifi_getSSIDName(apIndex, ssid);
11136 if (ret != RETURN_OK)
11137 return RETURN_ERR;
11138
11139 memset(hex_ssid, 0, sizeof(hex_ssid));
11140 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11141 sprintf(hex_ssid + k,"%02x", ssid[j]);
11142
11143 snprintf(hex_bssid, sizeof(hex_bssid),
11144 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11145 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11146 snprintf(bssid, sizeof(bssid),
11147 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11148 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11149
11150 snprintf(nr, sizeof(nr),
11151 "%s" // bssid
11152 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11153 "%02hhx" // operclass
11154 "%02hhx" // channel
11155 "%02hhx", // phy_mode
11156 hex_bssid,
11157 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11158 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11159 neighborReports[i].opClass,
11160 neighborReports[i].channel,
11161 neighborReports[i].phyTable);
11162
11163 snprintf(cmd, sizeof(cmd),
11164 "hostapd_cli set_neighbor "
11165 "%s " // bssid
11166 "ssid=%s " // ssid
11167 "nr=%s " // nr
11168 "-i %s%d",
11169 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
11170
11171 if (WEXITSTATUS(system(cmd)) != 0)
11172 {
11173 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11174 }
11175 }
11176
11177 return RETURN_OK;
11178}
11179
11180INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11181{
11182 return RETURN_OK;
11183}
11184
11185#ifdef _WIFI_HAL_TEST_
11186int main(int argc,char **argv)
11187{
11188 int index;
11189 INT ret=0;
11190 char buf[1024]="";
11191
11192 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11193 if(argc<3)
11194 {
11195 if(argc==2)
11196 {
11197 if(!strcmp(argv[1], "init"))
11198 return wifi_init();
11199 if(!strcmp(argv[1], "reset"))
11200 return wifi_reset();
11201 if(!strcmp(argv[1], "wifi_getHalVersion"))
11202 {
11203 char buffer[64];
11204 if(wifi_getHalVersion(buffer)==RETURN_OK)
11205 printf("Version: %s\n", buffer);
11206 else
11207 printf("Error in wifi_getHalVersion\n");
11208 return RETURN_OK;
11209 }
11210 }
11211 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11212 exit(-1);
11213 }
11214
11215 index = atoi(argv[2]);
11216 if(strstr(argv[1], "wifi_getApName")!=NULL)
11217 {
11218 wifi_getApName(index,buf);
11219 printf("Ap name is %s \n",buf);
11220 return 0;
11221 }
11222 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11223 {
11224 BOOL b = FALSE;
11225 BOOL *output_bool = &b;
11226 wifi_getRadioAutoChannelEnable(index,output_bool);
11227 printf("Channel enabled = %d \n",b);
11228 return 0;
11229 }
11230 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11231 {
11232 wifi_getApWpaEncryptionMode(index,buf);
11233 printf("encryption enabled = %s\n",buf);
11234 return 0;
11235 }
11236 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11237 {
11238 BOOL b = FALSE;
11239 BOOL *output_bool = &b;
11240 wifi_getApSsidAdvertisementEnable(index,output_bool);
11241 printf("advertisment enabled = %d\n",b);
11242 return 0;
11243 }
11244 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11245 {
11246 if(argc <= 3 )
11247 {
11248 printf("Insufficient arguments \n");
11249 exit(-1);
11250 }
11251
11252 char sta[20] = {'\0'};
11253 ULLONG handle= 0;
11254 strcpy(sta,argv[3]);
11255 mac_address_t st;
11256 mac_addr_aton(st,sta);
11257
11258 wifi_associated_dev_tid_stats_t tid_stats;
11259 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11260 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11261 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);
11262 }
11263
11264 if(strstr(argv[1], "getApEnable")!=NULL) {
11265 BOOL enable;
11266 ret=wifi_getApEnable(index, &enable);
11267 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11268 }
11269 else if(strstr(argv[1], "setApEnable")!=NULL) {
11270 BOOL enable = atoi(argv[3]);
11271 ret=wifi_setApEnable(index, enable);
11272 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11273 }
11274 else if(strstr(argv[1], "getApStatus")!=NULL) {
11275 char status[64];
11276 ret=wifi_getApStatus(index, status);
11277 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11278 }
11279 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11280 {
11281 wifi_getSSIDNameStatus(index,buf);
11282 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11283 return 0;
11284 }
11285 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11286 wifi_ssidTrafficStats2_t stats={0};
11287 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11288 printf("%s %d: returns %d\n", argv[1], index, ret);
11289 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11290 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11291 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11292 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11293 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11294 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11295 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11296 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11297 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11298 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11299 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11300 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11301 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11302 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11303 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11304 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11305 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11306 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11307 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11308 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11309 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11310 }
11311 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11312 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11313 UINT array_size=0;
11314 UINT i=0;
11315 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11316 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11317 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11318 printf(" neighbor %d:\n", i);
11319 printf(" ap_SSID =%s\n", pt->ap_SSID);
11320 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11321 printf(" ap_Mode =%s\n", pt->ap_Mode);
11322 printf(" ap_Channel =%d\n", pt->ap_Channel);
11323 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11324 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11325 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11326 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11327 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11328 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11329 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11330 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11331 printf(" ap_Noise =%d\n", pt->ap_Noise);
11332 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11333 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11334 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11335 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11336 }
11337 if(neighbor_ap_array)
11338 free(neighbor_ap_array); //make sure to free the list
11339 }
11340 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11341 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11342 UINT array_size=0;
11343 UINT i=0;
11344 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11345 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11346 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11347 printf(" associated_dev %d:\n", i);
11348 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11349 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11350 printf(" cli_SNR =%d\n", pt->cli_SNR);
11351 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11352 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11353 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11354 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11355 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11356 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11357 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11358 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11359 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11360 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11361 }
11362 if(associated_dev_array)
11363 free(associated_dev_array); //make sure to free the list
11364 }
11365
11366 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11367 {
11368#define MAX_ARRAY_SIZE 64
11369 int i, array_size;
11370 char *p, *ch_str;
11371 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11372
11373 if(argc != 5)
11374 {
11375 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11376 exit(-1);
11377 }
11378 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11379
11380 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11381 {
11382 strtok_r(ch_str, ",", &p);
11383 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11384 }
11385 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11386 if(!array_size)
11387 array_size=1;//Need to print current channel statistics
11388 for(i=0; i<array_size; i++)
11389 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11390 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11391 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11392 input_output_channelStats_array[i].ch_number,\
11393 input_output_channelStats_array[i].ch_noise,\
11394 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11395 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11396 input_output_channelStats_array[i].ch_utilization_busy,\
11397 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11398 input_output_channelStats_array[i].ch_utilization_total);
11399 }
11400
11401 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11402 {
11403 if(argc <= 3 )
11404 {
11405 printf("Insufficient arguments \n");
11406 exit(-1);
11407 }
11408 char mac_addr[20] = {'\0'};
11409 wifi_device_t output_struct;
11410 int dev_index = atoi(argv[3]);
11411
11412 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11413 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11414 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);
11415 }
11416
11417 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11418 {
11419 if (argc <= 3)
11420 {
11421 printf("Insufficient arguments\n");
11422 exit(-1);
11423 }
11424 char args[256];
11425 wifi_NeighborReport_t *neighborReports;
11426
11427 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11428 if (!neighborReports)
11429 {
11430 printf("Failed to allocate memory");
11431 exit(-1);
11432 }
11433
11434 for (int i = 3; i < argc; ++i)
11435 {
11436 char *val;
11437 int j = 0;
11438 memset(args, 0, sizeof(args));
11439 strncpy(args, argv[i], sizeof(args));
11440 val = strtok(args, ";");
11441 while (val != NULL)
11442 {
11443 if (j == 0)
11444 {
11445 mac_addr_aton(neighborReports[i - 3].bssid, val);
11446 } else if (j == 1)
11447 {
11448 neighborReports[i - 3].info = strtol(val, NULL, 16);
11449 } else if (j == 2)
11450 {
11451 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11452 } else if (j == 3)
11453 {
11454 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11455 } else if (j == 4)
11456 {
11457 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11458 } else {
11459 printf("Insufficient arguments]n\n");
11460 exit(-1);
11461 }
11462 val = strtok(NULL, ";");
11463 j++;
11464 }
11465 }
11466
11467 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11468 if (ret != RETURN_OK)
11469 {
11470 printf("wifi_setNeighborReports ret = %d", ret);
11471 exit(-1);
11472 }
11473 }
11474 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11475 {
11476 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11477 printf("%s.\n", buf);
11478 else
11479 printf("Error returned\n");
11480 }
11481 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11482 {
11483 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11484 printf("%s.\n", buf);
11485 else
11486 printf("Error returned\n");
11487 }
11488 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11489 {
11490 if (argc <= 2)
11491 {
11492 printf("Insufficient arguments\n");
11493 exit(-1);
11494 }
11495 char buf[64]= {'\0'};
11496 wifi_getRadioOperatingChannelBandwidth(index,buf);
11497 printf("Current bandwidth is %s \n",buf);
11498 return 0;
11499 }
11500 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11501 {
11502 if (argc <= 5)
11503 {
11504 printf("Insufficient arguments\n");
11505 exit(-1);
11506 }
11507 UINT channel = atoi(argv[3]);
11508 UINT width = atoi(argv[4]);
11509 UINT beacon = atoi(argv[5]);
11510 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11511 printf("Result = %d", ret);
11512 }
11513
11514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11515 return 0;
11516}
11517
11518#endif
11519
11520#ifdef WIFI_HAL_VERSION_3
11521
developer1e5aa162022-09-13 16:06:24 +080011522INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11523{
11524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11525 if (bitMap & WIFI_BITRATE_1MBPS)
11526 strcat(BasicRate, "1,");
11527 if (bitMap & WIFI_BITRATE_2MBPS)
11528 strcat(BasicRate, "2,");
11529 if (bitMap & WIFI_BITRATE_5_5MBPS)
11530 strcat(BasicRate, "5.5,");
11531 if (bitMap & WIFI_BITRATE_6MBPS)
11532 strcat(BasicRate, "6,");
11533 if (bitMap & WIFI_BITRATE_9MBPS)
11534 strcat(BasicRate, "9,");
11535 if (bitMap & WIFI_BITRATE_11MBPS)
11536 strcat(BasicRate, "11,");
11537 if (bitMap & WIFI_BITRATE_12MBPS)
11538 strcat(BasicRate, "12,");
11539 if (bitMap & WIFI_BITRATE_18MBPS)
11540 strcat(BasicRate, "18,");
11541 if (bitMap & WIFI_BITRATE_24MBPS)
11542 strcat(BasicRate, "24,");
11543 if (bitMap & WIFI_BITRATE_36MBPS)
11544 strcat(BasicRate, "36,");
11545 if (bitMap & WIFI_BITRATE_48MBPS)
11546 strcat(BasicRate, "48,");
11547 if (bitMap & WIFI_BITRATE_54MBPS)
11548 strcat(BasicRate, "54,");
11549 if (strlen(BasicRate) != 0) // remove last comma
11550 BasicRate[strlen(BasicRate) - 1] = '\0';
11551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11552 return RETURN_OK;
11553}
11554
11555INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11556{
11557 UINT BitMap = 0;
11558 char *rate;
11559
11560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11561 rate = strtok(BasicRatesList, ",");
11562 while(rate != NULL)
11563 {
11564 if (strcmp(rate, "1") == 0)
11565 BitMap |= WIFI_BITRATE_1MBPS;
11566 else if (strcmp(rate, "2") == 0)
11567 BitMap |= WIFI_BITRATE_2MBPS;
11568 else if (strcmp(rate, "5.5") == 0)
11569 BitMap |= WIFI_BITRATE_5_5MBPS;
11570 else if (strcmp(rate, "6") == 0)
11571 BitMap |= WIFI_BITRATE_6MBPS;
11572 else if (strcmp(rate, "9") == 0)
11573 BitMap |= WIFI_BITRATE_9MBPS;
11574 else if (strcmp(rate, "11") == 0)
11575 BitMap |= WIFI_BITRATE_11MBPS;
11576 else if (strcmp(rate, "12") == 0)
11577 BitMap |= WIFI_BITRATE_12MBPS;
11578 else if (strcmp(rate, "18") == 0)
11579 BitMap |= WIFI_BITRATE_18MBPS;
11580 else if (strcmp(rate, "24") == 0)
11581 BitMap |= WIFI_BITRATE_24MBPS;
11582 else if (strcmp(rate, "36") == 0)
11583 BitMap |= WIFI_BITRATE_36MBPS;
11584 else if (strcmp(rate, "48") == 0)
11585 BitMap |= WIFI_BITRATE_48MBPS;
11586 else if (strcmp(rate, "54") == 0)
11587 BitMap |= WIFI_BITRATE_54MBPS;
11588 rate = strtok(NULL, ",");
11589 }
11590 *basicRateBitMap = BitMap;
11591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11592 return RETURN_OK;
11593}
11594
11595// 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 +080011596INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11597{
developer1e5aa162022-09-13 16:06:24 +080011598 char buf[128] = {0};
11599 char cmd[128] = {0};
11600 char config_file[64] = {0};
11601 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011602 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011603 wifi_radio_operationParam_t current_param;
11604
11605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11606
11607 multiple_set = TRUE;
11608 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11609 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11610 return RETURN_ERR;
11611 }
11612 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11613 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11614 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11615 return RETURN_ERR;
11616 }
11617 }
developer5884e982022-10-06 10:52:50 +080011618
11619 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11620 bandwidth = 20;
11621 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11622 bandwidth = 40;
11623 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11624 bandwidth = 80;
11625 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11626 bandwidth = 160;
11627 if (operationParam->autoChannelEnabled){
11628 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11629 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11630 return RETURN_ERR;
11631 }
11632 }else{
developer1e5aa162022-09-13 16:06:24 +080011633 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11634 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11635 return RETURN_ERR;
11636 }
11637 }
developer5884e982022-10-06 10:52:50 +080011638
developer1e5aa162022-09-13 16:06:24 +080011639 if (current_param.variant != operationParam->variant) {
11640 // Two different definition bit map, so need to check every bit.
11641 if (operationParam->variant & WIFI_80211_VARIANT_A)
11642 set_mode |= WIFI_MODE_A;
11643 if (operationParam->variant & WIFI_80211_VARIANT_B)
11644 set_mode |= WIFI_MODE_B;
11645 if (operationParam->variant & WIFI_80211_VARIANT_G)
11646 set_mode |= WIFI_MODE_G;
11647 if (operationParam->variant & WIFI_80211_VARIANT_N)
11648 set_mode |= WIFI_MODE_N;
11649 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11650 set_mode |= WIFI_MODE_AC;
11651 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11652 set_mode |= WIFI_MODE_AX;
11653 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11654 memset(buf, 0, sizeof(buf));
11655 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11656 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11657 return RETURN_ERR;
11658 }
11659 }
11660 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11661 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11662 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11663 return RETURN_ERR;
11664 }
11665 }
11666 if (current_param.beaconInterval != operationParam->beaconInterval) {
11667 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11668 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11669 return RETURN_ERR;
11670 }
11671 }
11672 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11673 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11674 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11675 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11676 return RETURN_ERR;
11677 }
11678 }
11679 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11680 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11681 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11682 return RETURN_ERR;
11683 }
11684 }
11685 if (current_param.guardInterval != operationParam->guardInterval) {
11686 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11687 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11688 return RETURN_ERR;
11689 }
11690 }
11691 if (current_param.transmitPower != operationParam->transmitPower) {
11692 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11693 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11694 return RETURN_ERR;
11695 }
11696 }
11697 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11698 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11699 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11700 return RETURN_ERR;
11701 }
11702 }
11703 if (current_param.obssCoex != operationParam->obssCoex) {
11704 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11705 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11706 return RETURN_ERR;
11707 }
11708 }
11709 if (current_param.stbcEnable != operationParam->stbcEnable) {
11710 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11711 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11712 return RETURN_ERR;
11713 }
11714 }
11715 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11716 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11717 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11718 return RETURN_ERR;
11719 }
11720 }
11721
11722 // if enable is true, then restart the radio
11723 wifi_setRadioEnable(index, FALSE);
11724 if (operationParam->enable == TRUE)
11725 wifi_setRadioEnable(index, TRUE);
11726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11727
developer06a01d92022-09-07 16:32:39 +080011728 return RETURN_OK;
11729}
11730
11731INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11732{
developer1e5aa162022-09-13 16:06:24 +080011733 char band[64] = {0};
11734 char buf[256] = {0};
11735 char config_file[64] = {0};
11736 char cmd[128] = {0};
11737 int ret = RETURN_ERR;
11738 int mode = 0;
11739 ULONG channel = 0;
11740 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011741
11742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11743 printf("Entering %s index = %d\n", __func__, (int)index);
11744
developer1e5aa162022-09-13 16:06:24 +080011745 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11746 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11747 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011748 {
developer1e5aa162022-09-13 16:06:24 +080011749 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011750 return RETURN_ERR;
11751 }
11752 operationParam->enable = enabled;
11753
11754 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011755 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011756 {
developer1e5aa162022-09-13 16:06:24 +080011757 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011758 return RETURN_ERR;
11759 }
11760
11761 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011762 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011763 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011764 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011765 else if (!strcmp(band, "6GHz"))
11766 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011767 else
11768 {
developer1e5aa162022-09-13 16:06:24 +080011769 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011770 band);
11771 }
11772
developer1e5aa162022-09-13 16:06:24 +080011773 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11774 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11775 operationParam->channel = 0;
11776 operationParam->autoChannelEnabled = TRUE;
11777 } else {
11778 operationParam->channel = strtol(buf, NULL, 10);
11779 operationParam->autoChannelEnabled = FALSE;
11780 }
11781
developer06a01d92022-09-07 16:32:39 +080011782 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011783 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11784 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11785 return RETURN_ERR;
11786 }
developer06a01d92022-09-07 16:32:39 +080011787 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11788 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11789 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011790 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11791 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011792 else
11793 {
developer1e5aa162022-09-13 16:06:24 +080011794 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11795 return false;
developer06a01d92022-09-07 16:32:39 +080011796 }
11797
developer1e5aa162022-09-13 16:06:24 +080011798 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11799 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11800 return RETURN_ERR;
11801 }
11802 // Two different definition bit map, so need to check every bit.
11803 if (mode & WIFI_MODE_A)
11804 operationParam->variant |= WIFI_80211_VARIANT_A;
11805 if (mode & WIFI_MODE_B)
11806 operationParam->variant |= WIFI_80211_VARIANT_B;
11807 if (mode & WIFI_MODE_G)
11808 operationParam->variant |= WIFI_80211_VARIANT_G;
11809 if (mode & WIFI_MODE_N)
11810 operationParam->variant |= WIFI_80211_VARIANT_N;
11811 if (mode & WIFI_MODE_AC)
11812 operationParam->variant |= WIFI_80211_VARIANT_AC;
11813 if (mode & WIFI_MODE_AX)
11814 operationParam->variant |= WIFI_80211_VARIANT_AX;
11815 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11816 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11817 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011818 }
developer1e5aa162022-09-13 16:06:24 +080011819 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11820 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11821 return RETURN_ERR;
11822 }
11823 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11824 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11825 return RETURN_ERR;
11826 }
developer06a01d92022-09-07 16:32:39 +080011827
developer1e5aa162022-09-13 16:06:24 +080011828 memset(buf, 0, sizeof(buf));
11829 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11830 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11831 return RETURN_ERR;
11832 }
11833 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11834
11835 memset(buf, 0, sizeof(buf));
11836 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11837 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11838 return RETURN_ERR;
11839 }
11840 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11841
11842 memset(buf, 0, sizeof(buf));
11843 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11844 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11845
11846 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11847 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11848 return RETURN_ERR;
11849 }
11850 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11851 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11852 return RETURN_ERR;
11853 }
11854
11855 memset(buf, 0, sizeof(buf));
11856 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11857 if (strcmp(buf, "-1") == 0) {
11858 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11859 operationParam->ctsProtection = FALSE;
11860 } else {
11861 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11862 operationParam->ctsProtection = TRUE;
11863 }
11864
11865 memset(buf, 0, sizeof(buf));
11866 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11867 if (strcmp(buf, "0") == 0)
11868 operationParam->obssCoex = FALSE;
11869 else
11870 operationParam->obssCoex = TRUE;
11871
11872 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11873 _syscmd(cmd, buf, sizeof(buf));
11874 if (strlen(buf) != 0)
11875 operationParam->stbcEnable = TRUE;
11876 else
11877 operationParam->stbcEnable = FALSE;
11878
11879 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11880 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11881 return RETURN_ERR;
11882 }
11883
11884 // Below value is hardcoded
11885
11886 operationParam->numSecondaryChannels = 0;
11887 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11888 operationParam->channelSecondary[i] = 0;
11889 }
11890 operationParam->csa_beacon_count = 15;
11891 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011892
11893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11894 return RETURN_OK;
11895}
11896
11897static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11898{
developerc086fb72022-10-04 10:18:22 +080011899 int max_radio_num = 0;
11900
11901 wifi_getMaxRadioNumber(&max_radio_num);
11902 if (radioIndex >= max_radio_num || radioIndex < 0) {
11903 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11904 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011905 }
11906
developerc086fb72022-10-04 10:18:22 +080011907 return (arrayIndex * max_radio_num) + radioIndex;
11908}
developer06a01d92022-09-07 16:32:39 +080011909
developerc086fb72022-10-04 10:18:22 +080011910wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11911 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11912 return WIFI_BITRATE_1MBPS;
11913 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11914 return WIFI_BITRATE_2MBPS;
11915 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11916 return WIFI_BITRATE_5_5MBPS;
11917 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11918 return WIFI_BITRATE_6MBPS;
11919 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11920 return WIFI_BITRATE_9MBPS;
11921 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11922 return WIFI_BITRATE_11MBPS;
11923 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11924 return WIFI_BITRATE_12MBPS;
11925 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11926 return WIFI_BITRATE_18MBPS;
11927 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11928 return WIFI_BITRATE_24MBPS;
11929 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11930 return WIFI_BITRATE_36MBPS;
11931 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11932 return WIFI_BITRATE_48MBPS;
11933 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11934 return WIFI_BITRATE_54MBPS;
11935 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011936}
11937
developer1d57d002022-10-12 18:03:15 +080011938INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
11939{
11940 if (beacon == WIFI_BITRATE_1MBPS)
11941 strcpy(beacon_str, "1Mbps");
11942 else if (beacon == WIFI_BITRATE_2MBPS)
11943 strcpy(beacon_str, "2Mbps");
11944 else if (beacon == WIFI_BITRATE_5_5MBPS)
11945 strcpy(beacon_str, "5.5Mbps");
11946 else if (beacon == WIFI_BITRATE_6MBPS)
11947 strcpy(beacon_str, "6Mbps");
11948 else if (beacon == WIFI_BITRATE_9MBPS)
11949 strcpy(beacon_str, "9Mbps");
11950 else if (beacon == WIFI_BITRATE_11MBPS)
11951 strcpy(beacon_str, "11Mbps");
11952 else if (beacon == WIFI_BITRATE_12MBPS)
11953 strcpy(beacon_str, "12Mbps");
11954 else if (beacon == WIFI_BITRATE_18MBPS)
11955 strcpy(beacon_str, "18Mbps");
11956 else if (beacon == WIFI_BITRATE_24MBPS)
11957 strcpy(beacon_str, "24Mbps");
11958 else if (beacon == WIFI_BITRATE_36MBPS)
11959 strcpy(beacon_str, "36Mbps");
11960 else if (beacon == WIFI_BITRATE_48MBPS)
11961 strcpy(beacon_str, "48Mbps");
11962 else if (beacon == WIFI_BITRATE_54MBPS)
11963 strcpy(beacon_str, "54Mbps");
11964 return RETURN_OK;
11965}
11966
developer06a01d92022-09-07 16:32:39 +080011967INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11968{
developerc086fb72022-10-04 10:18:22 +080011969 INT mode = 0;
11970 INT ret = -1;
11971 INT output = 0;
11972 int i = 0;
11973 int vap_index = 0;
11974 BOOL enabled = FALSE;
11975 char buf[256] = {0};
11976 wifi_vap_security_t security;
11977 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011978
11979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11980 printf("Entering %s index = %d\n", __func__, (int)index);
11981
developer06a01d92022-09-07 16:32:39 +080011982 for (i = 0; i < 5; i++)
11983 {
developerc086fb72022-10-04 10:18:22 +080011984 map->vap_array[i].radio_index = index;
11985
developer06a01d92022-09-07 16:32:39 +080011986 vap_index = array_index_to_vap_index(index, i);
11987 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011988 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011989
developerc086fb72022-10-04 10:18:22 +080011990 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011991
11992 map->vap_array[i].vap_index = vap_index;
11993
11994 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011995 ret = wifi_getApName(vap_index, buf);
11996 if (ret != RETURN_OK) {
11997 printf("%s: wifi_getApName return error\n", __func__);
11998 return RETURN_ERR;
11999 }
12000 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12001
12002 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012003 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012004 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012005 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012006 return RETURN_ERR;
12007 }
12008 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 +080012009
12010 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012011 if (ret != RETURN_OK) {
12012 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012013 return RETURN_ERR;
12014 }
12015 map->vap_array[i].u.bss_info.enabled = enabled;
12016
developerc086fb72022-10-04 10:18:22 +080012017 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12018 if (ret != RETURN_OK) {
12019 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12020 return RETURN_ERR;
12021 }
developer06a01d92022-09-07 16:32:39 +080012022 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012023
12024 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12025 if (ret != RETURN_OK) {
12026 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12027 return RETURN_ERR;
12028 }
12029 map->vap_array[i].u.bss_info.isolation = enabled;
12030
12031 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12032 if (ret != RETURN_OK) {
12033 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12034 return RETURN_ERR;
12035 }
12036 map->vap_array[i].u.bss_info.bssMaxSta = output;
12037
12038 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12039 if (ret != RETURN_OK) {
12040 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12041 return RETURN_ERR;
12042 }
12043 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012044
developerc086fb72022-10-04 10:18:22 +080012045 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12046 if (ret != RETURN_OK) {
12047 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12048 return RETURN_ERR;
12049 }
12050 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012051
developerc086fb72022-10-04 10:18:22 +080012052 ret = wifi_getApSecurity(vap_index, &security);
12053 if (ret != RETURN_OK) {
12054 printf("%s: wifi_getApSecurity return error\n", __func__);
12055 return RETURN_ERR;
12056 }
12057 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012058
developerc086fb72022-10-04 10:18:22 +080012059 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12060 if (ret != RETURN_OK) {
12061 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12062 return RETURN_ERR;
12063 }
12064 if (mode == 0)
12065 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12066 else
12067 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12068 if (mode == 1)
12069 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12070 else if (mode == 2)
12071 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012072
developerc086fb72022-10-04 10:18:22 +080012073 ret = wifi_getApWmmEnable(vap_index, &enabled);
12074 if (ret != RETURN_OK) {
12075 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12076 return RETURN_ERR;
12077 }
12078 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012079
developerc086fb72022-10-04 10:18:22 +080012080 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12081 if (ret != RETURN_OK) {
12082 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012083 return RETURN_ERR;
12084 }
developerc086fb72022-10-04 10:18:22 +080012085 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012086
12087 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012088 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012089 if (ret != RETURN_OK) {
12090 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12091 return RETURN_ERR;
12092 }
12093 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012094
developerc086fb72022-10-04 10:18:22 +080012095 memset(buf, 0, sizeof(buf));
12096 ret = wifi_getBaseBSSID(vap_index, buf);
12097 if (ret != RETURN_OK) {
12098 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12099 return RETURN_ERR;
12100 }
12101 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12102 &map->vap_array[i].u.bss_info.bssid[0],
12103 &map->vap_array[i].u.bss_info.bssid[1],
12104 &map->vap_array[i].u.bss_info.bssid[2],
12105 &map->vap_array[i].u.bss_info.bssid[3],
12106 &map->vap_array[i].u.bss_info.bssid[4],
12107 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012108 // 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]);
12109
12110 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12111 if (ret != RETURN_OK) {
12112 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12113 return RETURN_ERR;
12114 }
12115 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012116
developerc086fb72022-10-04 10:18:22 +080012117 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012118 }
12119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12120 return RETURN_OK;
12121}
12122
12123INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12124{
12125 unsigned int i;
12126 wifi_vap_info_t *vap_info = NULL;
12127 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012128 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012129 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012130 char buf[256] = {0};
12131 char cmd[128] = {0};
12132 char config_file[64] = {0};
12133 char bssid[32] = {0};
12134 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012135
12136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12137 printf("Entering %s index = %d\n", __func__, (int)index);
12138 for (i = 0; i < map->num_vaps; i++)
12139 {
developer1d57d002022-10-12 18:03:15 +080012140 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012141 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012142 if (vap_info->u.bss_info.enabled == FALSE)
12143 continue;
developer06a01d92022-09-07 16:32:39 +080012144
developer1d57d002022-10-12 18:03:15 +080012145 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12146
12147 // multi-ap need to copy current radio config
12148 if (vap_info->radio_index != vap_info->vap_index) {
12149 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12150 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012151 }
developer06a01d92022-09-07 16:32:39 +080012152
developer1d57d002022-10-12 18:03:15 +080012153 struct params params[3];
12154 snprintf(vap_info->vap_name, 64, "%s%d", AP_PREFIX, vap_info->vap_index);
12155 params[0].name = "interface";
12156 params[0].value = vap_info->vap_name;
12157 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12158 params[1].name = "bssid";
12159 params[1].value = bssid;
12160 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12161 params[2].name = "wpa_psk_file";
12162 params[2].value = psk_file;
12163
12164 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12165 wifi_hostapdWrite(config_file, params, 3);
12166
12167 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12168 _syscmd(cmd, buf, sizeof(buf));
12169
12170 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12171 if (ret != RETURN_OK) {
12172 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12173 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012174 }
developer1d57d002022-10-12 18:03:15 +080012175
12176 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12177 if (ret != RETURN_OK) {
12178 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12179 return RETURN_ERR;
12180 }
12181
12182 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12183 if (ret != RETURN_OK) {
12184 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12185 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012186 }
12187
developer1d57d002022-10-12 18:03:15 +080012188 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12189 if (ret != RETURN_OK) {
12190 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12191 return RETURN_ERR;
12192 }
developer06a01d92022-09-07 16:32:39 +080012193
developer1d57d002022-10-12 18:03:15 +080012194 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12195 if (ret != RETURN_OK) {
12196 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12197 return RETURN_ERR;
12198 }
developer06a01d92022-09-07 16:32:39 +080012199
developer1d57d002022-10-12 18:03:15 +080012200 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12201 if (ret != RETURN_OK) {
12202 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12203 return RETURN_ERR;
12204 }
12205
developer804c64f2022-10-19 13:54:40 +080012206 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012207 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012208 }else {
12209 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012210 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012211 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12212 _syscmd(cmd, buf, sizeof(buf));
12213 }else{
developer1d57d002022-10-12 18:03:15 +080012214 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012215 }
developer1d57d002022-10-12 18:03:15 +080012216 }
12217
12218 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12219 if (ret != RETURN_OK) {
12220 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12221 return RETURN_ERR;
12222 }
12223
12224 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12225 if (ret != RETURN_OK) {
12226 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12227 return RETURN_ERR;
12228 }
12229
12230 memset(buf, 0, sizeof(buf));
12231 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12232 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12233 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12234 if (ret != RETURN_OK) {
12235 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12236 return RETURN_ERR;
12237 }
12238
12239 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12240 if (ret != RETURN_OK) {
12241 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12242 return RETURN_ERR;
12243 }
12244
12245 wifi_setApEnable(vap_info->vap_index, TRUE);
12246 multiple_set = FALSE;
12247
12248 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12249 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12250 if (ret != RETURN_OK) {
12251 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12252 return RETURN_ERR;
12253 }
12254
12255 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12256 if (ret != RETURN_OK) {
12257 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12258 return RETURN_ERR;
12259 }
developer06a01d92022-09-07 16:32:39 +080012260
developer1d57d002022-10-12 18:03:15 +080012261 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012262 }
12263 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12264 return RETURN_OK;
12265}
12266
12267int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12268{
12269 char *token, *next;
12270 const char s[2] = ",";
12271 int count =0;
12272
12273 /* get the first token */
12274 token = strtok_r(pchannels, s, &next);
12275
12276 /* walk through other tokens */
12277 while( token != NULL && count < MAX_CHANNELS) {
12278 chlistptr->channels_list[count++] = atoi(token);
12279 token = strtok_r(NULL, s, &next);
12280 }
12281
12282 return count;
12283}
12284
12285static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12286{
12287 INT status;
12288 wifi_channels_list_t *chlistp;
12289 CHAR output_string[64];
12290 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012291 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012292 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012293
12294 if(rcap == NULL)
12295 {
12296 return RETURN_ERR;
12297 }
12298
12299 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012300 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012301
developer1e5aa162022-09-13 16:06:24 +080012302 if (band == band_2_4)
12303 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12304 else if (band == band_5)
12305 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12306 else if (band == band_6)
12307 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012308
12309 chlistp = &(rcap->channel_list[0]);
12310 memset(pchannels, 0, sizeof(pchannels));
12311
12312 /* possible number of radio channels */
12313 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12314 {
12315 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12316 }
12317 /* Number of channels and list*/
12318 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12319
12320 /* autoChannelSupported */
12321 /* always ON with wifi_getRadioAutoChannelSupported */
12322 rcap->autoChannelSupported = TRUE;
12323
12324 /* DCSSupported */
12325 /* always ON with wifi_getRadioDCSSupported */
12326 rcap->DCSSupported = TRUE;
12327
12328 /* zeroDFSSupported - TBD */
12329 rcap->zeroDFSSupported = FALSE;
12330
12331 /* Supported Country List*/
12332 memset(output_string, 0, sizeof(output_string));
12333 status = wifi_getRadioCountryCode(radioIndex, output_string);
12334 if( status != 0 ) {
12335 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12336 return RETURN_ERR;
12337 } else {
12338 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12339 }
12340 if(!strcmp(output_string,"US")){
12341 rcap->countrySupported[0] = wifi_countrycode_US;
12342 rcap->countrySupported[1] = wifi_countrycode_CA;
12343 } else if (!strcmp(output_string,"CA")) {
12344 rcap->countrySupported[0] = wifi_countrycode_CA;
12345 rcap->countrySupported[1] = wifi_countrycode_US;
12346 } else {
12347 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12348 }
12349
12350 rcap->numcountrySupported = 2;
12351
12352 /* csi */
12353 rcap->csi.maxDevices = 8;
12354 rcap->csi.soudingFrameSupported = TRUE;
12355
developer033b37b2022-10-18 11:27:46 +080012356 phyId = radio_index_to_phy(radioIndex);
12357 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012358
12359 /* channelWidth - all supported bandwidths */
12360 int i=0;
12361 rcap->channelWidth[i] = 0;
12362 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12363 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12364 WIFI_CHANNELBANDWIDTH_40MHZ);
12365
12366 }
developer1e5aa162022-09-13 16:06:24 +080012367 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012368 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12369 WIFI_CHANNELBANDWIDTH_40MHZ |
12370 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12371 }
12372
12373
12374 /* mode - all supported variants */
12375 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12376 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012377 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 +080012378 }
12379 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012380 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12381 }
12382 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12383 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012384 }
12385 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12386 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12387
12388 /* supportedBitRate - all supported bitrates */
12389 rcap->supportedBitRate[i] = 0;
12390 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12391 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12392 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12393 }
developer1e5aa162022-09-13 16:06:24 +080012394 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012395 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12396 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12397 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12398 }
12399
12400
12401 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12402 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12403 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12404 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12405 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12406 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12407 rcap->cipherSupported = 0;
12408 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12409 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12410
12411 return RETURN_OK;
12412}
12413
12414INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12415{
12416 INT status, radioIndex;
12417 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12418 int iter = 0;
12419 unsigned int j;
12420 wifi_interface_name_idex_map_t *iface_info;
12421
12422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12423
12424 memset(cap, 0, sizeof(wifi_hal_capability_t));
12425
12426 /* version */
12427 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12428 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12429
12430 /* number of radios platform property */
12431 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12432 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012433 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012434
12435 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12436 {
12437 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12438 if (status != 0) {
12439 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12440 return RETURN_ERR;
12441 }
12442
12443 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12444 {
developer804c64f2022-10-19 13:54:40 +080012445 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012446 {
12447 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12448 return RETURN_ERR;
12449 }
12450 iface_info = &cap->wifi_prop.interface_map[iter];
12451 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12452 iface_info->rdk_radio_index = radioIndex;
12453 memset(output, 0, sizeof(output));
12454 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12455 {
12456 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12457 }
12458 // TODO: bridge name
12459 // TODO: vlan id
12460 // TODO: primary
12461 iface_info->index = array_index_to_vap_index(radioIndex, j);
12462 memset(output, 0, sizeof(output));
12463 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12464 {
12465 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12466 }
12467 iter++;
12468 }
12469 }
12470
12471 cap->BandSteeringSupported = FALSE;
12472 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12473 return RETURN_OK;
12474}
12475
developer9df4e652022-10-11 11:27:38 +080012476INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12477{
12478 struct params h_config={0};
12479 char config_file[64] = {0};
12480
12481 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12482
12483 h_config.name = "okc";
12484 h_config.value = okc_enable?"1":"0";
12485
12486 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12487 wifi_hostapdWrite(config_file, &h_config, 1);
12488 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12489
12490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12491 return RETURN_OK;
12492}
12493
12494INT wifi_setSAEMFP(int ap_index, BOOL enable)
12495{
12496 struct params h_config={0};
12497 char config_file[64] = {0};
12498 char buf[128] = {0};
12499
12500 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12501
12502 h_config.name = "sae_require_mfp";
12503 h_config.value = enable?"1":"0";
12504
12505 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12506 wifi_hostapdWrite(config_file, &h_config, 1);
12507 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12508
12509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12510 return RETURN_OK;
12511}
12512
12513INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12514{
12515 struct params h_config={0};
12516 char config_file[64] = {0};
12517 char buf[128] = {0};
12518
12519 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12520
12521 h_config.name = "sae_pwe";
12522 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12523 h_config.value = buf;
12524
12525 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12526 wifi_hostapdWrite(config_file, &h_config, 1);
12527 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12528
12529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12530 return RETURN_OK;
12531}
12532
12533INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12534{
12535 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12536 struct params h_config={0};
12537 char config_file[64] = {0};
12538
12539 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12540
12541 h_config.name = "wpa_disable_eapol_key_retries";
12542 h_config.value = disable_EAPOL_retries?"1":"0";
12543
12544 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12545 wifi_hostapdWrite(config_file, &h_config, 1);
12546 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12547
12548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12549 return RETURN_OK;
12550}
12551
developer06a01d92022-09-07 16:32:39 +080012552INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12553{
developer587c1b62022-09-27 15:58:59 +080012554 char buf[128] = {0};
12555 char config_file[128] = {0};
12556 char password[64] = {0};
12557 char mfp[32] = {0};
12558 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012559 BOOL okc_enable = FALSE;
12560 BOOL sae_MFP = FALSE;
12561 BOOL disable_EAPOL_retries = TRUE;
12562 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012563 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012564 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012565
12566 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12567
12568 multiple_set = TRUE;
12569 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12570 if (security->mode == wifi_security_mode_none) {
12571 strcpy(wpa_mode, "None");
12572 } else if (security->mode == wifi_security_mode_wpa_personal)
12573 strcpy(wpa_mode, "WPA-Personal");
12574 else if (security->mode == wifi_security_mode_wpa2_personal)
12575 strcpy(wpa_mode, "WPA2-Personal");
12576 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12577 strcpy(wpa_mode, "WPA-WPA2-Personal");
12578 else if (security->mode == wifi_security_mode_wpa_enterprise)
12579 strcpy(wpa_mode, "WPA-Enterprise");
12580 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12581 strcpy(wpa_mode, "WPA2-Enterprise");
12582 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12583 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012584 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012585 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012586 okc_enable = TRUE;
12587 sae_MFP = TRUE;
12588 sae_pwe = 2;
12589 disable_EAPOL_retries = FALSE;
12590 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012591 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012592 okc_enable = TRUE;
12593 sae_MFP = TRUE;
12594 sae_pwe = 2;
12595 disable_EAPOL_retries = FALSE;
12596 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012597 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012598 sae_MFP = TRUE;
12599 sae_pwe = 2;
12600 disable_EAPOL_retries = FALSE;
12601 }
12602
12603 band = wifi_index_to_band(ap_index);
12604 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12605 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12606 return RETURN_ERR;
12607 }
developer587c1b62022-09-27 15:58:59 +080012608
12609 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012610 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012611 wifi_setSAEMFP(ap_index, sae_MFP);
12612 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012613 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012614
developer9df4e652022-10-11 11:27:38 +080012615 if (security->mode != wifi_security_mode_none) {
12616 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12617 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12618 password[63] = '\0';
12619 wifi_setApSecurityKeyPassphrase(ap_index, password);
12620 }
12621 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12622 params.name = "sae_password";
12623 params.value = security->u.key.key;
12624 wifi_hostapdWrite(config_file, &params, 1);
12625 }
12626 }
developer587c1b62022-09-27 15:58:59 +080012627
12628 if (security->mode != wifi_security_mode_none) {
12629 memset(&params, 0, sizeof(params));
12630 params.name = "wpa_pairwise";
12631 if (security->encr == wifi_encryption_tkip)
12632 params.value = "TKIP";
12633 else if (security->encr == wifi_encryption_aes)
12634 params.value = "CCMP";
12635 else if (security->encr == wifi_encryption_aes_tkip)
12636 params.value = "TKIP CCMP";
12637 wifi_hostapdWrite(config_file, &params, 1);
12638 }
12639
12640 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012641 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012642 else if (security->mfp == wifi_mfp_cfg_optional)
12643 strcpy(mfp, "Optional");
12644 else if (security->mfp == wifi_mfp_cfg_required)
12645 strcpy(mfp, "Required");
12646 wifi_setApSecurityMFPConfig(ap_index, mfp);
12647
12648 memset(&params, 0, sizeof(params));
12649 params.name = "transition_disable";
12650 if (security->wpa3_transition_disable == TRUE)
12651 params.value = "0x01";
12652 else
12653 params.value = "0x00";
12654 wifi_hostapdWrite(config_file, &params, 1);
12655
12656 memset(&params, 0, sizeof(params));
12657 params.name = "wpa_group_rekey";
12658 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12659 params.value = buf;
12660 wifi_hostapdWrite(config_file, &params, 1);
12661
12662 memset(&params, 0, sizeof(params));
12663 params.name = "wpa_strict_rekey";
12664 params.value = security->strict_rekey?"1":"0";
12665 wifi_hostapdWrite(config_file, &params, 1);
12666
12667 memset(&params, 0, sizeof(params));
12668 params.name = "wpa_pairwise_update_count";
12669 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12670 params.value = buf;
12671 wifi_hostapdWrite(config_file, &params, 1);
12672
12673 memset(&params, 0, sizeof(params));
12674 params.name = "disable_pmksa_caching";
12675 params.value = security->disable_pmksa_caching?"1":"0";
12676 wifi_hostapdWrite(config_file, &params, 1);
12677
12678 wifi_setApEnable(ap_index, FALSE);
12679 wifi_setApEnable(ap_index, TRUE);
12680
12681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12682
developer06a01d92022-09-07 16:32:39 +080012683 return RETURN_OK;
12684}
12685
12686INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12687{
developer9df4e652022-10-11 11:27:38 +080012688 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012689 char config_file[128] = {0};
12690 int disable = 0;
12691 // struct params params = {0};
12692
12693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12694 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12695 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12696 security->mode = wifi_security_mode_none;
12697 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012698 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012699 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012700 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012701 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012702 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012703 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012704 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012705 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012706 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012707 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012708 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012709 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012710 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012711 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012712 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012713 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012714 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012715 security->mode = wifi_security_mode_wpa3_enterprise;
12716 }
12717
12718 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12719 if (security->mode == wifi_security_mode_none)
12720 security->encr = wifi_encryption_none;
12721 else {
12722 if (strcmp(buf, "TKIP") == 0)
12723 security->encr = wifi_encryption_tkip;
12724 else if (strcmp(buf, "CCMP") == 0)
12725 security->encr = wifi_encryption_aes;
12726 else
12727 security->encr = wifi_encryption_aes_tkip;
12728 }
12729
developer9df4e652022-10-11 11:27:38 +080012730 if (security->mode != wifi_encryption_none) {
12731 memset(buf, 0, sizeof(buf));
12732 // wpa3 can use one or both configs as password, so we check sae_password first.
12733 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12734 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12735 security->u.key.type = wifi_security_key_type_sae;
12736 } else {
12737 security->u.key.type = wifi_security_key_type_psk;
12738 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12739 }
12740 strncpy(security->u.key.key, buf, sizeof(buf));
12741 security->u.key.key[255] = '\0';
12742 }
12743
developer587c1b62022-09-27 15:58:59 +080012744 memset(buf, 0, sizeof(buf));
12745 wifi_getApSecurityMFPConfig(ap_index, buf);
12746 if (strcmp(buf, "Disabled") == 0)
12747 security->mfp = wifi_mfp_cfg_disabled;
12748 else if (strcmp(buf, "Optional") == 0)
12749 security->mfp = wifi_mfp_cfg_optional;
12750 else if (strcmp(buf, "Required") == 0)
12751 security->mfp = wifi_mfp_cfg_required;
12752
12753 memset(buf, 0, sizeof(buf));
12754 security->wpa3_transition_disable = FALSE;
12755 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12756 disable = strtol(buf, NULL, 16);
12757 if (disable != 0)
12758 security->wpa3_transition_disable = TRUE;
12759
12760 memset(buf, 0, sizeof(buf));
12761 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12762 if (strlen(buf) == 0)
12763 security->rekey_interval = 86400;
12764 else
12765 security->rekey_interval = strtol(buf, NULL, 10);
12766
12767 memset(buf, 0, sizeof(buf));
12768 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12769 if (strlen(buf) == 0)
12770 security->strict_rekey = 1;
12771 else
12772 security->strict_rekey = strtol(buf, NULL, 10);
12773
12774 memset(buf, 0, sizeof(buf));
12775 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12776 if (strlen(buf) == 0)
12777 security->eapol_key_retries = 4;
12778 else
12779 security->eapol_key_retries = strtol(buf, NULL, 10);
12780
12781 memset(buf, 0, sizeof(buf));
12782 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12783 if (strlen(buf) == 0)
12784 security->disable_pmksa_caching = FALSE;
12785 else
12786 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12787
12788 /* TODO
12789 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12790 */
12791 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12792 security->eap_identity_req_timeout = 0;
12793 security->eap_identity_req_retries = 0;
12794 security->eap_req_timeout = 0;
12795 security->eap_req_retries = 0;
12796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012797 return RETURN_OK;
12798}
12799
12800#endif /* WIFI_HAL_VERSION_3 */
12801
12802#ifdef WIFI_HAL_VERSION_3_PHASE2
12803INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12804{
developer13df9332022-09-27 16:53:22 +080012805 char cmd[128] = {0};
12806 char buf[128] = {0};
12807 char *mac_addr = NULL;
12808 BOOL status = FALSE;
12809 size_t len = 0;
12810
12811 if(ap_index > MAX_APS)
12812 return RETURN_ERR;
12813
12814 *output_numDevices = 0;
12815 wifi_getApEnable(ap_index, &status);
12816 if (status == FALSE)
12817 return RETURN_OK;
12818
12819 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12820 _syscmd(cmd, buf, sizeof(buf));
12821
12822 mac_addr = strtok(buf, "\n");
12823 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12824 *output_numDevices = i + 1;
12825 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12826 addr_ptr = output_deviceMacAddressArray[i];
12827 mac_addr_aton(addr_ptr, mac_addr);
12828 mac_addr = strtok(NULL, "\n");
12829 }
12830
12831 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012832}
12833#else
12834INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12835{
12836 char cmd[128];
12837 BOOL status = false;
12838
12839 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12840 return RETURN_ERR;
12841
12842 output_buf[0] = '\0';
12843
12844 wifi_getApEnable(ap_index,&status);
12845 if (!status)
12846 return RETURN_OK;
12847
12848 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12849 _syscmd(cmd, output_buf, output_buf_size);
12850
12851 return RETURN_OK;
12852}
12853#endif
developer2f513ab2022-09-13 14:26:06 +080012854
12855INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12856{
12857 char output[16]={'\0'};
12858 char config_file[MAX_BUF_SIZE] = {0};
12859
12860 if (!enable)
12861 return RETURN_ERR;
12862
12863 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12864 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12865
12866 if (strlen(output) == 0)
12867 *enable = FALSE;
12868 else if (strncmp(output, "1", 1) == 0)
12869 *enable = TRUE;
12870 else
12871 *enable = FALSE;
12872
12873 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12874 return RETURN_OK;
12875}
developer2d9c30f2022-09-13 15:06:14 +080012876
12877INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12878{
developer804c64f2022-10-19 13:54:40 +080012879 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080012880 return RETURN_ERR;
12881 *output_enable=TRUE;
12882 return RETURN_OK;
12883}
developerfd7d2892022-09-13 16:44:53 +080012884
12885INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12886{
12887 char cmd[128] = {0};
12888 char buf[128] = {0};
12889 char line[128] = {0};
12890 size_t len = 0;
12891 ssize_t read = 0;
12892 FILE *f = NULL;
12893 int index = 0;
12894 int exp = 0;
12895 int mantissa = 0;
12896 int duration = 0;
12897 int radio_index = 0;
12898 int max_radio_num = 0;
12899 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080012900 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080012901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12902
12903 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080012904
developerfd7d2892022-09-13 16:44:53 +080012905 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080012906
12907 phyId = radio_index_to_phy(radio_index);
12908 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080012909 _syscmd(cmd, buf, sizeof(buf));
12910 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12911 if (*numSessionReturned > maxNumberSessions)
12912 *numSessionReturned = maxNumberSessions;
12913 else if (*numSessionReturned < 1) {
12914 *numSessionReturned = 0;
12915 return RETURN_OK;
12916 }
12917
developer033b37b2022-10-18 11:27:46 +080012918 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 +080012919 if ((f = popen(cmd, "r")) == NULL) {
12920 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12921 return RETURN_ERR;
12922 }
12923
12924 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12925 while((read = fgets(line, sizeof(line), f)) != NULL) {
12926 char *tmp = NULL;
12927 strcpy(buf, line);
12928 tmp = strtok(buf, " ");
12929 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12930 tmp = strtok(NULL, " ");
12931 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12932 tmp = strtok(NULL, " ");
12933 if (strstr(tmp, "t")) {
12934 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12935 }
12936 if (strstr(tmp, "a")) {
12937 twtSessions[index].twtParameters.operation.announced = TRUE;
12938 }
12939 tmp = strtok(NULL, " ");
12940 exp = strtol(tmp, NULL, 10);
12941 tmp = strtok(NULL, " ");
12942 mantissa = strtol(tmp, NULL, 10);
12943 tmp = strtok(NULL, " ");
12944 duration = strtol(tmp, NULL, 10);
12945
12946 // only implicit supported
12947 twtSessions[index].twtParameters.operation.implicit = TRUE;
12948 // only individual agreement supported
12949 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12950
12951 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12952 twt_wake_interval = mantissa * (1 << exp);
12953 if (twt_wake_interval/mantissa != (1 << exp)) {
12954 // Overflow handling
12955 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12956 } else {
12957 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12958 }
12959 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12960 index++;
12961 }
12962
12963 pclose(f);
12964 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12965 return RETURN_OK;
12966}