blob: 478c5594ffda1dd5deca08274bc0fc9a11249b65 [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{
developerda1ed692022-09-13 13:59:20 +08002221#ifdef MTK_IMPL
2222 if(!wifi_getApChannel(radioIndex, output_ulong))
2223 return RETURN_OK;
2224 else
2225 return RETURN_ERR;
2226#else
developer06a01d92022-09-07 16:32:39 +08002227 char cmd[1024] = {0}, buf[5] = {0};
2228
2229 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2230 if (NULL == output_ulong)
2231 return RETURN_ERR;
2232
2233 snprintf(cmd, sizeof(cmd),
2234 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2235 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2236 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2237 _syscmd(cmd, buf, sizeof(buf));
2238
2239 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2240 if (*output_ulong <= 0) {
2241 *output_ulong = 0;
2242 return RETURN_ERR;
2243 }
2244
2245 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2246 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002247#endif
developer06a01d92022-09-07 16:32:39 +08002248}
2249
2250
2251INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2252{
2253 char cmd[1024] = {0}, buf[5] = {0};
2254 char interface_name[50] = {0};
2255
2256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2257 if (NULL == output_ulong)
2258 return RETURN_ERR;
2259
2260 wifi_getApName(apIndex,interface_name);
2261 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2262 _syscmd(cmd,buf,sizeof(buf));
2263 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2264 if (*output_ulong == 0) {
2265 return RETURN_ERR;
2266 }
2267
2268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2269 return RETURN_OK;
2270}
2271
2272//Storing the previous channel value
2273INT wifi_storeprevchanval(INT radioIndex)
2274{
2275 char buf[256] = {0};
2276 char output[4]={'\0'};
2277 char config_file[MAX_BUF_SIZE] = {0};
2278 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2279 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2280 if(radioIndex == 0)
2281 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2282 else if(radioIndex == 1)
2283 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2284 system(buf);
2285 Radio_flag = FALSE;
2286 return RETURN_OK;
2287}
2288
2289//Set the running channel number
2290INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2291{
developer76989232022-10-04 14:13:19 +08002292 // We only write hostapd config here
2293 char str_channel[8]={0};
2294 char *list_channel;
2295 char config_file[128] = {0};
2296 char possible_channels[256] = {0};
2297 int max_radio_num = 0;
2298 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002299
developer76989232022-10-04 14:13:19 +08002300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002301
developer76989232022-10-04 14:13:19 +08002302 // Check valid
2303 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002304
developer76989232022-10-04 14:13:19 +08002305 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2306 list_channel = strtok(possible_channels, ",");
2307 while(true)
developer06a01d92022-09-07 16:32:39 +08002308 {
developer76989232022-10-04 14:13:19 +08002309 if(list_channel == NULL) { // input not in the list
2310 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2311 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002312 }
developer76989232022-10-04 14:13:19 +08002313 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2314 break;
2315 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002316 }
2317
developer76989232022-10-04 14:13:19 +08002318 list.name = "channel";
2319 list.value = str_channel;
2320 wifi_getMaxRadioNumber(&max_radio_num);
2321 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002322 {
developer76989232022-10-04 14:13:19 +08002323 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2324 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002325 }
2326
developer76989232022-10-04 14:13:19 +08002327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002328 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002329}
developer06a01d92022-09-07 16:32:39 +08002330
2331INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2332{
developer76989232022-10-04 14:13:19 +08002333 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002334 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002335 char config_file[64];
2336 int max_num_radios = 0;
2337 wifi_band band = band_invalid;
2338
2339 band = wifi_index_to_band(radioIndex);
2340 if (band == band_2_4)
2341 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002342
developer06a01d92022-09-07 16:32:39 +08002343 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002344 list[0].name = "vht_oper_centr_freq_seg0_idx";
2345 list[0].value = str_idx;
2346 list[1].name = "he_oper_centr_freq_seg0_idx";
2347 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002348
developer76989232022-10-04 14:13:19 +08002349 wifi_getMaxRadioNumber(&max_num_radios);
2350 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002351 {
developer76989232022-10-04 14:13:19 +08002352 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2353 if (band == band_6)
2354 wifi_hostapdWrite(config_file, &list[1], 1);
2355 else
2356 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002357 }
2358
2359 return RETURN_OK;
2360}
2361
2362//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2363//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2364INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2365{
2366 //Set to wifi config only. Wait for wifi reset to apply.
2367 char buf[256] = {0};
2368 char str_channel[256] = {0};
2369 int count = 0;
2370 ULONG Value = 0;
2371 FILE *fp = NULL;
2372 if(enable == TRUE)
2373 {
developer06a01d92022-09-07 16:32:39 +08002374 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002375 }
developer5884e982022-10-06 10:52:50 +08002376 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002377}
2378
developer0b246d12022-09-30 15:24:20 +08002379INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2380{
2381 if (output_bool == NULL)
2382 return RETURN_ERR;
2383
2384 *output_bool = TRUE;
2385
2386 return RETURN_OK;
2387}
2388
developer06a01d92022-09-07 16:32:39 +08002389INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2390{
2391 if (NULL == output_bool)
2392 return RETURN_ERR;
2393 *output_bool=FALSE;
2394 return RETURN_OK;
2395}
2396
2397INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2398{
2399 if (NULL == output_bool)
2400 return RETURN_ERR;
2401 *output_bool=FALSE;
2402 return RETURN_OK;
2403}
2404
2405INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2406{
2407 //Set to wifi config only. Wait for wifi reset to apply.
2408 return RETURN_OK;
2409}
2410
2411INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2412{
2413 return RETURN_OK;
2414}
2415
2416INT wifi_factoryResetAP(int apIndex)
2417{
developer838cca92022-10-03 13:19:57 +08002418 char ap_config_file[64] = {0};
2419 char cmd[128] = {0};
2420
developer06a01d92022-09-07 16:32:39 +08002421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002422
2423 wifi_setApEnable(apIndex, FALSE);
2424 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2425 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2426 wifi_setApEnable(apIndex, TRUE);
2427
developer06a01d92022-09-07 16:32:39 +08002428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002429
developer06a01d92022-09-07 16:32:39 +08002430 return RETURN_OK;
2431}
2432
2433//To set Band Steering AP group
2434//To-do
2435INT wifi_setBandSteeringApGroup(char *ApGroup)
2436{
2437 return RETURN_OK;
2438}
2439
developer1e5aa162022-09-13 16:06:24 +08002440INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2441{
2442 char config_file[128] = {'\0'};
2443 char buf[128] = {'\0'};
2444
2445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2446 if (dtimInterval == NULL)
2447 return RETURN_ERR;
2448
2449 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2450 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2451
2452 if (strlen(buf) == 0) {
2453 *dtimInterval = 2;
2454 } else {
2455 *dtimInterval = strtoul(buf, NULL, 10);
2456 }
2457
2458 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2459 return RETURN_OK;
2460}
2461
developer06a01d92022-09-07 16:32:39 +08002462INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2463{
developer5f222492022-09-13 15:21:52 +08002464 struct params params={0};
2465 char config_file[MAX_BUF_SIZE] = {'\0'};
2466 char buf[MAX_BUF_SIZE] = {'\0'};
2467
2468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2469 if (dtimInterval < 1 || dtimInterval > 255) {
2470 return RETURN_ERR;
2471 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2472 }
2473
2474 params.name = "dtim_period";
2475 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2476 params.value = buf;
2477
2478 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2479 wifi_hostapdWrite(config_file, &params, 1);
2480 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2481
2482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2483 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002484}
2485
2486//Check if the driver support the Dfs
2487INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2488{
2489 if (NULL == output_bool)
2490 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002491 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002492 return RETURN_OK;
2493}
2494
2495//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.
2496//The value of this parameter is a comma seperated list of channel number
2497INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2498{
2499 if (NULL == output_pool)
2500 return RETURN_ERR;
2501 if (radioIndex==1)
2502 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2503 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2504
2505 return RETURN_OK;
2506}
2507
2508INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2509{
2510 //Set to wifi config. And apply instantly.
2511 return RETURN_OK;
2512}
2513
2514INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2515{
2516 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2517 return RETURN_ERR;
2518 *output_interval_seconds=1800;
2519 *output_dwell_milliseconds=40;
2520
2521 return RETURN_OK;
2522}
2523
2524INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2525{
2526 //Set to wifi config. And apply instantly.
2527 return RETURN_OK;
2528}
2529
developerbfc18512022-10-05 17:54:28 +08002530INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2531{
2532 if (output_bool == NULL)
2533 return RETURN_ERR;
2534 *output_bool = true;
2535 return RETURN_OK;
2536}
2537
2538INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2539{
2540 return RETURN_OK;
2541}
2542
developer06a01d92022-09-07 16:32:39 +08002543//Get the Dfs enable status
2544INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2545{
developer9964b5b2022-09-13 15:59:34 +08002546 char buf[16] = {0};
2547 FILE *f = NULL;
2548 wifi_band band;
2549
2550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2551
2552 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002553 if (NULL == output_bool)
2554 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002555
2556 band = wifi_index_to_band(radioIndex);
2557 if (band != band_5)
2558 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002559
developer9964b5b2022-09-13 15:59:34 +08002560 f = fopen(DFS_ENABLE_FILE, "r");
2561 if (f != NULL) {
2562 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002563 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002564 *output_bool = FALSE;
2565 fclose(f);
2566 }
2567 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002568 return RETURN_OK;
2569}
2570
2571//Set the Dfs enable status
2572INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2573{
developer9964b5b2022-09-13 15:59:34 +08002574 char config_file[128] = {0};
2575 FILE *f = NULL;
2576 struct params params={0};
2577 wifi_band band;
2578
2579 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2580
2581 band = wifi_index_to_band(radioIndex);
2582 if (band != band_5)
2583 return RETURN_OK;
2584
2585 f = fopen(DFS_ENABLE_FILE, "w");
2586 if (f == NULL)
2587 return RETURN_ERR;
2588 fprintf(f, "%d", enable);
2589 fclose(f);
2590
2591 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002592 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002593 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2594 wifi_hostapdWrite(config_file, &params, 1);
2595 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2596
2597 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2598
developer9964b5b2022-09-13 15:59:34 +08002599 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002600 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002601}
2602
2603//Check if the driver support the AutoChannelRefreshPeriod
2604INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2605{
2606 if (NULL == output_bool)
2607 return RETURN_ERR;
2608 *output_bool=FALSE; //not support
2609
2610 return RETURN_OK;
2611}
2612
2613//Get the ACS refresh period in seconds
2614INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2615{
2616 if (NULL == output_ulong)
2617 return RETURN_ERR;
2618 *output_ulong=300;
2619
2620 return RETURN_OK;
2621}
2622
2623//Set the ACS refresh period in seconds
2624INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2625{
2626 return RETURN_ERR;
2627}
2628
2629//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2630//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.
2631INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2632{
developer70490032022-09-13 15:45:20 +08002633 char cmd[128] = {0}, buf[64] = {0};
2634 char interface_name[64] = {0};
2635 int ret = 0, len=0;
2636 BOOL radio_enable = FALSE;
2637
2638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2639
developer06a01d92022-09-07 16:32:39 +08002640 if (NULL == output_string)
2641 return RETURN_ERR;
2642
developer70490032022-09-13 15:45:20 +08002643 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2644 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002645
developer70490032022-09-13 15:45:20 +08002646 if (radio_enable != TRUE)
2647 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002648
developer70490032022-09-13 15:45:20 +08002649 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002650 ret = _syscmd(cmd, buf, sizeof(buf));
2651 len = strlen(buf);
2652 if((ret != 0) || (len == 0))
2653 {
2654 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2655 return RETURN_ERR;
2656 }
2657
2658 buf[len-1] = '\0';
2659 snprintf(output_string, 64, "%sMHz", buf);
2660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2661
2662#if 0
2663 //TODO: revisit below implementation
2664 char output_buf[8]={0};
2665 char bw_value[10];
2666 char config_file[MAX_BUF_SIZE] = {0};
2667
2668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2669 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2670 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2671 readBandWidth(radioIndex,bw_value);
2672
2673 if(strstr (output_buf,"0") != NULL )
2674 {
2675 strcpy(output_string,bw_value);
2676 }
2677 else if (strstr (output_buf,"1") != NULL)
2678 {
2679 strcpy(output_string,"80MHz");
2680 }
2681 else if (strstr (output_buf,"2") != NULL)
2682 {
2683 strcpy(output_string,"160MHz");
2684 }
2685 else if (strstr (output_buf,"3") != NULL)
2686 {
2687 strcpy(output_string,"80+80");
2688 }
2689 else
2690 {
2691 strcpy(output_string,"Auto");
2692 }
2693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2694#endif
2695
2696 return RETURN_OK;
2697}
2698
2699//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002700INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002701{
developerf7a466e2022-09-29 11:55:56 +08002702 char config_file[128];
2703 char set_value[16];
2704 struct params params[2];
2705 int max_radio_num = 0;
2706
developer06a01d92022-09-07 16:32:39 +08002707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002708
developerf7a466e2022-09-29 11:55:56 +08002709 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002710 return RETURN_ERR;
2711
developerf7a466e2022-09-29 11:55:56 +08002712 if(strstr(bandwidth,"80+80") != NULL)
2713 strcpy(set_value, "3");
2714 else if(strstr(bandwidth,"160") != NULL)
2715 strcpy(set_value, "2");
2716 else if(strstr(bandwidth,"80") != NULL)
2717 strcpy(set_value, "1");
2718 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2719 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002720 else
2721 {
developerf7a466e2022-09-29 11:55:56 +08002722 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002723 return RETURN_ERR;
2724 }
2725
developerf7a466e2022-09-29 11:55:56 +08002726 params[0].name = "vht_oper_chwidth";
2727 params[0].value = set_value;
2728 params[1].name = "he_oper_chwidth";
2729 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002730
developerf7a466e2022-09-29 11:55:56 +08002731 wifi_getMaxRadioNumber(&max_radio_num);
2732 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002733 {
developerf7a466e2022-09-29 11:55:56 +08002734 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2735 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002736 }
2737
2738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2739 return RETURN_OK;
2740}
2741
2742//Getting current radio extension channel
2743INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2744{
2745 CHAR buf[150] = {0};
2746 CHAR cmd[150] = {0};
2747 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2748 _syscmd(cmd, buf, sizeof(buf));
2749 if(NULL != strstr(buf,"HT40+"))
2750 strcpy(Value,"AboveControlChannel");
2751 else if(NULL != strstr(buf,"HT40-"))
2752 strcpy(Value,"BelowControlChannel");
2753 return RETURN_OK;
2754}
2755
2756//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2757//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.
2758INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2759{
2760 if (NULL == output_string)
2761 return RETURN_ERR;
2762
2763 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2764#if 0
2765 CHAR Value[100] = {0};
2766 if (NULL == output_string)
2767 return RETURN_ERR;
2768 if(radioIndex == 0)
2769 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2770 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2771 {
2772 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2773 if(strcmp(Value,"40MHz") == 0)
2774 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2775 else
2776 strcpy(Value,"Auto");
2777 }
2778 strcpy(output_string,Value);
2779#endif
2780
2781 return RETURN_OK;
2782}
2783
2784//Set the extension channel.
2785INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2786{
2787 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2788 struct params params={'\0'};
2789 char config_file[MAX_BUF_SIZE] = {0};
2790 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002791 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002792 params.name = "ht_capab";
2793
developer033b37b2022-10-18 11:27:46 +08002794 if(NULL!= strstr(string,"Above"))
2795 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2796 else if(NULL!= strstr(string,"Below"))
2797 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2798 else
2799 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2800
developer06a01d92022-09-07 16:32:39 +08002801
2802 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002803
2804 wifi_getMaxRadioNumber(&max_radio_num);
2805 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002806 {
developer033b37b2022-10-18 11:27:46 +08002807 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002808 wifi_hostapdWrite(config_file, &params, 1);
2809 }
2810
2811 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2812 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2813 return RETURN_OK;
2814}
2815
2816//Get the guard interval value. eg "400nsec" or "800nsec"
2817//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.
2818INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2819{
developer454b9462022-09-13 15:29:16 +08002820 wifi_guard_interval_t GI;
2821
2822 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2823
2824 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002825 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002826
2827 if (GI == wifi_guard_interval_400)
2828 strcpy(output_string, "400nsec");
2829 else if (GI == wifi_guard_interval_800)
2830 strcpy(output_string, "800nsec");
2831 else if (GI == wifi_guard_interval_1600)
2832 strcpy(output_string, "1600nsec");
2833 else if (GI == wifi_guard_interval_3200)
2834 strcpy(output_string, "3200nsec");
2835 else
2836 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002837
developer454b9462022-09-13 15:29:16 +08002838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002839 return RETURN_OK;
2840}
2841
2842//Set the guard interval value.
2843INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2844{
developer454b9462022-09-13 15:29:16 +08002845 wifi_guard_interval_t GI;
2846 int ret = 0;
2847
2848 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2849
2850 if (strcmp(string, "400nsec") == 0)
2851 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002852 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002853 GI = wifi_guard_interval_800;
2854 else if (strcmp(string , "1600nsec") == 0)
2855 GI = wifi_guard_interval_1600;
2856 else if (strcmp(string , "3200nsec") == 0)
2857 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002858 else
2859 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002860
2861 ret = wifi_setGuardInterval(radioIndex, GI);
2862
2863 if (ret == RETURN_ERR) {
2864 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2865 return RETURN_ERR;
2866 }
2867
2868 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2869 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002870}
2871
2872//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2873INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2874{
developerf49437e2022-09-29 19:58:21 +08002875 char buf[32]={0};
2876 char mcs_file[64] = {0};
2877 char cmd[64] = {0};
2878 int mode_bitmap = 0;
2879
2880 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2881 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002882 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002883 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2884
2885 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2886 _syscmd(cmd, buf, sizeof(buf));
2887 if (strlen(buf) > 0)
2888 *output_int = strtol(buf, NULL, 10);
2889 else {
2890 // output the max MCS for the current radio mode
2891 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2892 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2893 return RETURN_ERR;
2894 }
2895 if (mode_bitmap & WIFI_MODE_AX) {
2896 *output_int = 11;
2897 } else if (mode_bitmap & WIFI_MODE_AC) {
2898 *output_int = 9;
2899 } else if (mode_bitmap & WIFI_MODE_N) {
2900 *output_int = 7;
2901 }
2902 }
2903 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002904
2905 return RETURN_OK;
2906}
2907
2908//Set the Modulation Coding Scheme index
2909INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2910{
developerf49437e2022-09-29 19:58:21 +08002911 // 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).
2912 char config_file[64] = {0};
2913 char set_value[16] = {0};
2914 char mcs_file[32] = {0};
2915 wifi_band band = band_invalid;
2916 struct params set_config = {0};
2917 FILE *f = NULL;
2918
2919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2920
2921 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2922
2923 if (MCS > 11 || MCS < 0) {
2924 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2925 return RETURN_ERR;
2926 }
2927
2928 if (MCS <= 7)
2929 strcpy(set_value, "0");
2930 else if (MCS <= 9)
2931 strcpy(set_value, "1");
2932 else
2933 strcpy(set_value, "2");
2934
2935 set_config.name = "he_basic_mcs_nss_set";
2936 set_config.value = set_value;
2937
2938 wifi_hostapdWrite(config_file, &set_config, 1);
2939 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2940
2941 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2942 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2943 f = fopen(mcs_file, "w");
2944 if (f == NULL) {
2945 fprintf(stderr, "%s: fopen failed\n", __func__);
2946 return RETURN_ERR;
2947 }
2948 fprintf(f, "%d", MCS);
2949 fclose(f);
2950
2951 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2952 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002953}
2954
2955//Get supported Transmit Power list, eg : "0,25,50,75,100"
2956//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.
2957INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2958{
2959 if (NULL == output_list)
2960 return RETURN_ERR;
2961 snprintf(output_list, 64,"0,25,50,75,100");
2962 return RETURN_OK;
2963}
2964
developera5005b62022-09-13 15:43:35 +08002965//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002966//The transmite power level is in units of full power for this radio.
2967INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2968{
2969 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002970 char buf[16]={0};
2971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002972
developera5005b62022-09-13 15:43:35 +08002973 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002974 return RETURN_ERR;
2975
developera5005b62022-09-13 15:43:35 +08002976 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 +08002977 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002978
developera5005b62022-09-13 15:43:35 +08002979 *output_ulong = strtol(buf, NULL, 10);
2980
2981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002982 return RETURN_OK;
2983}
2984
2985//Set Transmit Power
2986//The transmite power level is in units of full power for this radio.
2987INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2988{
developera5005b62022-09-13 15:43:35 +08002989 char *support;
developer06a01d92022-09-07 16:32:39 +08002990 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002991 char buf[128]={0};
2992 char txpower_str[64] = {0};
2993 int txpower = 0;
2994 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08002995 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08002996
2997 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002998
developera5005b62022-09-13 15:43:35 +08002999 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 +08003000 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003001 maximum_tx = strtol(buf, NULL, 10);
3002
3003 // Get the Tx power supported list and check that is the input in the list
3004 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3005 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3006 support = strtok(buf, ",");
3007 while(true)
3008 {
3009 if(support == NULL) { // input not in the list
3010 wifi_dbg_printf("Input value is invalid.\n");
3011 return RETURN_ERR;
3012 }
3013 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3014 break;
3015 }
3016 support = strtok(NULL, ",");
3017 }
3018 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003019 phyId = radio_index_to_phy(radioIndex);
3020 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003021 _syscmd(cmd, buf, sizeof(buf));
3022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003023
3024 return RETURN_OK;
3025}
3026
3027//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3028INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3029{
3030 if (NULL == Supported)
3031 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003032 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003033
3034 return RETURN_OK;
3035}
3036
3037//Get 80211h feature enable
3038INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3039{
developer3885fec2022-09-13 15:13:47 +08003040 char buf[64]={'\0'};
3041 char config_file[64] = {'\0'};
3042
3043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3044 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003045 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003046
3047 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3048 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003049
developer3885fec2022-09-13 15:13:47 +08003050 if (strncmp(buf, "1", 1) == 0)
3051 *enable = TRUE;
3052 else
3053 *enable = FALSE;
3054
3055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003056 return RETURN_OK;
3057}
3058
3059//Set 80211h feature enable
3060INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3061{
developer3885fec2022-09-13 15:13:47 +08003062 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3063 struct params params={'\0'};
3064 char config_file[MAX_BUF_SIZE] = {0};
3065
3066 params.name = "ieee80211h";
3067
3068 if (enable) {
3069 params.value = "1";
3070 } else {
3071 params.value = "0";
3072 }
3073
3074 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3075 wifi_hostapdWrite(config_file, &params, 1);
3076
3077 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3079 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003080}
3081
3082//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.
3083INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3084{
3085 if (NULL == output)
3086 return RETURN_ERR;
3087 *output=100;
3088
3089 return RETURN_OK;
3090}
3091
3092//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.
3093INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3094{
3095 if (NULL == output)
3096 return RETURN_ERR;
3097 *output = -99;
3098
3099 return RETURN_OK;
3100}
3101
3102INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3103{
3104 return RETURN_ERR;
3105}
3106
3107
3108//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3109INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3110{
developer5f222492022-09-13 15:21:52 +08003111 char cmd[MAX_BUF_SIZE]={'\0'};
3112 char buf[MAX_CMD_SIZE]={'\0'};
3113
3114 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3115 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003116 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003117
3118 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3119 _syscmd(cmd, buf, sizeof(buf));
3120 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003121
developer5f222492022-09-13 15:21:52 +08003122 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003123 return RETURN_OK;
3124}
3125
3126INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3127{
developer5f222492022-09-13 15:21:52 +08003128 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3129 struct params params={'\0'};
3130 char buf[MAX_BUF_SIZE] = {'\0'};
3131 char config_file[MAX_BUF_SIZE] = {'\0'};
3132
3133 params.name = "beacon_int";
3134 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3135 params.value = buf;
3136
3137 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3138 wifi_hostapdWrite(config_file, &params, 1);
3139
3140 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3141 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3142 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003143}
3144
3145//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.
3146INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3147{
developer06a01d92022-09-07 16:32:39 +08003148 //TODO: need to revisit below implementation
3149 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003150 char temp_output[128] = {0};
3151 char temp_TransmitRates[64] = {0};
3152 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003153
3154 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3155 if (NULL == output)
3156 return RETURN_ERR;
3157 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003158 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3159
3160 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3161 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3162 } else {
3163 temp = strtok(temp_TransmitRates," ");
3164 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003165 {
developere9d0abd2022-09-13 15:40:57 +08003166 // Convert 100 kbps to Mbps
3167 temp[strlen(temp)-1]=0;
3168 if((temp[0]=='5') && (temp[1]=='\0'))
3169 {
3170 temp="5.5";
3171 }
3172 strcat(temp_output,temp);
3173 temp = strtok(NULL," ");
3174 if(temp!=NULL)
3175 {
3176 strcat(temp_output,",");
3177 }
developer06a01d92022-09-07 16:32:39 +08003178 }
developere9d0abd2022-09-13 15:40:57 +08003179 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003180 }
developer06a01d92022-09-07 16:32:39 +08003181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003182 return RETURN_OK;
3183}
3184
3185INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3186{
3187 char *temp;
3188 char temp1[128];
3189 char temp_output[128];
3190 char temp_TransmitRates[128];
3191 char set[128];
3192 char sub_set[128];
3193 int set_count=0,subset_count=0;
3194 int set_index=0,subset_index=0;
3195 char *token;
3196 int flag=0, i=0;
3197 struct params params={'\0'};
3198 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003199 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003200
3201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3202 if(NULL == TransmitRates)
3203 return RETURN_ERR;
3204 strcpy(sub_set,TransmitRates);
3205
3206 //Allow only supported Data transmit rate to be set
3207 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3208 token = strtok(sub_set,",");
3209 while( token != NULL ) /* split the basic rate to be set, by comma */
3210 {
3211 sub_set[subset_count]=atoi(token);
3212 subset_count++;
3213 token=strtok(NULL,",");
3214 }
3215 token=strtok(set,",");
3216 while(token!=NULL) /* split the supported rate by comma */
3217 {
3218 set[set_count]=atoi(token);
3219 set_count++;
3220 token=strtok(NULL,",");
3221 }
3222 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3223 {
3224 for(set_index=0;set_index < set_count;set_index++)
3225 {
3226 flag=0;
3227 if(sub_set[subset_index]==set[set_index])
3228 break;
3229 else
3230 flag=1; /* No match found */
3231 }
3232 if(flag==1)
3233 return RETURN_ERR; //If value not found return Error
3234 }
3235 strcpy(temp_TransmitRates,TransmitRates);
3236
3237 for(i=0;i<strlen(temp_TransmitRates);i++)
3238 {
3239 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003240 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003241 {
3242 continue;
3243 }
3244 else
3245 {
3246 return RETURN_ERR;
3247 }
3248 }
3249 strcpy(temp_output,"");
3250 temp = strtok(temp_TransmitRates,",");
3251 while(temp!=NULL)
3252 {
3253 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003254 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003255 {
developeref938762022-10-19 17:21:01 +08003256 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003257 {
3258 return RETURN_ERR;
3259 }
3260 }
3261
3262 if(strcmp(temp,"5.5")==0)
3263 {
3264 strcpy(temp1,"55");
3265 }
3266 else
3267 {
3268 strcat(temp1,"0");
3269 }
3270 strcat(temp_output,temp1);
3271 temp = strtok(NULL,",");
3272 if(temp!=NULL)
3273 {
3274 strcat(temp_output," ");
3275 }
3276 }
3277 strcpy(TransmitRates,temp_output);
3278
3279 params.name= "basic_rates";
3280 params.value =TransmitRates;
3281
3282 wifi_dbg_printf("\n%s:",__func__);
3283 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3284 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3285 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3286 wifi_hostapdWrite(config_file,&params,1);
3287 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3288 return RETURN_OK;
3289}
3290
3291//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3292INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3293{
3294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3295 FILE *fp = NULL;
3296 char path[256] = {0}, output_string[256] = {0};
3297 int count = 0;
3298 char *interface = NULL;
3299
3300 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3301 if (fp == NULL)
3302 {
3303 printf("Failed to run command in Function %s\n", __FUNCTION__);
3304 return RETURN_ERR;
3305 }
3306 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3307 {
3308 interface = strchr(path, '=');
3309
3310 if (interface != NULL)
3311 {
3312 strcpy(output_string, interface + 1);
3313 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3314 interface_name[count] = output_string[count];
3315
3316 interface_name[count] = '\0';
3317 }
3318 }
3319 pclose(fp);
3320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3321 return RETURN_OK;
3322}
3323
3324INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3325{
3326 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3327 output_struct->radio_BytesSent = 0;
3328 output_struct->radio_BytesReceived = 0;
3329 output_struct->radio_PacketsSent = 0;
3330 output_struct->radio_PacketsReceived = 0;
3331 output_struct->radio_ErrorsSent = 0;
3332 output_struct->radio_ErrorsReceived = 0;
3333 output_struct->radio_DiscardPacketsSent = 0;
3334 output_struct->radio_DiscardPacketsReceived = 0;
3335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3336 return RETURN_OK;
3337}
3338
3339
3340INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3341{
3342 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3343 CHAR buf[MAX_CMD_SIZE] = {0};
3344 CHAR Value[MAX_BUF_SIZE] = {0};
3345 FILE *fp = NULL;
3346
3347 if (ifname == NULL || strlen(ifname) <= 1)
3348 return RETURN_OK;
3349
3350 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3351 system(buf);
3352
3353 fp = fopen("/tmp/Radio_Stats.txt", "r");
3354 if(fp == NULL)
3355 {
3356 printf("/tmp/Radio_Stats.txt not exists \n");
3357 return RETURN_ERR;
3358 }
3359 fclose(fp);
3360
3361 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3362 File_Reading(buf, Value);
3363 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3364
3365 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3366 File_Reading(buf, Value);
3367 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3368
3369 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3370 File_Reading(buf, Value);
3371 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3372
3373 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3374 File_Reading(buf, Value);
3375 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3376
3377 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3378 File_Reading(buf, Value);
3379 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3380
3381 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3382 File_Reading(buf, Value);
3383 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3384
3385 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3386 File_Reading(buf, Value);
3387 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3388
3389 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3390 File_Reading(buf, Value);
3391 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3392
3393 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3394 return RETURN_OK;
3395}
3396
3397INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3398{
3399 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3400 CHAR buf[MAX_CMD_SIZE] = {0};
3401 FILE *fp = NULL;
3402 INT count = 0;
3403
3404 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3405 {
3406 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3407 File_Reading(buf, status);
3408 }
3409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3410 return RETURN_OK;
3411}
3412
3413//Get detail radio traffic static info
3414INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3415{
3416
3417#if 0
3418 //ifconfig radio_x
3419 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3420 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3421 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3422 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3423
3424 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3425 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3426 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.
3427 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.
3428
3429 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3430 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].
3431 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3432 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.
3433 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
3434 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
3435 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
3436 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
3437 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
3438
3439 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
3440 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
3441 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
3442 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.
3443
3444 return RETURN_OK;
3445#endif
3446
developera91d99f2022-09-29 15:59:10 +08003447 CHAR interface_name[64] = {0};
3448 CHAR config_path[64] = {0};
3449 BOOL iface_status = FALSE;
3450 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003451
3452 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3453 if (NULL == output_struct)
3454 return RETURN_ERR;
3455
developera91d99f2022-09-29 15:59:10 +08003456 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3457 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003458
developera91d99f2022-09-29 15:59:10 +08003459 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003460
developera91d99f2022-09-29 15:59:10 +08003461 if (iface_status == TRUE)
3462 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3463 else
3464 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003465
developera91d99f2022-09-29 15:59:10 +08003466 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3467 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3468 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3469 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3470 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3471 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3472 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3473 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003474
3475 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3476 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].
3477 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3478 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.
3479 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
3480 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
3481 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
3482 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
3483 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
3484
3485 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
3486 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
3487 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
3488 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.
3489
3490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3491
3492 return RETURN_OK;
3493}
3494
3495//Set radio traffic static Measureing rules
3496INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3497{
3498 //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
3499 // Else, save the MeasuringRate and MeasuringInterval for future usage
3500
3501 return RETURN_OK;
3502}
3503
3504//To start or stop RadioTrafficStats
3505INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3506{
3507 //zqiu: If the RadioTrafficStats process running
3508 // if(enable)
3509 // return RETURN_OK.
3510 // else
3511 // Stop RadioTrafficStats process
3512 // Else
3513 // if(enable)
3514 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3515 // else
3516 // return RETURN_OK.
3517
3518 return RETURN_OK;
3519}
3520
3521//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
3522INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3523{
3524 //zqiu: Please ignor signalIndex.
3525 if (NULL == SignalLevel)
3526 return RETURN_ERR;
3527 *SignalLevel=(radioIndex==0)?-19:-19;
3528
3529 return RETURN_OK;
3530}
3531
3532//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3533INT wifi_applyRadioSettings(INT radioIndex)
3534{
3535 return RETURN_OK;
3536}
3537
3538//Get the radio index assocated with this SSID entry
3539INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3540{
3541 if (NULL == radioIndex)
3542 return RETURN_ERR;
3543 *radioIndex=ssidIndex%2;
3544
3545 return RETURN_OK;
3546}
3547
3548//Device.WiFi.SSID.{i}.Enable
3549//Get SSID enable configuration parameters (not the SSID enable status)
3550INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3551{
3552 if (NULL == output_bool)
3553 return RETURN_ERR;
3554
developer06a01d92022-09-07 16:32:39 +08003555 return wifi_getApEnable(ssidIndex, output_bool);
3556}
3557
3558//Device.WiFi.SSID.{i}.Enable
3559//Set SSID enable configuration parameters
3560INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3561{
developer06a01d92022-09-07 16:32:39 +08003562 return wifi_setApEnable(ssidIndex, enable);
3563}
3564
3565//Device.WiFi.SSID.{i}.Status
3566//Get the SSID enable status
3567INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3568{
3569 char cmd[MAX_CMD_SIZE]={0};
3570 char buf[MAX_BUF_SIZE]={0};
3571 BOOL output_bool;
3572
3573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3574 if (NULL == output_string)
3575 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003576
developer06a01d92022-09-07 16:32:39 +08003577 wifi_getApEnable(ssidIndex,&output_bool);
3578 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3579
3580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3581 return RETURN_OK;
3582}
3583
3584// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3585INT wifi_getSSIDName(INT apIndex, CHAR *output)
3586{
3587 char config_file[MAX_BUF_SIZE] = {0};
3588
3589 if (NULL == output)
3590 return RETURN_ERR;
3591
3592 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3593 wifi_hostapdRead(config_file,"ssid",output,32);
3594
3595 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3596 return RETURN_OK;
3597}
3598
3599// Set a max 32 byte string and sets an internal variable to the SSID name
3600INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3601{
3602 char str[MAX_BUF_SIZE]={'\0'};
3603 char cmd[MAX_CMD_SIZE]={'\0'};
3604 struct params params;
3605 char config_file[MAX_BUF_SIZE] = {0};
3606
3607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3608 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3609 return RETURN_ERR;
3610
3611 params.name = "ssid";
3612 params.value = ssid_string;
3613 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3614 wifi_hostapdWrite(config_file, &params, 1);
3615 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3617
3618 return RETURN_OK;
3619}
3620
3621//Get the BSSID
3622INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3623{
3624 char cmd[MAX_CMD_SIZE]="";
3625
3626 if (NULL == output_string)
3627 return RETURN_ERR;
3628
3629 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3630 {
developer1d57d002022-10-12 18:03:15 +08003631 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 +08003632 _syscmd(cmd, output_string, 64);
3633 return RETURN_OK;
3634 }
3635 strncpy(output_string, "\0", 1);
3636
3637 return RETURN_ERR;
3638}
3639
3640//Get the MAC address associated with this Wifi SSID
3641INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3642{
3643 wifi_getBaseBSSID(ssidIndex,output_string);
3644 return RETURN_OK;
3645}
3646
3647//Get the basic SSID traffic static info
3648//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3649//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3650INT wifi_applySSIDSettings(INT ssidIndex)
3651{
3652 BOOL status = false;
3653 char cmd[MAX_CMD_SIZE] = {0};
3654 char buf[MAX_CMD_SIZE] = {0};
3655 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003656 int max_radio_num = 0;
3657 int radioIndex = 0;
3658
3659 wifi_getMaxRadioNumber(&max_radio_num);
3660
3661 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003662
3663 wifi_getApEnable(ssidIndex,&status);
3664 // Do not apply when ssid index is disabled
3665 if (status == false)
3666 return RETURN_OK;
3667
3668 /* Doing full remove and add for ssid Index
3669 * Not all hostapd options are supported with reload
3670 * for example macaddr_acl
3671 */
3672 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3673 return RETURN_ERR;
3674
3675 ret = wifi_setApEnable(ssidIndex,true);
3676
3677 /* Workaround for hostapd issue with multiple bss definitions
3678 * when first created interface will be removed
3679 * then all vaps other vaps on same phy are removed
3680 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003681 for(int i=0; i < MAX_APS/max_radio_num; i++) {
3682 apIndex = max_radio_num*i+radioIndex;
developer06a01d92022-09-07 16:32:39 +08003683 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3684 _syscmd(cmd, buf, sizeof(buf));
3685 if(*buf == '1')
3686 wifi_setApEnable(apIndex, true);
3687 }
3688
3689 return ret;
3690}
3691
developera3c68b92022-09-13 15:27:29 +08003692struct channels_noise {
3693 int channel;
3694 int noise;
3695};
3696
3697// Return noise array for each channel
3698int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3699{
3700 FILE *f = NULL;
3701 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003702 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003703 size_t len = 0;
3704 ssize_t read = 0;
3705 int tmp = 0, arr_index = -1;
3706
3707 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3708
3709 if ((f = popen(cmd, "r")) == NULL) {
3710 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3711 return RETURN_ERR;
3712 }
developer5550e242022-09-30 09:59:32 +08003713
3714 while(fgets(line, sizeof(line), f) != NULL) {
3715 if(arr_index < channels_num){
3716 sscanf(line, "%d", &tmp);
3717 if (tmp > 0) { // channel frequency, the first line must be frequency
3718 arr_index++;
3719 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3720 } else { // noise
3721 channels_noise_arr[arr_index].noise = tmp;
3722 }
3723 }else{
3724 break;
developera3c68b92022-09-13 15:27:29 +08003725 }
3726 }
developera3c68b92022-09-13 15:27:29 +08003727 pclose(f);
3728 return RETURN_OK;
3729}
3730
developer06a01d92022-09-07 16:32:39 +08003731//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3732//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3733INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3734{
developera3c68b92022-09-13 15:27:29 +08003735 int index = -1;
3736 wifi_neighbor_ap2_t *scan_array = NULL;
3737 char cmd[256]={0};
3738 char buf[128]={0};
3739 char file_name[32] = {0};
3740 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003741 char line[256] = {0};
3742 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003743 int freq=0;
3744 FILE *f = NULL;
3745 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003746 int channels_num = 0;
3747 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003748 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003749 bool filter_enable = false;
3750 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003751 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003752
developer615510b2022-09-27 10:14:35 +08003753 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003754
3755 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3756 f = fopen(file_name, "r");
3757 if (f != NULL) {
3758 fgets(filter_SSID, sizeof(file_name), f);
3759 if (strlen(filter_SSID) != 0)
3760 filter_enable = true;
3761 fclose(f);
3762 }
3763
developer033b37b2022-10-18 11:27:46 +08003764 phyId = radio_index_to_phy(radioIndex);
3765 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003766 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003767 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003768
developer5550e242022-09-30 09:59:32 +08003769
developer06a01d92022-09-07 16:32:39 +08003770
developera3c68b92022-09-13 15:27:29 +08003771 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 +08003772 // 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 +08003773 fprintf(stderr, "cmd: %s\n", cmd);
3774 if ((f = popen(cmd, "r")) == NULL) {
3775 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3776 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003777 }
developer5550e242022-09-30 09:59:32 +08003778
3779 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3780 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3781
developer615510b2022-09-27 10:14:35 +08003782 ret = fgets(line, sizeof(line), f);
3783 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003784 if(strstr(line, "BSS") != NULL) { // new neighbor info
3785 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3786 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3787 // 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 +08003788
developera3c68b92022-09-13 15:27:29 +08003789 if (!filter_BSS) {
3790 index++;
3791 wifi_neighbor_ap2_t *tmp;
3792 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3793 if (tmp == NULL) { // no more memory to use
3794 index--;
3795 wifi_dbg_printf("%s: realloc failed\n", __func__);
3796 break;
3797 }
3798 scan_array = tmp;
3799 }
3800 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3801
3802 filter_BSS = false;
3803 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3804 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3805 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3806 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3807 } else if (strstr(line, "freq") != NULL) {
3808 sscanf(line," freq: %d", &freq);
3809 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3810
3811 if (freq >= 2412 && freq <= 2484) {
3812 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3813 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3814 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3815 }
3816 else if (freq >= 5160 && freq <= 5805) {
3817 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3818 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3819 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3820 }
3821
3822 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003823 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003824 for (int i = 0; i < channels_num; i++) {
3825 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3826 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3827 break;
3828 }
3829 }
3830 }
3831 } else if (strstr(line, "beacon interval") != NULL) {
3832 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3833 } else if (strstr(line, "signal") != NULL) {
3834 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3835 } else if (strstr(line,"SSID") != NULL) {
3836 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3837 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3838 filter_BSS = true;
3839 }
3840 } else if (strstr(line, "Supported rates") != NULL) {
3841 char SRate[80] = {0}, *tmp = NULL;
3842 memset(buf, 0, sizeof(buf));
3843 strcpy(SRate, line);
3844 tmp = strtok(SRate, ":");
3845 tmp = strtok(NULL, ":");
3846 strcpy(buf, tmp);
3847 memset(SRate, 0, sizeof(SRate));
3848
3849 tmp = strtok(buf, " \n");
3850 while (tmp != NULL) {
3851 strcat(SRate, tmp);
3852 if (SRate[strlen(SRate) - 1] == '*') {
3853 SRate[strlen(SRate) - 1] = '\0';
3854 }
3855 strcat(SRate, ",");
3856
3857 tmp = strtok(NULL, " \n");
3858 }
3859 SRate[strlen(SRate) - 1] = '\0';
3860 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3861 } else if (strstr(line, "DTIM") != NULL) {
3862 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3863 } else if (strstr(line, "VHT capabilities") != NULL) {
3864 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3865 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3866 } else if (strstr(line, "HT capabilities") != NULL) {
3867 strcat(scan_array[index].ap_SupportedStandards, ",n");
3868 strcpy(scan_array[index].ap_OperatingStandards, "n");
3869 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003870 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003871 sscanf(line," * channel width: %d", &vht_channel_width);
3872 if(vht_channel_width == 1) {
3873 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3874 } else {
3875 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3876 }
3877 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3878 continue;
3879 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003880 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003881 sscanf(line," * secondary channel offset: %s", &buf);
3882 if (!strcmp(buf, "above")) {
3883 //40Mhz +
3884 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3885 }
3886 else if (!strcmp(buf, "below")) {
3887 //40Mhz -
3888 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3889 } else {
3890 //20Mhz
3891 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3892 }
3893 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3894 continue;
3895 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003896 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3897 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3898 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003899 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3900 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003901 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003902 else
developer615510b2022-09-27 10:14:35 +08003903 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003904 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003905 if (strstr(line, "HE80/5GHz") != NULL) {
3906 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3907 ret = fgets(line, sizeof(line), f);
3908 } else
3909 continue;
developera3c68b92022-09-13 15:27:29 +08003910 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003911 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003912 }
developer615510b2022-09-27 10:14:35 +08003913 continue;
developera3c68b92022-09-13 15:27:29 +08003914 } else if (strstr(line, "WPA") != NULL) {
3915 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3916 } else if (strstr(line, "RSN") != NULL) {
3917 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3918 } else if (strstr(line, "Group cipher") != NULL) {
3919 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3920 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3921 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3922 }
3923 }
developer615510b2022-09-27 10:14:35 +08003924 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003925 }
3926
3927 if (!filter_BSS) {
3928 *output_array_size = index + 1;
3929 } else {
3930 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3931 *output_array_size = index;
3932 }
3933 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003934 pclose(f);
developer5550e242022-09-30 09:59:32 +08003935 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003936 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003937 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003938}
3939
3940//>> Deprecated: used for old RDKB code.
3941INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3942{
3943 INT status = RETURN_ERR;
3944
3945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3946 output_struct->wifi_PLCPErrorCount = 0;
3947 output_struct->wifi_FCSErrorCount = 0;
3948 output_struct->wifi_InvalidMACCount = 0;
3949 output_struct->wifi_PacketsOtherReceived = 0;
3950 output_struct->wifi_Noise = 0;
3951 status = RETURN_OK;
3952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3953 return status;
3954}
3955
3956INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3957{
3958 char cmd[128];
3959 char buf[1280];
3960 char *pos = NULL;
3961
3962 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3963 if (NULL == output_struct)
3964 return RETURN_ERR;
3965
3966 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3967
3968 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3969 _syscmd(cmd, buf, sizeof(buf));
3970
3971 pos = buf;
3972 if ((pos = strstr(pos, "RX packets:")) == NULL)
3973 return RETURN_ERR;
3974 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3975
3976 if ((pos = strstr(pos, "TX packets:")) == NULL)
3977 return RETURN_ERR;
3978 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3979
3980 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3981 return RETURN_ERR;
3982 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3983
3984 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3985 return RETURN_ERR;
3986 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3987
3988 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3989 _syscmd(cmd, buf, sizeof(buf));
3990 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3991
3992#if 0
3993 //TODO: need to revisit below implementation
3994 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3995 char interface_name[MAX_BUF_SIZE] = {0};
3996 char interface_status[MAX_BUF_SIZE] = {0};
3997 char Value[MAX_BUF_SIZE] = {0};
3998 char buf[MAX_CMD_SIZE] = {0};
3999 char cmd[MAX_CMD_SIZE] = {0};
4000 FILE *fp = NULL;
4001
4002 if (NULL == output_struct) {
4003 return RETURN_ERR;
4004 }
4005
4006 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4007
4008 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4009 {
4010 if(apIndex == 0) //private_wifi for 2.4G
4011 {
4012 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4013 }
4014 else if(apIndex == 1) //private_wifi for 5G
4015 {
4016 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4017 }
4018 else if(apIndex == 4) //public_wifi for 2.4G
4019 {
4020 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4021 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4022 {
4023 return RETURN_ERR;
4024 }
4025 if(buf[0] == '#')//tp-link
4026 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4027 else//tenda
4028 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4029 }
4030 else if(apIndex == 5) //public_wifi for 5G
4031 {
4032 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4033 }
4034
4035 GetIfacestatus(interface_name, interface_status);
4036
4037 if(0 != strcmp(interface_status, "1"))
4038 return RETURN_ERR;
4039
4040 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4041 system(cmd);
4042
4043 fp = fopen("/tmp/SSID_Stats.txt", "r");
4044 if(fp == NULL)
4045 {
4046 printf("/tmp/SSID_Stats.txt not exists \n");
4047 return RETURN_ERR;
4048 }
4049 fclose(fp);
4050
4051 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4052 File_Reading(buf, Value);
4053 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4054
4055 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4056 File_Reading(buf, Value);
4057 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4058
4059 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4060 File_Reading(buf, Value);
4061 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4062
4063 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4064 File_Reading(buf, Value);
4065 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4066
4067 /* There is no specific parameter from caller to associate the value wifi_Associations */
4068 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4069 //_syscmd(cmd, buf, sizeof(buf));
4070 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4071 }
4072#endif
4073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4074 return RETURN_OK;
4075}
4076
4077INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4078{
4079 char interface_name[MAX_BUF_SIZE] = {0};
4080 char interface_status[MAX_BUF_SIZE] = {0};
4081 char Value[MAX_BUF_SIZE] = {0};
4082 char buf[MAX_CMD_SIZE] = {0};
4083 char cmd[MAX_CMD_SIZE] = {0};
4084 FILE *fp = NULL;
4085
4086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4087 if (NULL == output_struct)
4088 return RETURN_ERR;
4089
4090 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4091
4092 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4093 {
4094 if(apIndex == 0) //private_wifi for 2.4G
4095 {
4096 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4097 }
4098 else if(apIndex == 1) //private_wifi for 5G
4099 {
4100 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4101 }
4102 else if(apIndex == 4) //public_wifi for 2.4G
4103 {
4104 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4105 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4106 {
4107 return RETURN_ERR;
4108 }
4109 if(buf[0] == '#')
4110 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4111 else
4112 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4113 }
4114 else if(apIndex == 5) //public_wifi for 5G
4115 {
4116 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4117 }
4118
4119 GetIfacestatus(interface_name, interface_status);
4120
4121 if(0 != strcmp(interface_status, "1"))
4122 return RETURN_ERR;
4123
4124 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4125 system(cmd);
4126
4127 fp = fopen("/tmp/SSID_Stats.txt", "r");
4128 if(fp == NULL)
4129 {
4130 printf("/tmp/SSID_Stats.txt not exists \n");
4131 return RETURN_ERR;
4132 }
4133 fclose(fp);
4134
4135 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4136 File_Reading(buf, Value);
4137 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4138
4139 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4140 File_Reading(buf, Value);
4141 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4142
4143 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4144 File_Reading(buf, Value);
4145 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4146
4147 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4148 File_Reading(buf, Value);
4149 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4150 }
4151
4152 output_struct->wifi_UnicastPacketsSent = 0;
4153 output_struct->wifi_UnicastPacketsReceived = 0;
4154 output_struct->wifi_MulticastPacketsSent = 0;
4155 output_struct->wifi_MulticastPacketsReceived = 0;
4156 output_struct->wifi_BroadcastPacketsSent = 0;
4157 output_struct->wifi_BroadcastPacketsRecevied = 0;
4158 output_struct->wifi_UnknownPacketsReceived = 0;
4159
4160 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4161 return RETURN_OK;
4162}
4163
4164INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4165{
4166 INT status = RETURN_ERR;
4167
4168 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4169 //Below values should get updated from hal
4170 output_struct->wifi_RetransCount=0;
4171 output_struct->wifi_FailedRetransCount=0;
4172 output_struct->wifi_RetryCount=0;
4173 output_struct->wifi_MultipleRetryCount=0;
4174 output_struct->wifi_ACKFailureCount=0;
4175 output_struct->wifi_AggregatedPacketCount=0;
4176
4177 status = RETURN_OK;
4178 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4179
4180 return status;
4181}
4182
4183INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4184{
4185 INT status = RETURN_ERR;
4186 UINT index;
4187 wifi_neighbor_ap_t *pt=NULL;
4188
4189 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4190 *output_array_size=2;
4191 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4192 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4193 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4194 strcpy(pt->ap_Radio,"");
4195 strcpy(pt->ap_SSID,"");
4196 strcpy(pt->ap_BSSID,"");
4197 strcpy(pt->ap_Mode,"");
4198 pt->ap_Channel=1;
4199 pt->ap_SignalStrength=0;
4200 strcpy(pt->ap_SecurityModeEnabled,"");
4201 strcpy(pt->ap_EncryptionMode,"");
4202 strcpy(pt->ap_OperatingFrequencyBand,"");
4203 strcpy(pt->ap_SupportedStandards,"");
4204 strcpy(pt->ap_OperatingStandards,"");
4205 strcpy(pt->ap_OperatingChannelBandwidth,"");
4206 pt->ap_BeaconPeriod=1;
4207 pt->ap_Noise=0;
4208 strcpy(pt->ap_BasicDataTransferRates,"");
4209 strcpy(pt->ap_SupportedDataTransferRates,"");
4210 pt->ap_DTIMPeriod=1;
4211 pt->ap_ChannelUtilization = 1;
4212 }
4213
4214 status = RETURN_OK;
4215 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4216
4217 return status;
4218}
4219
4220//----------------- AP HAL -------------------------------
4221
4222//>> Deprecated: used for old RDKB code.
4223INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4224{
4225 if (NULL == output_ulong || NULL == output_struct)
4226 return RETURN_ERR;
4227 *output_ulong = 0;
4228 *output_struct = NULL;
4229 return RETURN_OK;
4230}
4231
4232#ifdef HAL_NETLINK_IMPL
4233static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4234 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4235 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4236 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4237 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4238 char mac_addr[20];
4239 static int count=0;
4240 int rate=0;
4241
4242 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4243
4244 nla_parse(tb,
4245 NL80211_ATTR_MAX,
4246 genlmsg_attrdata(gnlh, 0),
4247 genlmsg_attrlen(gnlh, 0),
4248 NULL);
4249
4250 if(!tb[NL80211_ATTR_STA_INFO]) {
4251 fprintf(stderr, "sta stats missing!\n");
4252 return NL_SKIP;
4253 }
4254
4255
4256 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4257 fprintf(stderr, "failed to parse nested attributes!\n");
4258 return NL_SKIP;
4259 }
4260
4261 //devIndex starts from 1
4262 if( ++count == out->wifi_devIndex )
4263 {
4264 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4265 //Getting the mac addrress
4266 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4267
4268 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4269 fprintf(stderr, "failed to parse nested rate attributes!");
4270 return NL_SKIP;
4271 }
4272
4273 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4274 if(rinfo[NL80211_RATE_INFO_BITRATE])
4275 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4276 out->wifi_devTxRate = rate/10;
4277 }
4278
4279 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4280 fprintf(stderr, "failed to parse nested rate attributes!");
4281 return NL_SKIP;
4282 }
4283
4284 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4285 if(rinfo[NL80211_RATE_INFO_BITRATE])
4286 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4287 out->wifi_devRxRate = rate/10;
4288 }
4289 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4290 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4291
4292 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4293 count = 0; //starts the count for next cycle
4294 return NL_STOP;
4295 }
4296
4297 return NL_SKIP;
4298
4299}
4300#endif
4301
4302INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4303{
4304#ifdef HAL_NETLINK_IMPL
4305 Netlink nl;
4306 char if_name[10];
4307
4308 wifi_device_info_t info;
4309 info.wifi_devIndex = devIndex;
4310
4311 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4312
4313 nl.id = initSock80211(&nl);
4314
4315 if (nl.id < 0) {
4316 fprintf(stderr, "Error initializing netlink \n");
4317 return -1;
4318 }
4319
4320 struct nl_msg* msg = nlmsg_alloc();
4321
4322 if (!msg) {
4323 fprintf(stderr, "Failed to allocate netlink message.\n");
4324 nlfree(&nl);
4325 return -2;
4326 }
4327
4328 genlmsg_put(msg,
4329 NL_AUTO_PORT,
4330 NL_AUTO_SEQ,
4331 nl.id,
4332 0,
4333 NLM_F_DUMP,
4334 NL80211_CMD_GET_STATION,
4335 0);
4336
4337 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4338 nl_send_auto(nl.socket, msg);
4339 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4340 nl_recvmsgs(nl.socket, nl.cb);
4341 nlmsg_free(msg);
4342 nlfree(&nl);
4343
4344 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4345 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4346 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4347 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4348 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4349 return RETURN_OK;
4350#else
4351 //iw utility to retrieve station information
4352#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4353#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4354#define MACFILE "/tmp/wifi_AssoMac.txt"
4355#define TXRATEFILE "/tmp/wifi_txrate.txt"
4356#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4357 FILE *file = NULL;
4358 char if_name[10] = {'\0'};
4359 char pipeCmd[256] = {'\0'};
4360 char line[256];
4361 int count,device = 0;
4362
4363 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4364
4365 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4366 file = popen(pipeCmd, "r");
4367
4368 if(file == NULL)
4369 return RETURN_ERR; //popen failed
4370
4371 fgets(line, sizeof line, file);
4372 device = atoi(line);
4373 pclose(file);
4374
4375 if(device == 0)
4376 return RETURN_ERR; //No devices are connected
4377
4378 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4379 system(pipeCmd);
4380
4381 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4382
4383 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4384
4385 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4386
4387 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4388
4389 //devIndex starts from 1, ++count
4390 if((file = fopen(SIGNALFILE, "r")) != NULL )
4391 {
4392 for(count =0;fgets(line, sizeof line, file) != NULL;)
4393 {
4394 if (++count == devIndex)
4395 {
4396 output_struct->wifi_devSignalStrength = atoi(line);
4397 break;
4398 }
4399 }
4400 fclose(file);
4401 }
4402 else
4403 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4404
4405 if((file = fopen(MACFILE, "r")) != NULL )
4406 {
4407 for(count =0;fgets(line, sizeof line, file) != NULL;)
4408 {
4409 if (++count == devIndex)
4410 {
4411 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]);
4412 break;
4413 }
4414 }
4415 fclose(file);
4416 }
4417 else
4418 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4419
4420 if((file = fopen(TXRATEFILE, "r")) != NULL )
4421 {
4422 for(count =0;fgets(line, sizeof line, file) != NULL;)
4423 {
4424 if (++count == devIndex)
4425 {
4426 output_struct->wifi_devTxRate = atoi(line);
4427 break;
4428 }
4429 }
4430 fclose(file);
4431 }
4432 else
4433 fprintf(stderr,"fopen wifi_txrate.txt failed");
4434
4435 if((file = fopen(RXRATEFILE, "r")) != NULL)
4436 {
4437 for(count =0;fgets(line, sizeof line, file) != NULL;)
4438 {
4439 if (++count == devIndex)
4440 {
4441 output_struct->wifi_devRxRate = atoi(line);
4442 break;
4443 }
4444 }
4445 fclose(file);
4446 }
4447 else
4448 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4449
4450 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4451
4452 return RETURN_OK;
4453#endif
4454}
4455
4456INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4457{
4458 if (NULL == device)
4459 return RETURN_ERR;
4460 return RETURN_OK;
4461}
4462//<<
4463
4464
4465//--------------wifi_ap_hal-----------------------------
4466//enables CTS protection for the radio used by this AP
4467INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4468{
4469 //save config and Apply instantly
4470 return RETURN_ERR;
4471}
4472
4473// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4474INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4475{
developer463d39a2022-09-13 15:32:51 +08004476 char config_file[64] = {'\0'};
4477 char buf[64] = {'\0'};
4478 struct params list;
4479
4480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4481 list.name = "ht_coex";
4482 snprintf(buf, sizeof(buf), "%d", enable);
4483 list.value = buf;
4484
4485 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4486 wifi_hostapdWrite(config_file, &list, 1);
4487 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4488
4489 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4490
4491 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004492}
4493
4494//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4495INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4496{
developerea4bcce2022-09-13 15:26:13 +08004497 char config_file[MAX_BUF_SIZE] = {'\0'};
4498 char buf[MAX_BUF_SIZE] = {'\0'};
4499 struct params list;
4500
4501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4502 if (threshold < 256 || threshold > 2346 )
4503 return RETURN_ERR;
4504 list.name = "fragm_threshold";
4505 snprintf(buf, sizeof(buf), "%d", threshold);
4506 list.value = buf;
4507
4508 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4509 wifi_hostapdWrite(config_file, &list, 1);
4510 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004511
developerea4bcce2022-09-13 15:26:13 +08004512 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004513
4514 return RETURN_OK;
4515}
4516
4517// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4518INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4519{
developer51a927d2022-09-13 15:42:22 +08004520 char config_file[64] = {'\0'};
4521 char cmd[128] = {'\0'};
4522 char buf[64] = {'\0'};
4523 char stbc_config[16] = {'\0'};
4524 wifi_band band;
4525 int iterator = 0;
4526 BOOL current_stbc = FALSE;
4527
4528 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4529
4530 band = wifi_index_to_band(radioIndex);
4531 if (band == band_invalid)
4532 return RETURN_ERR;
4533
4534 if (band == band_2_4)
4535 iterator = 1;
4536 else if (band == band_5)
4537 iterator = 2;
4538 else
4539 return RETURN_OK;
4540
4541 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4542
4543 // set ht and vht config
4544 for (int i = 0; i < iterator; i++) {
4545 memset(stbc_config, 0, sizeof(stbc_config));
4546 memset(cmd, 0, sizeof(cmd));
4547 memset(buf, 0, sizeof(buf));
4548 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4549 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4550 _syscmd(cmd, buf, sizeof(buf));
4551 if (strlen(buf) != 0)
4552 current_stbc = TRUE;
4553 if (current_stbc == STBC_Enable)
4554 continue;
4555
4556 if (STBC_Enable == TRUE) {
4557 // Append the STBC flags in capab config
4558 memset(cmd, 0, sizeof(cmd));
4559 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004560 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004561 else
developer6372c2b2022-10-27 17:39:51 +08004562 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 +08004563 _syscmd(cmd, buf, sizeof(buf));
4564 } else if (STBC_Enable == FALSE) {
4565 // Remove the STBC flags and remain other flags in capab
4566 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004567 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004568 _syscmd(cmd, buf, sizeof(buf));
4569 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004570 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004571 _syscmd(cmd, buf, sizeof(buf));
4572 }
4573 }
4574
4575 wifi_reloadAp(radioIndex);
4576
4577 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4578 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004579}
4580
4581// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4582INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4583{
developer54e6b9f2022-09-28 14:41:20 +08004584 char AMSDU_file_path[64] = {0};
4585
4586 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4587
4588 if(output_bool == NULL)
4589 return RETURN_ERR;
4590
4591 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4592
4593 if (access(AMSDU_file_path, F_OK) == 0)
4594 *output_bool = TRUE;
4595 else
4596 *output_bool = FALSE;
4597
4598 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4599 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004600}
4601
4602// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4603INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4604{
developer54e6b9f2022-09-28 14:41:20 +08004605 char cmd[64]={0};
4606 char buf[64]={0};
4607 char AMSDU_file_path[64] = {0};
4608
4609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4610
4611 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4612 _syscmd(cmd, buf, sizeof(buf));
4613
4614 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4615 memset(cmd, 0, sizeof(cmd));
4616 if (amsduEnable == TRUE)
4617 sprintf(cmd, "touch %s", AMSDU_file_path);
4618 else
4619 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4620 _syscmd(cmd, buf, sizeof(buf));
4621
4622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4623 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004624}
4625
4626//P2 // outputs the number of Tx streams
4627INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4628{
developer2de97692022-09-26 14:00:03 +08004629 char buf[8] = {0};
4630 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004631 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004632
4633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4634
4635 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4636 _syscmd(cmd, buf, sizeof(buf));
4637
developer033b37b2022-10-18 11:27:46 +08004638 phyId = radio_index_to_phy(radioIndex);
developer2de97692022-09-26 14:00:03 +08004639 // if there is no record, output the max number of spatial streams
4640 if (strlen(buf) == 0) {
developer033b37b2022-10-18 11:27:46 +08004641 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 +08004642 _syscmd(cmd, buf, sizeof(buf));
4643 }
4644
4645 *output_int = (INT)strtol(buf, NULL, 10);
4646
4647 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4648
4649 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004650}
4651
4652//P2 // sets the number of Tx streams to an enviornment variable
4653INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4654{
developer2de97692022-09-26 14:00:03 +08004655 char cmd[128] = {0};
4656 char buf[128] = {0};
4657 char chain_mask_file[128] = {0};
4658 FILE *f = NULL;
developer033b37b2022-10-18 11:27:46 +08004659 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004660
4661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4662
4663 if (numStreams == 0) {
4664 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4665 return RETURN_ERR;
4666 }
4667 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004668
4669 phyId = radio_index_to_phy(radioIndex);
4670 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004671 _syscmd(cmd, buf, sizeof(buf));
4672
4673 if (strlen(buf) > 0) {
4674 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4675 return RETURN_ERR;
4676 }
4677 wifi_setRadioEnable(radioIndex, TRUE);
4678
4679 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4680 f = fopen(chain_mask_file, "w");
4681 if (f == NULL) {
4682 fprintf(stderr, "%s: fopen failed.\n", __func__);
4683 return RETURN_ERR;
4684 }
4685 fprintf(f, "%d", numStreams);
4686 fclose(f);
4687 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4688 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004689}
4690
4691//P2 // outputs the number of Rx streams
4692INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4693{
developer2de97692022-09-26 14:00:03 +08004694 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4695 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4696 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004697 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004698 }
4699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004700 return RETURN_OK;
4701}
4702
4703//P2 // sets the number of Rx streams to an enviornment variable
4704INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4705{
developer2de97692022-09-26 14:00:03 +08004706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4707 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4708 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4709 return RETURN_ERR;
4710 }
4711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004712 return RETURN_ERR;
4713}
4714
4715//Get radio RDG enable setting
4716INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4717{
4718 if (NULL == output_bool)
4719 return RETURN_ERR;
4720 *output_bool = TRUE;
4721 return RETURN_OK;
4722}
4723
4724//Get radio RDG enable setting
4725INT wifi_getRadioReverseDirectionGrantEnable(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 RDG enable setting
4734INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4735{
4736 return RETURN_ERR;
4737}
4738
4739//Get radio ADDBA enable setting
4740INT wifi_getRadioDeclineBARequestEnable(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 ADDBA enable setting
4749INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4750{
4751 return RETURN_ERR;
4752}
4753
4754//Get radio auto block ack enable setting
4755INT wifi_getRadioAutoBlockAckEnable(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//Set radio auto block ack enable setting
4764INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4765{
4766 return RETURN_ERR;
4767}
4768
4769//Get radio 11n pure mode enable support
4770INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4771{
4772 if (NULL == output_bool)
4773 return RETURN_ERR;
4774 *output_bool = TRUE;
4775 return RETURN_OK;
4776}
4777
4778//Get radio 11n pure mode enable setting
4779INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4780{
4781 if (NULL == output_bool)
4782 return RETURN_ERR;
4783 *output_bool = TRUE;
4784 return RETURN_OK;
4785}
4786
4787//Set radio 11n pure mode enable setting
4788INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4789{
4790 return RETURN_ERR;
4791}
4792
4793//Get radio IGMP snooping enable setting
4794INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4795{
developer81bf2ed2022-09-13 15:31:14 +08004796 char cmd[128]={0};
4797 char buf[4]={0};
4798 bool bridge = FALSE, mac80211 = FALSE;
4799 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4800
4801 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004802 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004803
4804 *output_bool = FALSE;
4805
4806 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4807 _syscmd(cmd, buf, sizeof(buf));
4808 if (strncmp(buf, "1", 1) == 0)
4809 bridge = TRUE;
4810
4811 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4812 _syscmd(cmd, buf, sizeof(buf));
4813 if (strncmp(buf, "1", 1) == 0)
4814 mac80211 = TRUE;
4815
4816 if (bridge && mac80211)
4817 *output_bool = TRUE;
4818
4819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004820 return RETURN_OK;
4821}
4822
4823//Set radio IGMP snooping enable setting
4824INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4825{
developer81bf2ed2022-09-13 15:31:14 +08004826 char cmd[128]={0};
4827 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004828 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004829 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4830
4831 // bridge
4832 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4833 _syscmd(cmd, buf, sizeof(buf));
4834
developer804c64f2022-10-19 13:54:40 +08004835 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004836 // mac80211
developer804c64f2022-10-19 13:54:40 +08004837 for (int i = 0; i < max_num_radios; i++) {
developer81bf2ed2022-09-13 15:31:14 +08004838 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4839 _syscmd(cmd, buf, sizeof(buf));
4840 }
4841 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4842 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004843}
4844
4845//Get the Reset count of radio
4846INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4847{
4848 if (NULL == output_int)
4849 return RETURN_ERR;
4850 *output_int = (radioIndex==0)? 1: 3;
4851
4852 return RETURN_OK;
4853}
4854
4855
4856//---------------------------------------------------------------------------------------------------
4857//
4858// Additional Wifi AP level APIs used for Access Point devices
4859//
4860//---------------------------------------------------------------------------------------------------
4861
4862// creates a new ap and pushes these parameters to the hardware
4863INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4864{
4865 char buf[1024];
4866 char cmd[128];
developer033b37b2022-10-18 11:27:46 +08004867 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004868
4869 if (NULL == essid)
4870 return RETURN_ERR;
4871
developer033b37b2022-10-18 11:27:46 +08004872 phyId = radio_index_to_phy(radioIndex);
4873 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 +08004874 _syscmd(cmd, buf, sizeof(buf));
4875
4876 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4877 _syscmd(cmd, buf, sizeof(buf));
4878
4879 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4880
4881 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4882 _syscmd(cmd, buf, sizeof(buf));
4883
4884 return RETURN_OK;
4885}
4886
4887// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4888INT wifi_deleteAp(INT apIndex)
4889{
4890 char buf[1024];
4891 char cmd[128];
4892
4893 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4894 _syscmd(cmd, buf, sizeof(buf));
4895
4896 wifi_removeApSecVaribles(apIndex);
4897
4898 return RETURN_OK;
4899}
4900
4901// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4902INT wifi_getApName(INT apIndex, CHAR *output_string)
4903{
4904 if(NULL == output_string)
4905 return RETURN_ERR;
4906
4907 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4908 return RETURN_OK;
4909}
4910
4911// Outputs the index number in that corresponds to the SSID string
4912INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4913{
4914 CHAR *pos = NULL;
4915
4916 *output_int = -1;
4917 pos = strstr(inputSsidString, AP_PREFIX);
4918 if(pos)
4919 {
4920 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4921 return RETURN_OK;
4922 }
4923 return RETURN_ERR;
4924}
4925
4926INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4927{
4928 return wifi_getIndexFromName(inputSsidString, output_int);
4929}
4930
4931// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4932INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4933{
4934 char buf[MAX_BUF_SIZE] = {0};
4935 char cmd[MAX_CMD_SIZE] = {0};
4936 char config_file[MAX_BUF_SIZE] = {0};
4937
4938 if(NULL == output_string)
4939 return RETURN_ERR;
4940
4941 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4942 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4943 if((strcmp(buf,"3")==0))
4944 snprintf(output_string, 32, "WPAand11i");
4945 else if((strcmp(buf,"2")==0))
4946 snprintf(output_string, 32, "11i");
4947 else if((strcmp(buf,"1")==0))
4948 snprintf(output_string, 32, "WPA");
4949 else
4950 snprintf(output_string, 32, "None");
4951
4952 return RETURN_OK;
4953}
4954
4955// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4956INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4957{
4958 char config_file[MAX_BUF_SIZE] = {0};
4959 struct params list;
4960
4961 if (NULL == beaconTypeString)
4962 return RETURN_ERR;
4963 list.name = "wpa";
4964 list.value = "0";
4965
4966 if((strcmp(beaconTypeString,"WPAand11i")==0))
4967 list.value="3";
4968 else if((strcmp(beaconTypeString,"11i")==0))
4969 list.value="2";
4970 else if((strcmp(beaconTypeString,"WPA")==0))
4971 list.value="1";
4972
4973 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4974 wifi_hostapdWrite(config_file, &list, 1);
4975 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4976 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4977 return RETURN_OK;
4978}
4979
4980// sets the beacon interval on the hardware for this AP
4981INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4982{
developer5f222492022-09-13 15:21:52 +08004983 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4984 struct params params={'\0'};
4985 char buf[MAX_BUF_SIZE] = {'\0'};
4986 char config_file[MAX_BUF_SIZE] = {'\0'};
4987
4988 params.name = "beacon_int";
4989 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4990 params.value = buf;
4991
4992 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4993 wifi_hostapdWrite(config_file, &params, 1);
4994
4995 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4996 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4997 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004998}
4999
5000INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5001{
5002 //save config and apply instantly
5003 return RETURN_ERR;
5004}
5005
5006// Get the packet size threshold supported.
5007INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5008{
5009 //save config and apply instantly
5010 if (NULL == output_bool)
5011 return RETURN_ERR;
5012 *output_bool = FALSE;
5013 return RETURN_OK;
5014}
5015
5016// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5017INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5018{
5019 char cmd[128];
5020 char buf[512];
5021
5022 if (threshold > 0)
5023 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
5024 else
5025 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
5026 _syscmd(cmd, buf, sizeof(buf));
5027
5028 return RETURN_OK;
5029}
5030
5031// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5032INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5033{
5034 if (NULL == output_string)
5035 return RETURN_ERR;
5036 snprintf(output_string, 32, "TKIPandAESEncryption");
5037 return RETURN_OK;
5038
5039}
5040
5041// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5042INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5043{
5044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5045 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
5046
5047 if(NULL == output_string)
5048 return RETURN_ERR;
5049
5050 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5051 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5052
5053 if(strcmp(buf,"0")==0)
5054 {
5055 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5056 snprintf(output_string, 32, "None");
5057 return RETURN_OK;
5058 }
5059 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5060 param_name = "rsn_pairwise";
5061 else if((strcmp(buf,"1")==0))
5062 param_name = "wpa_pairwise";
5063 else
5064 return RETURN_ERR;
5065 memset(output_string,'\0',32);
5066 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5067 wifi_hostapdRead(config_file,param_name,output_string,32);
5068 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5069
5070 if(strcmp(output_string,"TKIP") == 0)
5071 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5072 else if(strcmp(output_string,"CCMP") == 0)
5073 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5074 else if(strcmp(output_string,"TKIP CCMP") == 0)
5075 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5076
5077 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5078 return RETURN_OK;
5079}
5080
5081// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5082INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5083{
5084 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5085 struct params params={'\0'};
5086 char output_string[32];
5087 char config_file[MAX_BUF_SIZE] = {0};
5088
5089 memset(output_string,'\0',32);
5090 wifi_getApWpaEncryptionMode(apIndex,output_string);
5091
5092 if(strcmp(encMode, "TKIPEncryption") == 0)
5093 params.value = "TKIP";
5094 else if(strcmp(encMode,"AESEncryption") == 0)
5095 params.value = "CCMP";
5096 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5097 params.value = "TKIP CCMP";
5098
5099 if((strcmp(output_string,"WPAand11i")==0))
5100 {
5101 params.name = "wpa_pairwise";
5102 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5103 wifi_hostapdWrite(config_file, &params, 1);
5104 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5105
5106 params.name,"rsn_pairwise";
5107 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5108 wifi_hostapdWrite(config_file, &params, 1);
5109 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5110
5111 return RETURN_OK;
5112 }
5113 else if((strcmp(output_string,"11i")==0))
5114 {
5115 params.name = "rsn_pairwise";
5116 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5117 wifi_hostapdWrite(config_file, &params, 1);
5118 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5119 return RETURN_OK;
5120 }
5121 else if((strcmp(output_string,"WPA")==0))
5122 {
5123 params.name = "wpa_pairwise";
5124 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5125 wifi_hostapdWrite(config_file, &params, 1);
5126 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5127 return RETURN_OK;
5128 }
5129
5130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5131 return RETURN_OK;
5132}
5133
5134// deletes internal security varable settings for this ap
5135INT wifi_removeApSecVaribles(INT apIndex)
5136{
5137 //TODO: remove the entry in hostapd config file
5138 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5139 //_syscmd(cmd, buf, sizeof(buf));
5140
5141 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5142 //_syscmd(cmd, buf, sizeof(buf));
5143 return RETURN_ERR;
5144}
5145
5146// changes the hardware settings to disable encryption on this ap
5147INT wifi_disableApEncryption(INT apIndex)
5148{
5149 //Apply instantly
5150 return RETURN_ERR;
5151}
5152
5153// set the authorization mode on this ap
5154// mode mapping as: 1: open, 2: shared, 4:auto
5155INT wifi_setApAuthMode(INT apIndex, INT mode)
5156{
developeraf95c502022-09-13 16:18:22 +08005157 struct params params={0};
5158 char config_file[64] = {0};
5159 int ret;
5160
5161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5162
5163 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5164 params.name = "auth_algs";
5165
5166 if (mode & 1 && mode & 2)
5167 params.value = "3";
5168 else if (mode & 2)
5169 params.value = "2";
5170 else if (mode & 1)
5171 params.value = "1";
5172 else
5173 params.value = "0";
5174
5175 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5176 wifi_hostapdWrite(config_file, &params, 1);
5177 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5178 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5179
5180 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005181}
5182
5183// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5184INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5185{
5186 //save to wifi config, and wait for wifi restart to apply
5187 struct params params={'\0'};
5188 char config_file[MAX_BUF_SIZE] = {0};
5189 int ret;
5190
5191 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5192 if(authMode == NULL)
5193 return RETURN_ERR;
5194
5195 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5196 params.name = "wpa_key_mgmt";
5197
5198 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5199 params.value = "WPA-PSK";
5200 else if(strcmp(authMode,"EAPAuthentication") == 0)
5201 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005202 else if (strcmp(authMode, "SAEAuthentication") == 0)
5203 params.value = "SAE";
5204 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5205 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005206 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5207 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005208 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5209 return RETURN_OK; //This is taken careof in beaconType
5210
5211 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5212 ret=wifi_hostapdWrite(config_file,&params,1);
5213 if(!ret)
5214 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5215 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5216
5217 return ret;
5218}
5219
5220// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5221INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5222{
5223 //save to wifi config, and wait for wifi restart to apply
5224 char BeaconType[50] = {0};
5225 char config_file[MAX_BUF_SIZE] = {0};
5226
5227 *authMode = 0;
5228 wifi_getApBeaconType(apIndex,BeaconType);
5229 printf("%s____%s \n",__FUNCTION__,BeaconType);
5230
5231 if(strcmp(BeaconType,"None") == 0)
5232 strcpy(authMode,"None");
5233 else
5234 {
5235 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5236 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5237 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5238 if(strcmp(authMode,"WPA-PSK") == 0)
5239 strcpy(authMode,"SharedAuthentication");
5240 else if(strcmp(authMode,"WPA-EAP") == 0)
5241 strcpy(authMode,"EAPAuthentication");
5242 }
5243
5244 return RETURN_OK;
5245}
5246
5247// Outputs the number of stations associated per AP
5248INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5249{
5250 char cmd[128]={0};
5251 char buf[128]={0};
5252 BOOL status = false;
5253
5254 if(apIndex > MAX_APS)
5255 return RETURN_ERR;
5256
5257 wifi_getApEnable(apIndex,&status);
5258 if (!status)
5259 return RETURN_OK;
5260
5261 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5262 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5263 _syscmd(cmd, buf, sizeof(buf));
5264 sscanf(buf,"%lu", output_ulong);
5265
5266 return RETURN_OK;
5267}
5268
5269// manually removes any active wi-fi association with the device specified on this ap
5270INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5271{
5272 char buf[126]={'\0'};
5273
5274 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5275 system(buf);
5276
5277 return RETURN_OK;
5278}
5279
5280// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5281INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5282{
5283 if(NULL == output_int)
5284 return RETURN_ERR;
5285 *output_int = apIndex%2;
5286 return RETURN_OK;
5287}
5288
5289// sets the radio index for the specific ap
5290INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5291{
5292 //set to config only and wait for wifi reset to apply settings
5293 return RETURN_ERR;
5294}
5295
5296// Get the ACL MAC list per AP
5297INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5298{
5299 char cmd[MAX_CMD_SIZE]={'\0'};
5300 int ret = 0;
5301
5302 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5303 ret = _syscmd(cmd,macArray,buf_size);
5304 if (ret != 0)
5305 return RETURN_ERR;
5306
5307 return RETURN_OK;
5308}
5309
developere6aafda2022-09-13 14:59:28 +08005310INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5311{
5312 char cmd[MAX_CMD_SIZE]={'\0'};
5313 int ret = 0;
5314
5315 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5316 ret = _syscmd(cmd,macArray,buf_size);
5317 if (ret != 0)
5318 return RETURN_ERR;
5319
5320 return RETURN_OK;
5321}
5322
5323
developer06a01d92022-09-07 16:32:39 +08005324// Get the list of stations associated per AP
5325INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5326{
5327 char cmd[128];
5328
5329 if(apIndex > 3) //Currently supporting apIndex upto 3
5330 return RETURN_ERR;
5331 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5332 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5333 _syscmd(cmd, macArray, buf_size);
5334
5335 return RETURN_OK;
5336}
5337
5338// adds the mac address to the filter list
5339//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5340INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5341{
5342 char cmd[MAX_CMD_SIZE]={'\0'};
5343 char buf[MAX_BUF_SIZE]={'\0'};
5344
5345#if 0
5346 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5347 if(_syscmd(cmd,buf,sizeof(buf)))
5348 return RETURN_ERR;
5349#endif
5350 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5351 if(_syscmd(cmd,buf,sizeof(buf)))
5352 return RETURN_ERR;
5353
5354 return RETURN_OK;
5355}
5356
5357// deletes the mac address from the filter list
5358//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5359INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5360{
5361 char cmd[MAX_CMD_SIZE]={'\0'};
5362 char buf[MAX_BUF_SIZE]={'\0'};
5363
5364#if 0
5365 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5366 if(_syscmd(cmd,buf,sizeof(buf)))
5367 return RETURN_ERR;
5368
5369#endif
5370 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5371 if(_syscmd(cmd,buf,sizeof(buf)))
5372 return RETURN_ERR;
5373
5374 return RETURN_OK;
5375}
5376
5377// outputs the number of devices in the filter list
5378INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5379{
developere6aafda2022-09-13 14:59:28 +08005380 char cmd[MAX_BUF_SIZE]={0};
5381 char buf[MAX_CMD_SIZE]={0};
5382
5383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5384 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005385 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005386
5387 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5388 _syscmd(cmd, buf, sizeof(buf));
5389
5390 *output_uint = atoi(buf);
5391
5392 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5393 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005394}
5395
5396INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5397{
5398 char cmd[128]={'\0'};
5399 char buf[128]={'\0'};
5400
5401 if(strcmp(action,"DENY")==0)
5402 {
5403 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5404 system(buf);
5405 return RETURN_OK;
5406 }
5407
5408 if(strcmp(action,"ALLOW")==0)
5409 {
5410 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5411 system(buf);
5412 return RETURN_OK;
5413 }
5414
5415 return RETURN_ERR;
5416
5417}
5418
5419// enable kick for devices on acl black list
5420INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5421{
5422 char aclArray[512] = {0}, *acl = NULL;
5423 char assocArray[512] = {0}, *asso = NULL;
5424
developere6aafda2022-09-13 14:59:28 +08005425 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005426 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5427
5428 // if there are no devices connected there is nothing to do
5429 if (strlen(assocArray) < 17)
5430 return RETURN_OK;
5431
5432 if (enable == TRUE)
5433 {
5434 //kick off the MAC which is in ACL array (deny list)
5435 acl = strtok(aclArray, "\r\n");
5436 while (acl != NULL) {
5437 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5438 wifi_kickApAssociatedDevice(apIndex, acl);
5439
5440 acl = strtok(NULL, "\r\n");
5441 }
developere6aafda2022-09-13 14:59:28 +08005442 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005443 }
5444 else
5445 {
developere6aafda2022-09-13 14:59:28 +08005446 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005447 }
5448
5449#if 0
5450 //TODO: need to revisit below implementation
5451 char aclArray[512]={0}, *acl=NULL;
5452 char assocArray[512]={0}, *asso=NULL;
5453 char buf[256]={'\0'};
5454 char action[10]={'\0'};
5455 FILE *fr=NULL;
5456 char interface[10]={'\0'};
5457 char config_file[MAX_BUF_SIZE] = {0};
5458
5459 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5460 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5461 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5462 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5463
5464 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5465 system(buf);
5466 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5467 system(buf);
5468 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5469 system(buf);
5470 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5471 system(buf);
5472 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5473 system(buf);
5474
5475 if ( enable == TRUE )
5476 {
5477 int device_count=0;
5478 strcpy(action,"DENY");
5479 //kick off the MAC which is in ACL array (deny list)
5480 acl = strtok (aclArray,",");
5481 while (acl != NULL) {
5482 if(strlen(acl)>=17)
5483 {
5484 apply_rules(apIndex, acl,action,interface);
5485 device_count++;
5486 //Register mac to be blocked ,in syscfg.db persistent storage
5487 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5488 system(buf);
5489 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5490 system(buf);
5491 system("syscfg commit");
5492
5493 wifi_kickApAssociatedDevice(apIndex, acl);
5494 }
5495 acl = strtok (NULL, ",");
5496 }
5497 }
5498 else
5499 {
5500 int device_count=0;
5501 char cmdmac[20]={'\0'};
5502 strcpy(action,"ALLOW");
5503 //kick off the MAC which is not in ACL array (allow list)
5504 acl = strtok (aclArray,",");
5505 while (acl != NULL) {
5506 if(strlen(acl)>=17)
5507 {
5508 apply_rules(apIndex, acl,action,interface);
5509 device_count++;
5510 //Register mac to be Allowed ,in syscfg.db persistent storage
5511 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5512 system(buf);
5513 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5514 system(buf);
5515 sprintf(cmdmac,"%s",acl);
5516 }
5517 acl = strtok (NULL, ",");
5518 }
5519 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5520 system(buf);
5521
5522 //Disconnect the mac which is not in ACL
5523 asso = strtok (assocArray,",");
5524 while (asso != NULL) {
5525 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5526 wifi_kickApAssociatedDevice(apIndex, asso);
5527 asso = strtok (NULL, ",");
5528 }
5529 }
5530#endif
5531 return RETURN_OK;
5532}
5533
5534INT wifi_setPreferPrivateConnection(BOOL enable)
5535{
5536 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5537 char buf[1024] = {0};
5538
5539 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5540 if(enable == TRUE)
5541 {
5542 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5543 sprintf(buf,"ifconfig %s down" ,interface_name);
5544 system(buf);
5545 memset(buf,0,sizeof(buf));
5546 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5547 sprintf(buf,"ifconfig %s down" ,interface_name);
5548 system(buf);
5549 }
5550 else
5551 {
5552 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5553 if(strcmp(ssid_cur_value,"1") == 0)
5554 wifi_RestartPrivateWifi_5G();
5555 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5556 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5557 if(strcmp(ssid_cur_value,"1") == 0)
5558 wifi_RestartHostapd_2G();
5559 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5560 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5561 if(strcmp(ssid_cur_value,"1") == 0)
5562 wifi_RestartHostapd_5G();
5563 }
5564 return RETURN_OK;
5565}
5566
5567// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5568INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5569{
5570 int items = 1;
5571 struct params list[2];
5572 char buf[MAX_BUF_SIZE] = {0};
5573 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005574 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005575
5576 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005577
developer10adcc12022-09-13 14:39:17 +08005578 if (filterMode == 0) {
5579 sprintf(buf, "%d", 0);
5580 list[0].value = buf;
5581
5582 char cmd[128], rtn[128];
5583 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5584 _syscmd(cmd, rtn, sizeof(rtn));
5585 memset(cmd,0,sizeof(cmd));
5586 // Delete deny_mac_file in hostapd configuration
5587 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5588 _syscmd(cmd, rtn, sizeof(rtn));
5589 }
5590 else if (filterMode == 1) {
5591 sprintf(buf, "%d", filterMode);
5592 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005593 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5594 list[1].name = "accept_mac_file";
5595 list[1].value = acl_file;
5596 items = 2;
developer10adcc12022-09-13 14:39:17 +08005597 } else if (filterMode == 2) {
5598 //TODO: deny_mac_file
5599 sprintf(buf, "%d", 0);
5600 list[0].value = buf;
5601 list[1].name = "deny_mac_file";
5602 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5603 list[1].value = deny_file;
5604 items = 2;
5605 } else {
5606 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005607 }
developer10adcc12022-09-13 14:39:17 +08005608
developer06a01d92022-09-07 16:32:39 +08005609 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5610 wifi_hostapdWrite(config_file, list, items);
5611
5612 return RETURN_OK;
5613
5614#if 0
5615 if(apIndex==0 || apIndex==1)
5616 {
5617 //set the filtermode
5618 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5619 system(buf);
5620 system("syscfg commit");
5621
5622 if(filterMode==0)
5623 {
5624 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5625 system(buf);
5626 return RETURN_OK;
5627 }
5628 }
5629 return RETURN_OK;
5630#endif
5631}
5632
5633// 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.
5634INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5635{
5636 return RETURN_ERR;
5637}
5638
5639// gets the vlan ID for this ap from an internal enviornment variable
5640INT wifi_getApVlanID(INT apIndex, INT *output_int)
5641{
5642 if(apIndex=0)
5643 {
5644 *output_int=100;
5645 return RETURN_OK;
5646 }
5647
5648 return RETURN_ERR;
5649}
5650
5651// sets the vlan ID for this ap to an internal enviornment variable
5652INT wifi_setApVlanID(INT apIndex, INT vlanId)
5653{
5654 //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)
5655 return RETURN_ERR;
5656}
5657
5658// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5659INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5660{
5661 snprintf(bridgeName, 32, "brlan0");
5662 snprintf(IP, 32, "10.0.0.1");
5663 snprintf(subnet, 32, "255.255.255.0");
5664
5665 return RETURN_OK;
5666}
5667
5668//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5669INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5670{
5671 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5672 return RETURN_ERR;
5673}
5674
5675// reset the vlan configuration for this ap
5676INT wifi_resetApVlanCfg(INT apIndex)
5677{
developerf5fef612022-09-20 19:38:26 +08005678 char original_config_file[64] = {0};
5679 char current_config_file[64] = {0};
5680 char buf[64] = {0};
5681 char cmd[64] = {0};
5682 char vlan_file[64] = {0};
5683 char vlan_tagged_interface[16] = {0};
5684 char vlan_bridge[16] = {0};
5685 char vlan_naming[16] = {0};
5686 struct params list[4] = {0};
5687 wifi_band band;
5688
5689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5690
5691 band = wifi_index_to_band(apIndex);
5692 if (band == band_2_4)
5693 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5694 else if (band = band_5)
5695 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5696 else if (band = band_6)
5697 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5698
5699 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5700
5701 if (strlen(vlan_file) == 0)
5702 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005703
developerf5fef612022-09-20 19:38:26 +08005704 // The file should exist or this vap would not work.
5705 if (access(vlan_file, F_OK) != 0) {
5706 sprintf(cmd, "touch %s", vlan_file);
5707 _syscmd(cmd, buf, sizeof(buf));
5708 }
5709 list[0].name = "vlan_file";
5710 list[0].value = vlan_file;
5711
5712 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5713 list[1].name = "vlan_tagged_interface";
5714 list[1].value = vlan_tagged_interface;
5715
5716 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5717 list[2].name = "vlan_bridge";
5718 list[2].value = vlan_bridge;
5719
5720 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5721 list[3].name = "vlan_naming";
5722 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005723
developerf5fef612022-09-20 19:38:26 +08005724 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5725 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005726 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005727 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005728
developerf5fef612022-09-20 19:38:26 +08005729 // restart this ap
5730 wifi_setApEnable(apIndex, FALSE);
5731 wifi_setApEnable(apIndex, TRUE);
5732
5733 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5734
5735 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005736}
5737
5738// 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.
5739INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5740{
5741 return RETURN_ERR;
5742}
5743
5744// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5745INT wifi_startHostApd()
5746{
5747 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5748 system("systemctl start hostapd.service");
5749 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5750 return RETURN_OK;
5751 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5752}
5753
5754// stops hostapd
5755INT wifi_stopHostApd()
5756{
5757 char cmd[128] = {0};
5758 char buf[128] = {0};
5759
5760 sprintf(cmd,"systemctl stop hostapd");
5761 _syscmd(cmd, buf, sizeof(buf));
5762
5763 return RETURN_OK;
5764}
5765
5766// restart hostapd dummy function
5767INT wifi_restartHostApd()
5768{
5769 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5770 system("systemctl restart hostapd-global");
5771 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5772
5773 return RETURN_OK;
5774}
5775
5776static int align_hostapd_config(int index)
5777{
5778 ULONG lval;
5779 wifi_getRadioChannel(index%2, &lval);
5780 wifi_setRadioChannel(index%2, lval);
5781}
5782
5783// sets the AP enable status variable for the specified ap.
5784INT wifi_setApEnable(INT apIndex, BOOL enable)
5785{
5786 char config_file[MAX_BUF_SIZE] = {0};
5787 char cmd[MAX_CMD_SIZE] = {0};
5788 char buf[MAX_BUF_SIZE] = {0};
5789 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005790 int max_radio_num = 0;
5791 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005792
5793 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005794
5795 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005796 if (enable == status)
5797 return RETURN_OK;
5798
5799 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005800 int radioIndex = apIndex % max_radio_num;
5801 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005802 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5803 //Hostapd will bring up this interface
5804 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5805 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005806 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005807 _syscmd(cmd, buf, sizeof(buf));
5808 }
5809 else {
5810 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5811 _syscmd(cmd, buf, sizeof(buf));
5812 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5813 _syscmd(cmd, buf, sizeof(buf));
5814 }
5815 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5816 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5817 _syscmd(cmd, buf, sizeof(buf));
5818 //Wait for wifi up/down to apply
5819 return RETURN_OK;
5820}
5821
5822// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5823INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5824{
5825 char cmd[MAX_CMD_SIZE] = {'\0'};
5826 char buf[MAX_BUF_SIZE] = {'\0'};
5827
5828 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5829 return RETURN_ERR;
5830
5831 *output_bool = 0;
5832
5833 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5834 {
developer70490032022-09-13 15:45:20 +08005835 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005836 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5837 }
5838
5839 return RETURN_OK;
5840}
5841
5842// Outputs the AP "Enabled" "Disabled" status from driver
5843INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5844{
5845 char cmd[128] = {0};
5846 char buf[128] = {0};
5847 BOOL output_bool;
5848
5849 if ( NULL == output_string)
5850 return RETURN_ERR;
5851 wifi_getApEnable(apIndex,&output_bool);
5852
5853 if(output_bool == 1)
5854 snprintf(output_string, 32, "Up");
5855 else
5856 snprintf(output_string, 32, "Disable");
5857
5858 return RETURN_OK;
5859}
5860
5861//Indicates whether or not beacons include the SSID name.
5862// outputs a 1 if SSID on the AP is enabled, else outputs 0
5863INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5864{
5865 //get the running status
5866 char config_file[MAX_BUF_SIZE] = {0};
5867 char buf[16] = {0};
5868
5869 if (!output)
5870 return RETURN_ERR;
5871
5872 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5873 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005874 // default is enable
5875 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5876 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005877
5878 return RETURN_OK;
5879}
5880
5881// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5882INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5883{
5884 //store the config, apply instantly
5885 char config_file[MAX_BUF_SIZE] = {0};
5886 struct params list;
5887
5888 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5889 list.name = "ignore_broadcast_ssid";
5890 list.value = enable?"0":"1";
5891
5892 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5893 wifi_hostapdWrite(config_file, &list, 1);
5894 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5895 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005896 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005897 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5898
5899 return RETURN_OK;
5900}
5901
5902//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5903INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5904{
5905 //get the running status
5906 if(!output_uint)
5907 return RETURN_ERR;
5908 *output_uint=16;
5909 return RETURN_OK;
5910}
5911
5912INT wifi_setApRetryLimit(INT apIndex, UINT number)
5913{
5914 //apply instantly
5915 return RETURN_ERR;
5916}
5917
5918//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5919INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5920{
5921 if(!output)
5922 return RETURN_ERR;
5923 *output=TRUE;
5924 return RETURN_OK;
5925}
5926
5927//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5928INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5929{
5930 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005931 char cmd[128] = {0};
5932 char buf[128] = {0};
5933 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08005934 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08005935
developer0b246d12022-09-30 15:24:20 +08005936 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005937
developer0b246d12022-09-30 15:24:20 +08005938 wifi_getMaxRadioNumber(&max_radio_num);
5939 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08005940 phyId = radio_index_to_phy(radioIndex);
5941 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08005942 _syscmd(cmd,buf, sizeof(buf));
5943
5944 if (strlen(buf) > 0)
5945 *output = true;
5946
5947 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005948
developer06a01d92022-09-07 16:32:39 +08005949 return RETURN_OK;
5950}
5951
5952//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5953INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5954{
5955 //get the running status from driver
5956 if(!output)
5957 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005958
5959 char config_file[MAX_BUF_SIZE] = {0};
5960 char buf[16] = {0};
5961
5962 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5963 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005964 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08005965 *output = TRUE;
5966 else
5967 *output = FALSE;
5968
developer06a01d92022-09-07 16:32:39 +08005969 return RETURN_OK;
5970}
5971
5972// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5973INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5974{
5975 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005976 char config_file[MAX_BUF_SIZE] = {0};
5977 struct params list;
5978
5979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5980 list.name = "wmm_enabled";
5981 list.value = enable?"1":"0";
5982
5983 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5984 wifi_hostapdWrite(config_file, &list, 1);
5985 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5986 wifi_reloadAp(apIndex);
5987 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5988
5989 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005990}
5991
5992//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.
5993INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5994{
5995 //get the running status from driver
5996 if(!output)
5997 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08005998
5999 char config_file[128] = {0};
6000 char buf[16] = {0};
6001
6002 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6003 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6004 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6005 *output = TRUE;
6006 else
6007 *output = FALSE;
6008
developer06a01d92022-09-07 16:32:39 +08006009 return RETURN_OK;
6010}
6011
6012// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6013INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6014{
6015 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006016 char config_file[MAX_BUF_SIZE] = {0};
6017 struct params list;
6018
6019 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6020 list.name = "uapsd_advertisement_enabled";
6021 list.value = enable?"1":"0";
6022
6023 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6024 wifi_hostapdWrite(config_file, &list, 1);
6025 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6026 wifi_reloadAp(apIndex);
6027 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6028
6029 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006030}
6031
developer6daeb3f2022-09-30 13:36:39 +08006032// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006033INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6034{
developer6daeb3f2022-09-30 13:36:39 +08006035 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6036 char cmd[128] = {0};
6037 char buf[128] = {0};
6038 char ack_filepath[128] = {0};
6039 uint16_t bitmap = 0;
6040 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6041 FILE *f = NULL;
6042
6043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6044
6045 // Get current setting
6046 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6047 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6048 _syscmd(cmd, buf, sizeof(buf));
6049 if (strlen(buf) > 0)
6050 bitmap = strtoul(buf, NULL, 10);
6051
6052 bitmap = strtoul(buf, NULL, 10);
6053
6054 if (ackPolicy == TRUE) { // True, unset this class
6055 bitmap &= ~class_map[class];
6056 } else { // False, set this class
6057 bitmap |= class_map[class];
6058 }
6059
6060 f = fopen(ack_filepath, "w");
6061 if (f == NULL) {
6062 fprintf(stderr, "%s: fopen failed\n", __func__);
6063 return RETURN_ERR;
6064 }
6065 fprintf(f, "%hu", bitmap);
6066 fclose(f);
6067
6068 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
6069 _syscmd(cmd, buf, sizeof(buf));
6070
6071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6072 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006073}
6074
6075//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.
6076INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6077{
6078 //get the running status from driver
6079 if(!output_uint)
6080 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006081
6082 char output[16]={'\0'};
6083 char config_file[MAX_BUF_SIZE] = {0};
6084
6085 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6086 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6087 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6088 else {
6089 int device_num = atoi(output);
6090 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6091 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6092 return RETURN_ERR;
6093 }
6094 else {
6095 *output_uint = device_num;
6096 }
6097 }
6098
developer06a01d92022-09-07 16:32:39 +08006099 return RETURN_OK;
6100}
6101
6102INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6103{
6104 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006105 char str[MAX_BUF_SIZE]={'\0'};
6106 char cmd[MAX_CMD_SIZE]={'\0'};
6107 struct params params;
6108 char config_file[MAX_BUF_SIZE] = {0};
6109
6110 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6111 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6112 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6113 return RETURN_ERR;
6114 }
6115 sprintf(str, "%d", number);
6116 params.name = "max_num_sta";
6117 params.value = str;
6118
6119 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6120 int ret = wifi_hostapdWrite(config_file, &params, 1);
6121 if (ret) {
6122 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6123 ,__func__, ret);
6124 }
6125
6126 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6127 if (ret) {
6128 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6129 ,__func__, ret);
6130 }
6131 wifi_reloadAp(apIndex);
6132 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6133
6134 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006135}
6136
6137//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.
6138INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6139{
6140 //get the current threshold
6141 if(!output_uint)
6142 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006143 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6144 if (*output_uint == 0)
6145 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006146 return RETURN_OK;
6147}
6148
6149INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6150{
6151 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006152 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6153 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006154 return RETURN_ERR;
6155}
6156
6157//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.
6158INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6159{
6160 if(!output_uint)
6161 return RETURN_ERR;
6162 *output_uint = 3;
6163 return RETURN_OK;
6164}
6165
6166//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6167INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6168{
6169 if(!output_uint)
6170 return RETURN_ERR;
6171 *output_uint = 3;
6172 return RETURN_OK;
6173}
6174
6175//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.
6176INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6177{
6178 if(!output_in_seconds)
6179 return RETURN_ERR;
6180 *output_in_seconds = 0;
6181 return RETURN_OK;
6182}
6183
6184//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
6185INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6186{
6187 if(!output || apIndex>=MAX_APS)
6188 return RETURN_ERR;
6189 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006190 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006191 return RETURN_OK;
6192}
6193
6194//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6195INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6196{
developer587c1b62022-09-27 15:58:59 +08006197 char config_file[128] = {0};
6198 char wpa[16] = {0};
6199 char key_mgmt[64] = {0};
6200 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006201 if (!output)
6202 return RETURN_ERR;
6203
6204 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006205 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006206
developer587c1b62022-09-27 15:58:59 +08006207 strcpy(output, "None");//Copying "None" to output string for default case
6208 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006209 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006210 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006211 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006212 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006213 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006214 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006215 snprintf(output, 32, "WPA-WPA2-Personal");
6216
6217 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006218 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006219 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006220 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006221 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006222 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006223 snprintf(output, 32, "WPA-WPA2-Enterprise");
6224 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006225 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006226 snprintf(output, 32, "WPA3-Personal");
6227 else
developer4a359672022-10-13 15:30:46 +08006228 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006229 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6230 snprintf(output, 32, "WPA3-Enterprise");
6231 }
developer06a01d92022-09-07 16:32:39 +08006232
6233 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6234 return RETURN_OK;
6235#if 0
6236 //TODO: need to revisit below implementation
6237 char securityType[32], authMode[32];
6238 int enterpriseMode=0;
6239
6240 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6241 if(!output)
6242 return RETURN_ERR;
6243
6244 wifi_getApBeaconType(apIndex, securityType);
6245 strcpy(output,"None");//By default, copying "None" to output string
6246 if (strncmp(securityType,"None", strlen("None")) == 0)
6247 return RETURN_OK;
6248
6249 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6250 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6251
6252 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6253 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6254 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6255 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6256 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6257 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6259
6260 return RETURN_OK;
6261#endif
6262}
6263
6264INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6265{
6266 char securityType[32];
6267 char authMode[32];
6268
6269 //store settings and wait for wifi up to apply
6270 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6271 if(!encMode)
6272 return RETURN_ERR;
6273
developer06a01d92022-09-07 16:32:39 +08006274 if (strcmp(encMode, "None")==0)
6275 {
6276 strcpy(securityType,"None");
6277 strcpy(authMode,"None");
6278 }
6279 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6280 {
6281 strcpy(securityType,"WPAand11i");
6282 strcpy(authMode,"PSKAuthentication");
6283 }
6284 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6285 {
6286 strcpy(securityType,"WPAand11i");
6287 strcpy(authMode,"EAPAuthentication");
6288 }
6289 else if (strcmp(encMode, "WPA-Personal")==0)
6290 {
6291 strcpy(securityType,"WPA");
6292 strcpy(authMode,"PSKAuthentication");
6293 }
6294 else if (strcmp(encMode, "WPA-Enterprise")==0)
6295 {
6296 strcpy(securityType,"WPA");
6297 strcpy(authMode,"EAPAuthentication");
6298 }
6299 else if (strcmp(encMode, "WPA2-Personal")==0)
6300 {
6301 strcpy(securityType,"11i");
6302 strcpy(authMode,"PSKAuthentication");
6303 }
6304 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6305 {
6306 strcpy(securityType,"11i");
6307 strcpy(authMode,"EAPAuthentication");
6308 }
developer587c1b62022-09-27 15:58:59 +08006309 else if (strcmp(encMode, "WPA3-Personal") == 0)
6310 {
6311 strcpy(securityType,"11i");
6312 strcpy(authMode,"SAEAuthentication");
6313 }
developer4a359672022-10-13 15:30:46 +08006314 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006315 {
6316 strcpy(securityType, "11i");
6317 strcpy(authMode, "PSK-SAEAuthentication");
6318 }
developer587c1b62022-09-27 15:58:59 +08006319 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6320 {
6321 strcpy(securityType,"11i");
6322 strcpy(authMode,"EAP_192-bit_Authentication");
6323 }
developer06a01d92022-09-07 16:32:39 +08006324 else
6325 {
6326 strcpy(securityType,"None");
6327 strcpy(authMode,"None");
6328 }
6329 wifi_setApBeaconType(apIndex, securityType);
6330 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6332
6333 return RETURN_OK;
6334}
6335
6336
6337//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6338// output_string must be pre-allocated as 64 character string by caller
6339// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6340INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6341{
6342 char buf[16];
6343 char config_file[MAX_BUF_SIZE] = {0};
6344
6345 if(output_string==NULL)
6346 return RETURN_ERR;
6347
6348 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6349 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6350
6351 if(strcmp(buf,"0")==0)
6352 {
6353 printf("wpa_mode is %s ......... \n",buf);
6354 return RETURN_ERR;
6355 }
6356
6357 wifi_dbg_printf("\nFunc=%s\n",__func__);
6358 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6359 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6360 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6361
6362 return RETURN_OK;
6363}
6364
6365// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6366// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6367INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6368{
6369 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6370 struct params params={'\0'};
6371 int ret;
6372 char config_file[MAX_BUF_SIZE] = {0};
6373
6374 if(NULL == preSharedKey)
6375 return RETURN_ERR;
6376
6377 params.name = "wpa_passphrase";
6378
6379 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6380 {
6381 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6382 return RETURN_ERR;
6383 }
6384 params.value = preSharedKey;
6385 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6386 ret = wifi_hostapdWrite(config_file, &params, 1);
6387 if(!ret)
6388 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6389 return ret;
6390 //TODO: call hostapd_cli for dynamic_config_control
6391}
6392
6393//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6394// outputs the passphrase, maximum 63 characters
6395INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6396{
6397 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6398
6399 wifi_dbg_printf("\nFunc=%s\n",__func__);
6400 if (NULL == output_string)
6401 return RETURN_ERR;
6402
6403 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6404 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6405 if(strcmp(buf,"0")==0)
6406 {
6407 printf("wpa_mode is %s ......... \n",buf);
6408 return RETURN_ERR;
6409 }
6410
6411 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6412 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6413
6414 return RETURN_OK;
6415}
6416
6417// sets the passphrase enviornment variable, max 63 characters
6418INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6419{
6420 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6421 struct params params={'\0'};
6422 char config_file[MAX_BUF_SIZE] = {0};
6423 int ret;
6424
6425 if(NULL == passPhrase)
6426 return RETURN_ERR;
6427
6428 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6429 {
6430 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6431 return RETURN_ERR;
6432 }
6433 params.name = "wpa_passphrase";
6434 params.value = passPhrase;
6435 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6436 ret=wifi_hostapdWrite(config_file,&params,1);
6437 if(!ret)
6438 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6439
6440 return ret;
6441}
6442
6443//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.
6444INT wifi_setApSecurityReset(INT apIndex)
6445{
developer8d583982022-09-20 11:28:22 +08006446 char original_config_file[64] = {0};
6447 char current_config_file[64] = {0};
6448 char buf[64] = {0};
6449 char cmd[64] = {0};
6450 char wpa[4] = {0};
6451 char wpa_psk[64] = {0};
6452 char wpa_passphrase[64] = {0};
6453 char wpa_psk_file[128] = {0};
6454 char wpa_key_mgmt[64] = {0};
6455 char wpa_pairwise[32] = {0};
6456 wifi_band band;
6457 struct params list[6];
6458
6459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6460
6461 band = wifi_index_to_band(apIndex);
6462 if (band == band_2_4)
6463 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6464 else if (band = band_5)
6465 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6466 else if (band = band_6)
6467 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6468 else
6469 return RETURN_ERR;
6470
6471 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6472 list[0].name = "wpa";
6473 list[0].value = wpa;
6474
6475 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6476 list[1].name = "wpa_psk";
6477 list[1].value = wpa_psk;
6478
6479 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6480 list[2].name = "wpa_passphrase";
6481 list[2].value = wpa_passphrase;
6482
6483 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6484
6485 if (strlen(wpa_psk_file) == 0)
6486 strcpy(wpa_psk_file, PSK_FILE);
6487
6488 if (access(wpa_psk_file, F_OK) != 0) {
6489 sprintf(cmd, "touch %s", wpa_psk_file);
6490 _syscmd(cmd, buf, sizeof(buf));
6491 }
6492 list[3].name = "wpa_psk_file";
6493 list[3].value = wpa_psk_file;
6494
6495 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6496 list[4].name = "wpa_key_mgmt";
6497 list[4].value = wpa_key_mgmt;
6498
6499 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6500 list[5].name = "wpa_pairwise";
6501 list[5].value = wpa_pairwise;
6502
6503 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6504 wifi_hostapdWrite(current_config_file, list, 6);
6505
6506 wifi_setApEnable(apIndex, FALSE);
6507 wifi_setApEnable(apIndex, TRUE);
6508
6509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6510 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006511}
6512
6513//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).
6514INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6515{
developer8f2ddd52022-09-13 15:39:24 +08006516 char config_file[64] = {0};
6517 char buf[64] = {0};
6518 char cmd[256] = {0};
6519
6520 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6521
developer06a01d92022-09-07 16:32:39 +08006522 if(!IP_output || !Port_output || !RadiusSecret_output)
6523 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006524
developer8f2ddd52022-09-13 15:39:24 +08006525 // Read the first matched config
6526 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6527 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6528 _syscmd(cmd, buf, sizeof(buf));
6529 strncpy(IP_output, buf, 64);
6530
6531 memset(buf, 0, sizeof(buf));
6532 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6533 _syscmd(cmd, buf, sizeof(buf));
6534 *Port_output = atoi(buf);
6535
6536 memset(buf, 0, sizeof(buf));
6537 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6538 _syscmd(cmd, buf, sizeof(buf));
6539 strncpy(RadiusSecret_output, buf, 64);
6540
6541 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006542 return RETURN_OK;
6543}
6544
6545INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6546{
developer8f2ddd52022-09-13 15:39:24 +08006547 char config_file[64] = {0};
6548 char port_str[8] = {0};
6549 char cmd[256] = {0};
6550 char buf[128] = {0};
6551
6552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6553
6554 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6555
6556 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6557 _syscmd(cmd, buf, sizeof(buf));
6558 memset(cmd, 0, sizeof(cmd));
6559
6560 snprintf(port_str, sizeof(port_str), "%d", port);
6561 if (strlen(buf) == 0)
6562 // Append
6563 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6564 "auth_server_addr=%s\\n"
6565 "auth_server_port=%s\\n"
6566 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6567 else {
6568 // Delete the three lines setting after the "# radius 1" comment
6569 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6570 _syscmd(cmd, buf, sizeof(buf));
6571 memset(cmd, 0, sizeof(cmd));
6572 // Use "# radius 1" comment to find the location to insert the radius setting
6573 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6574 "# radius 1\\n"
6575 "auth_server_addr=%s\\n"
6576 "auth_server_port=%s\\n"
6577 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6578 }
6579 if(_syscmd(cmd, buf, sizeof(buf))) {
6580 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6581 return RETURN_ERR;
6582 }
6583
6584 wifi_reloadAp(apIndex);
6585 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6586 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006587}
6588
6589INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6590{
developer8f2ddd52022-09-13 15:39:24 +08006591 char config_file[64] = {0};
6592 char buf[64] = {0};
6593 char cmd[256] = {0};
6594
6595 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6596
developer06a01d92022-09-07 16:32:39 +08006597 if(!IP_output || !Port_output || !RadiusSecret_output)
6598 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006599
6600 // Read the second matched config
6601 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6602 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6603 _syscmd(cmd, buf, sizeof(buf));
6604 strncpy(IP_output, buf, 64);
6605
6606 memset(buf, 0, sizeof(buf));
6607 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6608 _syscmd(cmd, buf, sizeof(buf));
6609 *Port_output = atoi(buf);
6610
6611 memset(buf, 0, sizeof(buf));
6612 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6613 _syscmd(cmd, buf, sizeof(buf));
6614 strncpy(RadiusSecret_output, buf, 64);
6615
6616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006617 return RETURN_OK;
6618}
6619
6620INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6621{
developer8f2ddd52022-09-13 15:39:24 +08006622 char config_file[64] = {0};
6623 char port_str[8] = {0};
6624 char cmd[256] = {0};
6625 char buf[128] = {0};
6626
6627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6628
6629 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6630
6631 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6632 _syscmd(cmd, buf, sizeof(buf));
6633 memset(cmd, 0, sizeof(cmd));
6634
6635 snprintf(port_str, sizeof(port_str), "%d", port);
6636 if (strlen(buf) == 0)
6637 // Append
6638 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6639 "auth_server_addr=%s\\n"
6640 "auth_server_port=%s\\n"
6641 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6642 else {
6643 // Delete the three lines setting after the "# radius 2" comment
6644 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6645 _syscmd(cmd, buf, sizeof(buf));
6646 memset(cmd, 0, sizeof(cmd));
6647 // Use "# radius 2" comment to find the location to insert the radius setting
6648 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6649 "# radius 2\\n"
6650 "auth_server_addr=%s\\n"
6651 "auth_server_port=%s\\n"
6652 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6653 }
6654 if(_syscmd(cmd, buf, sizeof(buf))) {
6655 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6656 return RETURN_ERR;
6657 }
6658
6659 wifi_reloadAp(apIndex);
6660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6661 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006662}
6663
6664//RadiusSettings
6665INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6666{
6667 if(!output)
6668 return RETURN_ERR;
6669
6670 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6671 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6672 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6673 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6674 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6675 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.
6676 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6677 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6678 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6679 //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.
6680
6681 return RETURN_OK;
6682}
6683
6684INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6685{
6686 //store the paramters, and apply instantly
6687 return RETURN_ERR;
6688}
6689
6690//Device.WiFi.AccessPoint.{i}.WPS.Enable
6691//Enables or disables WPS functionality for this access point.
6692// outputs the WPS enable state of this ap in output_bool
6693INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6694{
6695 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6696 if(!output_bool || !(apIndex==0 || apIndex==1))
6697 return RETURN_ERR;
6698 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6699 _syscmd(cmd, buf, sizeof(buf));
6700 if(strstr(buf, "configured"))
6701 *output_bool=TRUE;
6702 else
6703 *output_bool=FALSE;
6704
6705 return RETURN_OK;
6706}
6707
6708//Device.WiFi.AccessPoint.{i}.WPS.Enable
6709// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6710INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6711{
6712 char config_file[MAX_BUF_SIZE] = {0};
6713 struct params params;
6714
6715 if(!(apIndex==0 || apIndex==1))
6716 return RETURN_ERR;
6717 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6718 //store the paramters, and wait for wifi up to apply
6719 params.name = "wps_state";
6720 params.value = enable ? "2":"0";
6721
6722 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6723 wifi_hostapdWrite(config_file, &params, 1);
6724 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6725 wifi_reloadAp(apIndex);
6726
6727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6728 return RETURN_OK;
6729}
6730
6731//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
6732INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6733{
6734 if(!output)
6735 return RETURN_ERR;
6736 snprintf(output, 128, "PushButton,PIN");
6737 return RETURN_OK;
6738}
6739
6740//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6741//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.
6742// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6743INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6744{
6745 if(!output)
6746 return RETURN_ERR;
6747 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6748
6749 return RETURN_OK;
6750}
6751
6752//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6753// 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
6754INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6755{
6756 //apply instantly. No setting need to be stored.
6757 char methods[MAX_BUF_SIZE], *token, *next_token;
6758 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6759 struct params params;
6760
6761 if(!methodString || !(apIndex==0 || apIndex==1))
6762 return RETURN_ERR;
6763 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6764 //store the paramters, and wait for wifi up to apply
6765
6766 snprintf(methods, sizeof(methods), "%s", methodString);
6767 for(token=methods; *token; token=next_token)
6768 {
6769 strtok_r(token, ",", &next_token);
6770 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6771 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6772 else if(*token=='E')
6773 {
6774 if(!strcmp(methods, "Ethernet"))
6775 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6776 else if(!strcmp(methods, "ExternalNFCToken"))
6777 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6778 else
6779 printf("%s: Unknown WpsConfigMethod\n", __func__);
6780 }
6781 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6782 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6783 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6784 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6785 else if(*token=='P' )
6786 {
6787 if(!strcmp(token, "PushButton"))
6788 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6789 else if(!strcmp(token, "PIN"))
6790 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6791 else
6792 printf("%s: Unknown WpsConfigMethod\n", __func__);
6793 }
6794 else
6795 printf("%s: Unknown WpsConfigMethod\n", __func__);
6796 }
6797 params.name = "config_methods";
6798 params.value = config_methods;
6799 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6800 wifi_hostapdWrite(config_file, &params, 1);
6801 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6802 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6803
6804 return RETURN_OK;
6805}
6806
6807// outputs the pin value, ulong_pin must be allocated by the caller
6808INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6809{
6810 char buf[MAX_BUF_SIZE] = {0};
6811 char cmd[MAX_CMD_SIZE] = {0};
6812
6813 if(!output_ulong || !(apIndex==0 || apIndex==1))
6814 return RETURN_ERR;
6815 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6816 _syscmd(cmd, buf, sizeof(buf));
6817 if(strlen(buf) > 0)
6818 *output_ulong=strtoul(buf, NULL, 10);
6819
6820 return RETURN_OK;
6821}
6822
6823// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6824INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6825{
6826 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6827 char ap_pin[16] = {0};
6828 char buf[MAX_BUF_SIZE] = {0};
6829 char config_file[MAX_BUF_SIZE] = {0};
6830 ULONG prev_pin = 0;
6831 struct params params;
6832
6833 if(!(apIndex==0 || apIndex==1))
6834 return RETURN_ERR;
6835 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6836 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6837 params.name = "ap_pin";
6838 params.value = ap_pin;
6839 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6840 wifi_hostapdWrite(config_file, &params, 1);
6841 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6842 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6843
6844 return RETURN_OK;
6845}
6846
6847// Output string is either Not configured or Configured, max 32 characters
6848INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6849{
6850 char cmd[MAX_CMD_SIZE];
6851 char buf[MAX_BUF_SIZE]={0};
6852
6853 if(!output_string || !(apIndex==0 || apIndex==1))
6854 return RETURN_ERR;
6855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6856 snprintf(output_string, 32, "Not configured");
6857 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6858 _syscmd(cmd, buf, sizeof(buf));
6859
developer348e3d92022-09-13 14:48:41 +08006860 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006861 snprintf(output_string, 32, "Configured");
6862 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6863
6864 return RETURN_OK;
6865}
6866
6867// sets the WPS pin for this AP
6868INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6869{
6870 char cmd[MAX_CMD_SIZE];
6871 char buf[MAX_BUF_SIZE]={0};
6872 BOOL enable;
6873
6874 if(!(apIndex==0 || apIndex==1))
6875 return RETURN_ERR;
6876 wifi_getApEnable(apIndex, &enable);
6877 if (!enable)
6878 return RETURN_ERR;
6879 wifi_getApWpsEnable(apIndex, &enable);
6880 if (!enable)
6881 return RETURN_ERR;
6882
6883 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6884 _syscmd(cmd, buf, sizeof(buf));
6885 if((strstr(buf, "OK"))!=NULL)
6886 return RETURN_OK;
6887
6888 return RETURN_ERR;
6889}
6890
6891// This function is called when the WPS push button has been pressed for this AP
6892INT wifi_setApWpsButtonPush(INT apIndex)
6893{
6894 char cmd[MAX_CMD_SIZE];
6895 char buf[MAX_BUF_SIZE]={0};
6896 BOOL enable=FALSE;
6897
6898 if(!(apIndex==0 || apIndex==1))
6899 return RETURN_ERR;
6900 wifi_getApEnable(apIndex, &enable);
6901 if (!enable)
6902 return RETURN_ERR;
6903
6904 wifi_getApWpsEnable(apIndex, &enable);
6905 if (!enable)
6906 return RETURN_ERR;
6907
6908 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6909 _syscmd(cmd, buf, sizeof(buf));
6910
6911 if((strstr(buf, "OK"))!=NULL)
6912 return RETURN_OK;
6913 return RETURN_ERR;
6914}
6915
6916// cancels WPS mode for this AP
6917INT wifi_cancelApWPS(INT apIndex)
6918{
6919 char cmd[MAX_CMD_SIZE];
6920 char buf[MAX_BUF_SIZE]={0};
6921
6922 if(!(apIndex==0 || apIndex==1))
6923 return RETURN_ERR;
6924 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6925 _syscmd(cmd,buf, sizeof(buf));
6926
6927 if((strstr(buf, "OK"))!=NULL)
6928 return RETURN_OK;
6929 return RETURN_ERR;
6930}
6931
6932//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6933//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6934INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6935{
6936 FILE *f;
6937 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6938 char cmd[256], buf[2048];
6939 char *param , *value, *line=NULL;
6940 size_t len = 0;
6941 ssize_t nread;
6942 wifi_associated_dev_t *dev=NULL;
6943
6944 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6945 *associated_dev_array = NULL;
6946 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6947 _syscmd(cmd,buf,sizeof(buf));
6948 *output_array_size = atoi(buf);
6949
6950 if (*output_array_size <= 0)
6951 return RETURN_OK;
6952
6953 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6954 *associated_dev_array = dev;
6955 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6956 _syscmd(cmd,buf,sizeof(buf));
6957 f = fopen("/tmp/connected_devices.txt", "r");
6958 if (f==NULL)
6959 {
6960 *output_array_size=0;
6961 return RETURN_ERR;
6962 }
6963 while ((nread = getline(&line, &len, f)) != -1)
6964 {
6965 param = strtok(line,"=");
6966 value = strtok(NULL,"=");
6967
6968 if( strcmp("flags",param) == 0 )
6969 {
6970 value[strlen(value)-1]='\0';
6971 if(strstr (value,"AUTHORIZED") != NULL )
6972 {
6973 dev[auth_temp].cli_AuthenticationState = 1;
6974 dev[auth_temp].cli_Active = 1;
6975 auth_temp++;
6976 read_flag=1;
6977 }
6978 }
6979 if(read_flag==1)
6980 {
6981 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6982 {
6983 value[strlen(value)-1]='\0';
6984 sscanf(value, "%x:%x:%x:%x:%x:%x",
6985 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6986 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6987 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6988 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6989 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6990 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6991 mac_temp++;
6992 read_flag=0;
6993 }
6994 }
6995 }
6996 *output_array_size = auth_temp;
6997 auth_temp=0;
6998 mac_temp=0;
6999 free(line);
7000 fclose(f);
7001 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7002 return RETURN_OK;
7003}
7004
7005#define MACADDRESS_SIZE 6
7006
7007INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7008{
7009 FILE *fp = NULL;
7010 char str[MAX_BUF_SIZE] = {0};
7011 int wificlientindex = 0 ;
7012 int count = 0;
7013 int signalstrength = 0;
7014 int arr[MACADDRESS_SIZE] = {0};
7015 unsigned char mac[MACADDRESS_SIZE] = {0};
7016 UINT wifi_count = 0;
7017 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7018 char pipeCmd[MAX_CMD_SIZE] = {0};
7019
7020 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7021 *output_array_size = 0;
7022 *associated_dev_array = NULL;
7023
7024 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7025 fp = popen(pipeCmd, "r");
7026 if (fp == NULL)
7027 {
7028 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7029 return RETURN_ERR;
7030 }
7031
7032 /* Read the output a line at a time - output it. */
7033 fgets(str, sizeof(str)-1, fp);
7034 wifi_count = (unsigned int) atoi ( str );
7035 *output_array_size = wifi_count;
7036 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7037 pclose(fp);
7038
7039 if(wifi_count == 0)
7040 {
7041 return RETURN_OK;
7042 }
7043 else
7044 {
7045 wifi_associated_dev3_t* temp = NULL;
7046 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7047 if(temp == NULL)
7048 {
7049 printf("Error Statement. Insufficient memory \n");
7050 return RETURN_ERR;
7051 }
7052
7053 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7054 system(pipeCmd);
7055 memset(pipeCmd,0,sizeof(pipeCmd));
7056 if(apIndex == 0)
7057 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7058 else if(apIndex == 1)
7059 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7060 system(pipeCmd);
7061
7062 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7063 if(fp == NULL)
7064 {
7065 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7066 return RETURN_ERR;
7067 }
7068 fclose(fp);
7069
7070 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7071 fp = popen(pipeCmd, "r");
7072 if(fp)
7073 {
7074 for(count =0 ; count < wifi_count; count++)
7075 {
7076 fgets(str, MAX_BUF_SIZE, fp);
7077 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7078 {
7079 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7080 {
7081 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7082
7083 }
7084 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7085 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]);
7086 }
7087 temp[count].cli_AuthenticationState = 1; //TODO
7088 temp[count].cli_Active = 1; //TODO
7089 }
7090 pclose(fp);
7091 }
7092
7093 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7094 fp = popen(pipeCmd, "r");
7095 if(fp)
7096 {
7097 pclose(fp);
7098 }
7099 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7100 if(fp)
7101 {
7102 for(count =0 ; count < wifi_count ;count++)
7103 {
7104 fgets(str, MAX_BUF_SIZE, fp);
7105 signalstrength = atoi(str);
7106 temp[count].cli_SignalStrength = signalstrength;
7107 temp[count].cli_RSSI = signalstrength;
7108 temp[count].cli_SNR = signalstrength + 95;
7109 }
7110 pclose(fp);
7111 }
7112
7113
7114 if((apIndex == 0) || (apIndex == 4))
7115 {
7116 for(count =0 ; count < wifi_count ;count++)
7117 {
7118 strcpy(temp[count].cli_OperatingStandard,"g");
7119 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7120 }
7121
7122 //BytesSent
7123 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7124 fp = popen(pipeCmd, "r");
7125 if(fp)
7126 {
7127 pclose(fp);
7128 }
7129 fp = popen("cat /tmp/Ass_Bytes_Send.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_BytesSent = strtoul(str, NULL, 10);
7136 }
7137 pclose(fp);
7138 }
7139
7140 //BytesReceived
7141 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7142 fp = popen(pipeCmd, "r");
7143 if (fp)
7144 {
7145 pclose(fp);
7146 }
7147 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7148 if (fp)
7149 {
7150 for (count = 0; count < wifi_count; count++)
7151 {
7152 fgets(str, MAX_BUF_SIZE, fp);
7153 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7154 }
7155 pclose(fp);
7156 }
7157
7158 //PacketsSent
7159 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7160 fp = popen(pipeCmd, "r");
7161 if (fp)
7162 {
7163 pclose(fp);
7164 }
7165
7166 fp = popen("cat /tmp/Ass_Packets_Send.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_PacketsSent = strtoul(str, NULL, 10);
7173 }
7174 pclose(fp);
7175 }
7176
7177 //PacketsReceived
7178 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7179 fp = popen(pipeCmd, "r");
7180 if (fp)
7181 {
7182 pclose(fp);
7183 }
7184 fp = popen("cat /tmp/Ass_Packets_Received.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_PacketsReceived = 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 //ErrorsSent
7214 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7215 fp = popen(pipeCmd, "r");
7216 if (fp)
7217 {
7218 pclose(fp);
7219 }
7220 fp = popen("cat /tmp/Ass_Tx_Failed.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_ErrorsSent = strtoul(str, NULL, 10);
7227 }
7228 pclose(fp);
7229 }
7230
7231 //LastDataDownlinkRate
7232 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7233 fp = popen(pipeCmd, "r");
7234 if (fp)
7235 {
7236 pclose(fp);
7237 }
7238 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7239 if (fp)
7240 {
7241 for (count = 0; count < wifi_count; count++)
7242 {
7243 fgets(str, MAX_BUF_SIZE, fp);
7244 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7245 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7246 }
7247 pclose(fp);
7248 }
7249
7250 //LastDataUplinkRate
7251 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7252 fp = popen(pipeCmd, "r");
7253 if (fp)
7254 {
7255 pclose(fp);
7256 }
7257 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7258 if (fp)
7259 {
7260 for (count = 0; count < wifi_count; count++)
7261 {
7262 fgets(str, MAX_BUF_SIZE, fp);
7263 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7264 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7265 }
7266 pclose(fp);
7267 }
7268
7269 }
7270 else if ((apIndex == 1) || (apIndex == 5))
7271 {
7272 for (count = 0; count < wifi_count; count++)
7273 {
7274 strcpy(temp[count].cli_OperatingStandard, "a");
7275 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7276 temp[count].cli_BytesSent = 0;
7277 temp[count].cli_BytesReceived = 0;
7278 temp[count].cli_LastDataUplinkRate = 0;
7279 temp[count].cli_LastDataDownlinkRate = 0;
7280 temp[count].cli_PacketsSent = 0;
7281 temp[count].cli_PacketsReceived = 0;
7282 temp[count].cli_ErrorsSent = 0;
7283 }
7284 }
7285
7286 for (count = 0; count < wifi_count; count++)
7287 {
7288 temp[count].cli_Retransmissions = 0;
7289 temp[count].cli_DataFramesSentAck = 0;
7290 temp[count].cli_DataFramesSentNoAck = 0;
7291 temp[count].cli_MinRSSI = 0;
7292 temp[count].cli_MaxRSSI = 0;
7293 strncpy(temp[count].cli_InterferenceSources, "", 64);
7294 memset(temp[count].cli_IPAddress, 0, 64);
7295 temp[count].cli_RetransCount = 0;
7296 temp[count].cli_FailedRetransCount = 0;
7297 temp[count].cli_RetryCount = 0;
7298 temp[count].cli_MultipleRetryCount = 0;
7299 }
7300 *associated_dev_array = temp;
7301 }
7302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7303 return RETURN_OK;
7304}
7305
7306int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7307{
7308 FILE *fp = NULL;
7309 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7310 char cmd[MAX_CMD_SIZE];
7311 int count = 0;
7312
7313 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7314 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7315 fp = popen(cmd,"r");
7316 if(fp == NULL)
7317 {
7318 printf("Failed to run command in Function %s\n",__FUNCTION__);
7319 return 0;
7320 }
7321 if(fgets(path, sizeof(path)-1, fp) != NULL)
7322 {
7323 for(count=0;path[count]!='\n';count++)
7324 status[count]=path[count];
7325 status[count]='\0';
7326 }
7327 strcpy(wifi_status,status);
7328 pclose(fp);
7329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7330 return RETURN_OK;
7331}
7332
7333/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7334struct hostapd_sta_param {
7335 char key[50];
7336 char value[100];
7337}
7338
7339static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7340 int i = 0;
7341
7342 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7343 if (strncmp(params[i].key,key,50) == 0){
7344 return &params[i].value;
7345 }
7346 i++;
7347 }
7348 return NULL;
7349
7350} */
7351
7352static unsigned int count_occurences(const char *buf, const char *word)
7353{
7354 unsigned int n = 0;
7355 char *ptr = strstr(buf, word);
7356
7357 while (ptr++) {
7358 n++;
7359 ptr = strstr(ptr, word);
7360 }
7361
7362 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7363 return n;
7364}
7365
7366static const char *get_line_from_str_buf(const char *buf, char *line)
7367{
7368 int i;
7369 int n = strlen(buf);
7370
7371 for (i = 0; i < n; i++) {
7372 line[i] = buf[i];
7373 if (buf[i] == '\n') {
7374 line[i] = '\0';
7375 return &buf[i + 1];
7376 }
7377 }
7378
7379 return NULL;
7380}
7381
7382INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7383{
7384 unsigned int assoc_cnt = 0;
7385 char interface_name[50] = {0};
7386 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7387 char cmd[MAX_CMD_SIZE] = {'\0'};
7388 char line[256] = {'\0'};
7389 int i = 0;
7390 int ret = 0;
7391 const char *ptr = NULL;
7392 char *key = NULL;
7393 char *val = NULL;
7394 wifi_associated_dev3_t *temp = NULL;
7395 int rssi;
7396
7397 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7398
7399 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7400 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7401 return RETURN_ERR;
7402 }
7403
7404 // Example filtered output of 'iw dev' command:
7405 // Station 0a:69:72:10:d2:fa (on wifi0)
7406 // signal avg:-67 [-71, -71] dBm
7407 // Station 28:c2:1f:25:5f:99 (on wifi0)
7408 // signal avg:-67 [-71, -70] dBm
7409 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7410 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7411 return RETURN_ERR;
7412 }
7413
7414 ret = _syscmd(cmd, buf, sizeof(buf));
7415 if (ret == RETURN_ERR) {
7416 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7417 return RETURN_ERR;
7418 }
7419
7420 *output_array_size = count_occurences(buf, "Station");
7421 if (*output_array_size == 0) return RETURN_OK;
7422
7423 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7424 if (temp == NULL) {
7425 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7426 return RETURN_ERR;
7427 }
7428 *associated_dev_array = temp;
7429
7430 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7431 ptr = get_line_from_str_buf(buf, line);
7432 i = -1;
7433 while (ptr) {
7434 if (strstr(line, "Station")) {
7435 i++;
7436 key = strtok(line, " ");
7437 val = strtok(NULL, " ");
7438 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7439 &temp[i].cli_MACAddress[0],
7440 &temp[i].cli_MACAddress[1],
7441 &temp[i].cli_MACAddress[2],
7442 &temp[i].cli_MACAddress[3],
7443 &temp[i].cli_MACAddress[4],
7444 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7445 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7446 free(*associated_dev_array);
7447 return RETURN_ERR;
7448 }
7449 }
7450 else if (i < 0) {
7451 ptr = get_line_from_str_buf(ptr, line);
7452 continue; // We didn't detect 'station' entry yet
7453 }
7454 else if (strstr(line, "signal avg")) {
7455 key = strtok(line, ":");
7456 val = strtok(NULL, " ");
7457 if (sscanf(val, "%d", &rssi) <= 0 ) {
7458 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7459 free(*associated_dev_array);
7460 return RETURN_ERR;
7461 }
7462 temp[i].cli_RSSI = rssi;
7463 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7464 }
7465 // Here other fields can be parsed if added to filter of 'iw dev' command
7466
7467 ptr = get_line_from_str_buf(ptr, line);
7468 };
7469
7470 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7471
7472 return RETURN_OK;
7473}
7474
7475#if 0
7476//To-do
7477INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7478{
7479 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7480
7481 //Using different approach to get required WiFi Parameters from system available commands
7482#if 0
7483 FILE *f;
7484 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7485 char cmd[256], buf[2048];
7486 char *param , *value, *line=NULL;
7487 size_t len = 0;
7488 ssize_t nread;
7489 wifi_associated_dev3_t *dev=NULL;
7490 *associated_dev_array = NULL;
7491 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7492 _syscmd(cmd,buf,sizeof(buf));
7493 *output_array_size = atoi(buf);
7494
7495 if (*output_array_size <= 0)
7496 return RETURN_OK;
7497
7498 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7499 *associated_dev_array = dev;
7500 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7501 _syscmd(cmd,buf,sizeof(buf));
7502 f = fopen("/tmp/connected_devices.txt", "r");
7503 if (f==NULL)
7504 {
7505 *output_array_size=0;
7506 return RETURN_ERR;
7507 }
7508 while ((nread = getline(&line, &len, f)) != -1)
7509 {
7510 param = strtok(line,"=");
7511 value = strtok(NULL,"=");
7512
7513 if( strcmp("flags",param) == 0 )
7514 {
7515 value[strlen(value)-1]='\0';
7516 if(strstr (value,"AUTHORIZED") != NULL )
7517 {
7518 dev[auth_temp].cli_AuthenticationState = 1;
7519 dev[auth_temp].cli_Active = 1;
7520 auth_temp++;
7521 read_flag=1;
7522 }
7523 }
7524 if(read_flag==1)
7525 {
7526 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7527 {
7528 value[strlen(value)-1]='\0';
7529 sscanf(value, "%x:%x:%x:%x:%x:%x",
7530 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7531 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7532 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7533 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7534 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7535 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7536
7537 }
7538 else if( strcmp("rx_packets",param) == 0 )
7539 {
7540 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7541 }
7542
7543 else if( strcmp("tx_packets",param) == 0 )
7544 {
7545 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7546 }
7547
7548 else if( strcmp("rx_bytes",param) == 0 )
7549 {
7550 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7551 }
7552
7553 else if( strcmp("tx_bytes",param) == 0 )
7554 {
7555 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7556 mac_temp++;
7557 read_flag=0;
7558 }
7559 }
7560 }
7561
7562 *output_array_size = auth_temp;
7563 auth_temp=0;
7564 mac_temp=0;
7565 free(line);
7566 fclose(f);
7567#endif
7568 char interface_name[MAX_BUF_SIZE] = {0};
7569 char wifi_status[MAX_BUF_SIZE] = {0};
7570 char hostapdconf[MAX_BUF_SIZE] = {0};
7571
7572 wifi_associated_dev3_t *dev_array = NULL;
7573 ULONG wifi_count = 0;
7574
7575 *associated_dev_array = NULL;
7576 *output_array_size = 0;
7577
7578 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7579 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7580 {
7581 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7582
7583 GetInterfaceName(interface_name, hostapdconf);
7584
7585 if(strlen(interface_name) > 1)
7586 {
7587 wifihal_interfacestatus(wifi_status,interface_name);
7588 if(strcmp(wifi_status,"RUNNING") == 0)
7589 {
7590 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7591
7592 *associated_dev_array = dev_array;
7593 *output_array_size = wifi_count;
7594 }
7595 else
7596 {
7597 *associated_dev_array = NULL;
7598 }
7599 }
7600 }
7601
7602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7603 return RETURN_OK;
7604}
7605#endif
7606
7607/* getIPAddress function */
7608/**
7609* @description Returning IpAddress of the Matched String
7610*
7611* @param
7612* @str Having MacAddress
7613* @ipaddr Having ipaddr
7614* @return The status of the operation
7615* @retval RETURN_OK if successful
7616* @retval RETURN_ERR if any error is detected
7617*
7618*/
7619
7620INT getIPAddress(char *str,char *ipaddr)
7621{
7622 FILE *fp = NULL;
7623 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7624 int LeaseTime = 0,ret = 0;
7625 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7626 {
7627 return RETURN_ERR;
7628 }
7629
7630 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7631 {
7632 /*
7633 Sample:sss
7634 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7635 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7636 */
7637 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7638 &(LeaseTime),
7639 phyAddr,
7640 ipAddr,
7641 hostName
7642 );
7643 if(ret != 4)
7644 continue;
7645 if(strcmp(str,phyAddr) == 0)
7646 strcpy(ipaddr,ipAddr);
7647 }
7648 return RETURN_OK;
7649}
7650
7651/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7652/**
7653* @description Returning Inactive wireless connected clients informations
7654*
7655* @param
7656* @filename Holding private_wifi 2g/5g content files
7657* @associated_dev_array Having inactiv wireless clients informations
7658* @output_array_size Returning Inactive wireless counts
7659* @return The status of the operation
7660* @retval RETURN_OK if successful
7661* @retval RETURN_ERR if any error is detected
7662*
7663*/
7664
7665INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7666{
7667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7668 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7669 FILE *fp = NULL;
7670 int arr[MACADDRESS_SIZE] = {0};
7671 unsigned char mac[MACADDRESS_SIZE] = {0};
7672 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7673 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7674 fp = popen(buf,"r");
7675 if(fp == NULL)
7676 return RETURN_ERR;
7677 else
7678 {
7679 fgets(path,sizeof(path),fp);
7680 maccount = atoi(path);
7681 }
7682 pclose(fp);
7683 *output_array_size = maccount;
7684 wifi_associated_dev3_t* temp = NULL;
7685 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7686 *associated_dev_array = temp;
7687 if(temp == NULL)
7688 {
7689 printf("Error Statement. Insufficient memory \n");
7690 return RETURN_ERR;
7691 }
7692 memset(buf,0,sizeof(buf));
7693 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7694 fp = popen(buf,"r");
7695 for(count = 0; count < maccount ; count++)
7696 {
7697 fgets(path,sizeof(path),fp);
7698 for(i = 0; path[i]!='\n';i++)
7699 str[i]=path[i];
7700 str[i]='\0';
7701 getIPAddress(str,ipaddr);
7702 memset(buf,0,sizeof(buf));
7703 if(strlen(ipaddr) > 0)
7704 {
7705 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7706 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7707 {
7708 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7709 {
7710 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7711 {
7712 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7713
7714 }
7715 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7716 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]);
7717 }
7718 temp[count].cli_AuthenticationState = 0; //TODO
7719 temp[count].cli_Active = 0; //TODO
7720 temp[count].cli_SignalStrength = 0;
7721 }
7722 else //Active wireless clients info
7723 {
7724 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7725 {
7726 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7727 {
7728 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7729
7730 }
7731 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7732 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]);
7733 }
7734 temp[count].cli_Active = 1;
7735 }
7736 }
7737 memset(ipaddr,0,sizeof(ipaddr));
7738 }
7739 pclose(fp);
7740 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7741 return RETURN_OK;
7742}
7743//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7744//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7745//To get Band Steering Capability
7746INT wifi_getBandSteeringCapability(BOOL *support)
7747{
7748 *support = FALSE;
7749 return RETURN_OK;
7750}
7751
7752
7753//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7754//To get Band Steering enable status
7755INT wifi_getBandSteeringEnable(BOOL *enable)
7756{
7757 *enable = FALSE;
7758 return RETURN_OK;
7759}
7760
7761//To turn on/off Band steering
7762INT wifi_setBandSteeringEnable(BOOL enable)
7763{
7764 return RETURN_OK;
7765}
7766
7767//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7768//To get Band Steering AP group
7769INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7770{
7771 if (NULL == output_ApGroup)
7772 return RETURN_ERR;
7773
7774 strcpy(output_ApGroup, "1,2");
7775 return RETURN_OK;
7776}
7777
7778//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7779//to set and read the band steering BandUtilizationThreshold parameters
7780INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7781{
7782 return RETURN_ERR;
7783}
7784
7785INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7786{
7787 return RETURN_ERR;
7788}
7789
7790//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7791//to set and read the band steering RSSIThreshold parameters
7792INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7793{
7794 return RETURN_ERR;
7795}
7796
7797INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7798{
7799 return RETURN_ERR;
7800}
7801
7802
7803//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7804//to set and read the band steering physical modulation rate threshold parameters
7805INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7806{
7807 //If chip is not support, return -1
7808 return RETURN_ERR;
7809}
7810
7811INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7812{
7813 //If chip is not support, return -1
7814 return RETURN_ERR;
7815}
7816
7817//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7818//to set and read the inactivity time (in seconds) for steering under overload condition
7819INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7820{
7821 return RETURN_ERR;
7822}
7823
7824INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7825{
7826 return RETURN_ERR;
7827}
7828
7829//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7830//to set and read the inactivity time (in seconds) for steering under Idle condition
7831INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7832{
7833 return RETURN_ERR;
7834}
7835
7836INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7837{
7838 return RETURN_ERR;
7839}
7840
7841//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7842//pClientMAC[64]
7843//pSourceSSIDIndex[64]
7844//pDestSSIDIndex[64]
7845//pSteeringReason[256]
7846INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7847{
7848 //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
7849 *pSteeringTime=time(NULL);
7850 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7851 return RETURN_OK;
7852}
7853
7854INT wifi_ifConfigDown(INT apIndex)
7855{
7856 INT status = RETURN_OK;
7857 char cmd[64];
7858
7859 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7860 printf("%s: %s\n", __func__, cmd);
7861 system(cmd);
7862
7863 return status;
7864}
7865
7866INT wifi_ifConfigUp(INT apIndex)
7867{
7868 char cmd[128];
7869 char buf[1024];
7870
7871 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7872 _syscmd(cmd, buf, sizeof(buf));
7873 return 0;
7874}
7875
7876//>> Deprecated. Replace with wifi_applyRadioSettings
7877INT wifi_pushBridgeInfo(INT apIndex)
7878{
7879 char ip[32];
7880 char subnet[32];
7881 char bridge[32];
7882 int vlanId;
7883 char cmd[128];
7884 char buf[1024];
7885
7886 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7887 wifi_getApVlanID(apIndex,&vlanId);
7888
7889 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7890 _syscmd(cmd,buf, sizeof(buf));
7891
7892 return 0;
7893}
7894
7895INT wifi_pushChannel(INT radioIndex, UINT channel)
7896{
7897 char cmd[128];
7898 char buf[1024];
7899 int apIndex;
7900
7901 apIndex=(radioIndex==0)?0:1;
7902 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7903 _syscmd(cmd,buf, sizeof(buf));
7904
7905 return 0;
7906}
7907
7908INT wifi_pushChannelMode(INT radioIndex)
7909{
7910 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7911 return RETURN_ERR;
7912}
7913
7914INT wifi_pushDefaultValues(INT radioIndex)
7915{
7916 //Apply Comcast specified default radio settings instantly
7917 //AMPDU=1
7918 //AMPDUFrames=32
7919 //AMPDULim=50000
7920 //txqueuelen=1000
7921
7922 return RETURN_ERR;
7923}
7924
7925INT wifi_pushTxChainMask(INT radioIndex)
7926{
7927 //Apply default TxChainMask instantly
7928 return RETURN_ERR;
7929}
7930
7931INT wifi_pushRxChainMask(INT radioIndex)
7932{
7933 //Apply default RxChainMask instantly
7934 return RETURN_ERR;
7935}
7936
7937INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7938{
7939 INT status;
7940
7941 status = wifi_setSSIDName(apIndex,ssid);
7942 wifi_setApEnable(apIndex,FALSE);
7943 wifi_setApEnable(apIndex,TRUE);
7944
7945 return status;
7946}
7947
7948INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7949{
7950 //Apply default Ssid Advertisement instantly
7951 return RETURN_ERR;
7952}
7953
7954INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7955{
7956 INT status = RETURN_ERR;
7957 *output = 0;
7958 return RETURN_ERR;
7959}
7960
7961INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7962{
7963 return RETURN_OK;
7964}
7965
7966INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7967{
7968 return RETURN_OK;
7969}
7970
7971//To-do
7972INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7973{
developereb199ae2022-09-13 14:04:27 +08007974 char output[16]={'\0'};
7975 char config_file[MAX_BUF_SIZE] = {0};
7976
7977 if (!output_string)
7978 return RETURN_ERR;
7979
7980 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7981 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7982
7983 if (strlen(output) == 0)
7984 snprintf(output_string, 64, "Disabled");
7985 else if (strncmp(output, "0", 1) == 0)
7986 snprintf(output_string, 64, "Disabled");
7987 else if (strncmp(output, "1", 1) == 0)
7988 snprintf(output_string, 64, "Optional");
7989 else if (strncmp(output, "2", 1) == 0)
7990 snprintf(output_string, 64, "Required");
7991 else {
7992 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7993 return RETURN_ERR;
7994 }
7995
7996 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007997 return RETURN_OK;
7998}
7999INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8000{
developereb199ae2022-09-13 14:04:27 +08008001 char str[MAX_BUF_SIZE]={'\0'};
8002 char cmd[MAX_CMD_SIZE]={'\0'};
8003 struct params params;
8004 char config_file[MAX_BUF_SIZE] = {0};
8005
8006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8007 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8008 return RETURN_ERR;
8009
8010 params.name = "ieee80211w";
8011 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8012 params.value = "0";
8013 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8014 params.value = "1";
8015 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8016 params.value = "2";
8017 else{
8018 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8019 return RETURN_ERR;
8020 }
8021 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8022 wifi_hostapdWrite(config_file, &params, 1);
8023 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008024 return RETURN_OK;
8025}
8026INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8027{
8028 char output[16]={'\0'};
8029 char config_file[MAX_BUF_SIZE] = {0};
8030
8031 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8032 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8033 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8034
8035 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8036 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8037
8038 return RETURN_OK;
8039}
8040
8041INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8042{
8043 return RETURN_OK;
8044}
8045
8046INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8047{
8048 return RETURN_OK;
8049}
8050
8051INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8052{
8053 return RETURN_OK;
8054}
8055
8056INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8057{
8058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8059 char config_file[MAX_BUF_SIZE] = {0};
8060
8061 if (NULL == output)
8062 return RETURN_ERR;
8063 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8064 wifi_hostapdRead(config_file,"hw_mode",output,64);
8065
8066 if(strcmp(output,"b")==0)
8067 sprintf(output, "%s", "1,2,5.5,11");
8068 else if (strcmp(output,"a")==0)
8069 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8070 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8071 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8072
8073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8074 return RETURN_OK;
8075}
8076
8077INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8078{
8079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8080 char *temp;
8081 char temp_output[128];
8082 char temp_TransmitRates[128];
8083 char config_file[MAX_BUF_SIZE] = {0};
8084
8085 if (NULL == output)
8086 return RETURN_ERR;
8087
8088 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8089 wifi_hostapdRead(config_file,"supported_rates",output,64);
8090
8091 strcpy(temp_TransmitRates,output);
8092 strcpy(temp_output,"");
8093 temp = strtok(temp_TransmitRates," ");
8094 while(temp!=NULL)
8095 {
8096 temp[strlen(temp)-1]=0;
8097 if((temp[0]=='5') && (temp[1]=='\0'))
8098 {
8099 temp="5.5";
8100 }
8101 strcat(temp_output,temp);
8102 temp = strtok(NULL," ");
8103 if(temp!=NULL)
8104 {
8105 strcat(temp_output,",");
8106 }
8107 }
8108 strcpy(output,temp_output);
8109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8110
8111 return RETURN_OK;
8112}
8113
8114INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8115{
8116 return RETURN_OK;
8117}
8118
8119
8120INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8121{
8122 int i=0;
8123 char *temp;
developeref938762022-10-19 17:21:01 +08008124 char temp1[128] = {0};
8125 char temp_output[128] = {0};
8126 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008127 struct params params={'\0'};
8128 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008129 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008130
8131 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8132 if(NULL == output)
8133 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008134 strcpy(temp_TransmitRates,output);
8135
8136 for(i=0;i<strlen(temp_TransmitRates);i++)
8137 {
developeref938762022-10-19 17:21:01 +08008138 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008139 {
8140 continue;
8141 }
8142 else
8143 {
8144 return RETURN_ERR;
8145 }
8146 }
8147 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008148 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008149 while(temp!=NULL)
8150 {
8151 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008152 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008153 {
developeref938762022-10-19 17:21:01 +08008154 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008155 {
8156 return RETURN_ERR;
8157 }
8158 }
8159
8160 if(strcmp(temp,"5.5")==0)
8161 {
8162 strcpy(temp1,"55");
8163 }
8164 else
8165 {
8166 strcat(temp1,"0");
8167 }
8168 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008169 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008170 if(temp!=NULL)
8171 {
8172 strcat(temp_output," ");
8173 }
8174 }
8175 strcpy(output,temp_output);
8176
developer06a01d92022-09-07 16:32:39 +08008177 params.name = "supported_rates";
8178 params.value = output;
8179
8180 wifi_dbg_printf("\n%s:",__func__);
8181 wifi_dbg_printf("params.value=%s\n",params.value);
8182 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8183 wifi_hostapdWrite(config_file,&params,1);
8184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8185
8186 return RETURN_OK;
8187}
8188
8189
8190static char *sncopy(char *dst, int dst_sz, const char *src)
8191{
8192 if (src && dst && dst_sz > 0) {
8193 strncpy(dst, src, dst_sz);
8194 dst[dst_sz - 1] = '\0';
8195 }
8196 return dst;
8197}
8198
8199static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8200{
8201 if (0 == strcmp(ht_mode, "HT40") ||
8202 0 == strcmp(ht_mode, "HT80") ||
8203 0 == strcmp(ht_mode, "HT160")) {
8204 switch (channel) {
8205 case 1 ... 7:
8206 case 36:
8207 case 44:
8208 case 52:
8209 case 60:
8210 case 100:
8211 case 108:
8212 case 116:
8213 case 124:
8214 case 132:
8215 case 140:
8216 case 149:
8217 case 157:
8218 return 1;
8219 case 8 ... 13:
8220 case 40:
8221 case 48:
8222 case 56:
8223 case 64:
8224 case 104:
8225 case 112:
8226 case 120:
8227 case 128:
8228 case 136:
8229 case 144:
8230 case 153:
8231 case 161:
8232 return -1;
8233 default:
8234 return -EINVAL;
8235 }
8236 }
8237
8238 return -EINVAL;
8239}
8240
developerb7593de2022-10-18 09:51:57 +08008241static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8242{
8243 int idx = channel%8;
8244 if (0 == strcmp(ht_mode, "HT40") ||
8245 0 == strcmp(ht_mode, "HT80") ||
8246 0 == strcmp(ht_mode, "HT160")) {
8247 switch (idx) {
8248 case 1:
8249 return 1;
8250 case 5:
8251 return -1;
8252 default:
8253 return -EINVAL;
8254 }
8255 }
8256
8257 return -EINVAL;
8258}
developer06a01d92022-09-07 16:32:39 +08008259static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8260{
8261 if (NULL == hw_mode) return;
8262
8263 if (0 == strcmp(hw_mode, "ac"))
8264 sncopy(bw_mode, bw_mode_len, "ht vht");
8265
8266 if (0 == strcmp(hw_mode, "n"))
8267 sncopy(bw_mode, bw_mode_len, "ht");
8268
8269 return;
8270}
8271
8272static int util_chan_to_freq(int chan)
8273{
8274 if (chan == 14)
8275 return 2484;
8276 else if (chan < 14)
8277 return 2407 + chan * 5;
8278 else if (chan >= 182 && chan <= 196)
8279 return 4000 + chan * 5;
8280 else
8281 return 5000 + chan * 5;
8282 return 0;
8283}
8284
developerb7593de2022-10-18 09:51:57 +08008285static int util_6G_chan_to_freq(int chan)
8286{
8287 if (chan)
8288 return 5950 + chan * 5;
8289 else
8290 return 0;
8291
8292}
developer06a01d92022-09-07 16:32:39 +08008293const int *util_unii_5g_chan2list(int chan, int width)
8294{
8295 static const int lists[] = {
8296 // <width>, <chan1>, <chan2>..., 0,
8297 20, 36, 0,
8298 20, 40, 0,
8299 20, 44, 0,
8300 20, 48, 0,
8301 20, 52, 0,
8302 20, 56, 0,
8303 20, 60, 0,
8304 20, 64, 0,
8305 20, 100, 0,
8306 20, 104, 0,
8307 20, 108, 0,
8308 20, 112, 0,
8309 20, 116, 0,
8310 20, 120, 0,
8311 20, 124, 0,
8312 20, 128, 0,
8313 20, 132, 0,
8314 20, 136, 0,
8315 20, 140, 0,
8316 20, 144, 0,
8317 20, 149, 0,
8318 20, 153, 0,
8319 20, 157, 0,
8320 20, 161, 0,
8321 20, 165, 0,
8322 40, 36, 40, 0,
8323 40, 44, 48, 0,
8324 40, 52, 56, 0,
8325 40, 60, 64, 0,
8326 40, 100, 104, 0,
8327 40, 108, 112, 0,
8328 40, 116, 120, 0,
8329 40, 124, 128, 0,
8330 40, 132, 136, 0,
8331 40, 140, 144, 0,
8332 40, 149, 153, 0,
8333 40, 157, 161, 0,
8334 80, 36, 40, 44, 48, 0,
8335 80, 52, 56, 60, 64, 0,
8336 80, 100, 104, 108, 112, 0,
8337 80, 116, 120, 124, 128, 0,
8338 80, 132, 136, 140, 144, 0,
8339 80, 149, 153, 157, 161, 0,
8340 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8341 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8342 -1 // final delimiter
8343 };
8344 const int *start;
8345 const int *p;
8346
8347 for (p = lists; *p != -1; p++) {
8348 if (*p == width) {
8349 for (start = ++p; *p != 0; p++) {
8350 if (*p == chan)
8351 return start;
8352 }
8353 }
8354 // move to the end of channel list of given width
8355 while (*p != 0) {
8356 p++;
8357 }
8358 }
8359
8360 return NULL;
8361}
8362
8363static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8364{
8365 if (NULL == ht_mode)
8366 return 0;
8367
8368 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8369 const int *chans = util_unii_5g_chan2list(channel, width);
8370 int sum = 0;
8371 int cnt = 0;
8372
8373 if (NULL == chans)
8374 return 0;
8375
8376 while (*chans) {
8377 sum += *chans;
8378 cnt++;
8379 chans++;
8380 }
8381 return sum / cnt;
8382}
8383
developerb7593de2022-10-18 09:51:57 +08008384static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8385{
8386 if (NULL == ht_mode)
8387 return 0;
8388
8389 int width = strtol((ht_mode + 2), NULL, 10);
8390
8391 int idx = 0 ;
8392 int centerchan = 0;
8393 int chan_ofs = 1;
8394
8395 if (width == 40){
8396 idx = ((channel/4) + chan_ofs)%2;
8397 switch (idx) {
8398 case 0:
8399 centerchan = (channel - 2);
8400 break;
8401 case 1:
8402 centerchan = (channel + 2);
8403 break;
8404 default:
8405 return -EINVAL;
8406 }
8407 }else if (width == 80){
8408 idx = ((channel/4) + chan_ofs)%4;
8409 switch (idx) {
8410 case 0:
8411 centerchan = (channel - 6);
8412 break;
8413 case 1:
8414 centerchan = (channel + 6);
8415 break;
8416 case 2:
8417 centerchan = (channel + 2);
8418 break;
8419 case 3:
8420 centerchan = (channel - 2);
8421 break;
8422 default:
8423 return -EINVAL;
8424 }
8425 }else if (width == 160){
8426 switch (channel) {
8427 case 1 ... 29:
8428 centerchan = 15;
8429 break;
8430 case 33 ... 61:
8431 centerchan = 47;
8432 break;
8433 case 65 ... 93:
8434 centerchan = 79;
8435 break;
8436 case 97 ... 125:
8437 centerchan = 111;
8438 break;
8439 case 129 ... 157:
8440 centerchan = 143;
8441 break;
8442 case 161 ... 189:
8443 centerchan = 175;
8444 break;
8445 case 193 ... 221:
8446 centerchan = 207;
8447 break;
8448 default:
8449 return -EINVAL;
8450 }
8451 }
8452 return centerchan;
8453}
developer06a01d92022-09-07 16:32:39 +08008454static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8455{
8456 BOOL onlyG, onlyN, onlyA;
8457 CHAR tmp[64];
8458 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8459 if (ret == RETURN_OK) {
8460 sncopy(hw_mode, hw_mode_size, tmp);
8461 }
8462 return ret;
8463}
8464
8465INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8466{
8467 // Sample commands:
8468 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8469 // hostapd_cli -i wifi0 chan_switch 30 2437
8470 char cmd[MAX_CMD_SIZE] = {0};
8471 char buf[MAX_BUF_SIZE] = {0};
8472 int freq = 0, ret = 0;
8473 char center_freq1_str[32] = ""; // center_freq1=%d
8474 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8475 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8476 char hw_mode[16] = ""; // n|ac
8477 char bw_mode[16] = ""; // ht|ht vht
8478 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8479 int sec_chan_offset;
8480 int width;
developer4fb0b922022-09-30 14:29:09 +08008481 char config_file[64] = {0};
8482 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008483 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008484 wifi_band band = band_invalid;
8485 int center_chan = 0;
8486 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008487
developer4fb0b922022-09-30 14:29:09 +08008488 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008489
8490 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8491
developerb7593de2022-10-18 09:51:57 +08008492 band = wifi_index_to_band(radioIndex);
8493
developer5884e982022-10-06 10:52:50 +08008494 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008495
8496 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008497 if (channel){
developerb7593de2022-10-18 09:51:57 +08008498 if (band == band_6){
8499 freq = util_6G_chan_to_freq(channel);
8500 }else{
8501 freq = util_chan_to_freq(channel);
8502 }
developer5884e982022-10-06 10:52:50 +08008503 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008504
developer5884e982022-10-06 10:52:50 +08008505 // Provide bandwith if specified
8506 if (channel_width_MHz > 20) {
8507 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8508 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8509 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008510
developer5884e982022-10-06 10:52:50 +08008511 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8512 }else if (channel_width_MHz == 20){
8513 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8514 }
developer06a01d92022-09-07 16:32:39 +08008515
developerb7593de2022-10-18 09:51:57 +08008516
developer5884e982022-10-06 10:52:50 +08008517 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008518 if (band == band_6){
8519 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8520 if(center_chan){
8521 center_freq1 = util_6G_chan_to_freq(center_chan);
8522 }
8523 }else{
8524 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8525 if(center_chan){
8526 center_freq1 = util_chan_to_freq(center_chan);
8527 }
developer5884e982022-10-06 10:52:50 +08008528 }
developerb7593de2022-10-18 09:51:57 +08008529
8530 if (center_freq1)
8531 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8532
8533 }
8534
8535 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8536 if (band == band_6){
8537 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8538 }else{
8539 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008540 }
developerb7593de2022-10-18 09:51:57 +08008541 if (sec_chan_offset != -EINVAL)
8542 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008543
developer5884e982022-10-06 10:52:50 +08008544 // Only the first AP, other are hanging on the same radio
8545 int apIndex = radioIndex;
8546 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8547 AP_PREFIX, apIndex, csa_beacon_count, freq,
8548 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8549 wifi_dbg_printf("execute: '%s'\n", cmd);
8550 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008551
developer5884e982022-10-06 10:52:50 +08008552 ret = wifi_setRadioChannel(radioIndex, channel);
8553 if (ret != RETURN_OK) {
8554 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8555 return RETURN_ERR;
8556 }
8557
8558 if (sec_chan_offset == 1) ext_str = "Above";
8559 else if (sec_chan_offset == -1) ext_str = "Below";
8560
8561 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008562
developer5884e982022-10-06 10:52:50 +08008563 } else {
8564 if (channel_width_MHz > 20)
8565 ext_str = "Above";
8566 }
developer4fb0b922022-09-30 14:29:09 +08008567 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8568 _syscmd(cmd, buf, sizeof(buf));
8569 if (strlen(buf) != 0)
8570 stbcEnable = TRUE;
8571
developer06a01d92022-09-07 16:32:39 +08008572 wifi_setRadioExtChannel(radioIndex, ext_str);
8573
developer4fb0b922022-09-30 14:29:09 +08008574 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8575
developer06a01d92022-09-07 16:32:39 +08008576 char mhz_str[16];
8577 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8578 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8579
8580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8581
8582 return RETURN_OK;
8583}
8584
8585INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8586{
developer615510b2022-09-27 10:14:35 +08008587 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008588 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008589 char cmd[256]={0};
8590 char buf[128]={0};
8591 char file_name[32] = {0};
8592 char filter_SSID[32] = {0};
8593 char line[256] = {0};
8594 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008595 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008596 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008597 size_t len=0;
8598 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008599 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008600 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008601 bool filter_enable = false;
8602 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008603 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008604
developer615510b2022-09-27 10:14:35 +08008605 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008606
developer615510b2022-09-27 10:14:35 +08008607 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8608 f = fopen(file_name, "r");
8609 if (f != NULL) {
8610 fgets(filter_SSID, sizeof(file_name), f);
8611 if (strlen(filter_SSID) != 0)
8612 filter_enable = true;
8613 fclose(f);
8614 }
8615
developer033b37b2022-10-18 11:27:46 +08008616 phyId = radio_index_to_phy(radio_index);
8617
8618 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008619 _syscmd(cmd, buf, sizeof(buf));
8620 channels_num = strtol(buf, NULL, 10);
8621
developer615510b2022-09-27 10:14:35 +08008622 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8623 // 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);
8624 fprintf(stderr, "cmd: %s\n", cmd);
8625 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008626 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8627 return RETURN_ERR;
8628 }
developer5550e242022-09-30 09:59:32 +08008629
8630 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8631 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8632
developer615510b2022-09-27 10:14:35 +08008633 ret = fgets(line, sizeof(line), f);
8634 while (ret != NULL) {
8635 if(strstr(line, "BSS") != NULL) { // new neighbor info
8636 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8637 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8638 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8639
8640 if (!filter_BSS) {
8641 index++;
8642 wifi_neighbor_ap2_t *tmp;
8643 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8644 if (tmp == NULL) { // no more memory to use
8645 index--;
8646 wifi_dbg_printf("%s: realloc failed\n", __func__);
8647 break;
8648 }
8649 scan_array = tmp;
8650 }
8651 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008652
developer615510b2022-09-27 10:14:35 +08008653 filter_BSS = false;
8654 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8655 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8656 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8657 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8658 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008659 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008660 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008661
developer615510b2022-09-27 10:14:35 +08008662 if (freq >= 2412 && freq <= 2484) {
8663 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8664 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8665 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8666 }
8667 else if (freq >= 5160 && freq <= 5805) {
8668 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8669 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8670 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8671 }
developer06a01d92022-09-07 16:32:39 +08008672
developer615510b2022-09-27 10:14:35 +08008673 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008674 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008675 for (int i = 0; i < channels_num; i++) {
8676 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8677 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8678 break;
8679 }
8680 }
developer06a01d92022-09-07 16:32:39 +08008681 }
developer615510b2022-09-27 10:14:35 +08008682 } else if (strstr(line, "beacon interval") != NULL) {
8683 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8684 } else if (strstr(line, "signal") != NULL) {
8685 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8686 } else if (strstr(line,"SSID") != NULL) {
8687 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8688 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8689 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008690 }
developer615510b2022-09-27 10:14:35 +08008691 } else if (strstr(line, "Supported rates") != NULL) {
8692 char SRate[80] = {0}, *tmp = NULL;
8693 memset(buf, 0, sizeof(buf));
8694 strcpy(SRate, line);
8695 tmp = strtok(SRate, ":");
8696 tmp = strtok(NULL, ":");
8697 strcpy(buf, tmp);
8698 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008699
developer615510b2022-09-27 10:14:35 +08008700 tmp = strtok(buf, " \n");
8701 while (tmp != NULL) {
8702 strcat(SRate, tmp);
8703 if (SRate[strlen(SRate) - 1] == '*') {
8704 SRate[strlen(SRate) - 1] = '\0';
8705 }
8706 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008707
developer615510b2022-09-27 10:14:35 +08008708 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008709 }
developer615510b2022-09-27 10:14:35 +08008710 SRate[strlen(SRate) - 1] = '\0';
8711 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8712 } else if (strstr(line, "DTIM") != NULL) {
8713 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8714 } else if (strstr(line, "VHT capabilities") != NULL) {
8715 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8716 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8717 } else if (strstr(line, "HT capabilities") != NULL) {
8718 strcat(scan_array[index].ap_SupportedStandards, ",n");
8719 strcpy(scan_array[index].ap_OperatingStandards, "n");
8720 } else if (strstr(line, "VHT operation") != NULL) {
8721 ret = fgets(line, sizeof(line), f);
8722 sscanf(line," * channel width: %d", &vht_channel_width);
8723 if(vht_channel_width == 1) {
8724 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8725 } else {
8726 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8727 }
8728 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8729 continue;
8730 } else if (strstr(line, "HT operation") != NULL) {
8731 ret = fgets(line, sizeof(line), f);
8732 sscanf(line," * secondary channel offset: %s", &buf);
8733 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008734 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008735 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 +08008736 }
developer615510b2022-09-27 10:14:35 +08008737 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008738 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008739 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8740 } else {
8741 //20Mhz
8742 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 +08008743 }
developer615510b2022-09-27 10:14:35 +08008744 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008745 continue;
developer615510b2022-09-27 10:14:35 +08008746 } else if (strstr(line, "HE capabilities") != NULL) {
8747 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8748 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8749 ret = fgets(line, sizeof(line), f);
8750 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8751 if (strstr(line, "HE40/2.4GHz") != NULL)
8752 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8753 else
8754 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8755 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8756 if (strstr(line, "HE80/5GHz") != NULL) {
8757 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8758 ret = fgets(line, sizeof(line), f);
8759 } else
8760 continue;
8761 if (strstr(line, "HE160/5GHz") != NULL)
8762 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008763 }
developer615510b2022-09-27 10:14:35 +08008764 continue;
8765 } else if (strstr(line, "WPA") != NULL) {
8766 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8767 } else if (strstr(line, "RSN") != NULL) {
8768 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8769 } else if (strstr(line, "Group cipher") != NULL) {
8770 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8771 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8772 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008773 }
developer06a01d92022-09-07 16:32:39 +08008774 }
developer615510b2022-09-27 10:14:35 +08008775 ret = fgets(line, sizeof(line), f);
8776 }
8777
8778 if (!filter_BSS) {
8779 *output_array_size = index + 1;
8780 } else {
8781 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8782 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008783 }
developer06a01d92022-09-07 16:32:39 +08008784 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008785 pclose(f);
developer5550e242022-09-30 09:59:32 +08008786 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008788 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008789}
developer615510b2022-09-27 10:14:35 +08008790
developer06a01d92022-09-07 16:32:39 +08008791INT wifi_getApAssociatedDeviceStats(
8792 INT apIndex,
8793 mac_address_t *clientMacAddress,
8794 wifi_associated_dev_stats_t *associated_dev_stats,
8795 u64 *handle)
8796{
8797 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8798 char interface_name[50] = {0};
8799 char cmd[1024] = {0};
8800 char mac_str[18] = {0};
8801 char *key = NULL;
8802 char *val = NULL;
8803 FILE *f = NULL;
8804 char *line = NULL;
8805 size_t len = 0;
8806 ssize_t read = 0;
8807
8808 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8809 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8810 return RETURN_ERR;
8811 }
8812
8813 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8814 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8815 if((f = popen(cmd, "r")) == NULL) {
8816 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8817 return RETURN_ERR;
8818 }
8819
8820 while ((read = getline(&line, &len, f)) != -1) {
8821 key = strtok(line,":");
8822 val = strtok(NULL,":");
8823
8824 if(!strncmp(key,"rx bytes",8))
8825 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8826 if(!strncmp(key,"tx bytes",8))
8827 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8828 if(!strncmp(key,"rx packets",10))
8829 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8830 if(!strncmp(key,"tx packets",10))
8831 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8832 if(!strncmp(key,"tx retries",10))
8833 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8834 if(!strncmp(key,"tx failed",9))
8835 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8836 if(!strncmp(key,"rx drop misc",13))
8837 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8838 if(!strncmp(key,"rx bitrate",10)) {
8839 val = strtok(val, " ");
8840 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8841 }
8842 if(!strncmp(key,"tx bitrate",10)) {
8843 val = strtok(val, " ");
8844 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8845 }
8846 }
8847 free(line);
8848 pclose(f);
8849 return RETURN_OK;
8850}
8851
8852INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8853{
8854 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8855
8856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8857 if (NULL == output_string)
8858 return RETURN_ERR;
8859
8860 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8861 _syscmd(cmd, buf, sizeof(buf));
8862
8863 //size of SSID name restricted to value less than 32 bytes
8864 snprintf(output_string, 32, "%s", buf);
8865 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8866
8867 return RETURN_OK;
8868}
8869
8870INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8871{
8872 //char cmd[MAX_CMD_SIZE] = {0};
8873 char config_file[MAX_BUF_SIZE] = {0};
8874 char buf[32] = {0};
8875
8876 if (!output_filterMode)
8877 return RETURN_ERR;
8878
8879 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8880 //_syscmd(cmd, buf, sizeof(buf));
8881 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8882 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008883 if(strlen(buf) == 0) {
8884 *output_filterMode = 0;
8885 }
8886 else {
8887 int macaddr_acl_mode = strtol(buf, NULL, 10);
8888 if (macaddr_acl_mode == 1) {
8889 *output_filterMode = 1;
8890 } else if (macaddr_acl_mode == 0) {
8891 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8892 if (strlen(buf) == 0) {
8893 *output_filterMode = 0;
8894 } else {
8895 *output_filterMode = 2;
8896 }
8897 } else {
8898 return RETURN_ERR;
8899 }
8900 }
developer06a01d92022-09-07 16:32:39 +08008901
8902 return RETURN_OK;
8903}
8904
8905INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8906{
8907 FILE *fp = NULL;
8908 char str[MAX_BUF_SIZE] = {0};
8909 int wificlientindex = 0 ;
8910 int count = 0;
8911 int signalstrength = 0;
8912 int arr[MACADDRESS_SIZE] = {0};
8913 unsigned char mac[MACADDRESS_SIZE] = {0};
8914 UINT wifi_count = 0;
8915 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8916 char pipeCmd[MAX_CMD_SIZE] = {0};
8917
8918 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8919 *output_array_size = 0;
8920 *associated_dev_array = NULL;
8921 char interface_name[50] = {0};
8922
8923 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8924 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8925 return RETURN_ERR;
8926 }
8927
8928 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8929 fp = popen(pipeCmd, "r");
8930 if (fp == NULL)
8931 {
8932 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8933 return RETURN_ERR;
8934 }
8935
8936 /* Read the output a line at a time - output it. */
8937 fgets(str, sizeof(str)-1, fp);
8938 wifi_count = (unsigned int) atoi ( str );
8939 *output_array_size = wifi_count;
8940 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8941 pclose(fp);
8942
8943 if(wifi_count == 0)
8944 {
8945 return RETURN_OK;
8946 }
8947 else
8948 {
8949 wifi_associated_dev2_t* temp = NULL;
8950 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8951 *associated_dev_array = temp;
8952 if(temp == NULL)
8953 {
8954 printf("Error Statement. Insufficient memory \n");
8955 return RETURN_ERR;
8956 }
8957
8958 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8959 system(pipeCmd);
8960
8961 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8962 if(fp == NULL)
8963 {
8964 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8965 return RETURN_ERR;
8966 }
8967 fclose(fp);
8968
8969 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8970 fp = popen(pipeCmd, "r");
8971 if(fp)
8972 {
8973 for(count =0 ; count < wifi_count; count++)
8974 {
8975 fgets(str, MAX_BUF_SIZE, fp);
8976 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8977 {
8978 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8979 {
8980 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8981
8982 }
8983 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8984 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]);
8985 }
8986 temp[count].cli_AuthenticationState = 1; //TODO
8987 temp[count].cli_Active = 1; //TODO
8988 }
8989 pclose(fp);
8990 }
8991
8992 //Updating RSSI per client
8993 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8994 fp = popen(pipeCmd, "r");
8995 if(fp)
8996 {
8997 pclose(fp);
8998 }
8999 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9000 if(fp)
9001 {
9002 for(count =0 ; count < wifi_count ;count++)
9003 {
9004 fgets(str, MAX_BUF_SIZE, fp);
9005 signalstrength = atoi(str);
9006 temp[count].cli_RSSI = signalstrength;
9007 }
9008 pclose(fp);
9009 }
9010
9011
9012 //LastDataDownlinkRate
9013 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
9014 fp = popen(pipeCmd, "r");
9015 if (fp)
9016 {
9017 pclose(fp);
9018 }
9019 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9020 if (fp)
9021 {
9022 for (count = 0; count < wifi_count; count++)
9023 {
9024 fgets(str, MAX_BUF_SIZE, fp);
9025 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9026 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9027 }
9028 pclose(fp);
9029 }
9030
9031 //LastDataUplinkRate
9032 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
9033 fp = popen(pipeCmd, "r");
9034 if (fp)
9035 {
9036 pclose(fp);
9037 }
9038 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9039 if (fp)
9040 {
9041 for (count = 0; count < wifi_count; count++)
9042 {
9043 fgets(str, MAX_BUF_SIZE, fp);
9044 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9045 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9046 }
9047 pclose(fp);
9048 }
9049 }
9050 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9051 return RETURN_OK;
9052
9053}
9054
9055INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9056{
9057#if 0
9058 /*char buf[1024] = {0};
9059 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
9060 _syscmd(cmd, buf, sizeof(buf));*/
9061
9062 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9063 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9064 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9065 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9066
9067 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.
9068 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].
9069 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].
9070 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].
9071 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9072 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9073
9074 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9075 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9076 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9077 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.
9078 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.
9079 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.
9080 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.
9081 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.
9082 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.
9083 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.
9084 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9085#endif
9086
9087 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08009088 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08009089 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009090 char pipeCmd[128] = {0};
9091 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009092 wifi_ssidTrafficStats2_t *out = output_struct;
9093
developerce736392022-09-13 15:24:34 +08009094 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009095 if (!output_struct)
9096 return RETURN_ERR;
9097
developerce736392022-09-13 15:24:34 +08009098 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9099 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
9100 GetInterfaceName(interface_name, HConf_file);
9101 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009102
developer06a01d92022-09-07 16:32:39 +08009103 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009104 if (fp == NULL) {
9105 fprintf(stderr, "%s: popen failed\n", __func__);
9106 return RETURN_ERR;
9107 }
9108 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08009109
developerce736392022-09-13 15:24:34 +08009110 if (strlen(str) == 0) // interface not exist
9111 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009112
developerce736392022-09-13 15:24:34 +08009113 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9114 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009115 pclose(fp);
9116
developerce736392022-09-13 15:24:34 +08009117 memset(str, 0, sizeof(str));
9118 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009119 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009120 if (fp == NULL) {
9121 fprintf(stderr, "%s: popen failed\n", __func__);
9122 return RETURN_ERR;
9123 }
9124 fgets(str, sizeof(str), fp);
9125
9126 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9127 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009128 pclose(fp);
developerce736392022-09-13 15:24:34 +08009129
9130 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9131 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9132
9133 // Not supported
9134 output_struct->ssid_RetransCount = 0;
9135 output_struct->ssid_FailedRetransCount = 0;
9136 output_struct->ssid_RetryCount = 0;
9137 output_struct->ssid_MultipleRetryCount = 0;
9138 output_struct->ssid_ACKFailureCount = 0;
9139 output_struct->ssid_AggregatedPacketCount = 0;
9140
developer06a01d92022-09-07 16:32:39 +08009141 return RETURN_OK;
9142}
9143
9144//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).
9145INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9146{
9147 char output_val[16]={'\0'};
9148 char config_file[MAX_BUF_SIZE] = {0};
9149
9150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9151 if (!output)
9152 return RETURN_ERR;
9153 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9154 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9155
9156 if( strcmp(output_val,"1") == 0 )
9157 *output = TRUE;
9158 else
9159 *output = FALSE;
9160 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9161
9162 return RETURN_OK;
9163}
9164
9165INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9166{
9167 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9168 char str[MAX_BUF_SIZE]={'\0'};
9169 char string[MAX_BUF_SIZE]={'\0'};
9170 char cmd[MAX_CMD_SIZE]={'\0'};
9171 char *ch;
9172 char config_file[MAX_BUF_SIZE] = {0};
9173 struct params params;
9174
9175 if(enable == TRUE)
9176 strcpy(string,"1");
9177 else
9178 strcpy(string,"0");
9179
9180 params.name = "ap_isolate";
9181 params.value = string;
9182
9183 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9184 wifi_hostapdWrite(config_file,&params,1);
9185 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9186
9187 return RETURN_OK;
9188}
9189
9190INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9191{
9192 if (NULL == output_dBm)
9193 return RETURN_ERR;
9194
9195 *output_dBm = 0;
9196 return RETURN_OK;
9197}
9198
9199INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9200{
9201 return RETURN_OK;
9202}
9203INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9204{
9205 return RETURN_OK;
9206}
9207INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9208{
9209 return RETURN_OK;
9210}
9211INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9212{
9213 return RETURN_OK;
9214}
9215INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9216{
9217 return RETURN_OK;
9218}
9219INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9220{
9221 char config_file[MAX_BUF_SIZE] = {0};
9222 struct params list;
9223
9224 list.name = "bss_transition";
9225 list.value = activate?"1":"0";
9226 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9227 wifi_hostapdWrite(config_file, &list, 1);
9228
9229 return RETURN_OK;
9230}
9231wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9232
9233void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9234{
9235 return;
9236}
9237
9238INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9239{
9240 // TODO Implement me!
9241 return RETURN_OK;
9242}
9243
9244INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9245{
developera3c68b92022-09-13 15:27:29 +08009246 char file_name[128] = {0};
9247 char buf[128] = {0};
9248 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009249 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009250
9251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9252
developer804c64f2022-10-19 13:54:40 +08009253 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009254 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009255 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009256 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9257 f = fopen(file_name, "w");
9258 if (f == NULL)
9259 return RETURN_ERR;
9260 // For mode == 0 is to disable filter, just don't write to the file.
9261 if (mode)
9262 fprintf(f, "%s", essid);
9263
9264 fclose(f);
9265 }
9266 } else { // special case, need to set AP's SSID as filter for each radio.
9267 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9268 f = fopen(file_name, "w");
9269 if (f == NULL)
9270 return RETURN_ERR;
9271
9272 // For mode == 0 is to disable filter, just don't write to the file.
9273 if (mode)
9274 fprintf(f, "%s", essid);
9275
9276 fclose(f);
9277 }
9278
9279 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009280 return RETURN_OK;
9281}
9282
9283INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9284{
9285 // TODO Implement me!
9286 //Apply wifi_pushRadioChannel() instantly
9287 return RETURN_ERR;
9288}
9289
9290INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9291{
9292 // TODO Implement me!
9293 return RETURN_OK;
9294}
9295
9296#ifdef HAL_NETLINK_IMPL
9297static int tidStats_callback(struct nl_msg *msg, void *arg) {
9298 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9299 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9300 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9301 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9302 int rem , tid_index = 0;
9303
9304 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9305 wifi_associated_dev_tid_entry_t *stats_entry;
9306
9307 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9308 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9309 };
9310 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9311 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9312 };
9313
9314 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9315 genlmsg_attrlen(gnlh, 0), NULL);
9316
9317
9318 if (!tb[NL80211_ATTR_STA_INFO]) {
9319 fprintf(stderr, "station stats missing!\n");
9320 return NL_SKIP;
9321 }
9322
9323 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9324 tb[NL80211_ATTR_STA_INFO],
9325 stats_policy)) {
9326 fprintf(stderr, "failed to parse nested attributes!\n");
9327 return NL_SKIP;
9328 }
9329
9330 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9331 {
9332 stats_entry = &out->tid_array[tid_index];
9333
9334 stats_entry->tid = tid_index;
9335 stats_entry->ac = _tid_ac_index_get[tid_index];
9336
9337 if(sinfo[NL80211_STA_INFO_TID_STATS])
9338 {
9339 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9340 printf("failed to parse nested stats attributes!");
9341 return NL_SKIP;
9342 }
9343 }
9344 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9345 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9346
9347 if(tid_index < (PS_MAX_TID - 1))
9348 tid_index++;
9349 }
9350 //ToDo: sum_time_ms, ewma_time_ms
9351 return NL_SKIP;
9352}
9353#endif
9354
9355INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9356{
9357#ifdef HAL_NETLINK_IMPL
9358 Netlink nl;
9359 char if_name[10];
9360
9361 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9362
9363 nl.id = initSock80211(&nl);
9364
9365 if (nl.id < 0) {
9366 fprintf(stderr, "Error initializing netlink \n");
9367 return -1;
9368 }
9369
9370 struct nl_msg* msg = nlmsg_alloc();
9371
9372 if (!msg) {
9373 fprintf(stderr, "Failed to allocate netlink message.\n");
9374 nlfree(&nl);
9375 return -2;
9376 }
9377
9378 genlmsg_put(msg,
9379 NL_AUTO_PORT,
9380 NL_AUTO_SEQ,
9381 nl.id,
9382 0,
9383 0,
9384 NL80211_CMD_GET_STATION,
9385 0);
9386
9387 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9388 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9389 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9390 nl_send_auto(nl.socket, msg);
9391 nl_recvmsgs(nl.socket, nl.cb);
9392 nlmsg_free(msg);
9393 nlfree(&nl);
9394 return RETURN_OK;
9395#else
9396//iw implementation
9397#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9398#define TOTAL_MAX_LINES 50
9399
9400 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9401 char if_name[10];
9402 FILE *fp=NULL;
9403 char pipeCmd[1024]= {'\0'};
9404 int lines,tid_index=0;
9405 char mac_addr[20] = {'\0'};
9406
9407 wifi_associated_dev_tid_entry_t *stats_entry;
9408
9409 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9410 strcpy(mac_addr,clientMacAddress);
9411
9412 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9413 fp= popen(pipeCmd,"r");
9414 if(fp == NULL)
9415 {
9416 perror("popen for station dump failed\n");
9417 return RETURN_ERR;
9418 }
9419 pclose(fp);
9420
9421 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9422 fp=popen(pipeCmd,"r");
9423 if(fp == NULL)
9424 {
9425 perror("popen for grep station failed\n");
9426 return RETURN_ERR;
9427 }
9428 else if(fgets(buf,sizeof(buf),fp) != NULL)
9429 lines=atoi(buf);
9430 else
9431 {
9432 pclose(fp);
9433 fprintf(stderr,"No devices are connected \n");
9434 return RETURN_ERR;
9435 }
9436 pclose(fp);
9437
9438 if(lines == 1)
9439 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9440
9441 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9442 {
9443 stats_entry = &tid_stats->tid_array[tid_index];
9444 stats_entry->tid = tid_index;
9445
9446 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);
9447
9448 fp=popen(pipeCmd,"r");
9449 if(fp ==NULL)
9450 {
9451 perror("Failed to read from tid file \n");
9452 return RETURN_ERR;
9453 }
9454 else if(fgets(buf,sizeof(buf),fp) != NULL)
9455 stats_entry->num_msdus = atol(buf);
9456
9457 pclose(fp);
9458 stats_entry->ac = _tid_ac_index_get[tid_index];
9459// TODO:
9460// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9461// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9462 }
9463 return RETURN_OK;
9464#endif
9465}
9466
9467
9468INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9469{
developer615510b2022-09-27 10:14:35 +08009470 char cmd[128]={0};
9471 char buf[128]={0};
9472 int freq = 0;
9473
9474 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9475
9476 // full mode is used to scan all channels.
9477 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9478 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9479 ieee80211_channel_to_frequency(chan_list[0], &freq);
9480
9481 if (freq)
9482 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9483 else
9484 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9485
9486 _syscmd(cmd, buf, sizeof(buf));
9487 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9488
developer06a01d92022-09-07 16:32:39 +08009489 return RETURN_OK;
9490}
9491
9492
9493INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9494{
9495 // TODO Implement me!
9496 return RETURN_ERR;
9497}
9498
9499INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9500{
9501 // TODO Implement me!
9502 return RETURN_ERR;
9503}
9504
9505INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9506{
9507 // TODO Implement me!
9508 return RETURN_ERR;
9509}
9510
9511INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9512{
9513 // TODO Implement me!
9514 return RETURN_ERR;
9515}
9516
9517INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9518{
9519 // TODO Implement me!
9520 return RETURN_ERR;
9521}
9522
9523INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9524{
9525 // TODO Implement me!
9526 return RETURN_ERR;
9527}
9528
9529INT wifi_steering_eventUnregister(void)
9530{
9531 // TODO Implement me!
9532 return RETURN_ERR;
9533}
9534
9535INT wifi_delApAclDevices(INT apIndex)
9536{
9537#if 0
9538 char cmd[MAX_BUF_SIZE] = {0};
9539 char buf[MAX_BUF_SIZE] = {0};
9540
9541 /* Not reset proof solution */
9542 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9543 if(_syscmd(cmd,buf,sizeof(buf)))
9544 return RETURN_ERR;
9545#endif
developere6aafda2022-09-13 14:59:28 +08009546 char cmd[MAX_CMD_SIZE]={0};
9547 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009548
developere6aafda2022-09-13 14:59:28 +08009549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9550 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9551 if(_syscmd(cmd, buf, sizeof(buf)))
9552 return RETURN_ERR;
9553 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009554
9555 return RETURN_OK;
9556}
9557
9558#ifdef HAL_NETLINK_IMPL
9559static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9560 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9561 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9562 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9563 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9564 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9565 char mac_addr[20],dev[20];
9566
9567 nla_parse(tb,
9568 NL80211_ATTR_MAX,
9569 genlmsg_attrdata(gnlh, 0),
9570 genlmsg_attrlen(gnlh, 0),
9571 NULL);
9572
9573 if(!tb[NL80211_ATTR_STA_INFO]) {
9574 fprintf(stderr, "sta stats missing!\n");
9575 return NL_SKIP;
9576 }
9577
9578 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9579 fprintf(stderr, "failed to parse nested attributes!\n");
9580 return NL_SKIP;
9581 }
9582 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9583
9584 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9585
9586 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9587 fprintf(stderr, "failed to parse nested rate attributes!");
9588 return NL_SKIP;
9589 }
9590
9591 if(sinfo[NL80211_STA_INFO_TID_STATS])
9592 {
9593 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9594 printf("failed to parse nested stats attributes!");
9595 return NL_SKIP;
9596 }
9597 }
9598
9599 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9600 {
9601 printf("Type is VHT\n");
9602 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9603 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9604
9605 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9606 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9607 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9608 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9609 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9610 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9611 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9612 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9613 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9614 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9615 }
9616 else
9617 {
9618 printf(" OFDM or CCK \n");
9619 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9620 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9621 }
9622
9623 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9624 if(rinfo[NL80211_RATE_INFO_MCS])
9625 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9626 }
9627 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9628 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9629 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9630 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9631
9632 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9633 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9634
9635 if (sinfo[NL80211_STA_INFO_SIGNAL])
9636 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9637 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9638 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9639 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9640 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9641 //rssi_array need to be filled
9642 return NL_SKIP;
9643}
9644#endif
9645
9646INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9647{
9648#ifdef HAL_NETLINK_IMPL
9649 Netlink nl;
9650 char if_name[10];
9651
9652 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9653
9654 if (*output_array_size <= 0)
9655 return RETURN_OK;
9656
9657 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9658 nl.id = initSock80211(&nl);
9659
9660 if (nl.id < 0) {
9661 fprintf(stderr, "Error initializing netlink \n");
9662 return 0;
9663 }
9664
9665 struct nl_msg* msg = nlmsg_alloc();
9666
9667 if (!msg) {
9668 fprintf(stderr, "Failed to allocate netlink message.\n");
9669 nlfree(&nl);
9670 return 0;
9671 }
9672
9673 genlmsg_put(msg,
9674 NL_AUTO_PORT,
9675 NL_AUTO_SEQ,
9676 nl.id,
9677 0,
9678 0,
9679 NL80211_CMD_GET_STATION,
9680 0);
9681
9682 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9683 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9684 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9685 nl_send_auto(nl.socket, msg);
9686 nl_recvmsgs(nl.socket, nl.cb);
9687 nlmsg_free(msg);
9688 nlfree(&nl);
9689 return RETURN_OK;
9690#else
9691 //TODO Implement me
9692 return RETURN_OK;
9693#endif
9694}
9695
9696#ifdef HAL_NETLINK_IMPL
9697static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9698 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9699 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9700 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9701 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9702 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9703 char mac_addr[20],dev[20];
9704
9705 nla_parse(tb,
9706 NL80211_ATTR_MAX,
9707 genlmsg_attrdata(gnlh, 0),
9708 genlmsg_attrlen(gnlh, 0),
9709 NULL);
9710
9711 if(!tb[NL80211_ATTR_STA_INFO]) {
9712 fprintf(stderr, "sta stats missing!\n");
9713 return NL_SKIP;
9714 }
9715
9716 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9717 fprintf(stderr, "failed to parse nested attributes!\n");
9718 return NL_SKIP;
9719 }
9720
9721 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9722
9723 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9724
9725 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9726 fprintf(stderr, "failed to parse nested rate attributes!");
9727 return NL_SKIP;
9728 }
9729
9730 if(sinfo[NL80211_STA_INFO_TID_STATS])
9731 {
9732 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9733 printf("failed to parse nested stats attributes!");
9734 return NL_SKIP;
9735 }
9736 }
9737 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9738 {
9739 printf("Type is VHT\n");
9740 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9741 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9742
9743 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9744 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9745 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9746 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9747 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9748 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9749 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9750 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9751 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9752 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9753 }
9754 else
9755 {
9756 printf(" OFDM or CCK \n");
9757 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9758 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9759 }
9760
9761 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9762 if(rinfo[NL80211_RATE_INFO_MCS])
9763 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9764 }
9765
9766 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9767 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9768 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9769 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9770
9771 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9772 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9773 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9774
9775 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9776 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9777
9778 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9779 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9780
9781 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9782 ((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]);
9783
9784 return NL_SKIP;
9785}
9786#endif
9787
9788INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9789{
9790#ifdef HAL_NETLINK_IMPL
9791 Netlink nl;
9792 char if_name[10];
9793
9794 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9795
9796 if (*output_array_size <= 0)
9797 return RETURN_OK;
9798
9799 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9800
9801 nl.id = initSock80211(&nl);
9802
9803 if(nl.id < 0) {
9804 fprintf(stderr, "Error initializing netlink \n");
9805 return 0;
9806 }
9807
9808 struct nl_msg* msg = nlmsg_alloc();
9809
9810 if(!msg) {
9811 fprintf(stderr, "Failed to allocate netlink message.\n");
9812 nlfree(&nl);
9813 return 0;
9814 }
9815
9816 genlmsg_put(msg,
9817 NL_AUTO_PORT,
9818 NL_AUTO_SEQ,
9819 nl.id,
9820 0,
9821 0,
9822 NL80211_CMD_GET_STATION,
9823 0);
9824
9825 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9826 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9827 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9828 nl_send_auto(nl.socket, msg);
9829 nl_recvmsgs(nl.socket, nl.cb);
9830 nlmsg_free(msg);
9831 nlfree(&nl);
9832 return RETURN_OK;
9833#else
9834 //TODO Implement me
9835 return RETURN_OK;
9836#endif
9837}
9838
9839INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9840{
9841 // TODO Implement me!
9842 char buf[MAX_BUF_SIZE] = {0};
9843 char config_file[MAX_BUF_SIZE] = {0};
9844
9845 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9846 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9847 *activate = (strncmp("1",buf,1) == 0);
9848
9849 return RETURN_OK;
9850}
9851
9852INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9853{
9854 char config_file[MAX_BUF_SIZE] = {0};
9855 struct params list;
9856
9857 list.name = "rrm_neighbor_report";
9858 list.value = activate?"1":"0";
9859 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9860 wifi_hostapdWrite(config_file, &list, 1);
9861
9862 return RETURN_OK;
9863}
9864
9865INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9866{
9867 char buf[32] = {0};
9868 char config_file[MAX_BUF_SIZE] = {0};
9869
9870 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9871 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9872 *activate = (strncmp("1",buf,1) == 0);
9873
9874 return RETURN_OK;
9875}
9876#undef HAL_NETLINK_IMPL
9877#ifdef HAL_NETLINK_IMPL
9878static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9879 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9880 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9881 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9882 char dev[20];
9883 int freq =0 ;
9884 static int i=0;
9885
9886 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9887
9888 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9889 };
9890
9891 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9892
9893 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9894
9895 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9896 fprintf(stderr, "survey data missing!\n");
9897 return NL_SKIP;
9898 }
9899
9900 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9901 {
9902 fprintf(stderr, "failed to parse nested attributes!\n");
9903 return NL_SKIP;
9904 }
9905
9906
9907 if(out[0].array_size == 1 )
9908 {
9909 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9910 {
9911 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9912 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9913 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9914
9915 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9916 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9917 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9918 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9919 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9920 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9921 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9922 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9923 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9924 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9925 if (sinfo[NL80211_SURVEY_INFO_TIME])
9926 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9927 return NL_STOP;
9928 }
9929 }
9930 else
9931 {
9932 if ( i <= out[0].array_size )
9933 {
9934 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9935 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9936 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9937
9938 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9939 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9940 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9941 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9942 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9943 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9944 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9945 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9946 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9947 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9948 if (sinfo[NL80211_SURVEY_INFO_TIME])
9949 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9950 }
9951 }
9952
9953 i++;
9954 return NL_SKIP;
9955}
9956#endif
9957
9958static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9959{
9960 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9961 FILE *fp;
9962
9963 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9964 {
9965 printf("Creating Frequency-Channel Map\n");
9966 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9967 }
9968 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9969 if((fp = popen(command, "r")))
9970 {
9971 fgets(output, sizeof(output), fp);
9972 *freqMHz = atoi(output);
9973 fclose(fp);
9974 }
9975
9976 return 0;
9977}
9978
9979static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9980{
9981 int freqMHz = -1;
9982 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +08009983 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009984
9985 ieee80211_channel_to_frequency(channel, &freqMHz);
9986 if (freqMHz == -1) {
9987 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9988 return -1;
9989 }
9990
developer033b37b2022-10-18 11:27:46 +08009991 phyId = radio_index_to_phy(radioIndex);
9992 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 +08009993 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9994 radioIndex, freqMHz);
9995 return -1;
9996 }
9997
9998 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9999 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10000 return -1;
10001 }
10002
10003 return 0;
10004}
10005
10006static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10007{
10008 const char *ptr = buf;
10009 char *key = NULL;
10010 char *val = NULL;
10011 char line[256] = { '\0' };
10012
10013 while (ptr = get_line_from_str_buf(ptr, line)) {
10014 if (strstr(line, "Frequency")) continue;
10015
10016 key = strtok(line, ":");
10017 val = strtok(NULL, " ");
10018 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10019
10020 if (!strcmp(key, "noise")) {
10021 sscanf(val, "%d", &stats->ch_noise);
10022 if (stats->ch_noise == 0) {
10023 // Workaround for missing noise information.
10024 // Assume -95 for 2.4G and -103 for 5G
10025 if (radioIndex == 0) stats->ch_noise = -95;
10026 if (radioIndex == 1) stats->ch_noise = -103;
10027 }
10028 }
10029 else if (!strcmp(key, "channel active time")) {
10030 sscanf(val, "%llu", &stats->ch_utilization_total);
10031 }
10032 else if (!strcmp(key, "channel busy time")) {
10033 sscanf(val, "%llu", &stats->ch_utilization_busy);
10034 }
10035 else if (!strcmp(key, "channel receive time")) {
10036 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10037 }
10038 else if (!strcmp(key, "channel transmit time")) {
10039 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10040 }
10041 };
10042
10043 return 0;
10044}
10045
10046INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10047{
10048 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10049#ifdef HAL_NETLINK_IMPL
10050 Netlink nl;
10051 wifi_channelStats_t_loc local[array_size];
10052 char if_name[10];
10053
10054 local[0].array_size = array_size;
10055
10056 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
10057
10058 nl.id = initSock80211(&nl);
10059
10060 if (nl.id < 0) {
10061 fprintf(stderr, "Error initializing netlink \n");
10062 return -1;
10063 }
10064
10065 struct nl_msg* msg = nlmsg_alloc();
10066
10067 if (!msg) {
10068 fprintf(stderr, "Failed to allocate netlink message.\n");
10069 nlfree(&nl);
10070 return -2;
10071 }
10072
10073 genlmsg_put(msg,
10074 NL_AUTO_PORT,
10075 NL_AUTO_SEQ,
10076 nl.id,
10077 0,
10078 NLM_F_DUMP,
10079 NL80211_CMD_GET_SURVEY,
10080 0);
10081
10082 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10083 nl_send_auto(nl.socket, msg);
10084 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10085 nl_recvmsgs(nl.socket, nl.cb);
10086 nlmsg_free(msg);
10087 nlfree(&nl);
10088 //Copying the Values
10089 for(int i=0;i<array_size;i++)
10090 {
10091 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10092 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10093 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10094 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10095 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10096 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10097 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10098 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10099 }
10100#else
10101 ULONG channel = 0;
10102 int i;
10103 int number_of_channels = array_size;
10104 char buf[512];
10105 INT ret;
10106 wifi_channelStats_t tmp_stats;
10107
10108 if (number_of_channels == 0) {
10109 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10110 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10111 return RETURN_ERR;
10112 }
10113 number_of_channels = 1;
10114 input_output_channelStats_array[0].ch_number = channel;
10115 }
10116
10117 for (i = 0; i < number_of_channels; i++) {
10118
10119 input_output_channelStats_array[i].ch_noise = 0;
10120 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10121 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10122 input_output_channelStats_array[i].ch_utilization_busy = 0;
10123 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10124 input_output_channelStats_array[i].ch_utilization_total = 0;
10125
10126 memset(buf, 0, sizeof(buf));
10127 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10128 return RETURN_ERR;
10129 }
10130 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10131 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10132 return RETURN_ERR;
10133 }
10134
10135 // XXX: fake missing 'self' counter which is not available in iw survey output
10136 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10137 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10138
10139 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10140 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10141 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10142 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10143 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10144
10145 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",
10146 __func__,
10147 input_output_channelStats_array[i].ch_number,
10148 input_output_channelStats_array[i].ch_noise,
10149 input_output_channelStats_array[i].ch_utilization_total,
10150 input_output_channelStats_array[i].ch_utilization_busy,
10151 input_output_channelStats_array[i].ch_utilization_busy_rx,
10152 input_output_channelStats_array[i].ch_utilization_busy_tx,
10153 input_output_channelStats_array[i].ch_utilization_busy_self,
10154 input_output_channelStats_array[i].ch_utilization_busy_ext);
10155 }
10156#endif
10157 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10158 return RETURN_OK;
10159}
10160#define HAL_NETLINK_IMPL
10161
10162/* Hostapd events */
10163
10164#ifndef container_of
10165#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10166#define container_of(ptr, type, member) \
10167 ((type *)((char *)ptr - offset_of(type, member)))
10168#endif /* container_of */
10169
10170struct ctrl {
10171 char sockpath[128];
10172 char sockdir[128];
10173 char bss[IFNAMSIZ];
10174 char reply[4096];
10175 int ssid_index;
10176 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10177 void (*overrun)(struct ctrl *ctrl);
10178 struct wpa_ctrl *wpa;
10179 unsigned int ovfl;
10180 size_t reply_len;
10181 int initialized;
10182 ev_timer retry;
10183 ev_timer watchdog;
10184 ev_stat stat;
10185 ev_io io;
10186};
10187static wifi_newApAssociatedDevice_callback clients_connect_cb;
10188static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10189static struct ctrl wpa_ctrl[MAX_APS];
10190static int initialized;
10191
10192static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10193{
10194 char cbuf[256] = {};
10195 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10196 struct cmsghdr *cmsg;
10197 unsigned int ovfl = ctrl->ovfl;
10198 unsigned int drop;
10199
10200 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10201 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10202 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10203 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10204
10205 drop = ovfl - ctrl->ovfl;
10206 ctrl->ovfl = ovfl;
10207
10208 return drop;
10209}
10210
10211static void ctrl_close(struct ctrl *ctrl)
10212{
10213 if (ctrl->io.cb)
10214 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10215 if (ctrl->retry.cb)
10216 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10217 if (!ctrl->wpa)
10218 return;
10219
10220 wpa_ctrl_detach(ctrl->wpa);
10221 wpa_ctrl_close(ctrl->wpa);
10222 ctrl->wpa = NULL;
10223 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10224}
10225
10226static void ctrl_process(struct ctrl *ctrl)
10227{
10228 const char *str;
10229 int drops;
10230 int level;
10231 int err;
10232
10233 /* Example events:
10234 *
10235 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10236 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10237 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10238 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10239 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10240 */
10241 if (!(str = index(ctrl->reply, '>')))
10242 return;
10243 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10244 return;
10245
10246 str++;
10247
10248 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10249 if (!(str = index(ctrl->reply, ' ')))
10250 return;
10251 wifi_associated_dev_t sta;
10252 memset(&sta, 0, sizeof(sta));
10253
10254 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10255 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10256 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10257
10258 sta.cli_Active=true;
10259
10260 (clients_connect_cb)(ctrl->ssid_index, &sta);
10261 goto handled;
10262 }
10263
10264 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10265 if (!(str = index(ctrl->reply, ' ')))
10266 return;
10267
10268 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10269 goto handled;
10270 }
10271
10272 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10273 printf("CTRL_WPA: handle TERMINATING event\n");
10274 goto retry;
10275 }
10276
10277 if (strncmp("AP-DISABLED", str, 11) == 0) {
10278 printf("CTRL_WPA: handle AP-DISABLED\n");
10279 goto retry;
10280 }
10281
10282 printf("Event not supported!!\n");
10283
10284handled:
10285
10286 if ((drops = ctrl_get_drops(ctrl))) {
10287 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10288 if (ctrl->overrun)
10289 ctrl->overrun(ctrl);
10290 }
10291
10292 return;
10293
10294retry:
10295 printf("WPA_CTRL: closing\n");
10296 ctrl_close(ctrl);
10297 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10298 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10299}
10300
10301static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10302{
10303 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10304 int err;
10305
10306 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10307 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10308 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10309 ctrl->reply[ctrl->reply_len] = 0;
10310 if (err < 0) {
10311 if (errno == EAGAIN || errno == EWOULDBLOCK)
10312 return;
10313 ctrl_close(ctrl);
10314 ev_timer_again(EV_A_ &ctrl->retry);
10315 return;
10316 }
10317
10318 ctrl_process(ctrl);
10319}
10320
10321static int ctrl_open(struct ctrl *ctrl)
10322{
10323 int fd;
10324
10325 if (ctrl->wpa)
10326 return 0;
10327
10328 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10329 if (!ctrl->wpa)
10330 goto err;
10331
10332 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10333 goto err_close;
10334
10335 fd = wpa_ctrl_get_fd(ctrl->wpa);
10336 if (fd < 0)
10337 goto err_detach;
10338
10339 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10340 goto err_detach;
10341
10342 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10343 ev_io_start(EV_DEFAULT_ &ctrl->io);
10344
10345 return 0;
10346
10347err_detach:
10348 wpa_ctrl_detach(ctrl->wpa);
10349err_close:
10350 wpa_ctrl_close(ctrl->wpa);
10351err:
10352 ctrl->wpa = NULL;
10353 return -1;
10354}
10355
10356static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10357{
10358 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10359
10360 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10361 ctrl_open(ctrl);
10362}
10363
10364static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10365{
10366 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10367
10368 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10369 if (ctrl_open(ctrl) == 0) {
10370 printf("WPA_CTRL: retry successful\n");
10371 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10372 }
10373}
10374
10375int ctrl_enable(struct ctrl *ctrl)
10376{
10377 if (ctrl->wpa)
10378 return 0;
10379
10380 if (!ctrl->stat.cb) {
10381 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10382 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10383 }
10384
10385 if (!ctrl->retry.cb) {
10386 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10387 }
10388
10389 return ctrl_open(ctrl);
10390}
10391
10392static void
10393ctrl_msg_cb(char *buf, size_t len)
10394{
10395 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10396
10397 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10398 ctrl_process(ctrl);
10399}
10400
10401static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10402{
10403 int err;
10404
10405 if (!ctrl->wpa)
10406 return -1;
10407 if (*reply_len < 2)
10408 return -1;
10409
10410 (*reply_len)--;
10411 ctrl->reply_len = sizeof(ctrl->reply);
10412 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10413 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10414 if (err < 0)
10415 return err;
10416
10417 if (ctrl->reply_len > *reply_len)
10418 ctrl->reply_len = *reply_len;
10419
10420 *reply_len = ctrl->reply_len;
10421 memcpy(reply, ctrl->reply, *reply_len);
10422 reply[*reply_len - 1] = 0;
10423 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10424 return 0;
10425}
10426
10427static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10428{
10429 const char *pong = "PONG";
10430 const char *ping = "PING";
10431 char reply[1024];
10432 size_t len = sizeof(reply);
10433 int err;
10434 ULONG s, snum;
10435 INT ret;
10436 BOOL status;
10437
10438 printf("WPA_CTRL: watchdog cb\n");
10439
10440 ret = wifi_getSSIDNumberOfEntries(&snum);
10441 if (ret != RETURN_OK) {
10442 printf("%s: failed to get SSID count", __func__);
10443 return;
10444 }
10445
10446 if (snum > MAX_APS) {
10447 printf("more ssid than supported! %lu\n", snum);
10448 return;
10449 }
10450
10451 for (s = 0; s < snum; s++) {
10452 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10453 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10454 continue;
10455 }
10456 if (status == false) continue;
10457
10458 memset(reply, 0, sizeof(reply));
10459 len = sizeof(reply);
10460 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10461 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10462 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10463 continue;
10464
10465 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10466 ctrl_close(&wpa_ctrl[s]);
10467 printf("WPA_CTRL: ev_timer_again %d\n", s);
10468 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10469 }
10470}
10471
10472static int init_wpa()
10473{
10474 int ret = 0, i = 0;
10475 ULONG s, snum;
10476
10477 ret = wifi_getSSIDNumberOfEntries(&snum);
10478 if (ret != RETURN_OK) {
10479 printf("%s: failed to get SSID count", __func__);
10480 return RETURN_ERR;
10481 }
10482
10483 if (snum > MAX_APS) {
10484 printf("more ssid than supported! %lu\n", snum);
10485 return RETURN_ERR;
10486 }
10487
10488 for (s = 0; s < snum; s++) {
10489 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10490 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10491 wpa_ctrl[s].ssid_index = s;
10492 ctrl_enable(&wpa_ctrl[s]);
10493 }
10494
10495 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10496 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10497
10498 initialized = 1;
10499 printf("WPA_CTRL: initialized\n");
10500
10501 return RETURN_OK;
10502}
10503
10504void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10505{
10506 clients_connect_cb = callback_proc;
10507 if (!initialized)
10508 init_wpa();
10509}
10510
10511void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10512{
10513 clients_disconnect_cb = callback_proc;
10514 if (!initialized)
10515 init_wpa();
10516}
10517
10518INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10519{
10520 // TODO Implement me!
10521 return RETURN_ERR;
10522}
10523
10524INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10525{
10526 // TODO Implement me!
10527 return RETURN_ERR;
10528}
10529
10530INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10531{
10532 int i;
10533 char cmd[256];
10534 char channel_numbers_buf[256];
10535 char dfs_state_buf[256];
10536 char line[256];
10537 const char *ptr;
10538
10539 memset(cmd, 0, sizeof(cmd));
10540 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10541 memset(line, 0, sizeof(line));
10542 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10543 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10544
10545 if (radioIndex == 0) { // 2.4G - all allowed
10546 if (outputMapSize < 11) {
10547 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10548 return RETURN_ERR;
10549 }
10550
10551 for (i = 0; i < 11; i++) {
10552 outputMap[i].ch_number = i + 1;
10553 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10554 }
10555
10556 return RETURN_OK;
10557 }
10558
10559 if (radioIndex == 1) { // 5G
10560// Example output of iw list:
10561//
10562// Frequencies:
10563// * 5180 MHz [36] (17.0 dBm)
10564// * 5200 MHz [40] (17.0 dBm)
10565// * 5220 MHz [44] (17.0 dBm)
10566// * 5240 MHz [48] (17.0 dBm)
10567// * 5260 MHz [52] (23.0 dBm) (radar detection)
10568// DFS state: usable (for 78930 sec)
10569// DFS CAC time: 60000 ms
10570// * 5280 MHz [56] (23.0 dBm) (radar detection)
10571// DFS state: usable (for 78930 sec)
10572// DFS CAC time: 60000 ms
10573// * 5300 MHz [60] (23.0 dBm) (radar detection)
10574// DFS state: usable (for 78930 sec)
10575// DFS CAC time: 60000 ms
10576// * 5320 MHz [64] (23.0 dBm) (radar detection)
10577// DFS state: usable (for 78930 sec)
10578// DFS CAC time: 60000 ms
10579// * 5500 MHz [100] (disabled)
10580// * 5520 MHz [104] (disabled)
10581// * 5540 MHz [108] (disabled)
10582// * 5560 MHz [112] (disabled)
10583//
10584// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10585 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10586 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10587 return RETURN_ERR;
10588 }
10589
10590 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10591 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10592 return RETURN_ERR;
10593 }
10594
10595 ptr = channel_numbers_buf;
10596 i = 0;
10597 while (ptr = get_line_from_str_buf(ptr, line)) {
10598 if (i >= outputMapSize) {
10599 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10600 return RETURN_ERR;
10601 }
10602 sscanf(line, "%d", &outputMap[i].ch_number);
10603
10604 memset(cmd, 0, sizeof(cmd));
10605 // Below command should fetch string for DFS state (usable, available or unavailable)
10606 // Example line: "DFS state: usable (for 78930 sec)"
10607 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) {
10608 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10609 return RETURN_ERR;
10610 }
10611
10612 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10613 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10614 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10615 return RETURN_ERR;
10616 }
10617
10618 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10619
10620 if (!strcmp(dfs_state_buf, "usable")) {
10621 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10622 } else if (!strcmp(dfs_state_buf, "available")) {
10623 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10624 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10625 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10626 } else {
10627 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10628 }
10629 i++;
10630 }
10631
10632 return RETURN_OK;
10633 }
10634
10635 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10636 return RETURN_ERR;
10637}
10638
10639INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10640{
10641 // TODO Implement me!
10642 return RETURN_ERR;
10643}
10644
10645INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10646{
10647 return RETURN_OK;
10648}
10649
10650INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10651{
10652 // TODO Implement me!
10653 return RETURN_ERR;
10654}
10655
10656INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10657{
10658 // TODO API refrence Implementaion is present on RPI hal
10659 return RETURN_ERR;
10660}
10661
10662INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10663{
developera5005b62022-09-13 15:43:35 +080010664 char cmd[128]={'\0'};
10665 char buf[128]={'\0'};
10666 char *support;
10667 int maximum_tx = 0, current_tx = 0;
10668
10669 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10670 if(txpwr_pcntg == NULL)
10671 return RETURN_ERR;
10672
10673 // Get the maximum tx power of the device
10674 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10675 _syscmd(cmd, buf, sizeof(buf));
10676 maximum_tx = strtol(buf, NULL, 10);
10677
10678 // Get the current tx power
10679 memset(cmd, 0, sizeof(cmd));
10680 memset(buf, 0, sizeof(buf));
10681 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10682 _syscmd(cmd, buf, sizeof(buf));
10683 current_tx = strtol(buf, NULL, 10);
10684
10685 // Get the power supported list and find the current power percentage in supported list
10686 memset(buf, 0, sizeof(buf));
10687 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10688 support = strtok(buf, ",");
10689 while(true)
10690 {
10691 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 +080010692 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010693 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010694 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010695 }
10696 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10697 if (tmp == current_tx) {
10698 *txpwr_pcntg = strtol(support, NULL, 10);
10699 break;
10700 }
10701 support = strtok(NULL, ",");
10702 }
10703 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010704 return RETURN_OK;
10705}
10706
10707INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10708{
developer58599c22022-09-13 16:40:34 +080010709 // TODO precac feature.
10710 struct params params = {0};
10711 char config_file[128] = {0};
10712
10713 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10714
10715 params.name = "enable_background_radar";
10716 params.value = enable?"1":"0";
10717 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10718 wifi_hostapdWrite(config_file, &params, 1);
10719 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10720
10721 /* TODO precac feature */
10722
10723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10724 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010725}
10726
10727INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10728{
developer58599c22022-09-13 16:40:34 +080010729 char config_file[128] = {0};
10730 char buf[64] = {0};
10731
10732 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10733 if (NULL == enable || NULL == precac)
10734 return RETURN_ERR;
10735
10736 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10737 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10738 if (strncmp(enable, "1", 1) == 0)
10739 *enable = true;
10740 else
10741 *enable = false;
10742
10743 /* TODO precac feature */
10744
10745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10746 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010747}
10748
10749INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10750{
developer58599c22022-09-13 16:40:34 +080010751 *supported = TRUE;
10752 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010753}
10754
developer3e6b1692022-09-30 18:04:05 +080010755INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10756{
10757 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10758 struct params params = {0};
10759 char config_file[64] = {0};
10760 char buf[64] = {0};
10761 unsigned int set_mu_type = 0;
10762 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10763
10764 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10765 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10766
10767 if (strlen(buf) > 0)
10768 set_mu_type = strtol(buf, NULL, 10);
10769
10770 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10771 set_mu_type &= ~0x05; // unset bit 0, 2
10772 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10773 set_mu_type |= 0x01;
10774 set_mu_type &= ~0x04;
10775 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10776 set_mu_type &= ~0x01;
10777 set_mu_type |= 0x04;
10778 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10779 set_mu_type |= 0x05; // set bit 0, 2
10780 }
10781
10782 params.name = "hemu_onoff";
10783 sprintf(buf, "%u", set_mu_type);
10784 params.value = buf;
10785 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10786 wifi_hostapdWrite(config_file, &params, 1);
10787 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10788
10789 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10790 return RETURN_OK;
10791}
10792
10793INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10794{
10795 struct params params={0};
10796 char config_file[64] = {0};
10797 char buf[64] = {0};
10798 unsigned int get_mu_type = 0;
10799
10800 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10801
10802 if (mu_type == NULL)
10803 return RETURN_ERR;
10804
10805 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10806 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10807 get_mu_type = strtol(buf, NULL, 10);
10808
10809 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10810 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10811 else if (get_mu_type & 0x04)
10812 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10813 else if (get_mu_type & 0x01)
10814 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10815 else
10816 *mu_type = WIFI_DL_MU_TYPE_NONE;
10817
10818 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10819 return RETURN_OK;
10820}
10821
10822INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10823{
10824 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10825 struct params params={0};
10826 char config_file[64] = {0};
10827 char buf[64] = {0};
10828 unsigned int set_mu_type = 0;
10829 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10830
10831 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10832 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10833
10834 if (strlen(buf) > 0)
10835 set_mu_type = strtol(buf, NULL, 10);
10836
10837 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10838 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10839 set_mu_type &= ~0x0a;
10840 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10841 set_mu_type |= 0x02;
10842 set_mu_type &= ~0x08;
10843 }
10844
10845 params.name = "hemu_onoff";
10846 sprintf(buf, "%u", set_mu_type);
10847 params.value = buf;
10848 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10849 wifi_hostapdWrite(config_file, &params, 1);
10850 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10851
10852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10853 return RETURN_OK;
10854}
10855
10856INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10857{
10858 struct params params={0};
10859 char config_file[64] = {0};
10860 char buf[64] = {0};
10861 unsigned int get_mu_type = 0;
10862
10863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10864
10865 if (mu_type == NULL)
10866 return RETURN_ERR;
10867
10868 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10869 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10870
10871 get_mu_type = strtol(buf, NULL, 10);
10872 if (get_mu_type & 0x02)
10873 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10874 else
10875 *mu_type = WIFI_DL_MU_TYPE_NONE;
10876
10877 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10878 return RETURN_OK;
10879}
10880
10881
developer454b9462022-09-13 15:29:16 +080010882INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10883{
10884 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010885 char buf[256] = {0};
10886 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010887 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010888 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010889 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010890 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010891
10892 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10893
developer254882b2022-09-30 17:12:31 +080010894 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010895 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10896 return RETURN_ERR;
10897 }
developer454b9462022-09-13 15:29:16 +080010898
developer254882b2022-09-30 17:12:31 +080010899 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010900 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010901
developer254882b2022-09-30 17:12:31 +080010902 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10903 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080010904 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010905 _syscmd(cmd, buf, sizeof(buf));
10906 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10907 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10908 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010909 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 +080010910 _syscmd(cmd, buf, sizeof(buf));
10911 }
10912 if (band == band_5) {
10913 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10914 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010915 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 +080010916 _syscmd(cmd, buf, sizeof(buf));
10917 }
10918 }
10919 }
10920 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010921
developer254882b2022-09-30 17:12:31 +080010922 if (guard_interval == wifi_guard_interval_400)
10923 strcpy(GI, "0.4");
10924 else if (guard_interval == wifi_guard_interval_800)
10925 strcpy(GI, "0.8");
10926 else if (guard_interval == wifi_guard_interval_1600)
10927 strcpy(GI, "1.6");
10928 else if (guard_interval == wifi_guard_interval_3200)
10929 strcpy(GI, "3.2");
10930 else if (guard_interval == wifi_guard_interval_auto)
10931 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010932 // Record GI for get GI function
10933 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10934 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010935 if (f == NULL)
10936 return RETURN_ERR;
10937 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010938 fclose(f);
10939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10940 return RETURN_OK;
10941}
10942
10943INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10944{
10945 char buf[32] = {0};
10946 char cmd[64] = {0};
10947
10948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10949
10950 if (guard_interval == NULL)
10951 return RETURN_ERR;
10952
10953 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10954 _syscmd(cmd, buf, sizeof(buf));
10955
10956 if (strncmp(buf, "0.4", 3) == 0)
10957 *guard_interval = wifi_guard_interval_400;
10958 else if (strncmp(buf, "0.8", 3) == 0)
10959 *guard_interval = wifi_guard_interval_800;
10960 else if (strncmp(buf, "1.6", 3) == 0)
10961 *guard_interval = wifi_guard_interval_1600;
10962 else if (strncmp(buf, "3.2", 3) == 0)
10963 *guard_interval = wifi_guard_interval_3200;
10964 else
10965 *guard_interval = wifi_guard_interval_auto;
10966
10967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10968 return RETURN_OK;
10969}
10970
developer3cc61d12022-09-13 16:36:05 +080010971INT wifi_setBSSColor(INT radio_index, UCHAR color)
10972{
10973 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10974 struct params params = {0};
10975 char config_file[128] = {0};
10976 char bss_color[4] ={0};
10977
10978 params.name = "he_bss_color";
10979 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10980 params.value = bss_color;
10981 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10982 wifi_hostapdWrite(config_file, &params, 1);
10983 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10984
10985 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10986 return RETURN_OK;
10987}
10988
10989INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10990{
10991 char config_file[128] = {0};
10992 char buf[64] = {0};
10993 char temp_output[128] = {'\0'};
10994
10995 wifi_dbg_printf("\nFunc=%s\n", __func__);
10996 if (NULL == color)
10997 return RETURN_ERR;
10998
10999 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11000 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11001
11002 if(strlen(buf) > 0) {
11003 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11004 } else {
11005 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11006 }
11007
11008 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11009 wifi_dbg_printf("\noutput_string=%s\n", color);
11010
11011 return RETURN_OK;
11012}
11013
developer06a01d92022-09-07 16:32:39 +080011014/* multi-psk support */
11015INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11016{
11017 char cmd[256];
11018
11019 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11020 AP_PREFIX,
11021 apIndex,
11022 mac[0],
11023 mac[1],
11024 mac[2],
11025 mac[3],
11026 mac[4],
11027 mac[5]
11028 );
11029 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11030 _syscmd(cmd, key->wifi_keyId, 64);
11031
11032
11033 return RETURN_OK;
11034}
11035
11036INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11037{
11038 FILE *fd = NULL;
11039 char fname[100];
11040 char cmd[128] = {0};
11041 char out[64] = {0};
11042 wifi_key_multi_psk_t * key = NULL;
11043 if(keysNumber < 0)
11044 return RETURN_ERR;
11045
11046 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11047 fd = fopen(fname, "w");
11048 if (!fd) {
11049 return RETURN_ERR;
11050 }
11051 key= (wifi_key_multi_psk_t *) keys;
11052 for(int i=0; i<keysNumber; ++i, key++) {
11053 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11054 }
11055 fclose(fd);
11056
11057 //reload file
11058 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
11059 _syscmd(cmd, out, 64);
11060 return RETURN_OK;
11061}
11062
11063INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11064{
11065 FILE *fd = NULL;
11066 char fname[100];
11067 char * line = NULL;
11068 char * pos = NULL;
11069 size_t len = 0;
11070 ssize_t read = 0;
11071 INT ret = RETURN_OK;
11072 wifi_key_multi_psk_t *keys_it = NULL;
11073
11074 if (keysNumber < 1) {
11075 return RETURN_ERR;
11076 }
11077
11078 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11079 fd = fopen(fname, "r");
11080 if (!fd) {
11081 return RETURN_ERR;
11082 }
11083
11084 if (keys == NULL) {
11085 ret = RETURN_ERR;
11086 goto close;
11087 }
11088
11089 keys_it = keys;
11090 while ((read = getline(&line, &len, fd)) != -1) {
11091 //Strip trailing new line if present
11092 if (read > 0 && line[read-1] == '\n') {
11093 line[read-1] = '\0';
11094 }
11095
11096 if(strcmp(line,"keyid=")) {
11097 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11098 if (!(pos = index(line, ' '))) {
11099 ret = RETURN_ERR;
11100 goto close;
11101 }
11102 pos++;
11103 //Here should be 00:00:00:00:00:00
11104 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11105 printf("Not supported MAC: %s\n", pos);
11106 }
11107 if (!(pos = index(pos, ' '))) {
11108 ret = RETURN_ERR;
11109 goto close;
11110 }
11111 pos++;
11112
11113 //The rest is PSK
11114 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11115 keys_it++;
11116
11117 if(--keysNumber <= 0)
11118 break;
11119 }
11120 }
11121
11122close:
11123 free(line);
11124 fclose(fd);
11125 return ret;
11126}
11127/* end of multi-psk support */
11128
11129INT wifi_setNeighborReports(UINT apIndex,
11130 UINT numNeighborReports,
11131 wifi_NeighborReport_t *neighborReports)
11132{
11133 char cmd[256] = { 0 };
11134 char hex_bssid[13] = { 0 };
11135 char bssid[18] = { 0 };
11136 char nr[256] = { 0 };
11137 char ssid[256];
11138 char hex_ssid[256];
11139 INT ret;
11140
11141 /*rmeove all neighbors*/
11142 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
11143 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);
11144 system(cmd);
11145
11146 for(unsigned int i = 0; i < numNeighborReports; i++)
11147 {
11148 memset(ssid, 0, sizeof(ssid));
11149 ret = wifi_getSSIDName(apIndex, ssid);
11150 if (ret != RETURN_OK)
11151 return RETURN_ERR;
11152
11153 memset(hex_ssid, 0, sizeof(hex_ssid));
11154 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11155 sprintf(hex_ssid + k,"%02x", ssid[j]);
11156
11157 snprintf(hex_bssid, sizeof(hex_bssid),
11158 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11159 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11160 snprintf(bssid, sizeof(bssid),
11161 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11162 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11163
11164 snprintf(nr, sizeof(nr),
11165 "%s" // bssid
11166 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11167 "%02hhx" // operclass
11168 "%02hhx" // channel
11169 "%02hhx", // phy_mode
11170 hex_bssid,
11171 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11172 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11173 neighborReports[i].opClass,
11174 neighborReports[i].channel,
11175 neighborReports[i].phyTable);
11176
11177 snprintf(cmd, sizeof(cmd),
11178 "hostapd_cli set_neighbor "
11179 "%s " // bssid
11180 "ssid=%s " // ssid
11181 "nr=%s " // nr
11182 "-i %s%d",
11183 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
11184
11185 if (WEXITSTATUS(system(cmd)) != 0)
11186 {
11187 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11188 }
11189 }
11190
11191 return RETURN_OK;
11192}
11193
11194INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11195{
11196 return RETURN_OK;
11197}
11198
11199#ifdef _WIFI_HAL_TEST_
11200int main(int argc,char **argv)
11201{
11202 int index;
11203 INT ret=0;
11204 char buf[1024]="";
11205
11206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11207 if(argc<3)
11208 {
11209 if(argc==2)
11210 {
11211 if(!strcmp(argv[1], "init"))
11212 return wifi_init();
11213 if(!strcmp(argv[1], "reset"))
11214 return wifi_reset();
11215 if(!strcmp(argv[1], "wifi_getHalVersion"))
11216 {
11217 char buffer[64];
11218 if(wifi_getHalVersion(buffer)==RETURN_OK)
11219 printf("Version: %s\n", buffer);
11220 else
11221 printf("Error in wifi_getHalVersion\n");
11222 return RETURN_OK;
11223 }
11224 }
11225 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11226 exit(-1);
11227 }
11228
11229 index = atoi(argv[2]);
11230 if(strstr(argv[1], "wifi_getApName")!=NULL)
11231 {
11232 wifi_getApName(index,buf);
11233 printf("Ap name is %s \n",buf);
11234 return 0;
11235 }
11236 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11237 {
11238 BOOL b = FALSE;
11239 BOOL *output_bool = &b;
11240 wifi_getRadioAutoChannelEnable(index,output_bool);
11241 printf("Channel enabled = %d \n",b);
11242 return 0;
11243 }
11244 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11245 {
11246 wifi_getApWpaEncryptionMode(index,buf);
11247 printf("encryption enabled = %s\n",buf);
11248 return 0;
11249 }
11250 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11251 {
11252 BOOL b = FALSE;
11253 BOOL *output_bool = &b;
11254 wifi_getApSsidAdvertisementEnable(index,output_bool);
11255 printf("advertisment enabled = %d\n",b);
11256 return 0;
11257 }
11258 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11259 {
11260 if(argc <= 3 )
11261 {
11262 printf("Insufficient arguments \n");
11263 exit(-1);
11264 }
11265
11266 char sta[20] = {'\0'};
11267 ULLONG handle= 0;
11268 strcpy(sta,argv[3]);
11269 mac_address_t st;
11270 mac_addr_aton(st,sta);
11271
11272 wifi_associated_dev_tid_stats_t tid_stats;
11273 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11274 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11275 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);
11276 }
11277
11278 if(strstr(argv[1], "getApEnable")!=NULL) {
11279 BOOL enable;
11280 ret=wifi_getApEnable(index, &enable);
11281 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11282 }
11283 else if(strstr(argv[1], "setApEnable")!=NULL) {
11284 BOOL enable = atoi(argv[3]);
11285 ret=wifi_setApEnable(index, enable);
11286 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11287 }
11288 else if(strstr(argv[1], "getApStatus")!=NULL) {
11289 char status[64];
11290 ret=wifi_getApStatus(index, status);
11291 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11292 }
11293 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11294 {
11295 wifi_getSSIDNameStatus(index,buf);
11296 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11297 return 0;
11298 }
11299 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11300 wifi_ssidTrafficStats2_t stats={0};
11301 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11302 printf("%s %d: returns %d\n", argv[1], index, ret);
11303 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11304 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11305 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11306 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11307 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11308 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11309 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11310 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11311 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11312 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11313 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11314 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11315 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11316 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11317 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11318 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11319 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11320 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11321 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11322 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11323 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11324 }
11325 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11326 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11327 UINT array_size=0;
11328 UINT i=0;
11329 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11330 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11331 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11332 printf(" neighbor %d:\n", i);
11333 printf(" ap_SSID =%s\n", pt->ap_SSID);
11334 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11335 printf(" ap_Mode =%s\n", pt->ap_Mode);
11336 printf(" ap_Channel =%d\n", pt->ap_Channel);
11337 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11338 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11339 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11340 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11341 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11342 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11343 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11344 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11345 printf(" ap_Noise =%d\n", pt->ap_Noise);
11346 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11347 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11348 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11349 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11350 }
11351 if(neighbor_ap_array)
11352 free(neighbor_ap_array); //make sure to free the list
11353 }
11354 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11355 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11356 UINT array_size=0;
11357 UINT i=0;
11358 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11359 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11360 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11361 printf(" associated_dev %d:\n", i);
11362 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11363 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11364 printf(" cli_SNR =%d\n", pt->cli_SNR);
11365 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11366 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11367 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11368 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11369 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11370 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11371 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11372 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11373 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11374 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11375 }
11376 if(associated_dev_array)
11377 free(associated_dev_array); //make sure to free the list
11378 }
11379
11380 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11381 {
11382#define MAX_ARRAY_SIZE 64
11383 int i, array_size;
11384 char *p, *ch_str;
11385 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11386
11387 if(argc != 5)
11388 {
11389 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11390 exit(-1);
11391 }
11392 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11393
11394 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11395 {
11396 strtok_r(ch_str, ",", &p);
11397 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11398 }
11399 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11400 if(!array_size)
11401 array_size=1;//Need to print current channel statistics
11402 for(i=0; i<array_size; i++)
11403 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11404 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11405 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11406 input_output_channelStats_array[i].ch_number,\
11407 input_output_channelStats_array[i].ch_noise,\
11408 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11409 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11410 input_output_channelStats_array[i].ch_utilization_busy,\
11411 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11412 input_output_channelStats_array[i].ch_utilization_total);
11413 }
11414
11415 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11416 {
11417 if(argc <= 3 )
11418 {
11419 printf("Insufficient arguments \n");
11420 exit(-1);
11421 }
11422 char mac_addr[20] = {'\0'};
11423 wifi_device_t output_struct;
11424 int dev_index = atoi(argv[3]);
11425
11426 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11427 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11428 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);
11429 }
11430
11431 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11432 {
11433 if (argc <= 3)
11434 {
11435 printf("Insufficient arguments\n");
11436 exit(-1);
11437 }
11438 char args[256];
11439 wifi_NeighborReport_t *neighborReports;
11440
11441 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11442 if (!neighborReports)
11443 {
11444 printf("Failed to allocate memory");
11445 exit(-1);
11446 }
11447
11448 for (int i = 3; i < argc; ++i)
11449 {
11450 char *val;
11451 int j = 0;
11452 memset(args, 0, sizeof(args));
11453 strncpy(args, argv[i], sizeof(args));
11454 val = strtok(args, ";");
11455 while (val != NULL)
11456 {
11457 if (j == 0)
11458 {
11459 mac_addr_aton(neighborReports[i - 3].bssid, val);
11460 } else if (j == 1)
11461 {
11462 neighborReports[i - 3].info = strtol(val, NULL, 16);
11463 } else if (j == 2)
11464 {
11465 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11466 } else if (j == 3)
11467 {
11468 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11469 } else if (j == 4)
11470 {
11471 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11472 } else {
11473 printf("Insufficient arguments]n\n");
11474 exit(-1);
11475 }
11476 val = strtok(NULL, ";");
11477 j++;
11478 }
11479 }
11480
11481 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11482 if (ret != RETURN_OK)
11483 {
11484 printf("wifi_setNeighborReports ret = %d", ret);
11485 exit(-1);
11486 }
11487 }
11488 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11489 {
11490 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11491 printf("%s.\n", buf);
11492 else
11493 printf("Error returned\n");
11494 }
11495 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11496 {
11497 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11498 printf("%s.\n", buf);
11499 else
11500 printf("Error returned\n");
11501 }
11502 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11503 {
11504 if (argc <= 2)
11505 {
11506 printf("Insufficient arguments\n");
11507 exit(-1);
11508 }
11509 char buf[64]= {'\0'};
11510 wifi_getRadioOperatingChannelBandwidth(index,buf);
11511 printf("Current bandwidth is %s \n",buf);
11512 return 0;
11513 }
11514 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11515 {
11516 if (argc <= 5)
11517 {
11518 printf("Insufficient arguments\n");
11519 exit(-1);
11520 }
11521 UINT channel = atoi(argv[3]);
11522 UINT width = atoi(argv[4]);
11523 UINT beacon = atoi(argv[5]);
11524 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11525 printf("Result = %d", ret);
11526 }
11527
11528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11529 return 0;
11530}
11531
11532#endif
11533
11534#ifdef WIFI_HAL_VERSION_3
11535
developer1e5aa162022-09-13 16:06:24 +080011536INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11537{
11538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11539 if (bitMap & WIFI_BITRATE_1MBPS)
11540 strcat(BasicRate, "1,");
11541 if (bitMap & WIFI_BITRATE_2MBPS)
11542 strcat(BasicRate, "2,");
11543 if (bitMap & WIFI_BITRATE_5_5MBPS)
11544 strcat(BasicRate, "5.5,");
11545 if (bitMap & WIFI_BITRATE_6MBPS)
11546 strcat(BasicRate, "6,");
11547 if (bitMap & WIFI_BITRATE_9MBPS)
11548 strcat(BasicRate, "9,");
11549 if (bitMap & WIFI_BITRATE_11MBPS)
11550 strcat(BasicRate, "11,");
11551 if (bitMap & WIFI_BITRATE_12MBPS)
11552 strcat(BasicRate, "12,");
11553 if (bitMap & WIFI_BITRATE_18MBPS)
11554 strcat(BasicRate, "18,");
11555 if (bitMap & WIFI_BITRATE_24MBPS)
11556 strcat(BasicRate, "24,");
11557 if (bitMap & WIFI_BITRATE_36MBPS)
11558 strcat(BasicRate, "36,");
11559 if (bitMap & WIFI_BITRATE_48MBPS)
11560 strcat(BasicRate, "48,");
11561 if (bitMap & WIFI_BITRATE_54MBPS)
11562 strcat(BasicRate, "54,");
11563 if (strlen(BasicRate) != 0) // remove last comma
11564 BasicRate[strlen(BasicRate) - 1] = '\0';
11565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11566 return RETURN_OK;
11567}
11568
11569INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11570{
11571 UINT BitMap = 0;
11572 char *rate;
11573
11574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11575 rate = strtok(BasicRatesList, ",");
11576 while(rate != NULL)
11577 {
11578 if (strcmp(rate, "1") == 0)
11579 BitMap |= WIFI_BITRATE_1MBPS;
11580 else if (strcmp(rate, "2") == 0)
11581 BitMap |= WIFI_BITRATE_2MBPS;
11582 else if (strcmp(rate, "5.5") == 0)
11583 BitMap |= WIFI_BITRATE_5_5MBPS;
11584 else if (strcmp(rate, "6") == 0)
11585 BitMap |= WIFI_BITRATE_6MBPS;
11586 else if (strcmp(rate, "9") == 0)
11587 BitMap |= WIFI_BITRATE_9MBPS;
11588 else if (strcmp(rate, "11") == 0)
11589 BitMap |= WIFI_BITRATE_11MBPS;
11590 else if (strcmp(rate, "12") == 0)
11591 BitMap |= WIFI_BITRATE_12MBPS;
11592 else if (strcmp(rate, "18") == 0)
11593 BitMap |= WIFI_BITRATE_18MBPS;
11594 else if (strcmp(rate, "24") == 0)
11595 BitMap |= WIFI_BITRATE_24MBPS;
11596 else if (strcmp(rate, "36") == 0)
11597 BitMap |= WIFI_BITRATE_36MBPS;
11598 else if (strcmp(rate, "48") == 0)
11599 BitMap |= WIFI_BITRATE_48MBPS;
11600 else if (strcmp(rate, "54") == 0)
11601 BitMap |= WIFI_BITRATE_54MBPS;
11602 rate = strtok(NULL, ",");
11603 }
11604 *basicRateBitMap = BitMap;
11605 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11606 return RETURN_OK;
11607}
11608
11609// 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 +080011610INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11611{
developer1e5aa162022-09-13 16:06:24 +080011612 char buf[128] = {0};
11613 char cmd[128] = {0};
11614 char config_file[64] = {0};
11615 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011616 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011617 wifi_radio_operationParam_t current_param;
11618
11619 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11620
11621 multiple_set = TRUE;
11622 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11623 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11624 return RETURN_ERR;
11625 }
11626 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11627 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11628 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11629 return RETURN_ERR;
11630 }
11631 }
developer5884e982022-10-06 10:52:50 +080011632
11633 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11634 bandwidth = 20;
11635 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11636 bandwidth = 40;
11637 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11638 bandwidth = 80;
11639 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11640 bandwidth = 160;
11641 if (operationParam->autoChannelEnabled){
11642 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11643 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11644 return RETURN_ERR;
11645 }
11646 }else{
developer1e5aa162022-09-13 16:06:24 +080011647 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11648 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11649 return RETURN_ERR;
11650 }
11651 }
developer5884e982022-10-06 10:52:50 +080011652
developer1e5aa162022-09-13 16:06:24 +080011653 if (current_param.variant != operationParam->variant) {
11654 // Two different definition bit map, so need to check every bit.
11655 if (operationParam->variant & WIFI_80211_VARIANT_A)
11656 set_mode |= WIFI_MODE_A;
11657 if (operationParam->variant & WIFI_80211_VARIANT_B)
11658 set_mode |= WIFI_MODE_B;
11659 if (operationParam->variant & WIFI_80211_VARIANT_G)
11660 set_mode |= WIFI_MODE_G;
11661 if (operationParam->variant & WIFI_80211_VARIANT_N)
11662 set_mode |= WIFI_MODE_N;
11663 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11664 set_mode |= WIFI_MODE_AC;
11665 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11666 set_mode |= WIFI_MODE_AX;
11667 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11668 memset(buf, 0, sizeof(buf));
11669 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11670 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11671 return RETURN_ERR;
11672 }
11673 }
11674 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11675 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11676 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11677 return RETURN_ERR;
11678 }
11679 }
11680 if (current_param.beaconInterval != operationParam->beaconInterval) {
11681 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11682 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11683 return RETURN_ERR;
11684 }
11685 }
11686 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11687 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11688 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11689 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11690 return RETURN_ERR;
11691 }
11692 }
11693 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11694 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11695 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11696 return RETURN_ERR;
11697 }
11698 }
11699 if (current_param.guardInterval != operationParam->guardInterval) {
11700 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11701 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11702 return RETURN_ERR;
11703 }
11704 }
11705 if (current_param.transmitPower != operationParam->transmitPower) {
11706 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11707 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11708 return RETURN_ERR;
11709 }
11710 }
11711 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11712 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11713 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11714 return RETURN_ERR;
11715 }
11716 }
11717 if (current_param.obssCoex != operationParam->obssCoex) {
11718 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11719 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11720 return RETURN_ERR;
11721 }
11722 }
11723 if (current_param.stbcEnable != operationParam->stbcEnable) {
11724 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11725 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11726 return RETURN_ERR;
11727 }
11728 }
11729 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11730 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11731 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11732 return RETURN_ERR;
11733 }
11734 }
11735
11736 // if enable is true, then restart the radio
11737 wifi_setRadioEnable(index, FALSE);
11738 if (operationParam->enable == TRUE)
11739 wifi_setRadioEnable(index, TRUE);
11740 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11741
developer06a01d92022-09-07 16:32:39 +080011742 return RETURN_OK;
11743}
11744
11745INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11746{
developer1e5aa162022-09-13 16:06:24 +080011747 char band[64] = {0};
11748 char buf[256] = {0};
11749 char config_file[64] = {0};
11750 char cmd[128] = {0};
11751 int ret = RETURN_ERR;
11752 int mode = 0;
11753 ULONG channel = 0;
11754 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011755
11756 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11757 printf("Entering %s index = %d\n", __func__, (int)index);
11758
developer1e5aa162022-09-13 16:06:24 +080011759 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11760 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11761 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011762 {
developer1e5aa162022-09-13 16:06:24 +080011763 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011764 return RETURN_ERR;
11765 }
11766 operationParam->enable = enabled;
11767
11768 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011769 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011770 {
developer1e5aa162022-09-13 16:06:24 +080011771 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011772 return RETURN_ERR;
11773 }
11774
11775 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011776 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011777 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011778 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011779 else if (!strcmp(band, "6GHz"))
11780 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011781 else
11782 {
developer1e5aa162022-09-13 16:06:24 +080011783 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011784 band);
11785 }
11786
developer1e5aa162022-09-13 16:06:24 +080011787 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11788 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11789 operationParam->channel = 0;
11790 operationParam->autoChannelEnabled = TRUE;
11791 } else {
11792 operationParam->channel = strtol(buf, NULL, 10);
11793 operationParam->autoChannelEnabled = FALSE;
11794 }
11795
developer06a01d92022-09-07 16:32:39 +080011796 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011797 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11798 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11799 return RETURN_ERR;
11800 }
developer06a01d92022-09-07 16:32:39 +080011801 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11802 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11803 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011804 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11805 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011806 else
11807 {
developer1e5aa162022-09-13 16:06:24 +080011808 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11809 return false;
developer06a01d92022-09-07 16:32:39 +080011810 }
11811
developer1e5aa162022-09-13 16:06:24 +080011812 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11813 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11814 return RETURN_ERR;
11815 }
11816 // Two different definition bit map, so need to check every bit.
11817 if (mode & WIFI_MODE_A)
11818 operationParam->variant |= WIFI_80211_VARIANT_A;
11819 if (mode & WIFI_MODE_B)
11820 operationParam->variant |= WIFI_80211_VARIANT_B;
11821 if (mode & WIFI_MODE_G)
11822 operationParam->variant |= WIFI_80211_VARIANT_G;
11823 if (mode & WIFI_MODE_N)
11824 operationParam->variant |= WIFI_80211_VARIANT_N;
11825 if (mode & WIFI_MODE_AC)
11826 operationParam->variant |= WIFI_80211_VARIANT_AC;
11827 if (mode & WIFI_MODE_AX)
11828 operationParam->variant |= WIFI_80211_VARIANT_AX;
11829 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11830 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11831 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011832 }
developer1e5aa162022-09-13 16:06:24 +080011833 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11834 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11835 return RETURN_ERR;
11836 }
11837 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11838 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11839 return RETURN_ERR;
11840 }
developer06a01d92022-09-07 16:32:39 +080011841
developer1e5aa162022-09-13 16:06:24 +080011842 memset(buf, 0, sizeof(buf));
11843 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11844 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11845 return RETURN_ERR;
11846 }
11847 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11848
11849 memset(buf, 0, sizeof(buf));
11850 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11851 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11852 return RETURN_ERR;
11853 }
11854 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11855
11856 memset(buf, 0, sizeof(buf));
11857 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11858 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11859
11860 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11861 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11862 return RETURN_ERR;
11863 }
11864 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11865 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11866 return RETURN_ERR;
11867 }
11868
11869 memset(buf, 0, sizeof(buf));
11870 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11871 if (strcmp(buf, "-1") == 0) {
11872 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11873 operationParam->ctsProtection = FALSE;
11874 } else {
11875 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11876 operationParam->ctsProtection = TRUE;
11877 }
11878
11879 memset(buf, 0, sizeof(buf));
11880 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11881 if (strcmp(buf, "0") == 0)
11882 operationParam->obssCoex = FALSE;
11883 else
11884 operationParam->obssCoex = TRUE;
11885
11886 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11887 _syscmd(cmd, buf, sizeof(buf));
11888 if (strlen(buf) != 0)
11889 operationParam->stbcEnable = TRUE;
11890 else
11891 operationParam->stbcEnable = FALSE;
11892
11893 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11894 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11895 return RETURN_ERR;
11896 }
11897
11898 // Below value is hardcoded
11899
11900 operationParam->numSecondaryChannels = 0;
11901 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11902 operationParam->channelSecondary[i] = 0;
11903 }
11904 operationParam->csa_beacon_count = 15;
11905 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011906
11907 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11908 return RETURN_OK;
11909}
11910
11911static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11912{
developerc086fb72022-10-04 10:18:22 +080011913 int max_radio_num = 0;
11914
11915 wifi_getMaxRadioNumber(&max_radio_num);
11916 if (radioIndex >= max_radio_num || radioIndex < 0) {
11917 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11918 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011919 }
11920
developerc086fb72022-10-04 10:18:22 +080011921 return (arrayIndex * max_radio_num) + radioIndex;
11922}
developer06a01d92022-09-07 16:32:39 +080011923
developerc086fb72022-10-04 10:18:22 +080011924wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11925 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11926 return WIFI_BITRATE_1MBPS;
11927 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11928 return WIFI_BITRATE_2MBPS;
11929 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11930 return WIFI_BITRATE_5_5MBPS;
11931 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11932 return WIFI_BITRATE_6MBPS;
11933 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11934 return WIFI_BITRATE_9MBPS;
11935 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11936 return WIFI_BITRATE_11MBPS;
11937 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11938 return WIFI_BITRATE_12MBPS;
11939 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11940 return WIFI_BITRATE_18MBPS;
11941 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11942 return WIFI_BITRATE_24MBPS;
11943 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11944 return WIFI_BITRATE_36MBPS;
11945 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11946 return WIFI_BITRATE_48MBPS;
11947 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11948 return WIFI_BITRATE_54MBPS;
11949 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011950}
11951
developer1d57d002022-10-12 18:03:15 +080011952INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
11953{
11954 if (beacon == WIFI_BITRATE_1MBPS)
11955 strcpy(beacon_str, "1Mbps");
11956 else if (beacon == WIFI_BITRATE_2MBPS)
11957 strcpy(beacon_str, "2Mbps");
11958 else if (beacon == WIFI_BITRATE_5_5MBPS)
11959 strcpy(beacon_str, "5.5Mbps");
11960 else if (beacon == WIFI_BITRATE_6MBPS)
11961 strcpy(beacon_str, "6Mbps");
11962 else if (beacon == WIFI_BITRATE_9MBPS)
11963 strcpy(beacon_str, "9Mbps");
11964 else if (beacon == WIFI_BITRATE_11MBPS)
11965 strcpy(beacon_str, "11Mbps");
11966 else if (beacon == WIFI_BITRATE_12MBPS)
11967 strcpy(beacon_str, "12Mbps");
11968 else if (beacon == WIFI_BITRATE_18MBPS)
11969 strcpy(beacon_str, "18Mbps");
11970 else if (beacon == WIFI_BITRATE_24MBPS)
11971 strcpy(beacon_str, "24Mbps");
11972 else if (beacon == WIFI_BITRATE_36MBPS)
11973 strcpy(beacon_str, "36Mbps");
11974 else if (beacon == WIFI_BITRATE_48MBPS)
11975 strcpy(beacon_str, "48Mbps");
11976 else if (beacon == WIFI_BITRATE_54MBPS)
11977 strcpy(beacon_str, "54Mbps");
11978 return RETURN_OK;
11979}
11980
developer06a01d92022-09-07 16:32:39 +080011981INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11982{
developerc086fb72022-10-04 10:18:22 +080011983 INT mode = 0;
11984 INT ret = -1;
11985 INT output = 0;
11986 int i = 0;
11987 int vap_index = 0;
11988 BOOL enabled = FALSE;
11989 char buf[256] = {0};
11990 wifi_vap_security_t security;
11991 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011992
11993 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11994 printf("Entering %s index = %d\n", __func__, (int)index);
11995
developer06a01d92022-09-07 16:32:39 +080011996 for (i = 0; i < 5; i++)
11997 {
developerc086fb72022-10-04 10:18:22 +080011998 map->vap_array[i].radio_index = index;
11999
developer06a01d92022-09-07 16:32:39 +080012000 vap_index = array_index_to_vap_index(index, i);
12001 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012002 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012003
developerc086fb72022-10-04 10:18:22 +080012004 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012005
12006 map->vap_array[i].vap_index = vap_index;
12007
12008 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012009 ret = wifi_getApName(vap_index, buf);
12010 if (ret != RETURN_OK) {
12011 printf("%s: wifi_getApName return error\n", __func__);
12012 return RETURN_ERR;
12013 }
12014 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12015
12016 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012017 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012018 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012019 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012020 return RETURN_ERR;
12021 }
12022 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 +080012023
12024 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012025 if (ret != RETURN_OK) {
12026 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012027 return RETURN_ERR;
12028 }
12029 map->vap_array[i].u.bss_info.enabled = enabled;
12030
developerc086fb72022-10-04 10:18:22 +080012031 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12032 if (ret != RETURN_OK) {
12033 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12034 return RETURN_ERR;
12035 }
developer06a01d92022-09-07 16:32:39 +080012036 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012037
12038 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12039 if (ret != RETURN_OK) {
12040 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12041 return RETURN_ERR;
12042 }
12043 map->vap_array[i].u.bss_info.isolation = enabled;
12044
12045 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12046 if (ret != RETURN_OK) {
12047 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12048 return RETURN_ERR;
12049 }
12050 map->vap_array[i].u.bss_info.bssMaxSta = output;
12051
12052 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12053 if (ret != RETURN_OK) {
12054 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12055 return RETURN_ERR;
12056 }
12057 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012058
developerc086fb72022-10-04 10:18:22 +080012059 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12060 if (ret != RETURN_OK) {
12061 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12062 return RETURN_ERR;
12063 }
12064 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012065
developerc086fb72022-10-04 10:18:22 +080012066 ret = wifi_getApSecurity(vap_index, &security);
12067 if (ret != RETURN_OK) {
12068 printf("%s: wifi_getApSecurity return error\n", __func__);
12069 return RETURN_ERR;
12070 }
12071 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012072
developerc086fb72022-10-04 10:18:22 +080012073 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12074 if (ret != RETURN_OK) {
12075 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12076 return RETURN_ERR;
12077 }
12078 if (mode == 0)
12079 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12080 else
12081 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12082 if (mode == 1)
12083 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12084 else if (mode == 2)
12085 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012086
developerc086fb72022-10-04 10:18:22 +080012087 ret = wifi_getApWmmEnable(vap_index, &enabled);
12088 if (ret != RETURN_OK) {
12089 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12090 return RETURN_ERR;
12091 }
12092 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012093
developerc086fb72022-10-04 10:18:22 +080012094 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12095 if (ret != RETURN_OK) {
12096 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012097 return RETURN_ERR;
12098 }
developerc086fb72022-10-04 10:18:22 +080012099 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012100
12101 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012102 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012103 if (ret != RETURN_OK) {
12104 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12105 return RETURN_ERR;
12106 }
12107 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012108
developerc086fb72022-10-04 10:18:22 +080012109 memset(buf, 0, sizeof(buf));
12110 ret = wifi_getBaseBSSID(vap_index, buf);
12111 if (ret != RETURN_OK) {
12112 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12113 return RETURN_ERR;
12114 }
12115 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12116 &map->vap_array[i].u.bss_info.bssid[0],
12117 &map->vap_array[i].u.bss_info.bssid[1],
12118 &map->vap_array[i].u.bss_info.bssid[2],
12119 &map->vap_array[i].u.bss_info.bssid[3],
12120 &map->vap_array[i].u.bss_info.bssid[4],
12121 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012122 // 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]);
12123
12124 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12125 if (ret != RETURN_OK) {
12126 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12127 return RETURN_ERR;
12128 }
12129 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012130
developerc086fb72022-10-04 10:18:22 +080012131 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012132 }
12133 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12134 return RETURN_OK;
12135}
12136
12137INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12138{
12139 unsigned int i;
12140 wifi_vap_info_t *vap_info = NULL;
12141 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012142 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012143 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012144 char buf[256] = {0};
12145 char cmd[128] = {0};
12146 char config_file[64] = {0};
12147 char bssid[32] = {0};
12148 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012149
12150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12151 printf("Entering %s index = %d\n", __func__, (int)index);
12152 for (i = 0; i < map->num_vaps; i++)
12153 {
developer1d57d002022-10-12 18:03:15 +080012154 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012155 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012156 if (vap_info->u.bss_info.enabled == FALSE)
12157 continue;
developer06a01d92022-09-07 16:32:39 +080012158
developer1d57d002022-10-12 18:03:15 +080012159 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12160
12161 // multi-ap need to copy current radio config
12162 if (vap_info->radio_index != vap_info->vap_index) {
12163 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12164 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012165 }
developer06a01d92022-09-07 16:32:39 +080012166
developer1d57d002022-10-12 18:03:15 +080012167 struct params params[3];
12168 snprintf(vap_info->vap_name, 64, "%s%d", AP_PREFIX, vap_info->vap_index);
12169 params[0].name = "interface";
12170 params[0].value = vap_info->vap_name;
12171 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12172 params[1].name = "bssid";
12173 params[1].value = bssid;
12174 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12175 params[2].name = "wpa_psk_file";
12176 params[2].value = psk_file;
12177
12178 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12179 wifi_hostapdWrite(config_file, params, 3);
12180
12181 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12182 _syscmd(cmd, buf, sizeof(buf));
12183
12184 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12185 if (ret != RETURN_OK) {
12186 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12187 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012188 }
developer1d57d002022-10-12 18:03:15 +080012189
12190 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12191 if (ret != RETURN_OK) {
12192 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12193 return RETURN_ERR;
12194 }
12195
12196 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12197 if (ret != RETURN_OK) {
12198 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12199 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012200 }
12201
developer1d57d002022-10-12 18:03:15 +080012202 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12203 if (ret != RETURN_OK) {
12204 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12205 return RETURN_ERR;
12206 }
developer06a01d92022-09-07 16:32:39 +080012207
developer1d57d002022-10-12 18:03:15 +080012208 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12209 if (ret != RETURN_OK) {
12210 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12211 return RETURN_ERR;
12212 }
developer06a01d92022-09-07 16:32:39 +080012213
developer1d57d002022-10-12 18:03:15 +080012214 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12215 if (ret != RETURN_OK) {
12216 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12217 return RETURN_ERR;
12218 }
12219
developer804c64f2022-10-19 13:54:40 +080012220 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012221 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012222 }else {
12223 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012224 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012225 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12226 _syscmd(cmd, buf, sizeof(buf));
12227 }else{
developer1d57d002022-10-12 18:03:15 +080012228 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012229 }
developer1d57d002022-10-12 18:03:15 +080012230 }
12231
12232 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12233 if (ret != RETURN_OK) {
12234 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12235 return RETURN_ERR;
12236 }
12237
12238 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12239 if (ret != RETURN_OK) {
12240 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12241 return RETURN_ERR;
12242 }
12243
12244 memset(buf, 0, sizeof(buf));
12245 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12246 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12247 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12248 if (ret != RETURN_OK) {
12249 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12250 return RETURN_ERR;
12251 }
12252
12253 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12254 if (ret != RETURN_OK) {
12255 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12256 return RETURN_ERR;
12257 }
12258
12259 wifi_setApEnable(vap_info->vap_index, TRUE);
12260 multiple_set = FALSE;
12261
12262 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12263 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12264 if (ret != RETURN_OK) {
12265 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12266 return RETURN_ERR;
12267 }
12268
12269 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12270 if (ret != RETURN_OK) {
12271 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12272 return RETURN_ERR;
12273 }
developer06a01d92022-09-07 16:32:39 +080012274
developer1d57d002022-10-12 18:03:15 +080012275 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012276 }
12277 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12278 return RETURN_OK;
12279}
12280
12281int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12282{
12283 char *token, *next;
12284 const char s[2] = ",";
12285 int count =0;
12286
12287 /* get the first token */
12288 token = strtok_r(pchannels, s, &next);
12289
12290 /* walk through other tokens */
12291 while( token != NULL && count < MAX_CHANNELS) {
12292 chlistptr->channels_list[count++] = atoi(token);
12293 token = strtok_r(NULL, s, &next);
12294 }
12295
12296 return count;
12297}
12298
12299static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12300{
12301 INT status;
12302 wifi_channels_list_t *chlistp;
12303 CHAR output_string[64];
12304 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012305 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012306 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012307
12308 if(rcap == NULL)
12309 {
12310 return RETURN_ERR;
12311 }
12312
12313 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012314 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012315
developer1e5aa162022-09-13 16:06:24 +080012316 if (band == band_2_4)
12317 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12318 else if (band == band_5)
12319 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12320 else if (band == band_6)
12321 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012322
12323 chlistp = &(rcap->channel_list[0]);
12324 memset(pchannels, 0, sizeof(pchannels));
12325
12326 /* possible number of radio channels */
12327 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12328 {
12329 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12330 }
12331 /* Number of channels and list*/
12332 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12333
12334 /* autoChannelSupported */
12335 /* always ON with wifi_getRadioAutoChannelSupported */
12336 rcap->autoChannelSupported = TRUE;
12337
12338 /* DCSSupported */
12339 /* always ON with wifi_getRadioDCSSupported */
12340 rcap->DCSSupported = TRUE;
12341
12342 /* zeroDFSSupported - TBD */
12343 rcap->zeroDFSSupported = FALSE;
12344
12345 /* Supported Country List*/
12346 memset(output_string, 0, sizeof(output_string));
12347 status = wifi_getRadioCountryCode(radioIndex, output_string);
12348 if( status != 0 ) {
12349 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12350 return RETURN_ERR;
12351 } else {
12352 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12353 }
12354 if(!strcmp(output_string,"US")){
12355 rcap->countrySupported[0] = wifi_countrycode_US;
12356 rcap->countrySupported[1] = wifi_countrycode_CA;
12357 } else if (!strcmp(output_string,"CA")) {
12358 rcap->countrySupported[0] = wifi_countrycode_CA;
12359 rcap->countrySupported[1] = wifi_countrycode_US;
12360 } else {
12361 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12362 }
12363
12364 rcap->numcountrySupported = 2;
12365
12366 /* csi */
12367 rcap->csi.maxDevices = 8;
12368 rcap->csi.soudingFrameSupported = TRUE;
12369
developer033b37b2022-10-18 11:27:46 +080012370 phyId = radio_index_to_phy(radioIndex);
12371 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012372
12373 /* channelWidth - all supported bandwidths */
12374 int i=0;
12375 rcap->channelWidth[i] = 0;
12376 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12377 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12378 WIFI_CHANNELBANDWIDTH_40MHZ);
12379
12380 }
developer1e5aa162022-09-13 16:06:24 +080012381 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012382 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12383 WIFI_CHANNELBANDWIDTH_40MHZ |
12384 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12385 }
12386
12387
12388 /* mode - all supported variants */
12389 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12390 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012391 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 +080012392 }
12393 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012394 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12395 }
12396 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12397 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012398 }
12399 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12400 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12401
12402 /* supportedBitRate - all supported bitrates */
12403 rcap->supportedBitRate[i] = 0;
12404 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12405 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12406 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12407 }
developer1e5aa162022-09-13 16:06:24 +080012408 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012409 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12410 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12411 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12412 }
12413
12414
12415 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12416 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12417 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12418 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12419 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12420 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12421 rcap->cipherSupported = 0;
12422 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12423 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12424
12425 return RETURN_OK;
12426}
12427
12428INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12429{
12430 INT status, radioIndex;
12431 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12432 int iter = 0;
12433 unsigned int j;
12434 wifi_interface_name_idex_map_t *iface_info;
12435
12436 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12437
12438 memset(cap, 0, sizeof(wifi_hal_capability_t));
12439
12440 /* version */
12441 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12442 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12443
12444 /* number of radios platform property */
12445 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12446 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012447 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012448
12449 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12450 {
12451 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12452 if (status != 0) {
12453 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12454 return RETURN_ERR;
12455 }
12456
12457 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12458 {
developer804c64f2022-10-19 13:54:40 +080012459 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012460 {
12461 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12462 return RETURN_ERR;
12463 }
12464 iface_info = &cap->wifi_prop.interface_map[iter];
12465 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12466 iface_info->rdk_radio_index = radioIndex;
12467 memset(output, 0, sizeof(output));
12468 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12469 {
12470 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12471 }
12472 // TODO: bridge name
12473 // TODO: vlan id
12474 // TODO: primary
12475 iface_info->index = array_index_to_vap_index(radioIndex, j);
12476 memset(output, 0, sizeof(output));
12477 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12478 {
12479 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12480 }
12481 iter++;
12482 }
12483 }
12484
12485 cap->BandSteeringSupported = FALSE;
12486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12487 return RETURN_OK;
12488}
12489
developer9df4e652022-10-11 11:27:38 +080012490INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12491{
12492 struct params h_config={0};
12493 char config_file[64] = {0};
12494
12495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12496
12497 h_config.name = "okc";
12498 h_config.value = okc_enable?"1":"0";
12499
12500 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12501 wifi_hostapdWrite(config_file, &h_config, 1);
12502 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12503
12504 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12505 return RETURN_OK;
12506}
12507
12508INT wifi_setSAEMFP(int ap_index, BOOL enable)
12509{
12510 struct params h_config={0};
12511 char config_file[64] = {0};
12512 char buf[128] = {0};
12513
12514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12515
12516 h_config.name = "sae_require_mfp";
12517 h_config.value = enable?"1":"0";
12518
12519 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12520 wifi_hostapdWrite(config_file, &h_config, 1);
12521 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12522
12523 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12524 return RETURN_OK;
12525}
12526
12527INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12528{
12529 struct params h_config={0};
12530 char config_file[64] = {0};
12531 char buf[128] = {0};
12532
12533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12534
12535 h_config.name = "sae_pwe";
12536 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12537 h_config.value = buf;
12538
12539 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12540 wifi_hostapdWrite(config_file, &h_config, 1);
12541 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12542
12543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12544 return RETURN_OK;
12545}
12546
12547INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12548{
12549 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12550 struct params h_config={0};
12551 char config_file[64] = {0};
12552
12553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12554
12555 h_config.name = "wpa_disable_eapol_key_retries";
12556 h_config.value = disable_EAPOL_retries?"1":"0";
12557
12558 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12559 wifi_hostapdWrite(config_file, &h_config, 1);
12560 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12561
12562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12563 return RETURN_OK;
12564}
12565
developer06a01d92022-09-07 16:32:39 +080012566INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12567{
developer587c1b62022-09-27 15:58:59 +080012568 char buf[128] = {0};
12569 char config_file[128] = {0};
12570 char password[64] = {0};
12571 char mfp[32] = {0};
12572 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012573 BOOL okc_enable = FALSE;
12574 BOOL sae_MFP = FALSE;
12575 BOOL disable_EAPOL_retries = TRUE;
12576 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012577 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012578 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012579
12580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12581
12582 multiple_set = TRUE;
12583 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12584 if (security->mode == wifi_security_mode_none) {
12585 strcpy(wpa_mode, "None");
12586 } else if (security->mode == wifi_security_mode_wpa_personal)
12587 strcpy(wpa_mode, "WPA-Personal");
12588 else if (security->mode == wifi_security_mode_wpa2_personal)
12589 strcpy(wpa_mode, "WPA2-Personal");
12590 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12591 strcpy(wpa_mode, "WPA-WPA2-Personal");
12592 else if (security->mode == wifi_security_mode_wpa_enterprise)
12593 strcpy(wpa_mode, "WPA-Enterprise");
12594 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12595 strcpy(wpa_mode, "WPA2-Enterprise");
12596 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12597 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012598 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012599 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012600 okc_enable = TRUE;
12601 sae_MFP = TRUE;
12602 sae_pwe = 2;
12603 disable_EAPOL_retries = FALSE;
12604 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012605 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012606 okc_enable = TRUE;
12607 sae_MFP = TRUE;
12608 sae_pwe = 2;
12609 disable_EAPOL_retries = FALSE;
12610 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012611 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012612 sae_MFP = TRUE;
12613 sae_pwe = 2;
12614 disable_EAPOL_retries = FALSE;
12615 }
12616
12617 band = wifi_index_to_band(ap_index);
12618 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12619 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12620 return RETURN_ERR;
12621 }
developer587c1b62022-09-27 15:58:59 +080012622
12623 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012624 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012625 wifi_setSAEMFP(ap_index, sae_MFP);
12626 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012627 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012628
developer9df4e652022-10-11 11:27:38 +080012629 if (security->mode != wifi_security_mode_none) {
12630 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12631 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12632 password[63] = '\0';
12633 wifi_setApSecurityKeyPassphrase(ap_index, password);
12634 }
12635 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12636 params.name = "sae_password";
12637 params.value = security->u.key.key;
12638 wifi_hostapdWrite(config_file, &params, 1);
12639 }
12640 }
developer587c1b62022-09-27 15:58:59 +080012641
12642 if (security->mode != wifi_security_mode_none) {
12643 memset(&params, 0, sizeof(params));
12644 params.name = "wpa_pairwise";
12645 if (security->encr == wifi_encryption_tkip)
12646 params.value = "TKIP";
12647 else if (security->encr == wifi_encryption_aes)
12648 params.value = "CCMP";
12649 else if (security->encr == wifi_encryption_aes_tkip)
12650 params.value = "TKIP CCMP";
12651 wifi_hostapdWrite(config_file, &params, 1);
12652 }
12653
12654 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012655 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012656 else if (security->mfp == wifi_mfp_cfg_optional)
12657 strcpy(mfp, "Optional");
12658 else if (security->mfp == wifi_mfp_cfg_required)
12659 strcpy(mfp, "Required");
12660 wifi_setApSecurityMFPConfig(ap_index, mfp);
12661
12662 memset(&params, 0, sizeof(params));
12663 params.name = "transition_disable";
12664 if (security->wpa3_transition_disable == TRUE)
12665 params.value = "0x01";
12666 else
12667 params.value = "0x00";
12668 wifi_hostapdWrite(config_file, &params, 1);
12669
12670 memset(&params, 0, sizeof(params));
12671 params.name = "wpa_group_rekey";
12672 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12673 params.value = buf;
12674 wifi_hostapdWrite(config_file, &params, 1);
12675
12676 memset(&params, 0, sizeof(params));
12677 params.name = "wpa_strict_rekey";
12678 params.value = security->strict_rekey?"1":"0";
12679 wifi_hostapdWrite(config_file, &params, 1);
12680
12681 memset(&params, 0, sizeof(params));
12682 params.name = "wpa_pairwise_update_count";
12683 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12684 params.value = buf;
12685 wifi_hostapdWrite(config_file, &params, 1);
12686
12687 memset(&params, 0, sizeof(params));
12688 params.name = "disable_pmksa_caching";
12689 params.value = security->disable_pmksa_caching?"1":"0";
12690 wifi_hostapdWrite(config_file, &params, 1);
12691
12692 wifi_setApEnable(ap_index, FALSE);
12693 wifi_setApEnable(ap_index, TRUE);
12694
12695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12696
developer06a01d92022-09-07 16:32:39 +080012697 return RETURN_OK;
12698}
12699
12700INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12701{
developer9df4e652022-10-11 11:27:38 +080012702 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012703 char config_file[128] = {0};
12704 int disable = 0;
12705 // struct params params = {0};
12706
12707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12708 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12709 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12710 security->mode = wifi_security_mode_none;
12711 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012712 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012713 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012714 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012715 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012716 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012717 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012718 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012719 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012720 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012721 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012722 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012723 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012724 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012725 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012726 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012727 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012728 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012729 security->mode = wifi_security_mode_wpa3_enterprise;
12730 }
12731
12732 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12733 if (security->mode == wifi_security_mode_none)
12734 security->encr = wifi_encryption_none;
12735 else {
12736 if (strcmp(buf, "TKIP") == 0)
12737 security->encr = wifi_encryption_tkip;
12738 else if (strcmp(buf, "CCMP") == 0)
12739 security->encr = wifi_encryption_aes;
12740 else
12741 security->encr = wifi_encryption_aes_tkip;
12742 }
12743
developer9df4e652022-10-11 11:27:38 +080012744 if (security->mode != wifi_encryption_none) {
12745 memset(buf, 0, sizeof(buf));
12746 // wpa3 can use one or both configs as password, so we check sae_password first.
12747 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12748 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12749 security->u.key.type = wifi_security_key_type_sae;
12750 } else {
12751 security->u.key.type = wifi_security_key_type_psk;
12752 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12753 }
12754 strncpy(security->u.key.key, buf, sizeof(buf));
12755 security->u.key.key[255] = '\0';
12756 }
12757
developer587c1b62022-09-27 15:58:59 +080012758 memset(buf, 0, sizeof(buf));
12759 wifi_getApSecurityMFPConfig(ap_index, buf);
12760 if (strcmp(buf, "Disabled") == 0)
12761 security->mfp = wifi_mfp_cfg_disabled;
12762 else if (strcmp(buf, "Optional") == 0)
12763 security->mfp = wifi_mfp_cfg_optional;
12764 else if (strcmp(buf, "Required") == 0)
12765 security->mfp = wifi_mfp_cfg_required;
12766
12767 memset(buf, 0, sizeof(buf));
12768 security->wpa3_transition_disable = FALSE;
12769 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12770 disable = strtol(buf, NULL, 16);
12771 if (disable != 0)
12772 security->wpa3_transition_disable = TRUE;
12773
12774 memset(buf, 0, sizeof(buf));
12775 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12776 if (strlen(buf) == 0)
12777 security->rekey_interval = 86400;
12778 else
12779 security->rekey_interval = strtol(buf, NULL, 10);
12780
12781 memset(buf, 0, sizeof(buf));
12782 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12783 if (strlen(buf) == 0)
12784 security->strict_rekey = 1;
12785 else
12786 security->strict_rekey = strtol(buf, NULL, 10);
12787
12788 memset(buf, 0, sizeof(buf));
12789 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12790 if (strlen(buf) == 0)
12791 security->eapol_key_retries = 4;
12792 else
12793 security->eapol_key_retries = strtol(buf, NULL, 10);
12794
12795 memset(buf, 0, sizeof(buf));
12796 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12797 if (strlen(buf) == 0)
12798 security->disable_pmksa_caching = FALSE;
12799 else
12800 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12801
12802 /* TODO
12803 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12804 */
12805 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12806 security->eap_identity_req_timeout = 0;
12807 security->eap_identity_req_retries = 0;
12808 security->eap_req_timeout = 0;
12809 security->eap_req_retries = 0;
12810 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012811 return RETURN_OK;
12812}
12813
12814#endif /* WIFI_HAL_VERSION_3 */
12815
12816#ifdef WIFI_HAL_VERSION_3_PHASE2
12817INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12818{
developer13df9332022-09-27 16:53:22 +080012819 char cmd[128] = {0};
12820 char buf[128] = {0};
12821 char *mac_addr = NULL;
12822 BOOL status = FALSE;
12823 size_t len = 0;
12824
12825 if(ap_index > MAX_APS)
12826 return RETURN_ERR;
12827
12828 *output_numDevices = 0;
12829 wifi_getApEnable(ap_index, &status);
12830 if (status == FALSE)
12831 return RETURN_OK;
12832
12833 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12834 _syscmd(cmd, buf, sizeof(buf));
12835
12836 mac_addr = strtok(buf, "\n");
12837 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12838 *output_numDevices = i + 1;
12839 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12840 addr_ptr = output_deviceMacAddressArray[i];
12841 mac_addr_aton(addr_ptr, mac_addr);
12842 mac_addr = strtok(NULL, "\n");
12843 }
12844
12845 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012846}
12847#else
12848INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12849{
12850 char cmd[128];
12851 BOOL status = false;
12852
12853 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12854 return RETURN_ERR;
12855
12856 output_buf[0] = '\0';
12857
12858 wifi_getApEnable(ap_index,&status);
12859 if (!status)
12860 return RETURN_OK;
12861
12862 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12863 _syscmd(cmd, output_buf, output_buf_size);
12864
12865 return RETURN_OK;
12866}
12867#endif
developer2f513ab2022-09-13 14:26:06 +080012868
12869INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12870{
12871 char output[16]={'\0'};
12872 char config_file[MAX_BUF_SIZE] = {0};
12873
12874 if (!enable)
12875 return RETURN_ERR;
12876
12877 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12878 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12879
12880 if (strlen(output) == 0)
12881 *enable = FALSE;
12882 else if (strncmp(output, "1", 1) == 0)
12883 *enable = TRUE;
12884 else
12885 *enable = FALSE;
12886
12887 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12888 return RETURN_OK;
12889}
developer2d9c30f2022-09-13 15:06:14 +080012890
12891INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12892{
developer804c64f2022-10-19 13:54:40 +080012893 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080012894 return RETURN_ERR;
12895 *output_enable=TRUE;
12896 return RETURN_OK;
12897}
developerfd7d2892022-09-13 16:44:53 +080012898
12899INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12900{
12901 char cmd[128] = {0};
12902 char buf[128] = {0};
12903 char line[128] = {0};
12904 size_t len = 0;
12905 ssize_t read = 0;
12906 FILE *f = NULL;
12907 int index = 0;
12908 int exp = 0;
12909 int mantissa = 0;
12910 int duration = 0;
12911 int radio_index = 0;
12912 int max_radio_num = 0;
12913 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080012914 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080012915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12916
12917 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080012918
developerfd7d2892022-09-13 16:44:53 +080012919 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080012920
12921 phyId = radio_index_to_phy(radio_index);
12922 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080012923 _syscmd(cmd, buf, sizeof(buf));
12924 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12925 if (*numSessionReturned > maxNumberSessions)
12926 *numSessionReturned = maxNumberSessions;
12927 else if (*numSessionReturned < 1) {
12928 *numSessionReturned = 0;
12929 return RETURN_OK;
12930 }
12931
developer033b37b2022-10-18 11:27:46 +080012932 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 +080012933 if ((f = popen(cmd, "r")) == NULL) {
12934 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12935 return RETURN_ERR;
12936 }
12937
12938 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12939 while((read = fgets(line, sizeof(line), f)) != NULL) {
12940 char *tmp = NULL;
12941 strcpy(buf, line);
12942 tmp = strtok(buf, " ");
12943 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12944 tmp = strtok(NULL, " ");
12945 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12946 tmp = strtok(NULL, " ");
12947 if (strstr(tmp, "t")) {
12948 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12949 }
12950 if (strstr(tmp, "a")) {
12951 twtSessions[index].twtParameters.operation.announced = TRUE;
12952 }
12953 tmp = strtok(NULL, " ");
12954 exp = strtol(tmp, NULL, 10);
12955 tmp = strtok(NULL, " ");
12956 mantissa = strtol(tmp, NULL, 10);
12957 tmp = strtok(NULL, " ");
12958 duration = strtol(tmp, NULL, 10);
12959
12960 // only implicit supported
12961 twtSessions[index].twtParameters.operation.implicit = TRUE;
12962 // only individual agreement supported
12963 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12964
12965 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12966 twt_wake_interval = mantissa * (1 << exp);
12967 if (twt_wake_interval/mantissa != (1 << exp)) {
12968 // Overflow handling
12969 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12970 } else {
12971 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12972 }
12973 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12974 index++;
12975 }
12976
12977 pclose(f);
12978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12979 return RETURN_OK;
12980}