blob: 2cbb0715e96cf32233965a6d7127e6d21ca77bd8 [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
developer7930d352022-12-21 17:55:42 +080066#define MAX_BUF_SIZE 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
developer06a01d92022-09-07 16:32:39 +080069#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080070#define ACL_PREFIX "/nvram/hostapd-acl"
71#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080072//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
73#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080074#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080075#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080076#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080077#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080078#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080079#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080080#define PSK_FILE "/nvram/hostapd"
developerf49437e2022-09-29 19:58:21 +080081#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080082#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080083
developer81bf2ed2022-09-13 15:31:14 +080084#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080085
86/*
87 MAX_APS - Number of all AP available in system
88 2x Home AP
89 2x Backhaul AP
90 2x Guest AP
91 2x Secure Onboard AP
92 2x Service AP
93
94*/
developer06a01d92022-09-07 16:32:39 +080095
developer033b37b2022-10-18 11:27:46 +080096
developera77d84b2023-02-22 16:10:50 +080097#define MAX_APS ((MAX_NUM_RADIOS)*(MAX_NUM_VAP_PER_RADIO))
developer06a01d92022-09-07 16:32:39 +080098#ifndef AP_PREFIX
99#define AP_PREFIX "wifi"
100#endif
101
102#ifndef RADIO_PREFIX
103#define RADIO_PREFIX "wlan"
104#endif
105
developer72ec5572023-01-05 16:27:13 +0800106#define MAX_ASSOCIATED_STA_NUM 63
developer06a01d92022-09-07 16:32:39 +0800107
108//Uncomment to enable debug logs
109//#define WIFI_DEBUG
110
111#ifdef WIFI_DEBUG
112#define wifi_dbg_printf printf
113#define WIFI_ENTRY_EXIT_DEBUG printf
114#else
115#define wifi_dbg_printf(format, args...) printf("")
116#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
117#endif
118
119#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
120#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
121#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
122#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
123#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
124#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
125#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
126#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
127#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
128#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
129
developer4fb0b922022-09-30 14:29:09 +0800130#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800131
132#define BW_FNAME "/nvram/bw_file.txt"
133
134#define PS_MAX_TID 16
135
136static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
137 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
138 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
139 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
141 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
142 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
143 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
144 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
153};
154
155typedef unsigned long long u64;
156
157/* Enum to define WiFi Bands */
158typedef enum
159{
160 band_invalid = -1,
161 band_2_4 = 0,
162 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800163 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800164} wifi_band;
165
developerdb744382022-09-13 15:34:54 +0800166typedef enum {
167 WIFI_MODE_A = 0x01,
168 WIFI_MODE_B = 0x02,
169 WIFI_MODE_G = 0x04,
170 WIFI_MODE_N = 0x08,
171 WIFI_MODE_AC = 0x10,
172 WIFI_MODE_AX = 0x20,
173} wifi_ieee80211_Mode;
174
developer06a01d92022-09-07 16:32:39 +0800175#ifdef WIFI_HAL_VERSION_3
176
177// Return number of elements in array
178#ifndef ARRAY_SIZE
179#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
180#endif /* ARRAY_SIZE */
181
182#ifndef ARRAY_AND_SIZE
183#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
184#endif /* ARRAY_AND_SIZE */
185
186#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
187
188typedef struct {
189 int32_t value;
190 int32_t param;
191 intptr_t key;
192 intptr_t data;
193} wifi_secur_list;
194
developerfa41b1f2023-01-06 10:25:51 +0800195static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
196static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800197static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800198wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
199wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
200char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800201static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800202
203static wifi_secur_list map_security[] =
204{
205 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
206 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
207 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
208 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800213 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800215 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800216 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800217};
218
219wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
220{
221 wifi_secur_list *item;
222 int i;
223
224 for (item = list,i = 0;i < list_sz; item++, i++) {
225 if ((int)(item->key) == key) {
226 return item;
227 }
228 }
229
230 return NULL;
231}
232
233char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
234{
235 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
236
237 if (!item) {
238 return "";
239 }
240
241 return (char *)(item->data);
242}
243
244wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
245{
246 wifi_secur_list *item;
247 int i;
248
249 for (item = list,i = 0;i < list_sz; item++, i++) {
250 if (strcmp((char *)(item->data), str) == 0) {
251 return item;
252 }
253 }
254
255 return NULL;
256}
257#endif /* WIFI_HAL_VERSION_3 */
258
259#ifdef HAL_NETLINK_IMPL
260typedef struct {
261 int id;
262 struct nl_sock* socket;
263 struct nl_cb* cb;
264} Netlink;
265
266static int mac_addr_aton(unsigned char *mac_addr, char *arg)
267{
268 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800269 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 +0800270 mac_addr[0] = mac_addr_int[0];
271 mac_addr[1] = mac_addr_int[1];
272 mac_addr[2] = mac_addr_int[2];
273 mac_addr[3] = mac_addr_int[3];
274 mac_addr[4] = mac_addr_int[4];
275 mac_addr[5] = mac_addr_int[5];
276 return 0;
277}
278
279static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
280{
281 unsigned int mac_addr_int[6]={};
282 mac_addr_int[0] = arg[0];
283 mac_addr_int[1] = arg[1];
284 mac_addr_int[2] = arg[2];
285 mac_addr_int[3] = arg[3];
286 mac_addr_int[4] = arg[4];
287 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800288 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 +0800289 return;
290}
291
292static int ieee80211_frequency_to_channel(int freq)
293{
developerf5745ee2022-10-05 16:09:53 +0800294 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800295 if (freq == 2484)
296 return 14;
developerf5745ee2022-10-05 16:09:53 +0800297 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
298 else if (freq == 5935)
299 return 2;
developer06a01d92022-09-07 16:32:39 +0800300 else if (freq < 2484)
301 return (freq - 2407) / 5;
302 else if (freq >= 4910 && freq <= 4980)
303 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800304 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800305 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800306 else if (freq <= 45000) /* DMG band lower limit */
307 /* see 802.11ax D6.1 27.3.23.2 */
308 return (freq - 5950) / 5;
309 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800310 return (freq - 56160) / 2160;
311 else
312 return 0;
313}
314
315static int initSock80211(Netlink* nl) {
316 nl->socket = nl_socket_alloc();
317 if (!nl->socket) {
318 fprintf(stderr, "Failing to allocate the sock\n");
319 return -ENOMEM;
320 }
321
322 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
323
324 if (genl_connect(nl->socket)) {
325 fprintf(stderr, "Failed to connect\n");
326 nl_close(nl->socket);
327 nl_socket_free(nl->socket);
328 return -ENOLINK;
329 }
330
331 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
332 if (nl->id< 0) {
333 fprintf(stderr, "interface not found.\n");
334 nl_close(nl->socket);
335 nl_socket_free(nl->socket);
336 return -ENOENT;
337 }
338
339 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
340 if ((!nl->cb)) {
341 fprintf(stderr, "Failed to allocate netlink callback.\n");
342 nl_close(nl->socket);
343 nl_socket_free(nl->socket);
344 return ENOMEM;
345 }
346
347 return nl->id;
348}
349
350static int nlfree(Netlink *nl)
351{
352 nl_cb_put(nl->cb);
353 nl_close(nl->socket);
354 nl_socket_free(nl->socket);
355 return 0;
356}
357
358static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
359 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
360 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
361 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
362};
363
364static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
365};
366
367static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
368};
369
370typedef struct _wifi_channelStats_loc {
371 INT array_size;
372 INT ch_number;
373 BOOL ch_in_pool;
374 INT ch_noise;
375 BOOL ch_radar_noise;
376 INT ch_max_80211_rssi;
377 INT ch_non_80211_noise;
378 INT ch_utilization;
379 ULLONG ch_utilization_total;
380 ULLONG ch_utilization_busy;
381 ULLONG ch_utilization_busy_tx;
382 ULLONG ch_utilization_busy_rx;
383 ULLONG ch_utilization_busy_self;
384 ULLONG ch_utilization_busy_ext;
385} wifi_channelStats_t_loc;
386
387typedef struct wifi_device_info {
388 INT wifi_devIndex;
389 UCHAR wifi_devMacAddress[6];
390 CHAR wifi_devIPAddress[64];
391 BOOL wifi_devAssociatedDeviceAuthentiationState;
392 INT wifi_devSignalStrength;
393 INT wifi_devTxRate;
394 INT wifi_devRxRate;
395} wifi_device_info_t;
396
397#endif
398
399//For 5g Alias Interfaces
400static BOOL priv_flag = TRUE;
401static BOOL pub_flag = TRUE;
402static BOOL Radio_flag = TRUE;
403//wifi_setApBeaconRate(1, beaconRate);
404
developer1e5aa162022-09-13 16:06:24 +0800405BOOL multiple_set = FALSE;
406
developer06a01d92022-09-07 16:32:39 +0800407struct params
408{
409 char * name;
410 char * value;
411};
412
413static int _syscmd(char *cmd, char *retBuf, int retBufSize)
414{
415 FILE *f;
416 char *ptr = retBuf;
417 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
418
419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
420 if((f = popen(cmd, "r")) == NULL) {
421 fprintf(stderr,"\npopen %s error\n", cmd);
422 return RETURN_ERR;
423 }
424
425 while(!feof(f))
426 {
427 *ptr = 0;
428 if(bufSize>=128) {
429 bufbytes=128;
430 } else {
431 bufbytes=bufSize-1;
432 }
433
434 fgets(ptr,bufbytes,f);
435 readbytes=strlen(ptr);
436
437 if(!readbytes)
438 break;
439
440 bufSize-=readbytes;
441 ptr += readbytes;
442 }
443 cmd_ret = pclose(f);
444 retBuf[retBufSize-1]=0;
445 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
446
447 return cmd_ret >> 8;
448}
449
developer033b37b2022-10-18 11:27:46 +0800450INT radio_index_to_phy(int radioIndex)
451{
452 char cmd[128] = {0};
453 char buf[64] = {0};
454 int phyIndex = 0;
455 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
456 _syscmd(cmd, buf, sizeof(buf));
457
458 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800459 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800460 return RETURN_ERR;
461 }
462 sscanf(buf, "phy%d", &phyIndex);
463
464 return phyIndex;
465}
developer026ac9e2022-11-07 13:46:24 +0800466
developer431128d2022-12-16 15:30:41 +0800467INT wifi_getMaxRadioNumber(INT *max_radio_num)
468{
469 char cmd[64] = {0};
470 char buf[4] = {0};
471
472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
473
474 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
475 _syscmd(cmd, buf, sizeof(buf));
476 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
477
478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
479
480 return RETURN_OK;
481}
482
developer59ff6de2023-02-08 17:58:14 +0800483static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
484{
485 char cmd[MAX_CMD_SIZE]={'\0'};
486 char buf[MAX_BUF_SIZE]={'\0'};
487 int ret = 0;
488
489 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
490 ret = _syscmd(cmd, buf, sizeof(buf));
491 if ((ret != 0) && (strlen(buf) == 0))
492 return -1;
493 snprintf(output, output_size, "%s", buf);
494
495 return 0;
496}
497
498static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
499{
500 char cmd[MAX_CMD_SIZE]={'\0'};
501 char buf[MAX_BUF_SIZE]={'\0'};
502
503 for(int i=0;i<item_count;i++)
504 {
505 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
506 if (strlen(buf) == 0) //Insert
507 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
508 else //Update
509 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
510
511 if(_syscmd(cmd, buf, sizeof(buf)))
512 return -1;
513 }
514
515 return 0;
516}
517
developer431128d2022-12-16 15:30:41 +0800518wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800519{
520 char cmd[128] = {0};
521 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800522 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800523 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800524 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800525 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800526 int radioIndex = 0;
527 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800528 wifi_band band = band_invalid;
529
530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800531
developer431128d2022-12-16 15:30:41 +0800532 wifi_getMaxRadioNumber(&max_radio_num);
533 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800534 phyIndex = radio_index_to_phy(radioIndex);
developer59ff6de2023-02-08 17:58:14 +0800535 snprintf(cmd, sizeof(cmd), "cat /sys/class/ieee80211/phy%d/device/device 2> /dev/null", phyIndex);
536 _syscmd(cmd, buf, sizeof(buf));
537 if (strncmp(buf, "0x7915", 6) == 0) { // harrier have two bands, consider as a special case.
538 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
539 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
540 if (strncmp(buf, "a", 1) == 0)
541 return band_5;
542 else
543 return band_2_4;
544 }
developer5884e982022-10-06 10:52:50 +0800545 while(i < 10){
developer59ff6de2023-02-08 17:58:14 +0800546 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800547 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800548 nl80211_band = strtol(buf, NULL, 10);
549 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800550 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800551 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800552 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800553 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800554 band = band_6;
555
556 if(band != band_invalid)
557 break;
558
559 i++;
560 sleep(1);
561 }
developerc707e972022-09-13 15:38:02 +0800562
563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
564 return band;
565}
566
developerd946fd62022-12-08 18:03:28 +0800567//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800568static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800569{
570 char config_file[128] = {0};
571
572 if (interface_name == NULL)
573 return RETURN_ERR;
574
575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
576
577 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
578 wifi_hostapdRead(config_file, "interface", interface_name, 16);
579 if (strlen(interface_name) == 0)
580 return RETURN_ERR;
581
582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
583 return RETURN_OK;
584}
585
developerac6f1142022-12-20 19:26:35 +0800586// wifi agent will call this function, do not change the parameter
587void GetInterfaceName(char *interface_name, char *conf_file)
588{
589 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
590 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
592}
593
developer06a01d92022-09-07 16:32:39 +0800594static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
595{
developerd946fd62022-12-08 18:03:28 +0800596 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800597 if (multiple_set == TRUE)
598 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800599 char cmd[MAX_CMD_SIZE]="", output[32]="";
600 FILE *fp;
601 int i;
602 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800603 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800604 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800605 for(i=0; i<item_count; i++, list++)
606 {
developerd946fd62022-12-08 18:03:28 +0800607 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800608 if((fp = popen(cmd, "r"))==NULL)
609 {
610 perror("popen failed");
611 return -1;
612 }
613 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
614 {
615 pclose(fp);
616 perror("fgets failed");
617 return -1;
618 }
619 pclose(fp);
620 }
621 return 0;
622}
623
624static int wifi_reloadAp(int apIndex)
625{
developerd946fd62022-12-08 18:03:28 +0800626 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800627 if (multiple_set == TRUE)
628 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800629 char cmd[MAX_CMD_SIZE]="";
630 char buf[MAX_BUF_SIZE]="";
631
developerac6f1142022-12-20 19:26:35 +0800632 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800633 return RETURN_ERR;
634 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800635 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
636 return RETURN_ERR;
637
developerd946fd62022-12-08 18:03:28 +0800638 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800639 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
640 return RETURN_ERR;
641
developerd946fd62022-12-08 18:03:28 +0800642 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800643 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
644 return RETURN_ERR;
645
646 return RETURN_OK;
647}
648
developer06a01d92022-09-07 16:32:39 +0800649INT File_Reading(CHAR *file, char *Value)
650{
651 FILE *fp = NULL;
652 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
653 int count = 0;
654
655 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
656 fp = popen(file,"r");
657 if(fp == NULL)
658 return RETURN_ERR;
659
660 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
661 {
662 for(count=0;buf[count]!='\n';count++)
663 copy_buf[count]=buf[count];
664 copy_buf[count]='\0';
665 }
666 strcpy(Value,copy_buf);
667 pclose(fp);
668 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
669
670 return RETURN_OK;
671}
672
673void wifi_RestartHostapd_2G()
674{
675 int Public2GApIndex = 4;
676
677 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
678 wifi_setApEnable(Public2GApIndex, FALSE);
679 wifi_setApEnable(Public2GApIndex, TRUE);
680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
681}
682
683void wifi_RestartHostapd_5G()
684{
685 int Public5GApIndex = 5;
686
687 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
688 wifi_setApEnable(Public5GApIndex, FALSE);
689 wifi_setApEnable(Public5GApIndex, TRUE);
690 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
691}
692
693void wifi_RestartPrivateWifi_2G()
694{
695 int PrivateApIndex = 0;
696
697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
698 wifi_setApEnable(PrivateApIndex, FALSE);
699 wifi_setApEnable(PrivateApIndex, TRUE);
700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
701}
702
703void wifi_RestartPrivateWifi_5G()
704{
705 int Private5GApIndex = 1;
706
707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
708 wifi_setApEnable(Private5GApIndex, FALSE);
709 wifi_setApEnable(Private5GApIndex, TRUE);
710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
711}
712
713static int writeBandWidth(int radioIndex,char *bw_value)
714{
715 char buf[MAX_BUF_SIZE];
716 char cmd[MAX_CMD_SIZE];
717
718 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
719 if(_syscmd(cmd, buf, sizeof(buf)))
720 {
721 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
722 _syscmd(cmd, buf, sizeof(buf));
723 return RETURN_OK;
724 }
725
726 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
727 _syscmd(cmd,buf,sizeof(buf));
728 return RETURN_OK;
729}
730
731static int readBandWidth(int radioIndex,char *bw_value)
732{
developer30423732022-12-01 16:17:49 +0800733 char buf[MAX_BUF_SIZE] = {0};
734 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800735 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
736 _syscmd(cmd,buf,sizeof(buf));
737 if(NULL!=strstr(buf,"20MHz"))
738 {
739 strcpy(bw_value,"20MHz");
740 }
741 else if(NULL!=strstr(buf,"40MHz"))
742 {
743 strcpy(bw_value,"40MHz");
744 }
745 else if(NULL!=strstr(buf,"80MHz"))
746 {
747 strcpy(bw_value,"80MHz");
748 }
749 else
750 {
751 return RETURN_ERR;
752 }
753 return RETURN_OK;
754}
755
developer264159b2022-11-02 09:41:35 +0800756// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800757INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
758{
developer5f222492022-09-13 15:21:52 +0800759 struct params params={'\0'};
760 char config_file[MAX_BUF_SIZE] = {0};
761 char buf[MAX_BUF_SIZE] = {'\0'};
762
763 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800764 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800765 if (strlen (beaconRate) >= 5) {
766 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
767 buf[strlen(beaconRate) - 4] = '\0';
768 } else if (strlen(beaconRate) > 0)
769 strcpy(buf, beaconRate);
770 else
771 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800772
773 params.name = "beacon_rate";
774 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
775 if (strncmp(buf, "5.5", 3) == 0) {
776 snprintf(buf, sizeof(buf), "55");
777 params.value = buf;
778 } else {
779 strcat(buf, "0");
780 params.value = buf;
781 }
782
783 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
784 wifi_hostapdWrite(config_file, &params, 1);
785 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
787
788 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800789}
790
791INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
792{
developer1d57d002022-10-12 18:03:15 +0800793 char config_file[128] = {'\0'};
794 char temp_output[128] = {'\0'};
795 char buf[128] = {'\0'};
796 char cmd[128] = {'\0'};
797 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800798 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800799
800 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
801 if (NULL == beaconRate)
802 return RETURN_ERR;
803
804 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
805 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800806 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800807 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
808 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800809 if (strncmp(buf, "55", 2) == 0)
810 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
811 else {
812 rate = strtol(buf, NULL, 10)/10;
813 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
814 }
developer5f222492022-09-13 15:21:52 +0800815 } else {
developer1d57d002022-10-12 18:03:15 +0800816 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800817 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 +0800818 _syscmd(cmd, buf, sizeof(buf));
819 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800820 }
821 strncpy(beaconRate, temp_output, sizeof(temp_output));
822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
823
824 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800825}
826
827INT wifi_setLED(INT radioIndex, BOOL enable)
828{
829 return 0;
830}
831INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
832{
833 return RETURN_OK;
834}
835/**********************************************************************************
836 *
837 * Wifi Subsystem level function prototypes
838 *
839**********************************************************************************/
840//---------------------------------------------------------------------------------------------------
841//Wifi system api
842//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
843INT wifi_getHalVersion(CHAR *output_string) //RDKB
844{
845 if(!output_string)
846 return RETURN_ERR;
847 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
848
849 return RETURN_OK;
850}
851
852
853/* wifi_factoryReset() function */
854/**
855* @description Clears internal variables to implement a factory reset of the Wi-Fi
856* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
857*
858* @param None
859*
860* @return The status of the operation.
861* @retval RETURN_OK if successful.
862* @retval RETURN_ERR if any error is detected
863*
864* @execution Synchronous
865* @sideeffect None
866*
867* @note This function must not suspend and must not invoke any blocking system
868* calls. It should probably just send a message to a driver event handler task.
869*
870*/
871INT wifi_factoryReset()
872{
873 char cmd[128];
874
875 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800876 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
877 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800878 system(cmd);
879 system("systemctl restart hostapd.service");
880
881 return RETURN_OK;
882}
883
884/* wifi_factoryResetRadios() function */
885/**
886* @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.
887*
888* @param None
889* @return The status of the operation
890* @retval RETURN_OK if successful
891* @retval RETURN_ERR if any error is detected
892*
893* @execution Synchronous
894*
895* @sideeffect None
896*
897* @note This function must not suspend and must not invoke any blocking system
898* calls. It should probably just send a message to a driver event handler task.
899*
900*/
901INT wifi_factoryResetRadios()
902{
developer72ec5572023-01-05 16:27:13 +0800903 int max_radio_num = 0;
904 wifi_getMaxRadioNumber(&max_radio_num);
905 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
906 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800907
developer72ec5572023-01-05 16:27:13 +0800908 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800909}
910
911
912/* wifi_factoryResetRadio() function */
913/**
914* @description Restore selected radio parameters without touching access point parameters
915*
916* @param radioIndex - Index of Wi-Fi Radio channel
917*
918* @return The status of the operation.
919* @retval RETURN_OK if successful.
920* @retval RETURN_ERR if any error is detected
921*
922* @execution Synchronous.
923* @sideeffect None.
924*
925* @note This function must not suspend and must not invoke any blocking system
926* calls. It should probably just send a message to a driver event handler task.
927*
928*/
929INT wifi_factoryResetRadio(int radioIndex) //RDKB
930{
developer72ec5572023-01-05 16:27:13 +0800931 char cmd[128] = {0};
932 char buf[128] = {0};
933 int max_radio_num = 0;
934
935 wifi_getMaxRadioNumber(&max_radio_num);
936 if (radioIndex < 0 || radioIndex > max_radio_num)
937 return RETURN_ERR;
938
939 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
940 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800941
developer06a01d92022-09-07 16:32:39 +0800942 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800943 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
944 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800945
developer72ec5572023-01-05 16:27:13 +0800946 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
947 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800948 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
949 return RETURN_OK;
950}
951
952/* wifi_initRadio() function */
953/**
954* Description: This function call initializes the specified radio.
955* Implementation specifics may dictate the functionality since
956* different hardware implementations may have different initilization requirements.
957* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
958*
959* @return The status of the operation.
960* @retval RETURN_OK if successful.
961* @retval RETURN_ERR if any error is detected
962*
963* @execution Synchronous.
964* @sideeffect None.
965*
966* @note This function must not suspend and must not invoke any blocking system
967* calls. It should probably just send a message to a driver event handler task.
968*
969*/
970INT wifi_initRadio(INT radioIndex)
971{
972 //TODO: Initializes the wifi subsystem (for specified radio)
973 return RETURN_OK;
974}
975void macfilter_init()
976{
977 char count[4]={'\0'};
978 char buf[253]={'\0'};
979 char tmp[19]={'\0'};
980 int dev_count,block,mac_entry=0;
981 char res[4]={'\0'};
982 char acl_file_path[64] = {'\0'};
983 FILE *fp = NULL;
984 int index=0;
985 char iface[10]={'\0'};
986 char config_file[MAX_BUF_SIZE] = {0};
987
988
989 sprintf(acl_file_path,"/tmp/mac_filter.sh");
990
991 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800992 if (fp == NULL) {
993 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
994 return RETURN_ERR;
995 }
developer06a01d92022-09-07 16:32:39 +0800996 sprintf(buf,"#!/bin/sh \n");
997 fprintf(fp,"%s\n",buf);
998
999 system("chmod 0777 /tmp/mac_filter.sh");
1000
1001 for(index=0;index<=1;index++)
1002 {
1003 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1004 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1005 sprintf(buf,"syscfg get %dcountfilter",index);
1006 _syscmd(buf,count,sizeof(count));
1007 mac_entry=atoi(count);
1008
1009 sprintf(buf,"syscfg get %dblockall",index);
1010 _syscmd(buf,res,sizeof(res));
1011 block = atoi(res);
1012
1013 //Allow only those macs mentioned in ACL
1014 if(block==1)
1015 {
1016 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1017 fprintf(fp,"%s\n",buf);
1018 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1019 {
1020 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1021 _syscmd(buf,tmp,sizeof(tmp));
1022 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1023 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1024 fprintf(fp,"%s\n",buf);
1025 }
1026 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1027 fprintf(fp,"%s\n",buf);
1028 }
1029
1030 //Block all the macs mentioned in ACL
1031 else if(block==2)
1032 {
1033 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1034 fprintf(fp,"%s\n",buf);
1035
1036 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1037 {
1038 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1039 _syscmd(buf,tmp,sizeof(tmp));
1040 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1041 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1042 fprintf(fp,"%s\n",buf);
1043 }
1044 }
1045 }
1046 fclose(fp);
1047}
1048
1049// Initializes the wifi subsystem (all radios)
1050INT wifi_init() //RDKB
1051{
1052 char interface[MAX_BUF_SIZE]={'\0'};
1053 char bridge_name[MAX_BUF_SIZE]={'\0'};
1054 INT len=0;
1055
1056 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1057 //Not intitializing macfilter for Turris-Omnia Platform for now
1058 //macfilter_init();
1059
1060 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001061 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001062 sleep(2);//sleep to wait for hostapd to start
1063
1064 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1065
1066 return RETURN_OK;
1067}
1068
1069/* wifi_reset() function */
1070/**
1071* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1072* Implementation specifics may dictate what is actualy reset since
1073* different hardware implementations may have different requirements.
1074* Parameters : None
1075*
1076* @return The status of the operation.
1077* @retval RETURN_OK if successful.
1078* @retval RETURN_ERR if any error is detected
1079*
1080* @execution Synchronous.
1081* @sideeffect None.
1082*
1083* @note This function must not suspend and must not invoke any blocking system
1084* calls. It should probably just send a message to a driver event handler task.
1085*
1086*/
1087INT wifi_reset()
1088{
1089 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001090 system("systemctl stop hostapd.service");
1091 sleep(2);
1092 system("systemctl start hostapd.service");
1093 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001094 return RETURN_OK;
1095}
1096
1097/* wifi_down() function */
1098/**
1099* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1100* Implementation specifics may dictate some functionality since
1101* different hardware implementations may have different requirements.
1102*
1103* @param None
1104*
1105* @return The status of the operation
1106* @retval RETURN_OK if successful
1107* @retval RETURN_ERR if any error is detected
1108*
1109* @execution Synchronous
1110* @sideeffect None
1111*
1112* @note This function must not suspend and must not invoke any blocking system
1113* calls. It should probably just send a message to a driver event handler task.
1114*
1115*/
1116INT wifi_down()
1117{
1118 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001119 int max_num_radios = 0;
1120 wifi_getMaxRadioNumber(&max_num_radios);
1121 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1122 wifi_setRadioEnable(radioIndex, FALSE);
1123
developer06a01d92022-09-07 16:32:39 +08001124 return RETURN_OK;
1125}
1126
1127
1128/* wifi_createInitialConfigFiles() function */
1129/**
1130* @description This function creates wifi configuration files. The format
1131* and content of these files are implementation dependent. This function call is
1132* used to trigger this task if necessary. Some implementations may not need this
1133* function. If an implementation does not need to create config files the function call can
1134* do nothing and return RETURN_OK.
1135*
1136* @param None
1137*
1138* @return The status of the operation
1139* @retval RETURN_OK if successful
1140* @retval RETURN_ERR if any error is detected
1141*
1142* @execution Synchronous
1143* @sideeffect None
1144*
1145* @note This function must not suspend and must not invoke any blocking system
1146* calls. It should probably just send a message to a driver event handler task.
1147*
1148*/
1149INT wifi_createInitialConfigFiles()
1150{
1151 //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)
1152 return RETURN_OK;
1153}
1154
1155// outputs the country code to a max 64 character string
1156INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1157{
developerd946fd62022-12-08 18:03:28 +08001158 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001159 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001160 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001161 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001162
developerac6f1142022-12-20 19:26:35 +08001163 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001164 return RETURN_ERR;
1165 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001166 _syscmd(cmd, buf, sizeof(buf));
1167 if(strlen(buf) > 0)
1168 snprintf(output_string, 64, "%s", buf);
1169 else
1170 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001171
1172 return RETURN_OK;
1173}
1174
1175INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1176{
1177 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001178 char str[MAX_BUF_SIZE]={'\0'};
1179 char cmd[MAX_CMD_SIZE]={'\0'};
1180 struct params params;
1181 char config_file[MAX_BUF_SIZE] = {0};
1182
1183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1184 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1185 return RETURN_ERR;
1186
developerb86c6f32022-10-07 14:34:58 +08001187 if (strlen(CountryCode) == 0)
1188 strcpy(CountryCode, "US");
1189
developer7543b3b2022-09-13 13:47:17 +08001190 params.name = "country_code";
1191 params.value = CountryCode;
1192 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1193 int ret = wifi_hostapdWrite(config_file, &params, 1);
1194 if (ret) {
1195 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1196 ,__func__, ret);
1197 }
1198
1199 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1200 if (ret) {
1201 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1202 ,__func__, ret);
1203 }
developer7543b3b2022-09-13 13:47:17 +08001204 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1205
developer06a01d92022-09-07 16:32:39 +08001206 return RETURN_OK;
1207}
1208
developera748dcf2022-09-13 15:56:48 +08001209INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1210{
developerd946fd62022-12-08 18:03:28 +08001211 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001212 char channel_util_file[64] = {0};
1213 char cmd[128] = {0};
1214 char buf[128] = {0};
1215 char line[128] = {0};
1216 char *param = NULL, *value = NULL;
1217 int read = 0;
1218 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1219 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1220 size_t len = 0;
1221 FILE *f = NULL;
1222
1223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1224
developerac6f1142022-12-20 19:26:35 +08001225 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001226 return RETURN_ERR;
1227 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001228 _syscmd(cmd, buf, sizeof(buf));
1229 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1230
1231 memset(cmd, 0, sizeof(cmd));
1232 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001233 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001234 if ((f = popen(cmd, "r")) == NULL) {
1235 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1236 return RETURN_ERR;
1237 }
1238
1239 read = getline(&line, &len, f);
1240 while (read != -1) {
1241 param = strtok(line, ":\t");
1242 value = strtok(NULL, " ");
1243 if(strstr(param, "frequency") != NULL) {
1244 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1245 }
1246 if(strstr(param, "noise") != NULL) {
1247 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1248 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1249 }
1250 if(strstr(param, "channel active time") != NULL) {
1251 ActiveTime = strtol(value, NULL, 10);
1252 }
1253 if(strstr(param, "channel busy time") != NULL) {
1254 BusyTime = strtol(value, NULL, 10);
1255 }
1256 if(strstr(param, "channel transmit time") != NULL) {
1257 TransmitTime = strtol(value, NULL, 10);
1258 }
1259 read = getline(&line, &len, f);
1260 }
1261 pclose(f);
1262
1263 // The file should store the last active, busy and transmit time
1264 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1265 f = fopen(channel_util_file, "r");
1266 if (f != NULL) {
1267 read = getline(&line, &len, f);
1268 preActiveTime = strtol(line, NULL, 10);
1269 read = getline(&line, &len, f);
1270 preBusyTime = strtol(line, NULL, 10);
1271 read = getline(&line, &len, f);
1272 preTransmitTime = strtol(line, NULL, 10);
1273 fclose(f);
1274 }
1275
1276 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1277 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1278
1279 f = fopen(channel_util_file, "w");
1280 if (f != NULL) {
1281 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1282 fclose(f);
1283 }
1284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1285 return RETURN_OK;
1286}
1287
developer06a01d92022-09-07 16:32:39 +08001288/**********************************************************************************
1289 *
1290 * Wifi radio level function prototypes
1291 *
1292**********************************************************************************/
1293
1294//Get the total number of radios in this wifi subsystem
1295INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1296{
1297 if (NULL == output)
1298 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001299 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001300
1301 return RETURN_OK;
1302}
1303
1304//Get the total number of SSID entries in this wifi subsystem
1305INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1306{
1307 if (NULL == output)
1308 return RETURN_ERR;
1309 *output = MAX_APS;
1310
1311 return RETURN_OK;
1312}
1313
1314//Get the Radio enable config parameter
1315INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1316{
developerd946fd62022-12-08 18:03:28 +08001317 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001318 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001319 int apIndex;
1320 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001321
1322 if (NULL == output_bool)
1323 return RETURN_ERR;
1324
1325 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001326
1327 wifi_getMaxRadioNumber(&max_radio_num);
1328
1329 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001330 return RETURN_ERR;
1331
developera77d84b2023-02-22 16:10:50 +08001332 /* loop all interface in radio, if any is enable, reture true, else return false */
1333 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1334 {
1335 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1336 continue;
1337 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1338 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001339
developera77d84b2023-02-22 16:10:50 +08001340 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1341 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1342 /* return true if any interface is eanble */
1343 *output_bool = TRUE;
1344 break;
1345 }
1346 }
developer06a01d92022-09-07 16:32:39 +08001347 return RETURN_OK;
1348}
1349
1350INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1351{
developerd946fd62022-12-08 18:03:28 +08001352 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001353 char cmd[MAX_CMD_SIZE] = {0};
1354 char buf[MAX_CMD_SIZE] = {0};
1355 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001356 int max_radio_num = 0;
1357 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001358
1359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001360
1361 phyId = radio_index_to_phy(radioIndex);
1362
1363 wifi_getMaxRadioNumber(&max_radio_num);
1364
developer06a01d92022-09-07 16:32:39 +08001365 if(enable==FALSE)
1366 {
developera77d84b2023-02-22 16:10:50 +08001367 /* disable from max apindex to min, to avoid fail in mbss case */
1368 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001369 {
developer1e125222022-12-29 09:35:25 +08001370 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001371 continue;
developer1e125222022-12-29 09:35:25 +08001372
developer06a01d92022-09-07 16:32:39 +08001373 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001374 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001375 _syscmd(cmd, buf, sizeof(buf));
1376 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001377 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001378
developerd946fd62022-12-08 18:03:28 +08001379 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08001380 _syscmd(cmd, buf, sizeof(buf));
1381 }
developer06a01d92022-09-07 16:32:39 +08001382 }
1383 else
1384 {
developer033b37b2022-10-18 11:27:46 +08001385 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001386 {
developer1e125222022-12-29 09:35:25 +08001387 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001388 continue;
developer1e125222022-12-29 09:35:25 +08001389
developerd946fd62022-12-08 18:03:28 +08001390 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001391 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001392 if(*buf == '1') {
1393 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1394 ret = _syscmd(cmd, buf, sizeof(buf));
1395 if ( ret == RETURN_ERR) {
1396 fprintf(stderr, "VAP interface creation failed\n");
1397 continue;
1398 }
1399
developer06a01d92022-09-07 16:32:39 +08001400 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001401 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001402 _syscmd(cmd, buf, sizeof(buf));
1403 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001404 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001405 }
1406 }
1407 }
1408
1409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1410 return RETURN_OK;
1411}
1412
1413//Get the Radio enable status
1414INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1415{
1416 if (NULL == output_bool)
1417 return RETURN_ERR;
1418
1419 return wifi_getRadioEnable(radioIndex, output_bool);
1420}
1421
1422//Get the Radio Interface name from platform, eg "wlan0"
1423INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1424{
developer804c64f2022-10-19 13:54:40 +08001425 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001426 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001427 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001428}
1429
1430//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1431//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.
1432INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1433{
developerbcc556a2022-09-22 20:02:45 +08001434 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1435 // For max bit rate, we should always choose the best MCS
1436 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001437 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001438 char *tmp = NULL;
1439 UINT mode_map = 0;
1440 UINT num_subcarrier = 0;
1441 UINT code_bits = 0;
1442 float code_rate = 0; // use max code rate
1443 int NSS = 0;
1444 UINT Symbol_duration = 0;
1445 UINT GI_duration = 0;
1446 wifi_band band = band_invalid;
1447 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1448 BOOL enable = FALSE;
1449 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001450
1451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1452 if (NULL == output_string)
1453 return RETURN_ERR;
1454
developerbcc556a2022-09-22 20:02:45 +08001455 wifi_getRadioEnable(radioIndex, &enable);
1456 if (enable == FALSE) {
1457 snprintf(output_string, 64, "0 Mb/s");
1458 return RETURN_OK;
1459 }
1460
1461 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1462 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1463 return RETURN_ERR;
1464 }
1465
1466 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1467 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1468 return RETURN_ERR;
1469 }
1470
1471 if (gi == wifi_guard_interval_3200)
1472 GI_duration = 32;
1473 else if (gi == wifi_guard_interval_1600)
1474 GI_duration = 16;
1475 else if (gi == wifi_guard_interval_800)
1476 GI_duration = 8;
1477 else // auto, 400
1478 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001479
developerbcc556a2022-09-22 20:02:45 +08001480 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1481 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1482 return RETURN_ERR;
1483 }
1484
1485 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1486 strcpy(channel_bandwidth_str, "160");
1487
1488 if (mode_map & WIFI_MODE_AX) {
1489 if (strstr(channel_bandwidth_str, "160") != NULL)
1490 num_subcarrier = 1960;
1491 else if (strstr(channel_bandwidth_str, "80") != NULL)
1492 num_subcarrier = 980;
1493 else if (strstr(channel_bandwidth_str, "40") != NULL)
1494 num_subcarrier = 468;
1495 else if (strstr(channel_bandwidth_str, "20") != NULL)
1496 num_subcarrier = 234;
1497 code_bits = 10;
1498 code_rate = (float)5/6;
1499 Symbol_duration = 128;
1500 } else if (mode_map & WIFI_MODE_AC) {
1501 if (strstr(channel_bandwidth_str, "160") != NULL)
1502 num_subcarrier = 468;
1503 else if (strstr(channel_bandwidth_str, "80") != NULL)
1504 num_subcarrier = 234;
1505 else if (strstr(channel_bandwidth_str, "40") != NULL)
1506 num_subcarrier = 108;
1507 else if (strstr(channel_bandwidth_str, "20") != NULL)
1508 num_subcarrier = 52;
1509 code_bits = 8;
1510 code_rate = (float)5/6;
1511 Symbol_duration = 32;
1512 } else if (mode_map & WIFI_MODE_N) {
1513 if (strstr(channel_bandwidth_str, "160") != NULL)
1514 num_subcarrier = 468;
1515 else if (strstr(channel_bandwidth_str, "80") != NULL)
1516 num_subcarrier = 234;
1517 else if (strstr(channel_bandwidth_str, "40") != NULL)
1518 num_subcarrier = 108;
1519 else if (strstr(channel_bandwidth_str, "20") != NULL)
1520 num_subcarrier = 52;
1521 code_bits = 6;
1522 code_rate = (float)3/4;
1523 Symbol_duration = 32;
1524 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1525 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1526 snprintf(output_string, 64, "65 Mb/s");
1527 return RETURN_OK;
1528 } else {
1529 snprintf(output_string, 64, "0 Mb/s");
1530 return RETURN_OK;
1531 }
developer06a01d92022-09-07 16:32:39 +08001532
developerbcc556a2022-09-22 20:02:45 +08001533 // Spatial streams
1534 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1535 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1536 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001537 }
developerbcc556a2022-09-22 20:02:45 +08001538
1539 // multiple 10 is to align duration unit (0.1 us)
1540 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1541 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1542
developer06a01d92022-09-07 16:32:39 +08001543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1544
1545 return RETURN_OK;
1546}
1547#if 0
1548INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1549{
1550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1551 char cmd[64];
1552 char buf[1024];
1553 int apIndex;
1554
1555 if (NULL == output_string)
1556 return RETURN_ERR;
1557
1558 apIndex=(radioIndex==0)?0:1;
1559
developerd946fd62022-12-08 18:03:28 +08001560 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001561 _syscmd(cmd,buf, sizeof(buf));
1562
1563 snprintf(output_string, 64, "%s", buf);
1564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1565 return RETURN_OK;
1566}
1567#endif
1568
1569
1570//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1571//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.
1572INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1573{
developer963da0c2022-09-13 15:58:27 +08001574 wifi_band band = band_invalid;
1575
developer06a01d92022-09-07 16:32:39 +08001576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1577 if (NULL == output_string)
1578 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001579
1580 band = wifi_index_to_band(radioIndex);
1581
1582 memset(output_string, 0, 10);
1583 if (band == band_2_4)
1584 strcpy(output_string, "2.4GHz");
1585 else if (band == band_5)
1586 strcpy(output_string, "5GHz");
1587 else if (band == band_6)
1588 strcpy(output_string, "6GHz");
1589 else
1590 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1592
1593 return RETURN_OK;
1594#if 0
1595 char buf[MAX_BUF_SIZE]={'\0'};
1596 char str[MAX_BUF_SIZE]={'\0'};
1597 char cmd[MAX_CMD_SIZE]={'\0'};
1598 char *ch=NULL;
1599 char *ch2=NULL;
1600
1601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1602 if (NULL == output_string)
1603 return RETURN_ERR;
1604
1605
1606 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1607
1608 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1609 {
1610 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1611 return RETURN_ERR;
1612 }
1613 ch=strchr(buf,'\n');
1614 *ch='\0';
1615 ch=strchr(buf,'=');
1616 if(ch==NULL)
1617 return RETURN_ERR;
1618
1619
1620 ch++;
1621
1622 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1623 strcpy(buf,"0");
1624 if(strlen(ch) == 1)
1625 ch=strcat(buf,ch);
1626
1627
1628 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1629
1630 if(_syscmd(cmd,str,64) == RETURN_ERR)
1631 {
1632 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1633 return RETURN_ERR;
1634 }
1635
1636
1637 ch2=strchr(str,'\n');
1638 //replace \n with \0
1639 *ch2='\0';
1640 ch2=strchr(str,'=');
1641 if(ch2==NULL)
1642 {
1643 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1644 return RETURN_ERR;
1645 }
1646 else
1647 wifi_dbg_printf("%s",ch2+1);
1648
1649
1650 ch2++;
1651
1652
1653 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1654
1655 memset(buf,'\0',sizeof(buf));
1656 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1657 {
1658 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1659 return RETURN_ERR;
1660 }
1661 if (strstr(buf,"2.4") != NULL )
1662 strcpy(output_string,"2.4GHz");
1663 else if(strstr(buf,"5.") != NULL )
1664 strcpy(output_string,"5GHz");
1665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1666
1667 return RETURN_OK;
1668#endif
1669}
1670
1671//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1672//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.
1673INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1674{
developerb7593de2022-10-18 09:51:57 +08001675 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1677 if (NULL == output_string)
1678 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001679 band = wifi_index_to_band(radioIndex);
1680
1681 if (band == band_2_4)
1682 snprintf(output_string, 64, "2.4GHz");
1683 else if (band == band_5)
1684 snprintf(output_string, 64, "5GHz");
1685 else if (band == band_6)
1686 snprintf(output_string, 64, "6GHz");
1687
developer06a01d92022-09-07 16:32:39 +08001688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1689
1690 return RETURN_OK;
1691#if 0
1692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1693 char buf[MAX_BUF_SIZE]={'\0'};
1694 char str[MAX_BUF_SIZE]={'\0'};
1695 char cmd[MAX_CMD_SIZE]={'\0'};
1696 char *ch=NULL;
1697 char *ch2=NULL;
1698 char ch1[5]="0";
1699
1700 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1701
1702 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1703 {
1704 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1705 return RETURN_ERR;
1706 }
1707
1708 ch=strchr(buf,'\n');
1709 *ch='\0';
1710 ch=strchr(buf,'=');
1711 if(ch==NULL)
1712 return RETURN_ERR;
1713 ch++;
1714
1715 if(strlen(ch)==1)
1716 {
1717 strcat(ch1,ch);
1718
1719 }
1720 else
1721 {
1722 strcpy(ch1,ch);
1723 }
1724
1725
1726
1727 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1728 if(_syscmd(cmd,str,64) == RETURN_ERR)
1729 {
1730 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1731 return RETURN_ERR;
1732 }
1733
1734
1735 ch2=strchr(str,'\n');
1736 //replace \n with \0
1737 *ch2='\0';
1738 ch2=strchr(str,'=');
1739 if(ch2==NULL)
1740 {
1741 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1742 return RETURN_ERR;
1743 }
1744 else
1745 wifi_dbg_printf("%s",ch2+1);
1746 ch2++;
1747
1748
1749 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1750 memset(buf,'\0',sizeof(buf));
1751 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1752 {
1753 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1754 return RETURN_ERR;
1755 }
1756
1757
1758 if(strstr(buf,"2.4")!=NULL)
1759 {
1760 strcpy(output_string,"2.4GHz");
1761 }
1762 if(strstr(buf,"5.")!=NULL)
1763 {
1764 strcpy(output_string,"5GHz");
1765 }
1766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1767 return RETURN_OK;
1768#endif
1769}
1770
1771//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1772//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.
1773INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1774{
developer963da0c2022-09-13 15:58:27 +08001775 char cmd[128]={0};
1776 char buf[128]={0};
1777 char temp_output[128] = {0};
1778 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001779 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001780
1781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001782 if (NULL == output_string)
1783 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001784
1785 band = wifi_index_to_band(radioIndex);
1786 if (band == band_2_4) {
1787 strcat(temp_output, "b,g,");
1788 } else if (band == band_5) {
1789 strcat(temp_output, "a,");
1790 }
developer033b37b2022-10-18 11:27:46 +08001791 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001792 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001793 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 +08001794 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001795 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001796 strcat(temp_output, "n,");
1797 }
developer06a01d92022-09-07 16:32:39 +08001798
developer963da0c2022-09-13 15:58:27 +08001799 // vht capabilities
1800 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001801 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 +08001802 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001803 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001804 strcat(temp_output, "ac,");
1805 }
1806 }
1807
1808 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001809 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 +08001810 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001811 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001812 strcat(temp_output, "ax,");
1813 }
1814
1815 // Remove the last comma
1816 if (strlen(temp_output) != 0)
1817 temp_output[strlen(temp_output)-1] = '\0';
1818 strncpy(output_string, temp_output, strlen(temp_output));
1819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001820 return RETURN_OK;
1821}
1822
1823//Get the radio operating mode, and pure mode flag. eg: "ac"
1824//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.
1825INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1826{
1827 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1828 if (NULL == output_string)
1829 return RETURN_ERR;
1830
1831 if (radioIndex == 0) {
1832 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1833 *gOnly = FALSE;
1834 *nOnly = TRUE;
1835 *acOnly = FALSE;
1836 } else {
1837 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1838 *gOnly = FALSE;
1839 *nOnly = FALSE;
1840 *acOnly = FALSE;
1841 }
1842 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1843
1844 return RETURN_OK;
1845#if 0
1846 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1847 char buf[64] = {0};
1848 char config_file[MAX_BUF_SIZE] = {0};
1849
1850 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1851 return RETURN_ERR;
1852
1853 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1854 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1855
1856 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1857 if (strlen(buf) == 0)
1858 {
1859 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1860 return RETURN_ERR;
1861 }
1862 if(strcmp(buf,"g")==0)
1863 {
1864 wifi_dbg_printf("\nG\n");
1865 *gOnly=TRUE;
1866 *nOnly=FALSE;
1867 *acOnly=FALSE;
1868 }
1869 else if(strcmp(buf,"n")==0)
1870 {
1871 wifi_dbg_printf("\nN\n");
1872 *gOnly=FALSE;
1873 *nOnly=TRUE;
1874 *acOnly=FALSE;
1875 }
1876 else if(strcmp(buf,"ac")==0)
1877 {
1878 wifi_dbg_printf("\nac\n");
1879 *gOnly=FALSE;
1880 *nOnly=FALSE;
1881 *acOnly=TRUE;
1882 }
1883 /* hostapd-5G.conf has "a" as hw_mode */
1884 else if(strcmp(buf,"a")==0)
1885 {
1886 wifi_dbg_printf("\na\n");
1887 *gOnly=FALSE;
1888 *nOnly=FALSE;
1889 *acOnly=FALSE;
1890 }
1891 else
1892 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1893
1894 //for a,n mode
1895 if(radioIndex == 1)
1896 {
1897 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1898 if(strcmp(buf,"1")==0)
1899 {
1900 strncpy(output_string, "n", 1);
1901 *nOnly=FALSE;
1902 }
1903 }
1904
1905 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1906 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1907 return RETURN_OK;
1908#endif
1909}
1910
developerdb744382022-09-13 15:34:54 +08001911INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1912{
1913 char cmd[128] = {0};
1914 char buf[64] = {0};
1915 char config_file[64] = {0};
1916 wifi_band band;
1917
1918 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1919 if(NULL == output_string || NULL == pureMode)
1920 return RETURN_ERR;
1921
1922 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001923 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerdb744382022-09-13 15:34:54 +08001924 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1925 _syscmd(cmd, buf, sizeof(buf));
1926
1927 band = wifi_index_to_band(radioIndex);
1928 // puremode is a bit map
1929 *pureMode = 0;
1930 if (band == band_2_4) {
1931 strcat(output_string, "b,g");
1932 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1933 if (strstr(buf, "n") != NULL) {
1934 strcat(output_string, ",n");
1935 *pureMode |= WIFI_MODE_N;
1936 }
1937 if (strstr(buf, "ax") != NULL) {
1938 strcat(output_string, ",ax");
1939 *pureMode |= WIFI_MODE_AX;
1940 }
1941 } else if (band == band_5) {
1942 strcat(output_string, "a");
1943 *pureMode |= WIFI_MODE_A;
1944 if (strstr(buf, "n") != NULL) {
1945 strcat(output_string, ",n");
1946 *pureMode |= WIFI_MODE_N;
1947 }
1948 if (strstr(buf, "ac") != NULL) {
1949 strcat(output_string, ",ac");
1950 *pureMode |= WIFI_MODE_AC;
1951 }
1952 if (strstr(buf, "ax") != NULL) {
1953 strcat(output_string, ",ax");
1954 *pureMode |= WIFI_MODE_AX;
1955 }
1956 } else if (band == band_6) {
1957 if (strstr(buf, "ax") != NULL) {
1958 strcat(output_string, "ax");
1959 *pureMode |= WIFI_MODE_AX;
1960 }
1961 }
1962
1963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1964 return RETURN_OK;
1965}
1966
1967// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001968INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1969{
1970 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1971 if (strcmp (channelMode,"11A") == 0)
1972 {
1973 writeBandWidth(radioIndex,"20MHz");
1974 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1975 printf("\nChannel Mode is 802.11a (5GHz)\n");
1976 }
1977 else if (strcmp (channelMode,"11NAHT20") == 0)
1978 {
1979 writeBandWidth(radioIndex,"20MHz");
1980 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1981 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1982 }
1983 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1984 {
1985 writeBandWidth(radioIndex,"40MHz");
1986 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1987 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1988 }
1989 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1990 {
1991 writeBandWidth(radioIndex,"40MHz");
1992 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1993 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1994 }
1995 else if (strcmp (channelMode,"11ACVHT20") == 0)
1996 {
1997 writeBandWidth(radioIndex,"20MHz");
1998 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1999 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2000 }
2001 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2002 {
2003 writeBandWidth(radioIndex,"40MHz");
2004 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2005 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2006 }
2007 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2008 {
2009 writeBandWidth(radioIndex,"40MHz");
2010 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2011 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2012 }
2013 else if (strcmp (channelMode,"11ACVHT80") == 0)
2014 {
2015 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2016 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2017 }
2018 else if (strcmp (channelMode,"11ACVHT160") == 0)
2019 {
2020 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2021 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2022 }
2023 else if (strcmp (channelMode,"11B") == 0)
2024 {
2025 writeBandWidth(radioIndex,"20MHz");
2026 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2027 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2028 }
2029 else if (strcmp (channelMode,"11G") == 0)
2030 {
2031 writeBandWidth(radioIndex,"20MHz");
2032 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2033 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2034 }
2035 else if (strcmp (channelMode,"11NGHT20") == 0)
2036 {
2037 writeBandWidth(radioIndex,"20MHz");
2038 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2039 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2040 }
2041 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2042 {
2043 writeBandWidth(radioIndex,"40MHz");
2044 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2045 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2046 }
2047 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2048 {
2049 writeBandWidth(radioIndex,"40MHz");
2050 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2051 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2052 }
2053 else
2054 {
2055 return RETURN_ERR;
2056 }
2057 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2058
2059 return RETURN_OK;
2060}
2061
developerdb744382022-09-13 15:34:54 +08002062// Set the radio operating mode, and pure mode flag.
2063INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2064{
2065 int num_hostapd_support_mode = 3; // n, ac, ax
2066 struct params list[num_hostapd_support_mode];
2067 char config_file[64] = {0};
2068 char bandwidth[16] = {0};
2069 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002070
developerdb744382022-09-13 15:34:54 +08002071
2072 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2073 // Set radio mode
2074 list[0].name = "ieee80211n";
2075 list[1].name = "ieee80211ac";
2076 list[2].name = "ieee80211ax";
2077 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2078
2079 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002080 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002081 list[0].value = "1";
2082 else
2083 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002084 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002085 list[1].value = "1";
2086 else
2087 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002088 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002089 list[2].value = "1";
2090 else
2091 list[2].value = "0";
2092 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2093
2094 if (channelMode == NULL || strlen(channelMode) == 0)
2095 return RETURN_OK;
2096 // Set bandwidth
2097 if (strstr(channelMode, "40") != NULL)
2098 strcpy(bandwidth, "40MHz");
2099 else if (strstr(channelMode, "80") != NULL)
2100 strcpy(bandwidth, "80MHz");
2101 else if (strstr(channelMode, "160") != NULL)
2102 strcpy(bandwidth, "160MHz");
2103 else // 11A, 11B, 11G....
2104 strcpy(bandwidth, "20MHz");
2105
2106 writeBandWidth(radioIndex, bandwidth);
2107 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2108
2109 wifi_reloadAp(radioIndex);
2110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2111
2112 return RETURN_OK;
2113}
2114
developer1d12ebf2022-10-04 15:13:38 +08002115INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2116
2117 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002118 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002119 struct params params = {0};
2120 wifi_band band = band_invalid;
2121
2122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2123
2124 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002125
2126 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002127 return RETURN_ERR;
2128 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2129 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002130 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2131 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002132
2133 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2134 params.name = "hw_mode";
2135 params.value = hw_mode;
2136 wifi_hostapdWrite(config_file, &params, 1);
2137 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2138
developeref938762022-10-19 17:21:01 +08002139 if (band == band_2_4) {
2140 if (strncmp(hw_mode, "b", 1) == 0) {
2141 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2142 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2143 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2144 snprintf(buf, sizeof(buf), "%s", "1,2");
2145 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2146 } else {
2147 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2148
2149 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2150 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2151 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2152 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2153 }
2154 }
2155
developer1d12ebf2022-10-04 15:13:38 +08002156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2157 return RETURN_OK;
2158}
2159
developere8988ba2022-10-18 17:42:30 +08002160INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2161{
2162 char config_file[64] = {0};
2163 struct params params = {0};
2164 wifi_band band = band_invalid;
2165
2166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2167
2168 band = wifi_index_to_band(radioIndex);
2169
2170 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2171 params.name = "noscan";
2172 params.value = noscan;
2173 wifi_hostapdWrite(config_file, &params, 1);
2174 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2175
2176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2177 return RETURN_OK;
2178}
2179
developer06a01d92022-09-07 16:32:39 +08002180//Get the list of supported channel. eg: "1-11"
2181//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.
2182INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2183{
developer6318ed52022-09-13 15:17:58 +08002184 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002185 if (NULL == output_string)
2186 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002187 char cmd[256] = {0};
2188 char buf[128] = {0};
2189 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002190 int phyId = 0;
2191
developer6318ed52022-09-13 15:17:58 +08002192 // Parse possible channel number and separate them with commas.
2193 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002194 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002195 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002196 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002197 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 +08002198 else
developer033b37b2022-10-18 11:27:46 +08002199 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 +08002200
2201 _syscmd(cmd,buf,sizeof(buf));
2202 strncpy(output_string, buf, sizeof(buf));
2203
2204 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2205 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002206}
2207
2208//Get the list for used channel. eg: "1,6,9,11"
2209//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.
2210INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2211{
developerd946fd62022-12-08 18:03:28 +08002212 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002213 char cmd[128] = {0};
2214 char buf[128] = {0};
2215 char config_file[64] = {0};
2216 int channel = 0;
2217 int freq = 0;
2218 int bandwidth = 0;
2219 int center_freq = 0;
2220 int center_channel = 0;
2221 int channel_delta = 0;
2222 wifi_band band = band_invalid;
2223
2224 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2225
developer06a01d92022-09-07 16:32:39 +08002226 if (NULL == output_string)
2227 return RETURN_ERR;
2228
developerac6f1142022-12-20 19:26:35 +08002229 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002230 return RETURN_ERR;
2231 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002232 _syscmd(cmd, buf, sizeof(buf));
2233 if (strlen(buf) == 0) {
2234 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2235 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002236 }
developerf5745ee2022-10-05 16:09:53 +08002237 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2238
2239 if (bandwidth == 20) {
2240 snprintf(output_string, 256, "%d", channel);
2241 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002242 }
developerf5745ee2022-10-05 16:09:53 +08002243
2244 center_channel = ieee80211_frequency_to_channel(center_freq);
2245
2246 band = wifi_index_to_band(radioIndex);
2247 if (band == band_2_4 && bandwidth == 40) {
2248 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2249 memset(buf, 0, sizeof(buf));
2250 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2251
developerf22724d2022-12-22 17:24:14 +08002252 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002253 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002254 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002255 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2256 } else {
2257 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2258 return RETURN_ERR;
2259 }
2260 } else if (band == band_5 || band == band_6){
2261 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developer72ec5572023-01-05 16:27:13 +08002262 // example: bandwidth 80: center is 42 (5210), channels are "36,40,44,48" (5170-5250). The delta should be 6.
developerf5745ee2022-10-05 16:09:53 +08002263 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002264 memset(output_string, 0, 256);
2265 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2266 // If i is not the last channel, we add a comma.
2267 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2268 strncat(output_string, buf, strlen(buf));
2269 }
developerf5745ee2022-10-05 16:09:53 +08002270 } else
2271 return RETURN_ERR;
2272
2273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002274 return RETURN_OK;
2275}
2276
2277//Get the running channel number
2278INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2279{
developer5b398df2022-11-17 20:39:48 +08002280 char channel_str[16] = {0};
2281 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002282
developer5b398df2022-11-17 20:39:48 +08002283 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002284 return RETURN_ERR;
2285
developer5b398df2022-11-17 20:39:48 +08002286 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2287 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002288
developer5b398df2022-11-17 20:39:48 +08002289 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002290
developer06a01d92022-09-07 16:32:39 +08002291 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002292}
2293
2294
2295INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2296{
2297 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002298 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002299
2300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2301 if (NULL == output_ulong)
2302 return RETURN_ERR;
2303
developer06a01d92022-09-07 16:32:39 +08002304 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002305 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2306 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002307 _syscmd(cmd,buf,sizeof(buf));
2308 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2309 if (*output_ulong == 0) {
2310 return RETURN_ERR;
2311 }
2312
2313 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2314 return RETURN_OK;
2315}
2316
2317//Storing the previous channel value
2318INT wifi_storeprevchanval(INT radioIndex)
2319{
2320 char buf[256] = {0};
2321 char output[4]={'\0'};
2322 char config_file[MAX_BUF_SIZE] = {0};
2323 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2324 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2325 if(radioIndex == 0)
2326 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2327 else if(radioIndex == 1)
2328 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2329 system(buf);
2330 Radio_flag = FALSE;
2331 return RETURN_OK;
2332}
2333
2334//Set the running channel number
2335INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2336{
developer76989232022-10-04 14:13:19 +08002337 // We only write hostapd config here
2338 char str_channel[8]={0};
2339 char *list_channel;
2340 char config_file[128] = {0};
2341 char possible_channels[256] = {0};
2342 int max_radio_num = 0;
2343 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002344
developer76989232022-10-04 14:13:19 +08002345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002346
developer76989232022-10-04 14:13:19 +08002347 // Check valid
2348 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002349
developer76989232022-10-04 14:13:19 +08002350 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2351 list_channel = strtok(possible_channels, ",");
2352 while(true)
developer06a01d92022-09-07 16:32:39 +08002353 {
developer76989232022-10-04 14:13:19 +08002354 if(list_channel == NULL) { // input not in the list
2355 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2356 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002357 }
developer76989232022-10-04 14:13:19 +08002358 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2359 break;
2360 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002361 }
2362
developer76989232022-10-04 14:13:19 +08002363 list.name = "channel";
2364 list.value = str_channel;
2365 wifi_getMaxRadioNumber(&max_radio_num);
2366 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002367 {
developer76989232022-10-04 14:13:19 +08002368 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2369 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002370 }
2371
developer76989232022-10-04 14:13:19 +08002372 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002373 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002374}
developer06a01d92022-09-07 16:32:39 +08002375
2376INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2377{
developer76989232022-10-04 14:13:19 +08002378 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002379 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002380 char config_file[64];
2381 int max_num_radios = 0;
2382 wifi_band band = band_invalid;
2383
2384 band = wifi_index_to_band(radioIndex);
2385 if (band == band_2_4)
2386 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002387
developer30423732022-12-01 16:17:49 +08002388 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002389 list[0].name = "vht_oper_centr_freq_seg0_idx";
2390 list[0].value = str_idx;
2391 list[1].name = "he_oper_centr_freq_seg0_idx";
2392 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002393
developer76989232022-10-04 14:13:19 +08002394 wifi_getMaxRadioNumber(&max_num_radios);
2395 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002396 {
developer76989232022-10-04 14:13:19 +08002397 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2398 if (band == band_6)
2399 wifi_hostapdWrite(config_file, &list[1], 1);
2400 else
2401 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002402 }
2403
2404 return RETURN_OK;
2405}
2406
2407//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2408//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2409INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2410{
2411 //Set to wifi config only. Wait for wifi reset to apply.
2412 char buf[256] = {0};
2413 char str_channel[256] = {0};
2414 int count = 0;
2415 ULONG Value = 0;
2416 FILE *fp = NULL;
2417 if(enable == TRUE)
2418 {
developer06a01d92022-09-07 16:32:39 +08002419 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002420 }
developer5884e982022-10-06 10:52:50 +08002421 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002422}
2423
developer0b246d12022-09-30 15:24:20 +08002424INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2425{
2426 if (output_bool == NULL)
2427 return RETURN_ERR;
2428
2429 *output_bool = TRUE;
2430
2431 return RETURN_OK;
2432}
2433
developer06a01d92022-09-07 16:32:39 +08002434INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2435{
2436 if (NULL == output_bool)
2437 return RETURN_ERR;
2438 *output_bool=FALSE;
2439 return RETURN_OK;
2440}
2441
2442INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2443{
2444 if (NULL == output_bool)
2445 return RETURN_ERR;
2446 *output_bool=FALSE;
2447 return RETURN_OK;
2448}
2449
2450INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2451{
2452 //Set to wifi config only. Wait for wifi reset to apply.
2453 return RETURN_OK;
2454}
2455
2456INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2457{
2458 return RETURN_OK;
2459}
2460
2461INT wifi_factoryResetAP(int apIndex)
2462{
developer838cca92022-10-03 13:19:57 +08002463 char ap_config_file[64] = {0};
2464 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002465 char buf[128] = {0};
developer838cca92022-10-03 13:19:57 +08002466
developer06a01d92022-09-07 16:32:39 +08002467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002468
2469 wifi_setApEnable(apIndex, FALSE);
2470 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2471 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002472 _syscmd(cmd, buf, sizeof(buf));
developer838cca92022-10-03 13:19:57 +08002473 wifi_setApEnable(apIndex, TRUE);
2474
developer06a01d92022-09-07 16:32:39 +08002475 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002476
developer06a01d92022-09-07 16:32:39 +08002477 return RETURN_OK;
2478}
2479
2480//To set Band Steering AP group
2481//To-do
2482INT wifi_setBandSteeringApGroup(char *ApGroup)
2483{
2484 return RETURN_OK;
2485}
2486
developer1e5aa162022-09-13 16:06:24 +08002487INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2488{
2489 char config_file[128] = {'\0'};
2490 char buf[128] = {'\0'};
2491
2492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2493 if (dtimInterval == NULL)
2494 return RETURN_ERR;
2495
2496 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2497 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2498
2499 if (strlen(buf) == 0) {
2500 *dtimInterval = 2;
2501 } else {
2502 *dtimInterval = strtoul(buf, NULL, 10);
2503 }
2504
2505 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2506 return RETURN_OK;
2507}
2508
developer06a01d92022-09-07 16:32:39 +08002509INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2510{
developer5f222492022-09-13 15:21:52 +08002511 struct params params={0};
2512 char config_file[MAX_BUF_SIZE] = {'\0'};
2513 char buf[MAX_BUF_SIZE] = {'\0'};
2514
2515 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2516 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002517 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002518 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002519 }
2520
2521 params.name = "dtim_period";
2522 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2523 params.value = buf;
2524
2525 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2526 wifi_hostapdWrite(config_file, &params, 1);
2527 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2528
2529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2530 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002531}
2532
2533//Check if the driver support the Dfs
2534INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2535{
developer78a15382022-11-02 10:57:40 +08002536 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002537 if (NULL == output_bool)
2538 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002539 *output_bool=FALSE;
2540
2541 band = wifi_index_to_band(radioIndex);
2542 if (band == band_5)
2543 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002544 return RETURN_OK;
2545}
2546
2547//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.
2548//The value of this parameter is a comma seperated list of channel number
2549INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2550{
2551 if (NULL == output_pool)
2552 return RETURN_ERR;
2553 if (radioIndex==1)
2554 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2555 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2556
2557 return RETURN_OK;
2558}
2559
2560INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2561{
2562 //Set to wifi config. And apply instantly.
2563 return RETURN_OK;
2564}
2565
2566INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2567{
2568 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2569 return RETURN_ERR;
2570 *output_interval_seconds=1800;
2571 *output_dwell_milliseconds=40;
2572
2573 return RETURN_OK;
2574}
2575
2576INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2577{
2578 //Set to wifi config. And apply instantly.
2579 return RETURN_OK;
2580}
2581
developerbfc18512022-10-05 17:54:28 +08002582INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2583{
2584 if (output_bool == NULL)
2585 return RETURN_ERR;
2586 *output_bool = true;
2587 return RETURN_OK;
2588}
2589
2590INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2591{
2592 return RETURN_OK;
2593}
2594
developer06a01d92022-09-07 16:32:39 +08002595//Get the Dfs enable status
2596INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2597{
developer9964b5b2022-09-13 15:59:34 +08002598 char buf[16] = {0};
2599 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002600
2601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2602
developer30423732022-12-01 16:17:49 +08002603 if (output_bool == NULL)
2604 return RETURN_ERR;
2605
developer9964b5b2022-09-13 15:59:34 +08002606 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002607 f = fopen(DFS_ENABLE_FILE, "r");
2608 if (f != NULL) {
2609 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002610 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002611 *output_bool = FALSE;
2612 fclose(f);
2613 }
2614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002615 return RETURN_OK;
2616}
2617
2618//Set the Dfs enable status
2619INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2620{
developer9964b5b2022-09-13 15:59:34 +08002621 char config_file[128] = {0};
2622 FILE *f = NULL;
2623 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002624
2625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2626
developer9964b5b2022-09-13 15:59:34 +08002627 f = fopen(DFS_ENABLE_FILE, "w");
2628 if (f == NULL)
2629 return RETURN_ERR;
2630 fprintf(f, "%d", enable);
2631 fclose(f);
2632
2633 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002634 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002635 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2636 wifi_hostapdWrite(config_file, &params, 1);
2637 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2638
2639 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2640
developer9964b5b2022-09-13 15:59:34 +08002641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002642 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002643}
2644
2645//Check if the driver support the AutoChannelRefreshPeriod
2646INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2647{
2648 if (NULL == output_bool)
2649 return RETURN_ERR;
2650 *output_bool=FALSE; //not support
2651
2652 return RETURN_OK;
2653}
2654
2655//Get the ACS refresh period in seconds
2656INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2657{
2658 if (NULL == output_ulong)
2659 return RETURN_ERR;
2660 *output_ulong=300;
2661
2662 return RETURN_OK;
2663}
2664
2665//Set the ACS refresh period in seconds
2666INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2667{
2668 return RETURN_ERR;
2669}
2670
2671//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2672//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.
2673INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2674{
developer72ec5572023-01-05 16:27:13 +08002675 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002676 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002677 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002678 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002679 wifi_band band;
developer70490032022-09-13 15:45:20 +08002680
2681 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2682
developer06a01d92022-09-07 16:32:39 +08002683 if (NULL == output_string)
2684 return RETURN_ERR;
2685
developer70490032022-09-13 15:45:20 +08002686 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2687 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002688
developer70490032022-09-13 15:45:20 +08002689 if (radio_enable != TRUE)
2690 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002691
developerfa41b1f2023-01-06 10:25:51 +08002692 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002693 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002694 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002695 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2696 snprintf(output_string, 64, "20MHz");
2697 else
2698 snprintf(output_string, 64, "40MHz");
2699
2700 } else {
2701 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2702 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2703 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2704 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2705 if (strncmp(buf, "0", 1) == 0)
2706 snprintf(output_string, 64, "20MHz");
2707 else
2708 snprintf(output_string, 64, "40MHz");
2709
2710 } else if (strncmp(buf, "1", 1) == 0)
2711 snprintf(output_string, 64, "80MHz");
2712 else if (strncmp(buf, "2", 1) == 0)
2713 snprintf(output_string, 64, "160MHz");
developer06a01d92022-09-07 16:32:39 +08002714 }
developer72ec5572023-01-05 16:27:13 +08002715
developer06a01d92022-09-07 16:32:39 +08002716 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002717
2718 return RETURN_OK;
2719}
2720
2721//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002722INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002723{
developerf7a466e2022-09-29 11:55:56 +08002724 char config_file[128];
2725 char set_value[16];
2726 struct params params[2];
2727 int max_radio_num = 0;
2728
developer06a01d92022-09-07 16:32:39 +08002729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002730
developerf7a466e2022-09-29 11:55:56 +08002731 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002732 return RETURN_ERR;
2733
developerfa41b1f2023-01-06 10:25:51 +08002734 if(strstr(bandwidth,"160") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002735 strcpy(set_value, "2");
2736 else if(strstr(bandwidth,"80") != NULL)
2737 strcpy(set_value, "1");
2738 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2739 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002740 else if (strstr(bandwidth, "Auto") != NULL)
2741 return RETURN_OK;
2742 else {
developerf7a466e2022-09-29 11:55:56 +08002743 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002744 return RETURN_ERR;
2745 }
2746
developerf7a466e2022-09-29 11:55:56 +08002747 params[0].name = "vht_oper_chwidth";
2748 params[0].value = set_value;
2749 params[1].name = "he_oper_chwidth";
2750 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002751
developerf7a466e2022-09-29 11:55:56 +08002752 wifi_getMaxRadioNumber(&max_radio_num);
2753 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002754 {
developerf7a466e2022-09-29 11:55:56 +08002755 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2756 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002757 }
2758
2759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2760 return RETURN_OK;
2761}
2762
2763//Getting current radio extension channel
2764INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2765{
2766 CHAR buf[150] = {0};
2767 CHAR cmd[150] = {0};
2768 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2769 _syscmd(cmd, buf, sizeof(buf));
2770 if(NULL != strstr(buf,"HT40+"))
2771 strcpy(Value,"AboveControlChannel");
2772 else if(NULL != strstr(buf,"HT40-"))
2773 strcpy(Value,"BelowControlChannel");
2774 return RETURN_OK;
2775}
2776
2777//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2778//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2779INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2780{
developerfa41b1f2023-01-06 10:25:51 +08002781 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002782 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002783
2784 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002785 return RETURN_ERR;
2786
developerfa41b1f2023-01-06 10:25:51 +08002787 band = wifi_index_to_band(radioIndex);
2788 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002789 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002790
2791 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2792
2793 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002794 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002795
2796 return RETURN_OK;
2797}
2798
2799//Set the extension channel.
2800INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002801{
developer06a01d92022-09-07 16:32:39 +08002802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002803 struct params params={0};
2804 char config_file[64] = {0};
2805 char ext_channel[128]={0};
2806 char buf[128] = {0};
2807 char cmd[128] = {0};
2808 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002809 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002810 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002811 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002812 wifi_band band;
2813
2814 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2815 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2816 _syscmd(cmd, buf, sizeof(buf));
2817 if (strlen(buf) != 0)
2818 stbcEnable = TRUE;
2819 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2820 return RETURN_ERR;
2821 bandwidth = strtol(buf, NULL, 10);
2822 // TDK expected to get error with 20MHz
2823 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2824 return RETURN_ERR;
2825
2826 band = wifi_index_to_band(radioIndex);
2827 if (band == band_invalid)
2828 return RETURN_ERR;
2829
2830 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2831 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002832
developer72ec5572023-01-05 16:27:13 +08002833 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2834 ret = util_get_sec_chan_offset(channel, buf);
2835 if (ret == -EINVAL)
2836 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002837
2838 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002839 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2840 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002841 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002842 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08002843 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
2844 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002845 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002846 } else {
developer033b37b2022-10-18 11:27:46 +08002847 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developerfa41b1f2023-01-06 10:25:51 +08002848 }
developer06a01d92022-09-07 16:32:39 +08002849
2850 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002851
2852 wifi_getMaxRadioNumber(&max_radio_num);
2853 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002854 {
developer033b37b2022-10-18 11:27:46 +08002855 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002856 wifi_hostapdWrite(config_file, &params, 1);
developerfa41b1f2023-01-06 10:25:51 +08002857 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
developer06a01d92022-09-07 16:32:39 +08002858 }
2859
2860 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2862 return RETURN_OK;
2863}
2864
2865//Get the guard interval value. eg "400nsec" or "800nsec"
2866//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.
2867INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2868{
developer454b9462022-09-13 15:29:16 +08002869 wifi_guard_interval_t GI;
2870
2871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2872
2873 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002874 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002875
2876 if (GI == wifi_guard_interval_400)
2877 strcpy(output_string, "400nsec");
2878 else if (GI == wifi_guard_interval_800)
2879 strcpy(output_string, "800nsec");
2880 else if (GI == wifi_guard_interval_1600)
2881 strcpy(output_string, "1600nsec");
2882 else if (GI == wifi_guard_interval_3200)
2883 strcpy(output_string, "3200nsec");
2884 else
developer78a15382022-11-02 10:57:40 +08002885 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002886
developer454b9462022-09-13 15:29:16 +08002887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002888 return RETURN_OK;
2889}
2890
2891//Set the guard interval value.
2892INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2893{
developer454b9462022-09-13 15:29:16 +08002894 wifi_guard_interval_t GI;
2895 int ret = 0;
2896
2897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2898
2899 if (strcmp(string, "400nsec") == 0)
2900 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002901 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002902 GI = wifi_guard_interval_800;
2903 else if (strcmp(string , "1600nsec") == 0)
2904 GI = wifi_guard_interval_1600;
2905 else if (strcmp(string , "3200nsec") == 0)
2906 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002907 else
2908 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002909
2910 ret = wifi_setGuardInterval(radioIndex, GI);
2911
2912 if (ret == RETURN_ERR) {
2913 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2914 return RETURN_ERR;
2915 }
2916
2917 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2918 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002919}
2920
2921//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2922INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2923{
developerf49437e2022-09-29 19:58:21 +08002924 char buf[32]={0};
2925 char mcs_file[64] = {0};
2926 char cmd[64] = {0};
2927 int mode_bitmap = 0;
2928
2929 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2930 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002931 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002932 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2933
2934 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2935 _syscmd(cmd, buf, sizeof(buf));
2936 if (strlen(buf) > 0)
2937 *output_int = strtol(buf, NULL, 10);
2938 else {
2939 // output the max MCS for the current radio mode
2940 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2941 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2942 return RETURN_ERR;
2943 }
2944 if (mode_bitmap & WIFI_MODE_AX) {
2945 *output_int = 11;
2946 } else if (mode_bitmap & WIFI_MODE_AC) {
2947 *output_int = 9;
2948 } else if (mode_bitmap & WIFI_MODE_N) {
2949 *output_int = 7;
2950 }
2951 }
2952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002953
2954 return RETURN_OK;
2955}
2956
2957//Set the Modulation Coding Scheme index
2958INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2959{
developerf49437e2022-09-29 19:58:21 +08002960 // 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).
2961 char config_file[64] = {0};
2962 char set_value[16] = {0};
2963 char mcs_file[32] = {0};
2964 wifi_band band = band_invalid;
2965 struct params set_config = {0};
2966 FILE *f = NULL;
2967
2968 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2969
2970 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2971
developer78a15382022-11-02 10:57:40 +08002972 // -1 means auto
2973 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08002974 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2975 return RETURN_ERR;
2976 }
2977
developer78a15382022-11-02 10:57:40 +08002978 if (MCS > 9 || MCS == -1)
2979 strcpy(set_value, "2");
2980 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08002981 strcpy(set_value, "1");
2982 else
developer78a15382022-11-02 10:57:40 +08002983 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08002984
2985 set_config.name = "he_basic_mcs_nss_set";
2986 set_config.value = set_value;
2987
2988 wifi_hostapdWrite(config_file, &set_config, 1);
2989 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2990
2991 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2992 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2993 f = fopen(mcs_file, "w");
2994 if (f == NULL) {
2995 fprintf(stderr, "%s: fopen failed\n", __func__);
2996 return RETURN_ERR;
2997 }
2998 fprintf(f, "%d", MCS);
2999 fclose(f);
3000
3001 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3002 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003003}
3004
3005//Get supported Transmit Power list, eg : "0,25,50,75,100"
3006//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.
3007INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3008{
3009 if (NULL == output_list)
3010 return RETURN_ERR;
3011 snprintf(output_list, 64,"0,25,50,75,100");
3012 return RETURN_OK;
3013}
3014
developera5005b62022-09-13 15:43:35 +08003015//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08003016//The transmite power level is in units of full power for this radio.
3017INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3018{
developerd946fd62022-12-08 18:03:28 +08003019 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003020 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003021 char buf[16]={0};
3022 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003023
developera5005b62022-09-13 15:43:35 +08003024 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003025 return RETURN_ERR;
3026
developerac6f1142022-12-20 19:26:35 +08003027 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003028 return RETURN_ERR;
3029 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003030 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003031
developera5005b62022-09-13 15:43:35 +08003032 *output_ulong = strtol(buf, NULL, 10);
3033
3034 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003035 return RETURN_OK;
3036}
3037
3038//Set Transmit Power
3039//The transmite power level is in units of full power for this radio.
3040INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3041{
developerd946fd62022-12-08 18:03:28 +08003042 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003043 char *support;
developer06a01d92022-09-07 16:32:39 +08003044 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003045 char buf[128]={0};
3046 char txpower_str[64] = {0};
3047 int txpower = 0;
3048 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08003049 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003050
3051 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003052
developerac6f1142022-12-20 19:26:35 +08003053 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003054 return RETURN_ERR;
3055 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003056 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003057 maximum_tx = strtol(buf, NULL, 10);
3058
3059 // Get the Tx power supported list and check that is the input in the list
3060 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3061 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3062 support = strtok(buf, ",");
3063 while(true)
3064 {
3065 if(support == NULL) { // input not in the list
3066 wifi_dbg_printf("Input value is invalid.\n");
3067 return RETURN_ERR;
3068 }
3069 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3070 break;
3071 }
3072 support = strtok(NULL, ",");
3073 }
3074 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003075 phyId = radio_index_to_phy(radioIndex);
3076 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003077 _syscmd(cmd, buf, sizeof(buf));
3078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003079
3080 return RETURN_OK;
3081}
3082
3083//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3084INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3085{
3086 if (NULL == Supported)
3087 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003088 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003089
3090 return RETURN_OK;
3091}
3092
3093//Get 80211h feature enable
3094INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3095{
developer3885fec2022-09-13 15:13:47 +08003096 char buf[64]={'\0'};
3097 char config_file[64] = {'\0'};
3098
3099 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3100 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003101 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003102
3103 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3104 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003105
developer3885fec2022-09-13 15:13:47 +08003106 if (strncmp(buf, "1", 1) == 0)
3107 *enable = TRUE;
3108 else
3109 *enable = FALSE;
3110
3111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003112 return RETURN_OK;
3113}
3114
3115//Set 80211h feature enable
3116INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3117{
developer3885fec2022-09-13 15:13:47 +08003118 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3119 struct params params={'\0'};
3120 char config_file[MAX_BUF_SIZE] = {0};
3121
3122 params.name = "ieee80211h";
3123
3124 if (enable) {
3125 params.value = "1";
3126 } else {
3127 params.value = "0";
3128 }
3129
3130 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3131 wifi_hostapdWrite(config_file, &params, 1);
3132
3133 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3135 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003136}
3137
3138//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.
3139INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3140{
3141 if (NULL == output)
3142 return RETURN_ERR;
3143 *output=100;
3144
3145 return RETURN_OK;
3146}
3147
3148//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.
3149INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3150{
3151 if (NULL == output)
3152 return RETURN_ERR;
3153 *output = -99;
3154
3155 return RETURN_OK;
3156}
3157
3158INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3159{
3160 return RETURN_ERR;
3161}
3162
3163
3164//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3165INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3166{
developerd946fd62022-12-08 18:03:28 +08003167 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003168 char cmd[MAX_BUF_SIZE]={'\0'};
3169 char buf[MAX_CMD_SIZE]={'\0'};
3170
3171 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3172 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003173 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003174
developerac6f1142022-12-20 19:26:35 +08003175 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003176 return RETURN_ERR;
3177 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer5f222492022-09-13 15:21:52 +08003178 _syscmd(cmd, buf, sizeof(buf));
3179 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003180
developer5f222492022-09-13 15:21:52 +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_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3186{
developer5f222492022-09-13 15:21:52 +08003187 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3188 struct params params={'\0'};
3189 char buf[MAX_BUF_SIZE] = {'\0'};
3190 char config_file[MAX_BUF_SIZE] = {'\0'};
3191
developer5b398df2022-11-17 20:39:48 +08003192 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3193 return RETURN_ERR;
3194
developer5f222492022-09-13 15:21:52 +08003195 params.name = "beacon_int";
3196 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3197 params.value = buf;
3198
3199 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3200 wifi_hostapdWrite(config_file, &params, 1);
3201
3202 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3204 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003205}
3206
3207//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.
3208INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3209{
developer06a01d92022-09-07 16:32:39 +08003210 //TODO: need to revisit below implementation
3211 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003212 char temp_output[128] = {0};
3213 char temp_TransmitRates[64] = {0};
3214 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003215
3216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3217 if (NULL == output)
3218 return RETURN_ERR;
3219 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003220 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3221
3222 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3223 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3224 } else {
3225 temp = strtok(temp_TransmitRates," ");
3226 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003227 {
developere9d0abd2022-09-13 15:40:57 +08003228 // Convert 100 kbps to Mbps
3229 temp[strlen(temp)-1]=0;
3230 if((temp[0]=='5') && (temp[1]=='\0'))
3231 {
3232 temp="5.5";
3233 }
3234 strcat(temp_output,temp);
3235 temp = strtok(NULL," ");
3236 if(temp!=NULL)
3237 {
3238 strcat(temp_output,",");
3239 }
developer06a01d92022-09-07 16:32:39 +08003240 }
developere9d0abd2022-09-13 15:40:57 +08003241 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003242 }
developer06a01d92022-09-07 16:32:39 +08003243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003244 return RETURN_OK;
3245}
3246
3247INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3248{
3249 char *temp;
3250 char temp1[128];
3251 char temp_output[128];
3252 char temp_TransmitRates[128];
3253 char set[128];
3254 char sub_set[128];
3255 int set_count=0,subset_count=0;
3256 int set_index=0,subset_index=0;
3257 char *token;
3258 int flag=0, i=0;
3259 struct params params={'\0'};
3260 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003261 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003262
3263 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3264 if(NULL == TransmitRates)
3265 return RETURN_ERR;
3266 strcpy(sub_set,TransmitRates);
3267
3268 //Allow only supported Data transmit rate to be set
3269 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3270 token = strtok(sub_set,",");
3271 while( token != NULL ) /* split the basic rate to be set, by comma */
3272 {
3273 sub_set[subset_count]=atoi(token);
3274 subset_count++;
3275 token=strtok(NULL,",");
3276 }
3277 token=strtok(set,",");
3278 while(token!=NULL) /* split the supported rate by comma */
3279 {
3280 set[set_count]=atoi(token);
3281 set_count++;
3282 token=strtok(NULL,",");
3283 }
3284 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3285 {
3286 for(set_index=0;set_index < set_count;set_index++)
3287 {
3288 flag=0;
3289 if(sub_set[subset_index]==set[set_index])
3290 break;
3291 else
3292 flag=1; /* No match found */
3293 }
3294 if(flag==1)
3295 return RETURN_ERR; //If value not found return Error
3296 }
3297 strcpy(temp_TransmitRates,TransmitRates);
3298
3299 for(i=0;i<strlen(temp_TransmitRates);i++)
3300 {
3301 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003302 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003303 {
3304 continue;
3305 }
3306 else
3307 {
3308 return RETURN_ERR;
3309 }
3310 }
3311 strcpy(temp_output,"");
3312 temp = strtok(temp_TransmitRates,",");
3313 while(temp!=NULL)
3314 {
3315 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003316 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003317 {
developeref938762022-10-19 17:21:01 +08003318 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003319 {
3320 return RETURN_ERR;
3321 }
3322 }
3323
3324 if(strcmp(temp,"5.5")==0)
3325 {
3326 strcpy(temp1,"55");
3327 }
3328 else
3329 {
3330 strcat(temp1,"0");
3331 }
3332 strcat(temp_output,temp1);
3333 temp = strtok(NULL,",");
3334 if(temp!=NULL)
3335 {
3336 strcat(temp_output," ");
3337 }
3338 }
3339 strcpy(TransmitRates,temp_output);
3340
3341 params.name= "basic_rates";
3342 params.value =TransmitRates;
3343
3344 wifi_dbg_printf("\n%s:",__func__);
3345 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3346 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3347 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3348 wifi_hostapdWrite(config_file,&params,1);
3349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3350 return RETURN_OK;
3351}
3352
3353//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003354INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003355{
3356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3357 FILE *fp = NULL;
3358 char path[256] = {0}, output_string[256] = {0};
3359 int count = 0;
3360 char *interface = NULL;
3361
3362 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3363 if (fp == NULL)
3364 {
3365 printf("Failed to run command in Function %s\n", __FUNCTION__);
3366 return RETURN_ERR;
3367 }
3368 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3369 {
3370 interface = strchr(path, '=');
3371
3372 if (interface != NULL)
3373 {
3374 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003375 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003376 interface_name[count] = output_string[count];
3377
3378 interface_name[count] = '\0';
3379 }
3380 }
3381 pclose(fp);
3382 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3383 return RETURN_OK;
3384}
3385
3386INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3387{
3388 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3389 output_struct->radio_BytesSent = 0;
3390 output_struct->radio_BytesReceived = 0;
3391 output_struct->radio_PacketsSent = 0;
3392 output_struct->radio_PacketsReceived = 0;
3393 output_struct->radio_ErrorsSent = 0;
3394 output_struct->radio_ErrorsReceived = 0;
3395 output_struct->radio_DiscardPacketsSent = 0;
3396 output_struct->radio_DiscardPacketsReceived = 0;
3397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3398 return RETURN_OK;
3399}
3400
3401
3402INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3403{
3404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3405 CHAR buf[MAX_CMD_SIZE] = {0};
3406 CHAR Value[MAX_BUF_SIZE] = {0};
3407 FILE *fp = NULL;
3408
3409 if (ifname == NULL || strlen(ifname) <= 1)
3410 return RETURN_OK;
3411
3412 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3413 system(buf);
3414
3415 fp = fopen("/tmp/Radio_Stats.txt", "r");
3416 if(fp == NULL)
3417 {
3418 printf("/tmp/Radio_Stats.txt not exists \n");
3419 return RETURN_ERR;
3420 }
3421 fclose(fp);
3422
3423 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3424 File_Reading(buf, Value);
3425 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3426
3427 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3428 File_Reading(buf, Value);
3429 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3430
3431 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3432 File_Reading(buf, Value);
3433 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3434
3435 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3436 File_Reading(buf, Value);
3437 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3438
3439 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3440 File_Reading(buf, Value);
3441 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3442
3443 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3444 File_Reading(buf, Value);
3445 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3446
3447 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3448 File_Reading(buf, Value);
3449 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3450
3451 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3452 File_Reading(buf, Value);
3453 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3454
3455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3456 return RETURN_OK;
3457}
3458
3459INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3460{
3461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3462 CHAR buf[MAX_CMD_SIZE] = {0};
3463 FILE *fp = NULL;
3464 INT count = 0;
3465
3466 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3467 {
3468 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3469 File_Reading(buf, status);
3470 }
3471 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3472 return RETURN_OK;
3473}
3474
3475//Get detail radio traffic static info
3476INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3477{
3478
3479#if 0
3480 //ifconfig radio_x
3481 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3482 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3483 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3484 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3485
3486 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3487 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3488 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.
3489 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.
3490
3491 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3492 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].
3493 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3494 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.
3495 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
3496 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
3497 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
3498 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
3499 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
3500
3501 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
3502 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
3503 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
3504 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.
3505
3506 return RETURN_OK;
3507#endif
3508
developera91d99f2022-09-29 15:59:10 +08003509 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003510 BOOL iface_status = FALSE;
3511 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003512
3513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3514 if (NULL == output_struct)
3515 return RETURN_ERR;
3516
developerac6f1142022-12-20 19:26:35 +08003517 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08003518 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003519
developera91d99f2022-09-29 15:59:10 +08003520 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003521
developera91d99f2022-09-29 15:59:10 +08003522 if (iface_status == TRUE)
3523 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3524 else
3525 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003526
developera91d99f2022-09-29 15:59:10 +08003527 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3528 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3529 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3530 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3531 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3532 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3533 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3534 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003535
3536 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3537 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].
3538 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3539 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.
3540 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
3541 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
3542 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
3543 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
3544 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
3545
3546 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
3547 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
3548 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
3549 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.
3550
3551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3552
3553 return RETURN_OK;
3554}
3555
3556//Set radio traffic static Measureing rules
3557INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3558{
3559 //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
3560 // Else, save the MeasuringRate and MeasuringInterval for future usage
3561
3562 return RETURN_OK;
3563}
3564
3565//To start or stop RadioTrafficStats
3566INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3567{
3568 //zqiu: If the RadioTrafficStats process running
3569 // if(enable)
3570 // return RETURN_OK.
3571 // else
3572 // Stop RadioTrafficStats process
3573 // Else
3574 // if(enable)
3575 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3576 // else
3577 // return RETURN_OK.
3578
3579 return RETURN_OK;
3580}
3581
3582//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
3583INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3584{
3585 //zqiu: Please ignor signalIndex.
3586 if (NULL == SignalLevel)
3587 return RETURN_ERR;
3588 *SignalLevel=(radioIndex==0)?-19:-19;
3589
3590 return RETURN_OK;
3591}
3592
3593//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3594INT wifi_applyRadioSettings(INT radioIndex)
3595{
3596 return RETURN_OK;
3597}
3598
3599//Get the radio index assocated with this SSID entry
3600INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3601{
developer5b398df2022-11-17 20:39:48 +08003602 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003603 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003604 int max_radio_num = 0;
3605 wifi_getMaxRadioNumber(&max_radio_num);
3606 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003607 return RETURN_OK;
3608}
3609
3610//Device.WiFi.SSID.{i}.Enable
3611//Get SSID enable configuration parameters (not the SSID enable status)
3612INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3613{
3614 if (NULL == output_bool)
3615 return RETURN_ERR;
3616
developer06a01d92022-09-07 16:32:39 +08003617 return wifi_getApEnable(ssidIndex, output_bool);
3618}
3619
3620//Device.WiFi.SSID.{i}.Enable
3621//Set SSID enable configuration parameters
3622INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3623{
developer06a01d92022-09-07 16:32:39 +08003624 return wifi_setApEnable(ssidIndex, enable);
3625}
3626
3627//Device.WiFi.SSID.{i}.Status
3628//Get the SSID enable status
3629INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3630{
3631 char cmd[MAX_CMD_SIZE]={0};
3632 char buf[MAX_BUF_SIZE]={0};
3633 BOOL output_bool;
3634
3635 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3636 if (NULL == output_string)
3637 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003638
developer06a01d92022-09-07 16:32:39 +08003639 wifi_getApEnable(ssidIndex,&output_bool);
3640 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3641
3642 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3643 return RETURN_OK;
3644}
3645
3646// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3647INT wifi_getSSIDName(INT apIndex, CHAR *output)
3648{
3649 char config_file[MAX_BUF_SIZE] = {0};
3650
3651 if (NULL == output)
3652 return RETURN_ERR;
3653
3654 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3655 wifi_hostapdRead(config_file,"ssid",output,32);
3656
3657 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3658 return RETURN_OK;
3659}
3660
3661// Set a max 32 byte string and sets an internal variable to the SSID name
3662INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3663{
3664 char str[MAX_BUF_SIZE]={'\0'};
3665 char cmd[MAX_CMD_SIZE]={'\0'};
3666 struct params params;
3667 char config_file[MAX_BUF_SIZE] = {0};
3668
3669 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3670 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3671 return RETURN_ERR;
3672
3673 params.name = "ssid";
3674 params.value = ssid_string;
3675 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3676 wifi_hostapdWrite(config_file, &params, 1);
3677 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3679
3680 return RETURN_OK;
3681}
3682
3683//Get the BSSID
3684INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3685{
3686 char cmd[MAX_CMD_SIZE]="";
3687
3688 if (NULL == output_string)
3689 return RETURN_ERR;
3690
3691 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3692 {
developer1d57d002022-10-12 18:03:15 +08003693 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 +08003694 _syscmd(cmd, output_string, 64);
3695 return RETURN_OK;
3696 }
3697 strncpy(output_string, "\0", 1);
3698
3699 return RETURN_ERR;
3700}
3701
3702//Get the MAC address associated with this Wifi SSID
3703INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3704{
3705 wifi_getBaseBSSID(ssidIndex,output_string);
3706 return RETURN_OK;
3707}
3708
3709//Get the basic SSID traffic static info
3710//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3711//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3712INT wifi_applySSIDSettings(INT ssidIndex)
3713{
developerd946fd62022-12-08 18:03:28 +08003714 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003715 BOOL status = false;
3716 char cmd[MAX_CMD_SIZE] = {0};
3717 char buf[MAX_CMD_SIZE] = {0};
3718 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003719 int max_radio_num = 0;
3720 int radioIndex = 0;
3721
3722 wifi_getMaxRadioNumber(&max_radio_num);
3723
3724 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003725
3726 wifi_getApEnable(ssidIndex,&status);
3727 // Do not apply when ssid index is disabled
3728 if (status == false)
3729 return RETURN_OK;
3730
3731 /* Doing full remove and add for ssid Index
3732 * Not all hostapd options are supported with reload
3733 * for example macaddr_acl
3734 */
3735 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3736 return RETURN_ERR;
3737
3738 ret = wifi_setApEnable(ssidIndex,true);
3739
3740 /* Workaround for hostapd issue with multiple bss definitions
3741 * when first created interface will be removed
3742 * then all vaps other vaps on same phy are removed
3743 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003744 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003745 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003746 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003747 continue;
developerd946fd62022-12-08 18:03:28 +08003748 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003749 _syscmd(cmd, buf, sizeof(buf));
3750 if(*buf == '1')
3751 wifi_setApEnable(apIndex, true);
3752 }
3753
3754 return ret;
3755}
3756
developera3c68b92022-09-13 15:27:29 +08003757struct channels_noise {
3758 int channel;
3759 int noise;
3760};
3761
3762// Return noise array for each channel
3763int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3764{
developerd946fd62022-12-08 18:03:28 +08003765 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003766 FILE *f = NULL;
3767 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003768 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003769 size_t len = 0;
3770 ssize_t read = 0;
3771 int tmp = 0, arr_index = -1;
3772
developerac6f1142022-12-20 19:26:35 +08003773 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003774 return RETURN_ERR;
3775 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003776
3777 if ((f = popen(cmd, "r")) == NULL) {
3778 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3779 return RETURN_ERR;
3780 }
developer5550e242022-09-30 09:59:32 +08003781
3782 while(fgets(line, sizeof(line), f) != NULL) {
3783 if(arr_index < channels_num){
3784 sscanf(line, "%d", &tmp);
3785 if (tmp > 0) { // channel frequency, the first line must be frequency
3786 arr_index++;
3787 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3788 } else { // noise
3789 channels_noise_arr[arr_index].noise = tmp;
3790 }
3791 }else{
3792 break;
developera3c68b92022-09-13 15:27:29 +08003793 }
3794 }
developera3c68b92022-09-13 15:27:29 +08003795 pclose(f);
3796 return RETURN_OK;
3797}
3798
developer06a01d92022-09-07 16:32:39 +08003799//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3800//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3801INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3802{
developera3c68b92022-09-13 15:27:29 +08003803 int index = -1;
3804 wifi_neighbor_ap2_t *scan_array = NULL;
3805 char cmd[256]={0};
3806 char buf[128]={0};
3807 char file_name[32] = {0};
3808 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003809 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003810 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003811 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003812 int freq=0;
3813 FILE *f = NULL;
3814 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003815 int channels_num = 0;
3816 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003817 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003818 bool filter_enable = false;
3819 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003820 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003821
developer615510b2022-09-27 10:14:35 +08003822 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003823
developerac6f1142022-12-20 19:26:35 +08003824 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003825 return RETURN_ERR;
3826
developera3c68b92022-09-13 15:27:29 +08003827 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3828 f = fopen(file_name, "r");
3829 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08003830 fgets(buf, sizeof(file_name), f);
3831 if ((strncmp(buf, "0", 1)) != 0) {
3832 fgets(filter_SSID, sizeof(file_name), f);
3833 if (strlen(filter_SSID) != 0)
3834 filter_enable = true;
3835 }
developera3c68b92022-09-13 15:27:29 +08003836 fclose(f);
3837 }
3838
developer033b37b2022-10-18 11:27:46 +08003839 phyId = radio_index_to_phy(radioIndex);
3840 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003841 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003842 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003843
developer5550e242022-09-30 09:59:32 +08003844
developer06a01d92022-09-07 16:32:39 +08003845
developerd946fd62022-12-08 18:03:28 +08003846 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3847 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
developera3c68b92022-09-13 15:27:29 +08003848 fprintf(stderr, "cmd: %s\n", cmd);
3849 if ((f = popen(cmd, "r")) == NULL) {
3850 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3851 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003852 }
developer5550e242022-09-30 09:59:32 +08003853
3854 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3855 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3856
developer615510b2022-09-27 10:14:35 +08003857 ret = fgets(line, sizeof(line), f);
3858 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003859 if(strstr(line, "BSS") != NULL) { // new neighbor info
3860 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3861 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3862 // 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 +08003863
developera3c68b92022-09-13 15:27:29 +08003864 if (!filter_BSS) {
3865 index++;
3866 wifi_neighbor_ap2_t *tmp;
3867 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3868 if (tmp == NULL) { // no more memory to use
3869 index--;
3870 wifi_dbg_printf("%s: realloc failed\n", __func__);
3871 break;
3872 }
3873 scan_array = tmp;
3874 }
3875 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3876
3877 filter_BSS = false;
3878 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3879 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3880 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3881 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3882 } else if (strstr(line, "freq") != NULL) {
3883 sscanf(line," freq: %d", &freq);
3884 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3885
3886 if (freq >= 2412 && freq <= 2484) {
3887 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3888 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3889 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3890 }
3891 else if (freq >= 5160 && freq <= 5805) {
3892 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3893 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3894 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3895 }
3896
3897 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003898 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003899 for (int i = 0; i < channels_num; i++) {
3900 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3901 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3902 break;
3903 }
3904 }
3905 }
3906 } else if (strstr(line, "beacon interval") != NULL) {
3907 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3908 } else if (strstr(line, "signal") != NULL) {
3909 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3910 } else if (strstr(line,"SSID") != NULL) {
3911 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3912 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3913 filter_BSS = true;
3914 }
3915 } else if (strstr(line, "Supported rates") != NULL) {
3916 char SRate[80] = {0}, *tmp = NULL;
3917 memset(buf, 0, sizeof(buf));
3918 strcpy(SRate, line);
3919 tmp = strtok(SRate, ":");
3920 tmp = strtok(NULL, ":");
3921 strcpy(buf, tmp);
3922 memset(SRate, 0, sizeof(SRate));
3923
3924 tmp = strtok(buf, " \n");
3925 while (tmp != NULL) {
3926 strcat(SRate, tmp);
3927 if (SRate[strlen(SRate) - 1] == '*') {
3928 SRate[strlen(SRate) - 1] = '\0';
3929 }
3930 strcat(SRate, ",");
3931
3932 tmp = strtok(NULL, " \n");
3933 }
3934 SRate[strlen(SRate) - 1] = '\0';
3935 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3936 } else if (strstr(line, "DTIM") != NULL) {
3937 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3938 } else if (strstr(line, "VHT capabilities") != NULL) {
3939 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3940 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3941 } else if (strstr(line, "HT capabilities") != NULL) {
3942 strcat(scan_array[index].ap_SupportedStandards, ",n");
3943 strcpy(scan_array[index].ap_OperatingStandards, "n");
3944 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003945 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003946 sscanf(line," * channel width: %d", &vht_channel_width);
3947 if(vht_channel_width == 1) {
3948 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3949 } else {
3950 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3951 }
3952 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3953 continue;
3954 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003955 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003956 sscanf(line," * secondary channel offset: %s", &buf);
3957 if (!strcmp(buf, "above")) {
3958 //40Mhz +
3959 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3960 }
3961 else if (!strcmp(buf, "below")) {
3962 //40Mhz -
3963 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3964 } else {
3965 //20Mhz
3966 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3967 }
3968 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3969 continue;
3970 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003971 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3972 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3973 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003974 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3975 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003976 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003977 else
developer615510b2022-09-27 10:14:35 +08003978 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003979 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003980 if (strstr(line, "HE80/5GHz") != NULL) {
3981 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3982 ret = fgets(line, sizeof(line), f);
3983 } else
3984 continue;
developera3c68b92022-09-13 15:27:29 +08003985 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003986 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003987 }
developer615510b2022-09-27 10:14:35 +08003988 continue;
developera3c68b92022-09-13 15:27:29 +08003989 } else if (strstr(line, "WPA") != NULL) {
3990 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3991 } else if (strstr(line, "RSN") != NULL) {
3992 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3993 } else if (strstr(line, "Group cipher") != NULL) {
3994 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3995 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3996 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3997 }
3998 }
developer615510b2022-09-27 10:14:35 +08003999 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004000 }
4001
4002 if (!filter_BSS) {
4003 *output_array_size = index + 1;
4004 } else {
4005 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4006 *output_array_size = index;
4007 }
4008 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004009 pclose(f);
developer5550e242022-09-30 09:59:32 +08004010 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004011 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004012 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004013}
4014
4015//>> Deprecated: used for old RDKB code.
4016INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4017{
4018 INT status = RETURN_ERR;
4019
4020 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4021 output_struct->wifi_PLCPErrorCount = 0;
4022 output_struct->wifi_FCSErrorCount = 0;
4023 output_struct->wifi_InvalidMACCount = 0;
4024 output_struct->wifi_PacketsOtherReceived = 0;
4025 output_struct->wifi_Noise = 0;
4026 status = RETURN_OK;
4027 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4028 return status;
4029}
4030
4031INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4032{
developerd946fd62022-12-08 18:03:28 +08004033 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004034 char cmd[128] = {0};
4035 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004036 char *pos = NULL;
4037
4038 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4039 if (NULL == output_struct)
4040 return RETURN_ERR;
4041
developerac6f1142022-12-20 19:26:35 +08004042 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004043 return RETURN_ERR;
4044
developer06a01d92022-09-07 16:32:39 +08004045 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4046
developerd946fd62022-12-08 18:03:28 +08004047 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004048 _syscmd(cmd, buf, sizeof(buf));
4049
4050 pos = buf;
4051 if ((pos = strstr(pos, "RX packets:")) == NULL)
4052 return RETURN_ERR;
4053 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4054
4055 if ((pos = strstr(pos, "TX packets:")) == NULL)
4056 return RETURN_ERR;
4057 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4058
4059 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4060 return RETURN_ERR;
4061 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4062
4063 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4064 return RETURN_ERR;
4065 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4066
developerd946fd62022-12-08 18:03:28 +08004067 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004068 _syscmd(cmd, buf, sizeof(buf));
4069 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4070
4071#if 0
4072 //TODO: need to revisit below implementation
4073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4074 char interface_name[MAX_BUF_SIZE] = {0};
4075 char interface_status[MAX_BUF_SIZE] = {0};
4076 char Value[MAX_BUF_SIZE] = {0};
4077 char buf[MAX_CMD_SIZE] = {0};
4078 char cmd[MAX_CMD_SIZE] = {0};
4079 FILE *fp = NULL;
4080
4081 if (NULL == output_struct) {
4082 return RETURN_ERR;
4083 }
4084
4085 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4086
4087 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4088 {
4089 if(apIndex == 0) //private_wifi for 2.4G
4090 {
developerac6f1142022-12-20 19:26:35 +08004091 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004092 }
4093 else if(apIndex == 1) //private_wifi for 5G
4094 {
developerac6f1142022-12-20 19:26:35 +08004095 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004096 }
4097 else if(apIndex == 4) //public_wifi for 2.4G
4098 {
4099 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4100 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4101 {
4102 return RETURN_ERR;
4103 }
4104 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004105 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004106 else//tenda
developerac6f1142022-12-20 19:26:35 +08004107 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004108 }
4109 else if(apIndex == 5) //public_wifi for 5G
4110 {
developerac6f1142022-12-20 19:26:35 +08004111 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004112 }
4113
4114 GetIfacestatus(interface_name, interface_status);
4115
4116 if(0 != strcmp(interface_status, "1"))
4117 return RETURN_ERR;
4118
4119 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4120 system(cmd);
4121
4122 fp = fopen("/tmp/SSID_Stats.txt", "r");
4123 if(fp == NULL)
4124 {
4125 printf("/tmp/SSID_Stats.txt not exists \n");
4126 return RETURN_ERR;
4127 }
4128 fclose(fp);
4129
4130 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4131 File_Reading(buf, Value);
4132 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4133
4134 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4135 File_Reading(buf, Value);
4136 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4137
4138 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4139 File_Reading(buf, Value);
4140 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4141
4142 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4143 File_Reading(buf, Value);
4144 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4145
4146 /* There is no specific parameter from caller to associate the value wifi_Associations */
4147 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4148 //_syscmd(cmd, buf, sizeof(buf));
4149 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4150 }
4151#endif
4152 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4153 return RETURN_OK;
4154}
4155
4156INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4157{
4158 char interface_name[MAX_BUF_SIZE] = {0};
4159 char interface_status[MAX_BUF_SIZE] = {0};
4160 char Value[MAX_BUF_SIZE] = {0};
4161 char buf[MAX_CMD_SIZE] = {0};
4162 char cmd[MAX_CMD_SIZE] = {0};
4163 FILE *fp = NULL;
4164
4165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4166 if (NULL == output_struct)
4167 return RETURN_ERR;
4168
4169 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4170
developerac6f1142022-12-20 19:26:35 +08004171 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004172 return RETURN_ERR;
4173 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004174
developerd946fd62022-12-08 18:03:28 +08004175 if(0 != strcmp(interface_status, "1"))
4176 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004177
developerd946fd62022-12-08 18:03:28 +08004178 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4179 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004180
developerd946fd62022-12-08 18:03:28 +08004181 fp = fopen("/tmp/SSID_Stats.txt", "r");
4182 if(fp == NULL)
4183 {
4184 printf("/tmp/SSID_Stats.txt not exists \n");
4185 return RETURN_ERR;
4186 }
4187 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004188
developerd946fd62022-12-08 18:03:28 +08004189 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4190 File_Reading(buf, Value);
4191 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004192
developerd946fd62022-12-08 18:03:28 +08004193 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4194 File_Reading(buf, Value);
4195 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004196
developerd946fd62022-12-08 18:03:28 +08004197 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4198 File_Reading(buf, Value);
4199 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004200
developerd946fd62022-12-08 18:03:28 +08004201 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4202 File_Reading(buf, Value);
4203 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004204
4205 output_struct->wifi_UnicastPacketsSent = 0;
4206 output_struct->wifi_UnicastPacketsReceived = 0;
4207 output_struct->wifi_MulticastPacketsSent = 0;
4208 output_struct->wifi_MulticastPacketsReceived = 0;
4209 output_struct->wifi_BroadcastPacketsSent = 0;
4210 output_struct->wifi_BroadcastPacketsRecevied = 0;
4211 output_struct->wifi_UnknownPacketsReceived = 0;
4212
4213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4214 return RETURN_OK;
4215}
4216
4217INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4218{
4219 INT status = RETURN_ERR;
4220
4221 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4222 //Below values should get updated from hal
4223 output_struct->wifi_RetransCount=0;
4224 output_struct->wifi_FailedRetransCount=0;
4225 output_struct->wifi_RetryCount=0;
4226 output_struct->wifi_MultipleRetryCount=0;
4227 output_struct->wifi_ACKFailureCount=0;
4228 output_struct->wifi_AggregatedPacketCount=0;
4229
4230 status = RETURN_OK;
4231 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4232
4233 return status;
4234}
4235
4236INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4237{
4238 INT status = RETURN_ERR;
4239 UINT index;
4240 wifi_neighbor_ap_t *pt=NULL;
4241
4242 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4243 *output_array_size=2;
4244 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4245 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4246 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4247 strcpy(pt->ap_Radio,"");
4248 strcpy(pt->ap_SSID,"");
4249 strcpy(pt->ap_BSSID,"");
4250 strcpy(pt->ap_Mode,"");
4251 pt->ap_Channel=1;
4252 pt->ap_SignalStrength=0;
4253 strcpy(pt->ap_SecurityModeEnabled,"");
4254 strcpy(pt->ap_EncryptionMode,"");
4255 strcpy(pt->ap_OperatingFrequencyBand,"");
4256 strcpy(pt->ap_SupportedStandards,"");
4257 strcpy(pt->ap_OperatingStandards,"");
4258 strcpy(pt->ap_OperatingChannelBandwidth,"");
4259 pt->ap_BeaconPeriod=1;
4260 pt->ap_Noise=0;
4261 strcpy(pt->ap_BasicDataTransferRates,"");
4262 strcpy(pt->ap_SupportedDataTransferRates,"");
4263 pt->ap_DTIMPeriod=1;
4264 pt->ap_ChannelUtilization = 1;
4265 }
4266
4267 status = RETURN_OK;
4268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4269
4270 return status;
4271}
4272
4273//----------------- AP HAL -------------------------------
4274
4275//>> Deprecated: used for old RDKB code.
4276INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4277{
4278 if (NULL == output_ulong || NULL == output_struct)
4279 return RETURN_ERR;
4280 *output_ulong = 0;
4281 *output_struct = NULL;
4282 return RETURN_OK;
4283}
4284
4285#ifdef HAL_NETLINK_IMPL
4286static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4287 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4288 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4289 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4290 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4291 char mac_addr[20];
4292 static int count=0;
4293 int rate=0;
4294
4295 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4296
4297 nla_parse(tb,
4298 NL80211_ATTR_MAX,
4299 genlmsg_attrdata(gnlh, 0),
4300 genlmsg_attrlen(gnlh, 0),
4301 NULL);
4302
4303 if(!tb[NL80211_ATTR_STA_INFO]) {
4304 fprintf(stderr, "sta stats missing!\n");
4305 return NL_SKIP;
4306 }
4307
4308
4309 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4310 fprintf(stderr, "failed to parse nested attributes!\n");
4311 return NL_SKIP;
4312 }
4313
4314 //devIndex starts from 1
4315 if( ++count == out->wifi_devIndex )
4316 {
4317 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4318 //Getting the mac addrress
4319 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4320
4321 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4322 fprintf(stderr, "failed to parse nested rate attributes!");
4323 return NL_SKIP;
4324 }
4325
4326 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4327 if(rinfo[NL80211_RATE_INFO_BITRATE])
4328 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4329 out->wifi_devTxRate = rate/10;
4330 }
4331
4332 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4333 fprintf(stderr, "failed to parse nested rate attributes!");
4334 return NL_SKIP;
4335 }
4336
4337 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4338 if(rinfo[NL80211_RATE_INFO_BITRATE])
4339 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4340 out->wifi_devRxRate = rate/10;
4341 }
4342 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4343 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4344
4345 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4346 count = 0; //starts the count for next cycle
4347 return NL_STOP;
4348 }
4349
4350 return NL_SKIP;
4351
4352}
4353#endif
4354
4355INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4356{
4357#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004358 Netlink nl = {0};
4359 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004360 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004361
developer30423732022-12-01 16:17:49 +08004362 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004363 info.wifi_devIndex = devIndex;
4364
developerac6f1142022-12-20 19:26:35 +08004365 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004366 return RETURN_ERR;
4367
4368 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004369
4370 nl.id = initSock80211(&nl);
4371
4372 if (nl.id < 0) {
4373 fprintf(stderr, "Error initializing netlink \n");
4374 return -1;
4375 }
4376
4377 struct nl_msg* msg = nlmsg_alloc();
4378
4379 if (!msg) {
4380 fprintf(stderr, "Failed to allocate netlink message.\n");
4381 nlfree(&nl);
4382 return -2;
4383 }
4384
4385 genlmsg_put(msg,
4386 NL_AUTO_PORT,
4387 NL_AUTO_SEQ,
4388 nl.id,
4389 0,
4390 NLM_F_DUMP,
4391 NL80211_CMD_GET_STATION,
4392 0);
4393
4394 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4395 nl_send_auto(nl.socket, msg);
4396 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4397 nl_recvmsgs(nl.socket, nl.cb);
4398 nlmsg_free(msg);
4399 nlfree(&nl);
4400
4401 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4402 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4403 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4404 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4405 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4406 return RETURN_OK;
4407#else
4408 //iw utility to retrieve station information
4409#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4410#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4411#define MACFILE "/tmp/wifi_AssoMac.txt"
4412#define TXRATEFILE "/tmp/wifi_txrate.txt"
4413#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4414 FILE *file = NULL;
4415 char if_name[10] = {'\0'};
4416 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004417 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004418 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004419 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004420
developerac6f1142022-12-20 19:26:35 +08004421 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004422 return RETURN_ERR;
4423
4424 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004425
4426 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4427 file = popen(pipeCmd, "r");
4428
4429 if(file == NULL)
4430 return RETURN_ERR; //popen failed
4431
4432 fgets(line, sizeof line, file);
4433 device = atoi(line);
4434 pclose(file);
4435
4436 if(device == 0)
4437 return RETURN_ERR; //No devices are connected
4438
4439 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4440 system(pipeCmd);
4441
4442 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4443
4444 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4445
4446 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4447
4448 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4449
4450 //devIndex starts from 1, ++count
4451 if((file = fopen(SIGNALFILE, "r")) != NULL )
4452 {
4453 for(count =0;fgets(line, sizeof line, file) != NULL;)
4454 {
4455 if (++count == devIndex)
4456 {
4457 output_struct->wifi_devSignalStrength = atoi(line);
4458 break;
4459 }
4460 }
4461 fclose(file);
4462 }
4463 else
4464 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4465
4466 if((file = fopen(MACFILE, "r")) != NULL )
4467 {
4468 for(count =0;fgets(line, sizeof line, file) != NULL;)
4469 {
4470 if (++count == devIndex)
4471 {
4472 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]);
4473 break;
4474 }
4475 }
4476 fclose(file);
4477 }
4478 else
4479 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4480
4481 if((file = fopen(TXRATEFILE, "r")) != NULL )
4482 {
4483 for(count =0;fgets(line, sizeof line, file) != NULL;)
4484 {
4485 if (++count == devIndex)
4486 {
4487 output_struct->wifi_devTxRate = atoi(line);
4488 break;
4489 }
4490 }
4491 fclose(file);
4492 }
4493 else
4494 fprintf(stderr,"fopen wifi_txrate.txt failed");
4495
4496 if((file = fopen(RXRATEFILE, "r")) != NULL)
4497 {
4498 for(count =0;fgets(line, sizeof line, file) != NULL;)
4499 {
4500 if (++count == devIndex)
4501 {
4502 output_struct->wifi_devRxRate = atoi(line);
4503 break;
4504 }
4505 }
4506 fclose(file);
4507 }
4508 else
4509 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4510
4511 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4512
4513 return RETURN_OK;
4514#endif
4515}
4516
4517INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4518{
4519 if (NULL == device)
4520 return RETURN_ERR;
4521 return RETURN_OK;
4522}
4523//<<
4524
4525
4526//--------------wifi_ap_hal-----------------------------
4527//enables CTS protection for the radio used by this AP
4528INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4529{
4530 //save config and Apply instantly
4531 return RETURN_ERR;
4532}
4533
4534// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4535INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4536{
developer463d39a2022-09-13 15:32:51 +08004537 char config_file[64] = {'\0'};
4538 char buf[64] = {'\0'};
4539 struct params list;
4540
4541 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4542 list.name = "ht_coex";
4543 snprintf(buf, sizeof(buf), "%d", enable);
4544 list.value = buf;
4545
4546 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4547 wifi_hostapdWrite(config_file, &list, 1);
4548 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4549
4550 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4551
4552 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004553}
4554
4555//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4556INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4557{
developerea4bcce2022-09-13 15:26:13 +08004558 char config_file[MAX_BUF_SIZE] = {'\0'};
4559 char buf[MAX_BUF_SIZE] = {'\0'};
4560 struct params list;
4561
4562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4563 if (threshold < 256 || threshold > 2346 )
4564 return RETURN_ERR;
4565 list.name = "fragm_threshold";
4566 snprintf(buf, sizeof(buf), "%d", threshold);
4567 list.value = buf;
4568
4569 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4570 wifi_hostapdWrite(config_file, &list, 1);
4571 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004572
developerea4bcce2022-09-13 15:26:13 +08004573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004574
4575 return RETURN_OK;
4576}
4577
4578// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4579INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4580{
developer51a927d2022-09-13 15:42:22 +08004581 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004582 char cmd[512] = {'\0'};
4583 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004584 char stbc_config[16] = {'\0'};
4585 wifi_band band;
4586 int iterator = 0;
4587 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004588 int ant_count = 0;
4589 int ant_bitmap = 0;
4590 struct params list;
developer51a927d2022-09-13 15:42:22 +08004591
4592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4593
4594 band = wifi_index_to_band(radioIndex);
4595 if (band == band_invalid)
4596 return RETURN_ERR;
4597
4598 if (band == band_2_4)
4599 iterator = 1;
4600 else if (band == band_5)
4601 iterator = 2;
4602 else
4603 return RETURN_OK;
4604
developer110b8a32022-12-26 15:56:44 +08004605 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4606 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4607 ant_count += ant_bitmap & 1;
4608
4609 if (ant_count == 1 && STBC_Enable == TRUE) {
4610 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4611 return RETURN_OK;
4612 }
4613
developer51a927d2022-09-13 15:42:22 +08004614 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4615
4616 // set ht and vht config
4617 for (int i = 0; i < iterator; i++) {
4618 memset(stbc_config, 0, sizeof(stbc_config));
4619 memset(cmd, 0, sizeof(cmd));
4620 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004621 list.name = (i == 0)?"ht_capab":"vht_capab";
4622 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004623 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4624 _syscmd(cmd, buf, sizeof(buf));
4625 if (strlen(buf) != 0)
4626 current_stbc = TRUE;
4627 if (current_stbc == STBC_Enable)
4628 continue;
4629
4630 if (STBC_Enable == TRUE) {
4631 // Append the STBC flags in capab config
4632 memset(cmd, 0, sizeof(cmd));
4633 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004634 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004635 else
developer6372c2b2022-10-27 17:39:51 +08004636 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 +08004637 _syscmd(cmd, buf, sizeof(buf));
4638 } else if (STBC_Enable == FALSE) {
4639 // Remove the STBC flags and remain other flags in capab
4640 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004641 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004642 _syscmd(cmd, buf, sizeof(buf));
4643 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004644 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004645 _syscmd(cmd, buf, sizeof(buf));
4646 }
developer110b8a32022-12-26 15:56:44 +08004647 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4648 list.value = buf;
4649 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004650 }
4651
4652 wifi_reloadAp(radioIndex);
4653
4654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4655 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004656}
4657
4658// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4659INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4660{
developerfe7aefc2022-12-23 17:13:37 +08004661 char cmd[128] = {0};
4662 char buf[128] = {0};
4663 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004664
4665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4666
4667 if(output_bool == NULL)
4668 return RETURN_ERR;
4669
developerfe7aefc2022-12-23 17:13:37 +08004670 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4671 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004672
developerfe7aefc2022-12-23 17:13:37 +08004673 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4674 _syscmd(cmd, buf, sizeof(buf));
4675
4676 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004677 *output_bool = TRUE;
4678 else
4679 *output_bool = FALSE;
4680
4681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4682 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004683}
4684
4685// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4686INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4687{
developerfe7aefc2022-12-23 17:13:37 +08004688 char config_file[128] = {0};
4689 struct params list = {0};
4690 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004691
4692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4693
developerfe7aefc2022-12-23 17:13:37 +08004694 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004695 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004696
developerfe7aefc2022-12-23 17:13:37 +08004697 if (amsduEnable == enable)
4698 return RETURN_OK;
4699
4700 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4701 list.name = "amsdu";
4702 list.value = amsduEnable? "1":"0";
4703 wifi_hostapdWrite(config_file, &list, 1);
4704 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4705 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004706
4707 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4708 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004709}
4710
4711//P2 // outputs the number of Tx streams
4712INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4713{
developer2de97692022-09-26 14:00:03 +08004714 char buf[8] = {0};
4715 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004716 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004717
4718 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4719
developer033b37b2022-10-18 11:27:46 +08004720 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004721 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004722 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004723
developer110b8a32022-12-26 15:56:44 +08004724 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004725
4726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4727
4728 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004729}
4730
developer110b8a32022-12-26 15:56:44 +08004731INT fitChainMask(INT radioIndex, int antcount)
4732{
4733 char buf[128] = {0};
4734 char cmd[128] = {0};
4735 char config_file[64] = {0};
4736 wifi_band band;
4737 struct params list[2] = {0};
4738
4739 band = wifi_index_to_band(radioIndex);
4740 if (band == band_invalid)
4741 return RETURN_ERR;
4742
4743 list[0].name = "he_mu_beamformer";
4744 list[1].name = "he_su_beamformer";
4745
4746 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4747 if (antcount == 1) {
4748 // remove config about multiple antennas
4749 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4750 _syscmd(cmd, buf, sizeof(buf));
4751
4752 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4753 _syscmd(cmd, buf, sizeof(buf));
4754
4755 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4756 _syscmd(cmd, buf, sizeof(buf));
4757
4758 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4759 _syscmd(cmd, buf, sizeof(buf));
4760
4761 list[0].value = "0";
4762 list[1].value = "0";
4763 } else {
4764 // If we only set RX STBC means STBC is enable and TX STBC is disable when last time set one antenna. so we need to add it back.
4765 if (band == band_2_4 || band == band_5) {
4766 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4767 _syscmd(cmd, buf, sizeof(buf));
4768 if (strlen(buf) > 0) {
4769 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4770 _syscmd(cmd, buf, sizeof(buf));
4771 }
4772 }
4773 if (band == band_5) {
4774 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4775 _syscmd(cmd, buf, sizeof(buf));
4776 if (strlen(buf) > 0) {
4777 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4778 _syscmd(cmd, buf, sizeof(buf));
4779 }
4780 }
4781
4782 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4783 _syscmd(cmd, buf, sizeof(buf));
4784 if (strlen(buf) == 0) {
4785 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4786 _syscmd(cmd, buf, sizeof(buf));
4787 }
4788
4789 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4790 _syscmd(cmd, buf, sizeof(buf));
4791 if (strlen(buf) == 0) {
4792 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4793 _syscmd(cmd, buf, sizeof(buf));
4794 }
4795
4796 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4797 _syscmd(cmd, buf, sizeof(buf));
4798 if (strlen(buf) == 0) {
4799 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4800 } else {
4801 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4802 }
4803 _syscmd(cmd, buf, sizeof(buf));
4804
4805 list[0].value = "1";
4806 list[1].value = "1";
4807 }
4808 wifi_hostapdWrite(config_file, list, 2);
4809}
4810
developer06a01d92022-09-07 16:32:39 +08004811//P2 // sets the number of Tx streams to an enviornment variable
4812INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4813{
developer2de97692022-09-26 14:00:03 +08004814 char cmd[128] = {0};
4815 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004816 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08004817 int cur_mask = 0;
4818 int antcount = 0;
4819 wifi_band band;
developer2de97692022-09-26 14:00:03 +08004820
4821 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4822
developer110b8a32022-12-26 15:56:44 +08004823 if (numStreams <= 0) {
4824 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08004825 return RETURN_ERR;
4826 }
developer110b8a32022-12-26 15:56:44 +08004827
4828 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4829 if (cur_mask == numStreams)
4830 return RETURN_OK;
4831
developer2de97692022-09-26 14:00:03 +08004832 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004833
4834 phyId = radio_index_to_phy(radioIndex);
4835 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004836 _syscmd(cmd, buf, sizeof(buf));
4837
4838 if (strlen(buf) > 0) {
4839 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4840 return RETURN_ERR;
4841 }
developer2de97692022-09-26 14:00:03 +08004842
developer110b8a32022-12-26 15:56:44 +08004843 // if chain mask changed, we need to make the hostapd config valid.
4844 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
4845 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08004846 }
developer110b8a32022-12-26 15:56:44 +08004847 fitChainMask(radioIndex, antcount);
4848
4849 wifi_setRadioEnable(radioIndex, TRUE);
4850
developer2de97692022-09-26 14:00:03 +08004851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4852 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004853}
4854
4855//P2 // outputs the number of Rx streams
4856INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4857{
developer110b8a32022-12-26 15:56:44 +08004858 char buf[8] = {0};
4859 char cmd[128] = {0};
4860 int phyId = 0;
4861
developer2de97692022-09-26 14:00:03 +08004862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004863
4864 phyId = radio_index_to_phy(radioIndex);
4865 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
4866 _syscmd(cmd, buf, sizeof(buf));
4867
4868 *output_int = (INT)strtol(buf, NULL, 16);
4869
developer2de97692022-09-26 14:00:03 +08004870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004871
developer06a01d92022-09-07 16:32:39 +08004872 return RETURN_OK;
4873}
4874
4875//P2 // sets the number of Rx streams to an enviornment variable
4876INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4877{
developer2de97692022-09-26 14:00:03 +08004878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4879 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4880 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4881 return RETURN_ERR;
4882 }
4883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004884 return RETURN_ERR;
4885}
4886
4887//Get radio RDG enable setting
4888INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4889{
4890 if (NULL == output_bool)
4891 return RETURN_ERR;
4892 *output_bool = TRUE;
4893 return RETURN_OK;
4894}
4895
4896//Get radio RDG enable setting
4897INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4898{
4899 if (NULL == output_bool)
4900 return RETURN_ERR;
4901 *output_bool = TRUE;
4902 return RETURN_OK;
4903}
4904
4905//Set radio RDG enable setting
4906INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4907{
4908 return RETURN_ERR;
4909}
4910
4911//Get radio ADDBA enable setting
4912INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4913{
4914 if (NULL == output_bool)
4915 return RETURN_ERR;
4916 *output_bool = TRUE;
4917 return RETURN_OK;
4918}
4919
4920//Set radio ADDBA enable setting
4921INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4922{
4923 return RETURN_ERR;
4924}
4925
4926//Get radio auto block ack enable setting
4927INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4928{
4929 if (NULL == output_bool)
4930 return RETURN_ERR;
4931 *output_bool = TRUE;
4932 return RETURN_OK;
4933}
4934
4935//Set radio auto block ack enable setting
4936INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4937{
4938 return RETURN_ERR;
4939}
4940
4941//Get radio 11n pure mode enable support
4942INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4943{
4944 if (NULL == output_bool)
4945 return RETURN_ERR;
4946 *output_bool = TRUE;
4947 return RETURN_OK;
4948}
4949
4950//Get radio 11n pure mode enable setting
4951INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4952{
4953 if (NULL == output_bool)
4954 return RETURN_ERR;
4955 *output_bool = TRUE;
4956 return RETURN_OK;
4957}
4958
4959//Set radio 11n pure mode enable setting
4960INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4961{
4962 return RETURN_ERR;
4963}
4964
4965//Get radio IGMP snooping enable setting
4966INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4967{
developerd946fd62022-12-08 18:03:28 +08004968 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004969 char cmd[128]={0};
4970 char buf[4]={0};
4971 bool bridge = FALSE, mac80211 = FALSE;
4972 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4973
4974 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004975 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004976
4977 *output_bool = FALSE;
4978
4979 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4980 _syscmd(cmd, buf, sizeof(buf));
4981 if (strncmp(buf, "1", 1) == 0)
4982 bridge = TRUE;
4983
developerac6f1142022-12-20 19:26:35 +08004984 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004985 return RETURN_ERR;
4986 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
developer81bf2ed2022-09-13 15:31:14 +08004987 _syscmd(cmd, buf, sizeof(buf));
4988 if (strncmp(buf, "1", 1) == 0)
4989 mac80211 = TRUE;
4990
4991 if (bridge && mac80211)
4992 *output_bool = TRUE;
4993
4994 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004995 return RETURN_OK;
4996}
4997
4998//Set radio IGMP snooping enable setting
4999INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5000{
developerd946fd62022-12-08 18:03:28 +08005001 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005002 char cmd[128]={0};
5003 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08005004 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08005005 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5006
5007 // bridge
5008 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5009 _syscmd(cmd, buf, sizeof(buf));
5010
developer804c64f2022-10-19 13:54:40 +08005011 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005012 // mac80211
developer804c64f2022-10-19 13:54:40 +08005013 for (int i = 0; i < max_num_radios; i++) {
developerac6f1142022-12-20 19:26:35 +08005014 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005015 return RETURN_ERR;
5016 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
developer81bf2ed2022-09-13 15:31:14 +08005017 _syscmd(cmd, buf, sizeof(buf));
5018 }
5019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5020 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005021}
5022
5023//Get the Reset count of radio
5024INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5025{
5026 if (NULL == output_int)
5027 return RETURN_ERR;
5028 *output_int = (radioIndex==0)? 1: 3;
5029
5030 return RETURN_OK;
5031}
5032
5033
5034//---------------------------------------------------------------------------------------------------
5035//
5036// Additional Wifi AP level APIs used for Access Point devices
5037//
5038//---------------------------------------------------------------------------------------------------
5039
5040// creates a new ap and pushes these parameters to the hardware
5041INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5042{
developer7930d352022-12-21 17:55:42 +08005043 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005044 return RETURN_OK;
5045}
5046
5047// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5048INT wifi_deleteAp(INT apIndex)
5049{
developerd946fd62022-12-08 18:03:28 +08005050 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005051 char buf[1024];
5052 char cmd[128];
5053
developerac6f1142022-12-20 19:26:35 +08005054 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005055 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005056
developer7930d352022-12-21 17:55:42 +08005057 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005058 _syscmd(cmd, buf, sizeof(buf));
5059
5060 wifi_removeApSecVaribles(apIndex);
5061
5062 return RETURN_OK;
5063}
5064
5065// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5066INT wifi_getApName(INT apIndex, CHAR *output_string)
5067{
developerd946fd62022-12-08 18:03:28 +08005068 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005069 if(NULL == output_string)
5070 return RETURN_ERR;
5071
developerac6f1142022-12-20 19:26:35 +08005072 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005073 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005074 else
5075 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005076 return RETURN_OK;
5077}
5078
5079// Outputs the index number in that corresponds to the SSID string
5080INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5081{
developerd946fd62022-12-08 18:03:28 +08005082 char cmd [128] = {0};
5083 char buf[32] = {0};
5084 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005085 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005086
developerd946fd62022-12-08 18:03:28 +08005087 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5088 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005089
developerac6f1142022-12-20 19:26:35 +08005090 if (strlen(buf) != 0) {
5091 apIndex_str = strtok(buf, "\n");
5092 *output_int = strtoul(apIndex_str, NULL, 10);
5093 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005094 }
developer67b8ee92022-12-20 10:48:43 +08005095
5096 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5097 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5098 if (apIndex_str) {
5099 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5100 return RETURN_OK;
5101 }
developerd946fd62022-12-08 18:03:28 +08005102 *output_int = -1;
5103 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005104}
5105
5106INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5107{
5108 return wifi_getIndexFromName(inputSsidString, output_int);
5109}
5110
5111// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5112INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5113{
5114 char buf[MAX_BUF_SIZE] = {0};
5115 char cmd[MAX_CMD_SIZE] = {0};
5116 char config_file[MAX_BUF_SIZE] = {0};
5117
5118 if(NULL == output_string)
5119 return RETURN_ERR;
5120
5121 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5122 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5123 if((strcmp(buf,"3")==0))
5124 snprintf(output_string, 32, "WPAand11i");
5125 else if((strcmp(buf,"2")==0))
5126 snprintf(output_string, 32, "11i");
5127 else if((strcmp(buf,"1")==0))
5128 snprintf(output_string, 32, "WPA");
5129 else
5130 snprintf(output_string, 32, "None");
5131
5132 return RETURN_OK;
5133}
5134
5135// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5136INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5137{
5138 char config_file[MAX_BUF_SIZE] = {0};
5139 struct params list;
5140
5141 if (NULL == beaconTypeString)
5142 return RETURN_ERR;
5143 list.name = "wpa";
5144 list.value = "0";
5145
5146 if((strcmp(beaconTypeString,"WPAand11i")==0))
5147 list.value="3";
5148 else if((strcmp(beaconTypeString,"11i")==0))
5149 list.value="2";
5150 else if((strcmp(beaconTypeString,"WPA")==0))
5151 list.value="1";
5152
5153 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5154 wifi_hostapdWrite(config_file, &list, 1);
5155 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5156 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5157 return RETURN_OK;
5158}
5159
5160// sets the beacon interval on the hardware for this AP
5161INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5162{
developer5f222492022-09-13 15:21:52 +08005163 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5164 struct params params={'\0'};
5165 char buf[MAX_BUF_SIZE] = {'\0'};
5166 char config_file[MAX_BUF_SIZE] = {'\0'};
5167
5168 params.name = "beacon_int";
5169 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5170 params.value = buf;
5171
5172 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5173 wifi_hostapdWrite(config_file, &params, 1);
5174
5175 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5177 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005178}
5179
5180INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5181{
developer5b398df2022-11-17 20:39:48 +08005182 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5183 return RETURN_ERR;
5184 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005185}
5186
5187// Get the packet size threshold supported.
5188INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5189{
5190 //save config and apply instantly
5191 if (NULL == output_bool)
5192 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005193 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005194 return RETURN_OK;
5195}
5196
5197// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5198INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5199{
developer514406b2022-12-05 17:20:21 +08005200 char buf[16] = {0};
5201 char config_file[128] = {0};
5202 struct params param = {0};
5203
5204 if (threshold > 65535) {
5205 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5206 return RETURN_ERR;
5207 }
developer06a01d92022-09-07 16:32:39 +08005208
developer23e71282023-01-18 10:25:19 +08005209 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005210 snprintf(buf, sizeof(buf), "%u", threshold);
5211 param.name = "rts_threshold";
5212 param.value = buf;
5213 wifi_hostapdWrite(config_file, &param, 1);
5214 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5215 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005216
5217 return RETURN_OK;
5218}
5219
5220// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5221INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5222{
5223 if (NULL == output_string)
5224 return RETURN_ERR;
5225 snprintf(output_string, 32, "TKIPandAESEncryption");
5226 return RETURN_OK;
5227
5228}
5229
5230// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5231INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5232{
5233 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005234 char *param_name = NULL;
5235 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005236
5237 if(NULL == output_string)
5238 return RETURN_ERR;
5239
5240 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5241 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5242
5243 if(strcmp(buf,"0")==0)
5244 {
5245 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5246 snprintf(output_string, 32, "None");
5247 return RETURN_OK;
5248 }
5249 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5250 param_name = "rsn_pairwise";
5251 else if((strcmp(buf,"1")==0))
5252 param_name = "wpa_pairwise";
5253 else
5254 return RETURN_ERR;
5255 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005256 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005257 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5258 param_name = "wpa_pairwise";
5259 memset(output_string, '\0', 32);
5260 wifi_hostapdRead(config_file, param_name, output_string, 32);
5261 }
developer06a01d92022-09-07 16:32:39 +08005262 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5263
developer72ec5572023-01-05 16:27:13 +08005264 if(strcmp(output_string,"TKIP CCMP") == 0)
5265 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5266 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005267 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5268 else if(strcmp(output_string,"CCMP") == 0)
5269 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005270
5271 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5272 return RETURN_OK;
5273}
5274
5275// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5276INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5277{
5278 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5279 struct params params={'\0'};
5280 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005281 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005282
5283 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005284 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005285
5286 if(strcmp(encMode, "TKIPEncryption") == 0)
5287 params.value = "TKIP";
5288 else if(strcmp(encMode,"AESEncryption") == 0)
5289 params.value = "CCMP";
5290 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5291 params.value = "TKIP CCMP";
5292
5293 if((strcmp(output_string,"WPAand11i")==0))
5294 {
5295 params.name = "wpa_pairwise";
5296 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5297 wifi_hostapdWrite(config_file, &params, 1);
5298 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5299
developer30423732022-12-01 16:17:49 +08005300 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005301 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5302 wifi_hostapdWrite(config_file, &params, 1);
5303 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5304
5305 return RETURN_OK;
5306 }
5307 else if((strcmp(output_string,"11i")==0))
5308 {
5309 params.name = "rsn_pairwise";
5310 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5311 wifi_hostapdWrite(config_file, &params, 1);
5312 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5313 return RETURN_OK;
5314 }
5315 else if((strcmp(output_string,"WPA")==0))
5316 {
5317 params.name = "wpa_pairwise";
5318 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5319 wifi_hostapdWrite(config_file, &params, 1);
5320 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5321 return RETURN_OK;
5322 }
5323
5324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5325 return RETURN_OK;
5326}
5327
5328// deletes internal security varable settings for this ap
5329INT wifi_removeApSecVaribles(INT apIndex)
5330{
5331 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005332 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005333 //_syscmd(cmd, buf, sizeof(buf));
5334
developerd946fd62022-12-08 18:03:28 +08005335 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005336 //_syscmd(cmd, buf, sizeof(buf));
5337 return RETURN_ERR;
5338}
5339
5340// changes the hardware settings to disable encryption on this ap
5341INT wifi_disableApEncryption(INT apIndex)
5342{
5343 //Apply instantly
5344 return RETURN_ERR;
5345}
5346
5347// set the authorization mode on this ap
5348// mode mapping as: 1: open, 2: shared, 4:auto
5349INT wifi_setApAuthMode(INT apIndex, INT mode)
5350{
developeraf95c502022-09-13 16:18:22 +08005351 struct params params={0};
5352 char config_file[64] = {0};
5353 int ret;
5354
5355 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5356
5357 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5358 params.name = "auth_algs";
5359
developer72ec5572023-01-05 16:27:13 +08005360 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005361 params.value = "3";
5362 else if (mode & 2)
5363 params.value = "2";
5364 else if (mode & 1)
5365 params.value = "1";
5366 else
5367 params.value = "0";
5368
5369 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5370 wifi_hostapdWrite(config_file, &params, 1);
5371 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005372 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005373 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5374
5375 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005376}
5377
5378// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5379INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5380{
5381 //save to wifi config, and wait for wifi restart to apply
5382 struct params params={'\0'};
5383 char config_file[MAX_BUF_SIZE] = {0};
5384 int ret;
5385
5386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5387 if(authMode == NULL)
5388 return RETURN_ERR;
5389
5390 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5391 params.name = "wpa_key_mgmt";
5392
5393 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5394 params.value = "WPA-PSK";
5395 else if(strcmp(authMode,"EAPAuthentication") == 0)
5396 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005397 else if (strcmp(authMode, "SAEAuthentication") == 0)
5398 params.value = "SAE";
5399 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5400 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005401 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5402 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005403 else if (strcmp(authMode, "Enhanced_Open") == 0)
5404 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005405 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5406 return RETURN_OK; //This is taken careof in beaconType
5407
5408 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5409 ret=wifi_hostapdWrite(config_file,&params,1);
5410 if(!ret)
5411 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5412 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5413
5414 return ret;
5415}
5416
5417// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5418INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5419{
5420 //save to wifi config, and wait for wifi restart to apply
5421 char BeaconType[50] = {0};
5422 char config_file[MAX_BUF_SIZE] = {0};
5423
5424 *authMode = 0;
5425 wifi_getApBeaconType(apIndex,BeaconType);
5426 printf("%s____%s \n",__FUNCTION__,BeaconType);
5427
5428 if(strcmp(BeaconType,"None") == 0)
5429 strcpy(authMode,"None");
5430 else
5431 {
5432 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5433 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5434 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5435 if(strcmp(authMode,"WPA-PSK") == 0)
5436 strcpy(authMode,"SharedAuthentication");
5437 else if(strcmp(authMode,"WPA-EAP") == 0)
5438 strcpy(authMode,"EAPAuthentication");
5439 }
5440
5441 return RETURN_OK;
5442}
5443
5444// Outputs the number of stations associated per AP
5445INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5446{
developerd946fd62022-12-08 18:03:28 +08005447 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005448 char cmd[128]={0};
5449 char buf[128]={0};
5450 BOOL status = false;
5451
5452 if(apIndex > MAX_APS)
5453 return RETURN_ERR;
5454
5455 wifi_getApEnable(apIndex,&status);
5456 if (!status)
5457 return RETURN_OK;
5458
developerd946fd62022-12-08 18:03:28 +08005459 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005460 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005461 return RETURN_ERR;
5462 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005463 _syscmd(cmd, buf, sizeof(buf));
5464 sscanf(buf,"%lu", output_ulong);
5465
5466 return RETURN_OK;
5467}
5468
5469// manually removes any active wi-fi association with the device specified on this ap
5470INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5471{
developerd946fd62022-12-08 18:03:28 +08005472 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005473 char buf[126]={'\0'};
5474
developerac6f1142022-12-20 19:26:35 +08005475 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005476 return RETURN_ERR;
5477 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005478 system(buf);
5479
5480 return RETURN_OK;
5481}
5482
5483// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5484INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5485{
5486 if(NULL == output_int)
5487 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005488 int max_radio_num = 0;
5489 wifi_getMaxRadioNumber(&max_radio_num);
5490 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005491 return RETURN_OK;
5492}
5493
5494// sets the radio index for the specific ap
5495INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5496{
5497 //set to config only and wait for wifi reset to apply settings
5498 return RETURN_ERR;
5499}
5500
5501// Get the ACL MAC list per AP
5502INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5503{
developerd946fd62022-12-08 18:03:28 +08005504 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005505 char cmd[MAX_CMD_SIZE]={'\0'};
5506 int ret = 0;
5507
developerac6f1142022-12-20 19:26:35 +08005508 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005509 return RETURN_ERR;
5510 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005511 ret = _syscmd(cmd,macArray,buf_size);
5512 if (ret != 0)
5513 return RETURN_ERR;
5514
5515 return RETURN_OK;
5516}
5517
developere6aafda2022-09-13 14:59:28 +08005518INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5519{
developerd946fd62022-12-08 18:03:28 +08005520 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005521 char cmd[MAX_CMD_SIZE]={'\0'};
5522 int ret = 0;
5523
developerac6f1142022-12-20 19:26:35 +08005524 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005525 return RETURN_ERR;
5526 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005527 ret = _syscmd(cmd,macArray,buf_size);
5528 if (ret != 0)
5529 return RETURN_ERR;
5530
5531 return RETURN_OK;
5532}
5533
5534
developer06a01d92022-09-07 16:32:39 +08005535// Get the list of stations associated per AP
5536INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5537{
developerd946fd62022-12-08 18:03:28 +08005538 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005539 char cmd[128];
5540
5541 if(apIndex > 3) //Currently supporting apIndex upto 3
5542 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005543 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005544 return RETURN_ERR;
5545 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5546 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005547 _syscmd(cmd, macArray, buf_size);
5548
5549 return RETURN_OK;
5550}
5551
5552// adds the mac address to the filter list
5553//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5554INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5555{
5556 char cmd[MAX_CMD_SIZE]={'\0'};
5557 char buf[MAX_BUF_SIZE]={'\0'};
5558
5559#if 0
developerd946fd62022-12-08 18:03:28 +08005560 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005561 if(_syscmd(cmd,buf,sizeof(buf)))
5562 return RETURN_ERR;
5563#endif
5564 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5565 if(_syscmd(cmd,buf,sizeof(buf)))
5566 return RETURN_ERR;
5567
5568 return RETURN_OK;
5569}
5570
5571// deletes the mac address from the filter list
5572//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5573INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5574{
5575 char cmd[MAX_CMD_SIZE]={'\0'};
5576 char buf[MAX_BUF_SIZE]={'\0'};
5577
5578#if 0
developerd946fd62022-12-08 18:03:28 +08005579 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005580 if(_syscmd(cmd,buf,sizeof(buf)))
5581 return RETURN_ERR;
5582
5583#endif
5584 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5585 if(_syscmd(cmd,buf,sizeof(buf)))
5586 return RETURN_ERR;
5587
5588 return RETURN_OK;
5589}
5590
5591// outputs the number of devices in the filter list
5592INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5593{
developere6aafda2022-09-13 14:59:28 +08005594 char cmd[MAX_BUF_SIZE]={0};
5595 char buf[MAX_CMD_SIZE]={0};
5596
5597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5598 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005599 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005600
5601 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5602 _syscmd(cmd, buf, sizeof(buf));
5603
5604 *output_uint = atoi(buf);
5605
5606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5607 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005608}
5609
5610INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5611{
5612 char cmd[128]={'\0'};
5613 char buf[128]={'\0'};
5614
5615 if(strcmp(action,"DENY")==0)
5616 {
5617 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5618 system(buf);
5619 return RETURN_OK;
5620 }
5621
5622 if(strcmp(action,"ALLOW")==0)
5623 {
5624 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5625 system(buf);
5626 return RETURN_OK;
5627 }
5628
5629 return RETURN_ERR;
5630
5631}
5632
5633// enable kick for devices on acl black list
5634INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5635{
5636 char aclArray[512] = {0}, *acl = NULL;
5637 char assocArray[512] = {0}, *asso = NULL;
5638
developere6aafda2022-09-13 14:59:28 +08005639 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005640 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5641
5642 // if there are no devices connected there is nothing to do
5643 if (strlen(assocArray) < 17)
5644 return RETURN_OK;
5645
5646 if (enable == TRUE)
5647 {
5648 //kick off the MAC which is in ACL array (deny list)
5649 acl = strtok(aclArray, "\r\n");
5650 while (acl != NULL) {
5651 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5652 wifi_kickApAssociatedDevice(apIndex, acl);
5653
5654 acl = strtok(NULL, "\r\n");
5655 }
developere6aafda2022-09-13 14:59:28 +08005656 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005657 }
5658 else
5659 {
developere6aafda2022-09-13 14:59:28 +08005660 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005661 }
5662
5663#if 0
5664 //TODO: need to revisit below implementation
5665 char aclArray[512]={0}, *acl=NULL;
5666 char assocArray[512]={0}, *asso=NULL;
5667 char buf[256]={'\0'};
5668 char action[10]={'\0'};
5669 FILE *fr=NULL;
5670 char interface[10]={'\0'};
5671 char config_file[MAX_BUF_SIZE] = {0};
5672
5673 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5674 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5675 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5676 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5677
5678 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5679 system(buf);
5680 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5681 system(buf);
5682 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5683 system(buf);
5684 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5685 system(buf);
5686 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5687 system(buf);
5688
5689 if ( enable == TRUE )
5690 {
5691 int device_count=0;
5692 strcpy(action,"DENY");
5693 //kick off the MAC which is in ACL array (deny list)
5694 acl = strtok (aclArray,",");
5695 while (acl != NULL) {
5696 if(strlen(acl)>=17)
5697 {
5698 apply_rules(apIndex, acl,action,interface);
5699 device_count++;
5700 //Register mac to be blocked ,in syscfg.db persistent storage
5701 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5702 system(buf);
5703 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5704 system(buf);
5705 system("syscfg commit");
5706
5707 wifi_kickApAssociatedDevice(apIndex, acl);
5708 }
5709 acl = strtok (NULL, ",");
5710 }
5711 }
5712 else
5713 {
5714 int device_count=0;
5715 char cmdmac[20]={'\0'};
5716 strcpy(action,"ALLOW");
5717 //kick off the MAC which is not in ACL array (allow list)
5718 acl = strtok (aclArray,",");
5719 while (acl != NULL) {
5720 if(strlen(acl)>=17)
5721 {
5722 apply_rules(apIndex, acl,action,interface);
5723 device_count++;
5724 //Register mac to be Allowed ,in syscfg.db persistent storage
5725 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5726 system(buf);
5727 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5728 system(buf);
5729 sprintf(cmdmac,"%s",acl);
5730 }
5731 acl = strtok (NULL, ",");
5732 }
5733 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5734 system(buf);
5735
5736 //Disconnect the mac which is not in ACL
5737 asso = strtok (assocArray,",");
5738 while (asso != NULL) {
5739 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5740 wifi_kickApAssociatedDevice(apIndex, asso);
5741 asso = strtok (NULL, ",");
5742 }
5743 }
5744#endif
5745 return RETURN_OK;
5746}
5747
5748INT wifi_setPreferPrivateConnection(BOOL enable)
5749{
developer06a01d92022-09-07 16:32:39 +08005750 return RETURN_OK;
5751}
5752
5753// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5754INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5755{
developerd946fd62022-12-08 18:03:28 +08005756 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005757 int items = 1;
5758 struct params list[2];
5759 char buf[MAX_BUF_SIZE] = {0};
5760 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005761 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005762
5763 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005764
developer10adcc12022-09-13 14:39:17 +08005765 if (filterMode == 0) {
5766 sprintf(buf, "%d", 0);
5767 list[0].value = buf;
5768
5769 char cmd[128], rtn[128];
developerac6f1142022-12-20 19:26:35 +08005770 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005771 return RETURN_ERR;
5772 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
developer10adcc12022-09-13 14:39:17 +08005773 _syscmd(cmd, rtn, sizeof(rtn));
5774 memset(cmd,0,sizeof(cmd));
5775 // Delete deny_mac_file in hostapd configuration
5776 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5777 _syscmd(cmd, rtn, sizeof(rtn));
5778 }
5779 else if (filterMode == 1) {
5780 sprintf(buf, "%d", filterMode);
5781 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005782 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5783 list[1].name = "accept_mac_file";
5784 list[1].value = acl_file;
5785 items = 2;
developer10adcc12022-09-13 14:39:17 +08005786 } else if (filterMode == 2) {
5787 //TODO: deny_mac_file
5788 sprintf(buf, "%d", 0);
5789 list[0].value = buf;
5790 list[1].name = "deny_mac_file";
5791 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5792 list[1].value = deny_file;
5793 items = 2;
5794 } else {
5795 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005796 }
developer10adcc12022-09-13 14:39:17 +08005797
developer06a01d92022-09-07 16:32:39 +08005798 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5799 wifi_hostapdWrite(config_file, list, items);
5800
5801 return RETURN_OK;
5802
5803#if 0
5804 if(apIndex==0 || apIndex==1)
5805 {
5806 //set the filtermode
5807 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5808 system(buf);
5809 system("syscfg commit");
5810
5811 if(filterMode==0)
5812 {
5813 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5814 system(buf);
5815 return RETURN_OK;
5816 }
5817 }
5818 return RETURN_OK;
5819#endif
5820}
5821
5822// 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.
5823INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5824{
5825 return RETURN_ERR;
5826}
5827
5828// gets the vlan ID for this ap from an internal enviornment variable
5829INT wifi_getApVlanID(INT apIndex, INT *output_int)
5830{
developer30423732022-12-01 16:17:49 +08005831 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005832 {
5833 *output_int=100;
5834 return RETURN_OK;
5835 }
5836
5837 return RETURN_ERR;
5838}
5839
5840// sets the vlan ID for this ap to an internal enviornment variable
5841INT wifi_setApVlanID(INT apIndex, INT vlanId)
5842{
5843 //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)
5844 return RETURN_ERR;
5845}
5846
5847// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5848INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5849{
5850 snprintf(bridgeName, 32, "brlan0");
5851 snprintf(IP, 32, "10.0.0.1");
5852 snprintf(subnet, 32, "255.255.255.0");
5853
5854 return RETURN_OK;
5855}
5856
5857//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5858INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5859{
5860 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5861 return RETURN_ERR;
5862}
5863
5864// reset the vlan configuration for this ap
5865INT wifi_resetApVlanCfg(INT apIndex)
5866{
developerf5fef612022-09-20 19:38:26 +08005867 char original_config_file[64] = {0};
5868 char current_config_file[64] = {0};
5869 char buf[64] = {0};
5870 char cmd[64] = {0};
5871 char vlan_file[64] = {0};
5872 char vlan_tagged_interface[16] = {0};
5873 char vlan_bridge[16] = {0};
5874 char vlan_naming[16] = {0};
5875 struct params list[4] = {0};
5876 wifi_band band;
5877
5878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5879
5880 band = wifi_index_to_band(apIndex);
5881 if (band == band_2_4)
5882 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08005883 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08005884 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08005885 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08005886 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5887
5888 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5889
5890 if (strlen(vlan_file) == 0)
5891 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005892
developerf5fef612022-09-20 19:38:26 +08005893 // The file should exist or this vap would not work.
5894 if (access(vlan_file, F_OK) != 0) {
5895 sprintf(cmd, "touch %s", vlan_file);
5896 _syscmd(cmd, buf, sizeof(buf));
5897 }
5898 list[0].name = "vlan_file";
5899 list[0].value = vlan_file;
5900
5901 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5902 list[1].name = "vlan_tagged_interface";
5903 list[1].value = vlan_tagged_interface;
5904
5905 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5906 list[2].name = "vlan_bridge";
5907 list[2].value = vlan_bridge;
5908
5909 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5910 list[3].name = "vlan_naming";
5911 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005912
developerf5fef612022-09-20 19:38:26 +08005913 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5914 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005915 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005916 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005917
developerf5fef612022-09-20 19:38:26 +08005918 // restart this ap
5919 wifi_setApEnable(apIndex, FALSE);
5920 wifi_setApEnable(apIndex, TRUE);
5921
5922 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5923
5924 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005925}
5926
5927// 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.
5928INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5929{
5930 return RETURN_ERR;
5931}
5932
5933// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5934INT wifi_startHostApd()
5935{
5936 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5937 system("systemctl start hostapd.service");
5938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5939 return RETURN_OK;
5940 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5941}
5942
5943// stops hostapd
5944INT wifi_stopHostApd()
5945{
5946 char cmd[128] = {0};
5947 char buf[128] = {0};
5948
5949 sprintf(cmd,"systemctl stop hostapd");
5950 _syscmd(cmd, buf, sizeof(buf));
5951
5952 return RETURN_OK;
5953}
5954
5955// restart hostapd dummy function
5956INT wifi_restartHostApd()
5957{
5958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5959 system("systemctl restart hostapd-global");
5960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5961
5962 return RETURN_OK;
5963}
5964
5965static int align_hostapd_config(int index)
5966{
5967 ULONG lval;
5968 wifi_getRadioChannel(index%2, &lval);
5969 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08005970 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005971}
5972
5973// sets the AP enable status variable for the specified ap.
5974INT wifi_setApEnable(INT apIndex, BOOL enable)
5975{
developerd946fd62022-12-08 18:03:28 +08005976 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005977 char config_file[MAX_BUF_SIZE] = {0};
5978 char cmd[MAX_CMD_SIZE] = {0};
5979 char buf[MAX_BUF_SIZE] = {0};
5980 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005981 int max_radio_num = 0;
5982 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005983
5984 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005985
5986 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005987 if (enable == status)
5988 return RETURN_OK;
5989
developerac6f1142022-12-20 19:26:35 +08005990 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005991 return RETURN_ERR;
5992
developer06a01d92022-09-07 16:32:39 +08005993 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005994 int radioIndex = apIndex % max_radio_num;
5995 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005996 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5997 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08005998 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005999 _syscmd(cmd, buf, sizeof(buf));
developer23e71282023-01-18 10:25:19 +08006000 sprintf(cmd, "iw %s del", interface_name);
6001 _syscmd(cmd, buf, sizeof(buf));
6002 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6003 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08006004 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006005 _syscmd(cmd, buf, sizeof(buf));
6006 }
6007 else {
developerd946fd62022-12-08 18:03:28 +08006008 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006009 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006010 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006011 _syscmd(cmd, buf, sizeof(buf));
6012 }
developera77d84b2023-02-22 16:10:50 +08006013
developer431128d2022-12-16 15:30:41 +08006014 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006015 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006016 _syscmd(cmd, buf, sizeof(buf));
6017 //Wait for wifi up/down to apply
6018 return RETURN_OK;
6019}
6020
6021// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6022INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6023{
developerd946fd62022-12-08 18:03:28 +08006024 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006025 char cmd[MAX_CMD_SIZE] = {'\0'};
6026 char buf[MAX_BUF_SIZE] = {'\0'};
6027
6028 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6029 return RETURN_ERR;
6030
6031 *output_bool = 0;
6032
6033 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6034 {
developerac6f1142022-12-20 19:26:35 +08006035 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006036 *output_bool = FALSE;
6037 return RETURN_OK;
6038 }
6039 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006040 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6041 }
6042
6043 return RETURN_OK;
6044}
6045
6046// Outputs the AP "Enabled" "Disabled" status from driver
6047INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6048{
6049 char cmd[128] = {0};
6050 char buf[128] = {0};
6051 BOOL output_bool;
6052
6053 if ( NULL == output_string)
6054 return RETURN_ERR;
6055 wifi_getApEnable(apIndex,&output_bool);
6056
6057 if(output_bool == 1)
6058 snprintf(output_string, 32, "Up");
6059 else
6060 snprintf(output_string, 32, "Disable");
6061
6062 return RETURN_OK;
6063}
6064
6065//Indicates whether or not beacons include the SSID name.
6066// outputs a 1 if SSID on the AP is enabled, else outputs 0
6067INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6068{
6069 //get the running status
6070 char config_file[MAX_BUF_SIZE] = {0};
6071 char buf[16] = {0};
6072
6073 if (!output)
6074 return RETURN_ERR;
6075
6076 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6077 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006078 // default is enable
6079 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6080 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006081
6082 return RETURN_OK;
6083}
6084
6085// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6086INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6087{
6088 //store the config, apply instantly
6089 char config_file[MAX_BUF_SIZE] = {0};
6090 struct params list;
6091
6092 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6093 list.name = "ignore_broadcast_ssid";
6094 list.value = enable?"0":"1";
6095
6096 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6097 wifi_hostapdWrite(config_file, &list, 1);
6098 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6099 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006100 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6102
6103 return RETURN_OK;
6104}
6105
6106//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6107INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6108{
6109 //get the running status
6110 if(!output_uint)
6111 return RETURN_ERR;
6112 *output_uint=16;
6113 return RETURN_OK;
6114}
6115
6116INT wifi_setApRetryLimit(INT apIndex, UINT number)
6117{
6118 //apply instantly
6119 return RETURN_ERR;
6120}
6121
6122//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6123INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6124{
6125 if(!output)
6126 return RETURN_ERR;
6127 *output=TRUE;
6128 return RETURN_OK;
6129}
6130
6131//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6132INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6133{
6134 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006135 char cmd[128] = {0};
6136 char buf[128] = {0};
6137 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006138 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006139
developer0b246d12022-09-30 15:24:20 +08006140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006141
developer0b246d12022-09-30 15:24:20 +08006142 wifi_getMaxRadioNumber(&max_radio_num);
6143 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006144 phyId = radio_index_to_phy(radioIndex);
6145 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006146 _syscmd(cmd,buf, sizeof(buf));
6147
6148 if (strlen(buf) > 0)
6149 *output = true;
6150
6151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006152
developer06a01d92022-09-07 16:32:39 +08006153 return RETURN_OK;
6154}
6155
6156//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6157INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6158{
6159 //get the running status from driver
6160 if(!output)
6161 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006162
6163 char config_file[MAX_BUF_SIZE] = {0};
6164 char buf[16] = {0};
6165
6166 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6167 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006168 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006169 *output = TRUE;
6170 else
6171 *output = FALSE;
6172
developer06a01d92022-09-07 16:32:39 +08006173 return RETURN_OK;
6174}
6175
6176// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6177INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6178{
6179 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006180 char config_file[MAX_BUF_SIZE] = {0};
6181 struct params list;
6182
6183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6184 list.name = "wmm_enabled";
6185 list.value = enable?"1":"0";
6186
6187 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6188 wifi_hostapdWrite(config_file, &list, 1);
6189 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6190 wifi_reloadAp(apIndex);
6191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6192
6193 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006194}
6195
6196//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.
6197INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6198{
6199 //get the running status from driver
6200 if(!output)
6201 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006202
6203 char config_file[128] = {0};
6204 char buf[16] = {0};
6205
6206 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6207 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6208 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6209 *output = TRUE;
6210 else
6211 *output = FALSE;
6212
developer06a01d92022-09-07 16:32:39 +08006213 return RETURN_OK;
6214}
6215
6216// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6217INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6218{
6219 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006220 char config_file[MAX_BUF_SIZE] = {0};
6221 struct params list;
6222
6223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6224 list.name = "uapsd_advertisement_enabled";
6225 list.value = enable?"1":"0";
6226
6227 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6228 wifi_hostapdWrite(config_file, &list, 1);
6229 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6230 wifi_reloadAp(apIndex);
6231 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6232
6233 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006234}
6235
developer6daeb3f2022-09-30 13:36:39 +08006236// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006237INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6238{
developerd946fd62022-12-08 18:03:28 +08006239 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006240 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6241 char cmd[128] = {0};
6242 char buf[128] = {0};
6243 char ack_filepath[128] = {0};
6244 uint16_t bitmap = 0;
6245 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6246 FILE *f = NULL;
6247
6248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6249
6250 // Get current setting
6251 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6252 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6253 _syscmd(cmd, buf, sizeof(buf));
6254 if (strlen(buf) > 0)
6255 bitmap = strtoul(buf, NULL, 10);
6256
6257 bitmap = strtoul(buf, NULL, 10);
6258
6259 if (ackPolicy == TRUE) { // True, unset this class
6260 bitmap &= ~class_map[class];
6261 } else { // False, set this class
6262 bitmap |= class_map[class];
6263 }
6264
6265 f = fopen(ack_filepath, "w");
6266 if (f == NULL) {
6267 fprintf(stderr, "%s: fopen failed\n", __func__);
6268 return RETURN_ERR;
6269 }
6270 fprintf(f, "%hu", bitmap);
6271 fclose(f);
6272
developerac6f1142022-12-20 19:26:35 +08006273 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006274 return RETURN_ERR;
6275 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006276 _syscmd(cmd, buf, sizeof(buf));
6277
6278 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6279 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006280}
6281
6282//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.
6283INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6284{
6285 //get the running status from driver
6286 if(!output_uint)
6287 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006288
6289 char output[16]={'\0'};
6290 char config_file[MAX_BUF_SIZE] = {0};
6291
6292 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6293 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6294 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6295 else {
6296 int device_num = atoi(output);
6297 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6298 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6299 return RETURN_ERR;
6300 }
6301 else {
6302 *output_uint = device_num;
6303 }
6304 }
6305
developer06a01d92022-09-07 16:32:39 +08006306 return RETURN_OK;
6307}
6308
6309INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6310{
6311 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006312 char str[MAX_BUF_SIZE]={'\0'};
6313 char cmd[MAX_CMD_SIZE]={'\0'};
6314 struct params params;
6315 char config_file[MAX_BUF_SIZE] = {0};
6316
6317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006318 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006319 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006320 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006321 }
6322 sprintf(str, "%d", number);
6323 params.name = "max_num_sta";
6324 params.value = str;
6325
6326 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6327 int ret = wifi_hostapdWrite(config_file, &params, 1);
6328 if (ret) {
6329 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6330 ,__func__, ret);
6331 }
6332
6333 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6334 if (ret) {
6335 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6336 ,__func__, ret);
6337 }
6338 wifi_reloadAp(apIndex);
6339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6340
6341 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006342}
6343
6344//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.
6345INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6346{
6347 //get the current threshold
6348 if(!output_uint)
6349 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006350 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6351 if (*output_uint == 0)
6352 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006353 return RETURN_OK;
6354}
6355
6356INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6357{
6358 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006359 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6360 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006361 return RETURN_ERR;
6362}
6363
6364//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.
6365INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6366{
6367 if(!output_uint)
6368 return RETURN_ERR;
6369 *output_uint = 3;
6370 return RETURN_OK;
6371}
6372
6373//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6374INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6375{
6376 if(!output_uint)
6377 return RETURN_ERR;
6378 *output_uint = 3;
6379 return RETURN_OK;
6380}
6381
6382//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.
6383INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6384{
6385 if(!output_in_seconds)
6386 return RETURN_ERR;
6387 *output_in_seconds = 0;
6388 return RETURN_OK;
6389}
6390
6391//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
6392INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6393{
6394 if(!output || apIndex>=MAX_APS)
6395 return RETURN_ERR;
6396 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006397 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006398 return RETURN_OK;
6399}
6400
6401//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6402INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6403{
developer587c1b62022-09-27 15:58:59 +08006404 char config_file[128] = {0};
6405 char wpa[16] = {0};
6406 char key_mgmt[64] = {0};
6407 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006408 if (!output)
6409 return RETURN_ERR;
6410
6411 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006412 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006413
developer587c1b62022-09-27 15:58:59 +08006414 strcpy(output, "None");//Copying "None" to output string for default case
6415 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006416 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006417 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006418 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006419 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006420 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006421 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006422 snprintf(output, 32, "WPA-WPA2-Personal");
6423
developer72ec5572023-01-05 16:27:13 +08006424 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6425 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006426 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006427 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006428 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006429 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006430 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006431 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006432 snprintf(output, 32, "WPA-WPA2-Enterprise");
6433 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006434 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006435 snprintf(output, 32, "WPA3-Personal");
6436 else
developer4a359672022-10-13 15:30:46 +08006437 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006438 }
developer06a01d92022-09-07 16:32:39 +08006439
6440 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6441 return RETURN_OK;
6442#if 0
6443 //TODO: need to revisit below implementation
6444 char securityType[32], authMode[32];
6445 int enterpriseMode=0;
6446
6447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6448 if(!output)
6449 return RETURN_ERR;
6450
6451 wifi_getApBeaconType(apIndex, securityType);
6452 strcpy(output,"None");//By default, copying "None" to output string
6453 if (strncmp(securityType,"None", strlen("None")) == 0)
6454 return RETURN_OK;
6455
6456 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6457 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6458
6459 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6460 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6461 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6462 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6463 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6464 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6466
6467 return RETURN_OK;
6468#endif
6469}
6470
6471INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6472{
6473 char securityType[32];
6474 char authMode[32];
6475
6476 //store settings and wait for wifi up to apply
6477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6478 if(!encMode)
6479 return RETURN_ERR;
6480
developer06a01d92022-09-07 16:32:39 +08006481 if (strcmp(encMode, "None")==0)
6482 {
6483 strcpy(securityType,"None");
6484 strcpy(authMode,"None");
6485 }
6486 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6487 {
6488 strcpy(securityType,"WPAand11i");
6489 strcpy(authMode,"PSKAuthentication");
6490 }
6491 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6492 {
6493 strcpy(securityType,"WPAand11i");
6494 strcpy(authMode,"EAPAuthentication");
6495 }
6496 else if (strcmp(encMode, "WPA-Personal")==0)
6497 {
6498 strcpy(securityType,"WPA");
6499 strcpy(authMode,"PSKAuthentication");
6500 }
6501 else if (strcmp(encMode, "WPA-Enterprise")==0)
6502 {
6503 strcpy(securityType,"WPA");
6504 strcpy(authMode,"EAPAuthentication");
6505 }
6506 else if (strcmp(encMode, "WPA2-Personal")==0)
6507 {
6508 strcpy(securityType,"11i");
6509 strcpy(authMode,"PSKAuthentication");
6510 }
6511 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6512 {
6513 strcpy(securityType,"11i");
6514 strcpy(authMode,"EAPAuthentication");
6515 }
developer587c1b62022-09-27 15:58:59 +08006516 else if (strcmp(encMode, "WPA3-Personal") == 0)
6517 {
6518 strcpy(securityType,"11i");
6519 strcpy(authMode,"SAEAuthentication");
6520 }
developer4a359672022-10-13 15:30:46 +08006521 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006522 {
6523 strcpy(securityType, "11i");
6524 strcpy(authMode, "PSK-SAEAuthentication");
6525 }
developer587c1b62022-09-27 15:58:59 +08006526 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6527 {
6528 strcpy(securityType,"11i");
6529 strcpy(authMode,"EAP_192-bit_Authentication");
6530 }
developer5c9fee82023-01-13 14:44:16 +08006531 else if (strcmp(encMode, "OWE") == 0)
6532 {
6533 strcpy(securityType,"11i");
6534 strcpy(authMode,"Enhanced_Open");
6535 }
developer06a01d92022-09-07 16:32:39 +08006536 else
6537 {
6538 strcpy(securityType,"None");
6539 strcpy(authMode,"None");
6540 }
6541 wifi_setApBeaconType(apIndex, securityType);
6542 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6544
6545 return RETURN_OK;
6546}
6547
6548
developer4b102122023-02-15 10:53:03 +08006549// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006550//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006551INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6552{
developer30423732022-12-01 16:17:49 +08006553 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006554 char config_file[MAX_BUF_SIZE] = {0};
6555
6556 if(output_string==NULL)
6557 return RETURN_ERR;
6558
6559 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6560 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6561
6562 if(strcmp(buf,"0")==0)
6563 {
6564 printf("wpa_mode is %s ......... \n",buf);
6565 return RETURN_ERR;
6566 }
6567
6568 wifi_dbg_printf("\nFunc=%s\n",__func__);
6569 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006570 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006571 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6572
6573 return RETURN_OK;
6574}
6575
developer4b102122023-02-15 10:53:03 +08006576// Set PreSharedKey associated with a Access Point.
6577// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006578INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6579{
6580 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6581 struct params params={'\0'};
6582 int ret;
6583 char config_file[MAX_BUF_SIZE] = {0};
6584
6585 if(NULL == preSharedKey)
6586 return RETURN_ERR;
6587
developer4b102122023-02-15 10:53:03 +08006588 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006589
developer4b102122023-02-15 10:53:03 +08006590 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006591 {
developer4b102122023-02-15 10:53:03 +08006592 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006593 return RETURN_ERR;
6594 }
6595 params.value = preSharedKey;
6596 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6597 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006598 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006599 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006600 wifi_reloadAp(apIndex);
6601 }
developer06a01d92022-09-07 16:32:39 +08006602 return ret;
6603 //TODO: call hostapd_cli for dynamic_config_control
6604}
6605
6606//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6607// outputs the passphrase, maximum 63 characters
6608INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6609{
6610 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6611
6612 wifi_dbg_printf("\nFunc=%s\n",__func__);
6613 if (NULL == output_string)
6614 return RETURN_ERR;
6615
6616 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6617 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6618 if(strcmp(buf,"0")==0)
6619 {
6620 printf("wpa_mode is %s ......... \n",buf);
6621 return RETURN_ERR;
6622 }
6623
6624 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6625 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6626
6627 return RETURN_OK;
6628}
6629
6630// sets the passphrase enviornment variable, max 63 characters
6631INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6632{
6633 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6634 struct params params={'\0'};
6635 char config_file[MAX_BUF_SIZE] = {0};
6636 int ret;
6637
6638 if(NULL == passPhrase)
6639 return RETURN_ERR;
6640
6641 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6642 {
6643 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6644 return RETURN_ERR;
6645 }
6646 params.name = "wpa_passphrase";
6647 params.value = passPhrase;
6648 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6649 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006650 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006651 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006652 wifi_reloadAp(apIndex);
6653 }
developer06a01d92022-09-07 16:32:39 +08006654
6655 return ret;
6656}
6657
6658//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.
6659INT wifi_setApSecurityReset(INT apIndex)
6660{
developer8d583982022-09-20 11:28:22 +08006661 char original_config_file[64] = {0};
6662 char current_config_file[64] = {0};
6663 char buf[64] = {0};
6664 char cmd[64] = {0};
6665 char wpa[4] = {0};
6666 char wpa_psk[64] = {0};
6667 char wpa_passphrase[64] = {0};
6668 char wpa_psk_file[128] = {0};
6669 char wpa_key_mgmt[64] = {0};
6670 char wpa_pairwise[32] = {0};
6671 wifi_band band;
6672 struct params list[6];
6673
6674 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6675
6676 band = wifi_index_to_band(apIndex);
6677 if (band == band_2_4)
6678 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006679 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006680 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006681 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006682 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6683 else
6684 return RETURN_ERR;
6685
6686 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6687 list[0].name = "wpa";
6688 list[0].value = wpa;
6689
6690 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6691 list[1].name = "wpa_psk";
6692 list[1].value = wpa_psk;
6693
6694 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6695 list[2].name = "wpa_passphrase";
6696 list[2].value = wpa_passphrase;
6697
6698 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6699
6700 if (strlen(wpa_psk_file) == 0)
6701 strcpy(wpa_psk_file, PSK_FILE);
6702
6703 if (access(wpa_psk_file, F_OK) != 0) {
6704 sprintf(cmd, "touch %s", wpa_psk_file);
6705 _syscmd(cmd, buf, sizeof(buf));
6706 }
6707 list[3].name = "wpa_psk_file";
6708 list[3].value = wpa_psk_file;
6709
6710 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6711 list[4].name = "wpa_key_mgmt";
6712 list[4].value = wpa_key_mgmt;
6713
6714 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6715 list[5].name = "wpa_pairwise";
6716 list[5].value = wpa_pairwise;
6717
6718 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6719 wifi_hostapdWrite(current_config_file, list, 6);
6720
6721 wifi_setApEnable(apIndex, FALSE);
6722 wifi_setApEnable(apIndex, TRUE);
6723
6724 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6725 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006726}
6727
6728//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).
6729INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6730{
developer8f2ddd52022-09-13 15:39:24 +08006731 char config_file[64] = {0};
6732 char buf[64] = {0};
6733 char cmd[256] = {0};
6734
6735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6736
developer06a01d92022-09-07 16:32:39 +08006737 if(!IP_output || !Port_output || !RadiusSecret_output)
6738 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006739
developer8f2ddd52022-09-13 15:39:24 +08006740 // Read the first matched config
6741 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6742 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6743 _syscmd(cmd, buf, sizeof(buf));
6744 strncpy(IP_output, buf, 64);
6745
6746 memset(buf, 0, sizeof(buf));
6747 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6748 _syscmd(cmd, buf, sizeof(buf));
6749 *Port_output = atoi(buf);
6750
6751 memset(buf, 0, sizeof(buf));
6752 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6753 _syscmd(cmd, buf, sizeof(buf));
6754 strncpy(RadiusSecret_output, buf, 64);
6755
6756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006757 return RETURN_OK;
6758}
6759
6760INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6761{
developer8f2ddd52022-09-13 15:39:24 +08006762 char config_file[64] = {0};
6763 char port_str[8] = {0};
6764 char cmd[256] = {0};
6765 char buf[128] = {0};
6766
6767 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08006768 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
6769 return RETURN_ERR;
6770
6771 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
6772 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006773
6774 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6775
6776 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6777 _syscmd(cmd, buf, sizeof(buf));
6778 memset(cmd, 0, sizeof(cmd));
6779
6780 snprintf(port_str, sizeof(port_str), "%d", port);
6781 if (strlen(buf) == 0)
6782 // Append
6783 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6784 "auth_server_addr=%s\\n"
6785 "auth_server_port=%s\\n"
6786 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6787 else {
6788 // Delete the three lines setting after the "# radius 1" comment
6789 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6790 _syscmd(cmd, buf, sizeof(buf));
6791 memset(cmd, 0, sizeof(cmd));
6792 // Use "# radius 1" comment to find the location to insert the radius setting
6793 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6794 "# radius 1\\n"
6795 "auth_server_addr=%s\\n"
6796 "auth_server_port=%s\\n"
6797 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6798 }
6799 if(_syscmd(cmd, buf, sizeof(buf))) {
6800 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6801 return RETURN_ERR;
6802 }
6803
6804 wifi_reloadAp(apIndex);
6805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6806 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006807}
6808
6809INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6810{
developer8f2ddd52022-09-13 15:39:24 +08006811 char config_file[64] = {0};
6812 char buf[64] = {0};
6813 char cmd[256] = {0};
6814
6815 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6816
developer06a01d92022-09-07 16:32:39 +08006817 if(!IP_output || !Port_output || !RadiusSecret_output)
6818 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006819
6820 // Read the second matched config
6821 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6822 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6823 _syscmd(cmd, buf, sizeof(buf));
6824 strncpy(IP_output, buf, 64);
6825
6826 memset(buf, 0, sizeof(buf));
6827 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6828 _syscmd(cmd, buf, sizeof(buf));
6829 *Port_output = atoi(buf);
6830
6831 memset(buf, 0, sizeof(buf));
6832 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6833 _syscmd(cmd, buf, sizeof(buf));
6834 strncpy(RadiusSecret_output, buf, 64);
6835
6836 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006837 return RETURN_OK;
6838}
6839
6840INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6841{
developer8f2ddd52022-09-13 15:39:24 +08006842 char config_file[64] = {0};
6843 char port_str[8] = {0};
6844 char cmd[256] = {0};
6845 char buf[128] = {0};
6846
6847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08006848 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
6849 return RETURN_ERR;
6850
6851 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
6852 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006853
6854 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6855
6856 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6857 _syscmd(cmd, buf, sizeof(buf));
6858 memset(cmd, 0, sizeof(cmd));
6859
6860 snprintf(port_str, sizeof(port_str), "%d", port);
6861 if (strlen(buf) == 0)
6862 // Append
6863 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6864 "auth_server_addr=%s\\n"
6865 "auth_server_port=%s\\n"
6866 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6867 else {
6868 // Delete the three lines setting after the "# radius 2" comment
6869 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6870 _syscmd(cmd, buf, sizeof(buf));
6871 memset(cmd, 0, sizeof(cmd));
6872 // Use "# radius 2" comment to find the location to insert the radius setting
6873 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6874 "# radius 2\\n"
6875 "auth_server_addr=%s\\n"
6876 "auth_server_port=%s\\n"
6877 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6878 }
6879 if(_syscmd(cmd, buf, sizeof(buf))) {
6880 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6881 return RETURN_ERR;
6882 }
6883
6884 wifi_reloadAp(apIndex);
6885 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6886 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006887}
6888
6889//RadiusSettings
6890INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6891{
6892 if(!output)
6893 return RETURN_ERR;
6894
6895 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6896 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6897 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6898 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6899 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6900 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.
6901 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6902 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6903 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6904 //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.
6905
6906 return RETURN_OK;
6907}
6908
6909INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6910{
6911 //store the paramters, and apply instantly
6912 return RETURN_ERR;
6913}
6914
6915//Device.WiFi.AccessPoint.{i}.WPS.Enable
6916//Enables or disables WPS functionality for this access point.
6917// outputs the WPS enable state of this ap in output_bool
6918INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6919{
developerd946fd62022-12-08 18:03:28 +08006920 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006921 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006922 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006923 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08006924 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006925 return RETURN_ERR;
6926 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006927 _syscmd(cmd, buf, sizeof(buf));
6928 if(strstr(buf, "configured"))
6929 *output_bool=TRUE;
6930 else
6931 *output_bool=FALSE;
6932
6933 return RETURN_OK;
6934}
6935
6936//Device.WiFi.AccessPoint.{i}.WPS.Enable
6937// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6938INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6939{
6940 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08006941 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08006942 struct params params;
6943
developer06a01d92022-09-07 16:32:39 +08006944 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6945 //store the paramters, and wait for wifi up to apply
6946 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08006947 if (enable == TRUE) {
6948 wifi_getApBeaconType(apIndex, buf);
6949 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
6950 params.value = "1";
6951 else // If ap set encryption
6952 params.value = "2";
6953 } else {
6954 params.value = "0";
6955 }
developer06a01d92022-09-07 16:32:39 +08006956
6957 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6958 wifi_hostapdWrite(config_file, &params, 1);
6959 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6960 wifi_reloadAp(apIndex);
6961
6962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6963 return RETURN_OK;
6964}
6965
6966//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
6967INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6968{
6969 if(!output)
6970 return RETURN_ERR;
6971 snprintf(output, 128, "PushButton,PIN");
6972 return RETURN_OK;
6973}
6974
6975//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6976//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.
6977// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6978INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6979{
6980 if(!output)
6981 return RETURN_ERR;
6982 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6983
6984 return RETURN_OK;
6985}
6986
6987//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6988// 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
6989INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6990{
6991 //apply instantly. No setting need to be stored.
6992 char methods[MAX_BUF_SIZE], *token, *next_token;
6993 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6994 struct params params;
6995
developer5b398df2022-11-17 20:39:48 +08006996 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006997 return RETURN_ERR;
6998 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6999 //store the paramters, and wait for wifi up to apply
7000
7001 snprintf(methods, sizeof(methods), "%s", methodString);
7002 for(token=methods; *token; token=next_token)
7003 {
7004 strtok_r(token, ",", &next_token);
7005 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7006 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7007 else if(*token=='E')
7008 {
7009 if(!strcmp(methods, "Ethernet"))
7010 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7011 else if(!strcmp(methods, "ExternalNFCToken"))
7012 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7013 else
7014 printf("%s: Unknown WpsConfigMethod\n", __func__);
7015 }
7016 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7017 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7018 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7019 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7020 else if(*token=='P' )
7021 {
7022 if(!strcmp(token, "PushButton"))
7023 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
7024 else if(!strcmp(token, "PIN"))
7025 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7026 else
7027 printf("%s: Unknown WpsConfigMethod\n", __func__);
7028 }
7029 else
7030 printf("%s: Unknown WpsConfigMethod\n", __func__);
7031 }
7032 params.name = "config_methods";
7033 params.value = config_methods;
7034 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7035 wifi_hostapdWrite(config_file, &params, 1);
7036 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7037 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7038
7039 return RETURN_OK;
7040}
7041
7042// outputs the pin value, ulong_pin must be allocated by the caller
7043INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7044{
7045 char buf[MAX_BUF_SIZE] = {0};
7046 char cmd[MAX_CMD_SIZE] = {0};
7047
developer5b398df2022-11-17 20:39:48 +08007048 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007049 return RETURN_ERR;
7050 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7051 _syscmd(cmd, buf, sizeof(buf));
7052 if(strlen(buf) > 0)
7053 *output_ulong=strtoul(buf, NULL, 10);
7054
7055 return RETURN_OK;
7056}
7057
7058// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7059INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7060{
7061 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7062 char ap_pin[16] = {0};
7063 char buf[MAX_BUF_SIZE] = {0};
7064 char config_file[MAX_BUF_SIZE] = {0};
7065 ULONG prev_pin = 0;
7066 struct params params;
7067
developer06a01d92022-09-07 16:32:39 +08007068 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7069 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7070 params.name = "ap_pin";
7071 params.value = ap_pin;
7072 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7073 wifi_hostapdWrite(config_file, &params, 1);
7074 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7076
7077 return RETURN_OK;
7078}
7079
7080// Output string is either Not configured or Configured, max 32 characters
7081INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7082{
developerd946fd62022-12-08 18:03:28 +08007083 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007084 char cmd[MAX_CMD_SIZE];
7085 char buf[MAX_BUF_SIZE]={0};
7086
developer5b398df2022-11-17 20:39:48 +08007087 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007088 return RETURN_ERR;
7089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7090 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007091 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007092 return RETURN_ERR;
7093 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007094 _syscmd(cmd, buf, sizeof(buf));
7095
developer348e3d92022-09-13 14:48:41 +08007096 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007097 snprintf(output_string, 32, "Configured");
7098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7099
7100 return RETURN_OK;
7101}
7102
7103// sets the WPS pin for this AP
7104INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7105{
developerd946fd62022-12-08 18:03:28 +08007106 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007107 char cmd[MAX_CMD_SIZE];
7108 char buf[MAX_BUF_SIZE]={0};
7109 BOOL enable;
7110
developer06a01d92022-09-07 16:32:39 +08007111 wifi_getApEnable(apIndex, &enable);
7112 if (!enable)
7113 return RETURN_ERR;
7114 wifi_getApWpsEnable(apIndex, &enable);
7115 if (!enable)
7116 return RETURN_ERR;
7117
developerac6f1142022-12-20 19:26:35 +08007118 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007119 return RETURN_ERR;
7120 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007121 _syscmd(cmd, buf, sizeof(buf));
7122 if((strstr(buf, "OK"))!=NULL)
7123 return RETURN_OK;
7124
7125 return RETURN_ERR;
7126}
7127
7128// This function is called when the WPS push button has been pressed for this AP
7129INT wifi_setApWpsButtonPush(INT apIndex)
7130{
7131 char cmd[MAX_CMD_SIZE];
7132 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007133 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007134 BOOL enable=FALSE;
7135
developer06a01d92022-09-07 16:32:39 +08007136 wifi_getApEnable(apIndex, &enable);
7137 if (!enable)
7138 return RETURN_ERR;
7139
7140 wifi_getApWpsEnable(apIndex, &enable);
7141 if (!enable)
7142 return RETURN_ERR;
7143
developerac6f1142022-12-20 19:26:35 +08007144 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007145 return RETURN_ERR;
7146
7147 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
developer06a01d92022-09-07 16:32:39 +08007148 _syscmd(cmd, buf, sizeof(buf));
7149
7150 if((strstr(buf, "OK"))!=NULL)
7151 return RETURN_OK;
7152 return RETURN_ERR;
7153}
7154
7155// cancels WPS mode for this AP
7156INT wifi_cancelApWPS(INT apIndex)
7157{
developerd946fd62022-12-08 18:03:28 +08007158 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007159 char cmd[MAX_CMD_SIZE];
7160 char buf[MAX_BUF_SIZE]={0};
7161
developerac6f1142022-12-20 19:26:35 +08007162 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007163 return RETURN_ERR;
7164 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007165 _syscmd(cmd,buf, sizeof(buf));
7166
7167 if((strstr(buf, "OK"))!=NULL)
7168 return RETURN_OK;
7169 return RETURN_ERR;
7170}
7171
7172//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7173//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7174INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7175{
developerd946fd62022-12-08 18:03:28 +08007176 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007177 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007178 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007179 char cmd[256] = {0}, buf[2048] = {0};
7180 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007181 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007182 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007183 wifi_associated_dev_t *dev=NULL;
7184
7185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7186 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007187 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007188 return RETURN_ERR;
7189 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007190 _syscmd(cmd,buf,sizeof(buf));
7191 *output_array_size = atoi(buf);
7192
7193 if (*output_array_size <= 0)
7194 return RETURN_OK;
7195
7196 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7197 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007198 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007199 _syscmd(cmd,buf,sizeof(buf));
7200 f = fopen("/tmp/connected_devices.txt", "r");
7201 if (f==NULL)
7202 {
7203 *output_array_size=0;
7204 return RETURN_ERR;
7205 }
developer30423732022-12-01 16:17:49 +08007206 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007207 {
7208 param = strtok(line,"=");
7209 value = strtok(NULL,"=");
7210
7211 if( strcmp("flags",param) == 0 )
7212 {
7213 value[strlen(value)-1]='\0';
7214 if(strstr (value,"AUTHORIZED") != NULL )
7215 {
7216 dev[auth_temp].cli_AuthenticationState = 1;
7217 dev[auth_temp].cli_Active = 1;
7218 auth_temp++;
7219 read_flag=1;
7220 }
7221 }
7222 if(read_flag==1)
7223 {
7224 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7225 {
7226 value[strlen(value)-1]='\0';
7227 sscanf(value, "%x:%x:%x:%x:%x:%x",
7228 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7229 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7230 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7231 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7232 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7233 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7234 mac_temp++;
7235 read_flag=0;
7236 }
7237 }
7238 }
7239 *output_array_size = auth_temp;
7240 auth_temp=0;
7241 mac_temp=0;
7242 free(line);
7243 fclose(f);
7244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7245 return RETURN_OK;
7246}
7247
7248#define MACADDRESS_SIZE 6
7249
7250INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7251{
7252 FILE *fp = NULL;
7253 char str[MAX_BUF_SIZE] = {0};
7254 int wificlientindex = 0 ;
7255 int count = 0;
7256 int signalstrength = 0;
7257 int arr[MACADDRESS_SIZE] = {0};
7258 unsigned char mac[MACADDRESS_SIZE] = {0};
7259 UINT wifi_count = 0;
7260 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7261 char pipeCmd[MAX_CMD_SIZE] = {0};
7262
7263 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7264 *output_array_size = 0;
7265 *associated_dev_array = NULL;
7266
7267 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7268 fp = popen(pipeCmd, "r");
7269 if (fp == NULL)
7270 {
7271 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7272 return RETURN_ERR;
7273 }
7274
7275 /* Read the output a line at a time - output it. */
7276 fgets(str, sizeof(str)-1, fp);
7277 wifi_count = (unsigned int) atoi ( str );
7278 *output_array_size = wifi_count;
7279 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7280 pclose(fp);
7281
7282 if(wifi_count == 0)
7283 {
7284 return RETURN_OK;
7285 }
7286 else
7287 {
7288 wifi_associated_dev3_t* temp = NULL;
7289 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7290 if(temp == NULL)
7291 {
7292 printf("Error Statement. Insufficient memory \n");
7293 return RETURN_ERR;
7294 }
7295
7296 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7297 system(pipeCmd);
7298 memset(pipeCmd,0,sizeof(pipeCmd));
7299 if(apIndex == 0)
7300 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7301 else if(apIndex == 1)
7302 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7303 system(pipeCmd);
7304
7305 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7306 if(fp == NULL)
7307 {
7308 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007309 free(temp);
developer06a01d92022-09-07 16:32:39 +08007310 return RETURN_ERR;
7311 }
7312 fclose(fp);
7313
developer30423732022-12-01 16:17:49 +08007314 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007315 fp = popen(pipeCmd, "r");
7316 if(fp)
7317 {
7318 for(count =0 ; count < wifi_count; count++)
7319 {
7320 fgets(str, MAX_BUF_SIZE, fp);
7321 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7322 {
7323 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7324 {
7325 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7326
7327 }
7328 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7329 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]);
7330 }
7331 temp[count].cli_AuthenticationState = 1; //TODO
7332 temp[count].cli_Active = 1; //TODO
7333 }
7334 pclose(fp);
7335 }
7336
developer30423732022-12-01 16:17:49 +08007337 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
developer06a01d92022-09-07 16:32:39 +08007338 fp = popen(pipeCmd, "r");
7339 if(fp)
7340 {
7341 pclose(fp);
7342 }
7343 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7344 if(fp)
7345 {
7346 for(count =0 ; count < wifi_count ;count++)
7347 {
7348 fgets(str, MAX_BUF_SIZE, fp);
7349 signalstrength = atoi(str);
7350 temp[count].cli_SignalStrength = signalstrength;
7351 temp[count].cli_RSSI = signalstrength;
7352 temp[count].cli_SNR = signalstrength + 95;
7353 }
7354 pclose(fp);
7355 }
7356
7357
7358 if((apIndex == 0) || (apIndex == 4))
7359 {
7360 for(count =0 ; count < wifi_count ;count++)
7361 {
7362 strcpy(temp[count].cli_OperatingStandard,"g");
7363 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7364 }
7365
7366 //BytesSent
developer30423732022-12-01 16:17:49 +08007367 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007368 fp = popen(pipeCmd, "r");
7369 if(fp)
7370 {
7371 pclose(fp);
7372 }
7373 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7374 if(fp)
7375 {
7376 for (count = 0; count < wifi_count; count++)
7377 {
7378 fgets(str, MAX_BUF_SIZE, fp);
7379 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7380 }
7381 pclose(fp);
7382 }
7383
7384 //BytesReceived
developer30423732022-12-01 16:17:49 +08007385 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007386 fp = popen(pipeCmd, "r");
7387 if (fp)
7388 {
7389 pclose(fp);
7390 }
7391 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7392 if (fp)
7393 {
7394 for (count = 0; count < wifi_count; count++)
7395 {
7396 fgets(str, MAX_BUF_SIZE, fp);
7397 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7398 }
7399 pclose(fp);
7400 }
7401
7402 //PacketsSent
developer30423732022-12-01 16:17:49 +08007403 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007404 fp = popen(pipeCmd, "r");
7405 if (fp)
7406 {
7407 pclose(fp);
7408 }
7409
7410 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7411 if (fp)
7412 {
7413 for (count = 0; count < wifi_count; count++)
7414 {
7415 fgets(str, MAX_BUF_SIZE, fp);
7416 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7417 }
7418 pclose(fp);
7419 }
7420
7421 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007422 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007423 fp = popen(pipeCmd, "r");
7424 if (fp)
7425 {
7426 pclose(fp);
7427 }
7428 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7429 if (fp)
7430 {
7431 for (count = 0; count < wifi_count; count++)
7432 {
7433 fgets(str, MAX_BUF_SIZE, fp);
7434 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7435 }
7436 pclose(fp);
7437 }
7438
7439 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007440 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
developer06a01d92022-09-07 16:32:39 +08007441 fp = popen(pipeCmd, "r");
7442 if (fp)
7443 {
7444 pclose(fp);
7445 }
7446 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7447 if (fp)
7448 {
7449 for (count = 0; count < wifi_count; count++)
7450 {
7451 fgets(str, MAX_BUF_SIZE, fp);
7452 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7453 }
7454 pclose(fp);
7455 }
7456
7457 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007458 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
developer06a01d92022-09-07 16:32:39 +08007459 fp = popen(pipeCmd, "r");
7460 if (fp)
7461 {
7462 pclose(fp);
7463 }
7464 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7465 if (fp)
7466 {
7467 for (count = 0; count < wifi_count; count++)
7468 {
7469 fgets(str, MAX_BUF_SIZE, fp);
7470 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7471 }
7472 pclose(fp);
7473 }
7474
7475 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007476 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007477 fp = popen(pipeCmd, "r");
7478 if (fp)
7479 {
7480 pclose(fp);
7481 }
7482 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7483 if (fp)
7484 {
7485 for (count = 0; count < wifi_count; count++)
7486 {
7487 fgets(str, MAX_BUF_SIZE, fp);
7488 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7489 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7490 }
7491 pclose(fp);
7492 }
7493
7494 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007495 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007496 fp = popen(pipeCmd, "r");
7497 if (fp)
7498 {
7499 pclose(fp);
7500 }
7501 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7502 if (fp)
7503 {
7504 for (count = 0; count < wifi_count; count++)
7505 {
7506 fgets(str, MAX_BUF_SIZE, fp);
7507 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7508 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7509 }
7510 pclose(fp);
7511 }
7512
7513 }
7514 else if ((apIndex == 1) || (apIndex == 5))
7515 {
7516 for (count = 0; count < wifi_count; count++)
7517 {
7518 strcpy(temp[count].cli_OperatingStandard, "a");
7519 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7520 temp[count].cli_BytesSent = 0;
7521 temp[count].cli_BytesReceived = 0;
7522 temp[count].cli_LastDataUplinkRate = 0;
7523 temp[count].cli_LastDataDownlinkRate = 0;
7524 temp[count].cli_PacketsSent = 0;
7525 temp[count].cli_PacketsReceived = 0;
7526 temp[count].cli_ErrorsSent = 0;
7527 }
7528 }
7529
7530 for (count = 0; count < wifi_count; count++)
7531 {
7532 temp[count].cli_Retransmissions = 0;
7533 temp[count].cli_DataFramesSentAck = 0;
7534 temp[count].cli_DataFramesSentNoAck = 0;
7535 temp[count].cli_MinRSSI = 0;
7536 temp[count].cli_MaxRSSI = 0;
7537 strncpy(temp[count].cli_InterferenceSources, "", 64);
7538 memset(temp[count].cli_IPAddress, 0, 64);
7539 temp[count].cli_RetransCount = 0;
7540 temp[count].cli_FailedRetransCount = 0;
7541 temp[count].cli_RetryCount = 0;
7542 temp[count].cli_MultipleRetryCount = 0;
7543 }
7544 *associated_dev_array = temp;
7545 }
7546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7547 return RETURN_OK;
7548}
7549
7550int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7551{
7552 FILE *fp = NULL;
7553 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7554 char cmd[MAX_CMD_SIZE];
7555 int count = 0;
7556
7557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7558 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7559 fp = popen(cmd,"r");
7560 if(fp == NULL)
7561 {
7562 printf("Failed to run command in Function %s\n",__FUNCTION__);
7563 return 0;
7564 }
7565 if(fgets(path, sizeof(path)-1, fp) != NULL)
7566 {
7567 for(count=0;path[count]!='\n';count++)
7568 status[count]=path[count];
7569 status[count]='\0';
7570 }
7571 strcpy(wifi_status,status);
7572 pclose(fp);
7573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7574 return RETURN_OK;
7575}
7576
7577/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7578struct hostapd_sta_param {
7579 char key[50];
7580 char value[100];
7581}
7582
7583static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7584 int i = 0;
7585
7586 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7587 if (strncmp(params[i].key,key,50) == 0){
7588 return &params[i].value;
7589 }
7590 i++;
7591 }
7592 return NULL;
7593
7594} */
7595
7596static unsigned int count_occurences(const char *buf, const char *word)
7597{
7598 unsigned int n = 0;
7599 char *ptr = strstr(buf, word);
7600
7601 while (ptr++) {
7602 n++;
7603 ptr = strstr(ptr, word);
7604 }
7605
7606 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7607 return n;
7608}
7609
7610static const char *get_line_from_str_buf(const char *buf, char *line)
7611{
7612 int i;
7613 int n = strlen(buf);
7614
7615 for (i = 0; i < n; i++) {
7616 line[i] = buf[i];
7617 if (buf[i] == '\n') {
7618 line[i] = '\0';
7619 return &buf[i + 1];
7620 }
7621 }
7622
7623 return NULL;
7624}
7625
7626INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7627{
7628 unsigned int assoc_cnt = 0;
7629 char interface_name[50] = {0};
7630 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7631 char cmd[MAX_CMD_SIZE] = {'\0'};
7632 char line[256] = {'\0'};
7633 int i = 0;
7634 int ret = 0;
7635 const char *ptr = NULL;
7636 char *key = NULL;
7637 char *val = NULL;
7638 wifi_associated_dev3_t *temp = NULL;
7639 int rssi;
7640
7641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7642
7643 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7644 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7645 return RETURN_ERR;
7646 }
7647
7648 // Example filtered output of 'iw dev' command:
7649 // Station 0a:69:72:10:d2:fa (on wifi0)
7650 // signal avg:-67 [-71, -71] dBm
7651 // Station 28:c2:1f:25:5f:99 (on wifi0)
7652 // signal avg:-67 [-71, -70] dBm
7653 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7654 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7655 return RETURN_ERR;
7656 }
7657
7658 ret = _syscmd(cmd, buf, sizeof(buf));
7659 if (ret == RETURN_ERR) {
7660 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7661 return RETURN_ERR;
7662 }
7663
7664 *output_array_size = count_occurences(buf, "Station");
7665 if (*output_array_size == 0) return RETURN_OK;
7666
7667 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7668 if (temp == NULL) {
7669 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7670 return RETURN_ERR;
7671 }
7672 *associated_dev_array = temp;
7673
7674 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7675 ptr = get_line_from_str_buf(buf, line);
7676 i = -1;
7677 while (ptr) {
7678 if (strstr(line, "Station")) {
7679 i++;
7680 key = strtok(line, " ");
7681 val = strtok(NULL, " ");
7682 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7683 &temp[i].cli_MACAddress[0],
7684 &temp[i].cli_MACAddress[1],
7685 &temp[i].cli_MACAddress[2],
7686 &temp[i].cli_MACAddress[3],
7687 &temp[i].cli_MACAddress[4],
7688 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7689 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7690 free(*associated_dev_array);
7691 return RETURN_ERR;
7692 }
7693 }
7694 else if (i < 0) {
7695 ptr = get_line_from_str_buf(ptr, line);
7696 continue; // We didn't detect 'station' entry yet
7697 }
7698 else if (strstr(line, "signal avg")) {
7699 key = strtok(line, ":");
7700 val = strtok(NULL, " ");
7701 if (sscanf(val, "%d", &rssi) <= 0 ) {
7702 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7703 free(*associated_dev_array);
7704 return RETURN_ERR;
7705 }
7706 temp[i].cli_RSSI = rssi;
7707 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7708 }
7709 // Here other fields can be parsed if added to filter of 'iw dev' command
7710
7711 ptr = get_line_from_str_buf(ptr, line);
7712 };
7713
7714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7715
7716 return RETURN_OK;
7717}
7718
7719#if 0
7720//To-do
7721INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7722{
7723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7724
7725 //Using different approach to get required WiFi Parameters from system available commands
7726#if 0
7727 FILE *f;
7728 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7729 char cmd[256], buf[2048];
7730 char *param , *value, *line=NULL;
7731 size_t len = 0;
7732 ssize_t nread;
7733 wifi_associated_dev3_t *dev=NULL;
7734 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007735 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007736 _syscmd(cmd,buf,sizeof(buf));
7737 *output_array_size = atoi(buf);
7738
7739 if (*output_array_size <= 0)
7740 return RETURN_OK;
7741
7742 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7743 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007744 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007745 _syscmd(cmd,buf,sizeof(buf));
7746 f = fopen("/tmp/connected_devices.txt", "r");
7747 if (f==NULL)
7748 {
7749 *output_array_size=0;
7750 return RETURN_ERR;
7751 }
7752 while ((nread = getline(&line, &len, f)) != -1)
7753 {
7754 param = strtok(line,"=");
7755 value = strtok(NULL,"=");
7756
7757 if( strcmp("flags",param) == 0 )
7758 {
7759 value[strlen(value)-1]='\0';
7760 if(strstr (value,"AUTHORIZED") != NULL )
7761 {
7762 dev[auth_temp].cli_AuthenticationState = 1;
7763 dev[auth_temp].cli_Active = 1;
7764 auth_temp++;
7765 read_flag=1;
7766 }
7767 }
7768 if(read_flag==1)
7769 {
7770 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7771 {
7772 value[strlen(value)-1]='\0';
7773 sscanf(value, "%x:%x:%x:%x:%x:%x",
7774 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7775 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7776 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7777 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7778 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7779 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7780
7781 }
7782 else if( strcmp("rx_packets",param) == 0 )
7783 {
7784 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7785 }
7786
7787 else if( strcmp("tx_packets",param) == 0 )
7788 {
7789 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7790 }
7791
7792 else if( strcmp("rx_bytes",param) == 0 )
7793 {
7794 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7795 }
7796
7797 else if( strcmp("tx_bytes",param) == 0 )
7798 {
7799 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7800 mac_temp++;
7801 read_flag=0;
7802 }
7803 }
7804 }
7805
7806 *output_array_size = auth_temp;
7807 auth_temp=0;
7808 mac_temp=0;
7809 free(line);
7810 fclose(f);
7811#endif
7812 char interface_name[MAX_BUF_SIZE] = {0};
7813 char wifi_status[MAX_BUF_SIZE] = {0};
7814 char hostapdconf[MAX_BUF_SIZE] = {0};
7815
7816 wifi_associated_dev3_t *dev_array = NULL;
7817 ULONG wifi_count = 0;
7818
7819 *associated_dev_array = NULL;
7820 *output_array_size = 0;
7821
7822 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7823 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7824 {
7825 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7826
developerac6f1142022-12-20 19:26:35 +08007827 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08007828
7829 if(strlen(interface_name) > 1)
7830 {
7831 wifihal_interfacestatus(wifi_status,interface_name);
7832 if(strcmp(wifi_status,"RUNNING") == 0)
7833 {
7834 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7835
7836 *associated_dev_array = dev_array;
7837 *output_array_size = wifi_count;
7838 }
7839 else
7840 {
7841 *associated_dev_array = NULL;
7842 }
7843 }
7844 }
7845
7846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7847 return RETURN_OK;
7848}
7849#endif
7850
7851/* getIPAddress function */
7852/**
7853* @description Returning IpAddress of the Matched String
7854*
7855* @param
7856* @str Having MacAddress
7857* @ipaddr Having ipaddr
7858* @return The status of the operation
7859* @retval RETURN_OK if successful
7860* @retval RETURN_ERR if any error is detected
7861*
7862*/
7863
7864INT getIPAddress(char *str,char *ipaddr)
7865{
7866 FILE *fp = NULL;
7867 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7868 int LeaseTime = 0,ret = 0;
7869 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7870 {
7871 return RETURN_ERR;
7872 }
7873
7874 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7875 {
7876 /*
7877 Sample:sss
7878 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7879 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7880 */
7881 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08007882 &(LeaseTime),
7883 phyAddr,
7884 ipAddr,
7885 hostName
7886 );
developer06a01d92022-09-07 16:32:39 +08007887 if(ret != 4)
7888 continue;
7889 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08007890 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08007891 }
developerd946fd62022-12-08 18:03:28 +08007892 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08007893 return RETURN_OK;
7894}
7895
7896/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7897/**
7898* @description Returning Inactive wireless connected clients informations
7899*
7900* @param
7901* @filename Holding private_wifi 2g/5g content files
7902* @associated_dev_array Having inactiv wireless clients informations
7903* @output_array_size Returning Inactive wireless counts
7904* @return The status of the operation
7905* @retval RETURN_OK if successful
7906* @retval RETURN_ERR if any error is detected
7907*
7908*/
7909
7910INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7911{
7912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7913 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7914 FILE *fp = NULL;
7915 int arr[MACADDRESS_SIZE] = {0};
7916 unsigned char mac[MACADDRESS_SIZE] = {0};
7917 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7918 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7919 fp = popen(buf,"r");
7920 if(fp == NULL)
7921 return RETURN_ERR;
7922 else
7923 {
7924 fgets(path,sizeof(path),fp);
7925 maccount = atoi(path);
7926 }
7927 pclose(fp);
7928 *output_array_size = maccount;
7929 wifi_associated_dev3_t* temp = NULL;
7930 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7931 *associated_dev_array = temp;
7932 if(temp == NULL)
7933 {
7934 printf("Error Statement. Insufficient memory \n");
7935 return RETURN_ERR;
7936 }
7937 memset(buf,0,sizeof(buf));
7938 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7939 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08007940 if (fp == NULL) {
7941 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7942 return RETURN_ERR;
7943 }
developer06a01d92022-09-07 16:32:39 +08007944 for(count = 0; count < maccount ; count++)
7945 {
7946 fgets(path,sizeof(path),fp);
7947 for(i = 0; path[i]!='\n';i++)
7948 str[i]=path[i];
7949 str[i]='\0';
7950 getIPAddress(str,ipaddr);
7951 memset(buf,0,sizeof(buf));
7952 if(strlen(ipaddr) > 0)
7953 {
7954 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7955 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7956 {
7957 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7958 {
7959 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7960 {
7961 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7962
7963 }
7964 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7965 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]);
7966 }
7967 temp[count].cli_AuthenticationState = 0; //TODO
7968 temp[count].cli_Active = 0; //TODO
7969 temp[count].cli_SignalStrength = 0;
7970 }
7971 else //Active wireless clients info
7972 {
7973 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7974 {
7975 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7976 {
7977 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7978
7979 }
7980 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7981 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]);
7982 }
7983 temp[count].cli_Active = 1;
7984 }
7985 }
7986 memset(ipaddr,0,sizeof(ipaddr));
7987 }
7988 pclose(fp);
7989 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7990 return RETURN_OK;
7991}
7992//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7993//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7994//To get Band Steering Capability
7995INT wifi_getBandSteeringCapability(BOOL *support)
7996{
7997 *support = FALSE;
7998 return RETURN_OK;
7999}
8000
8001
8002//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8003//To get Band Steering enable status
8004INT wifi_getBandSteeringEnable(BOOL *enable)
8005{
8006 *enable = FALSE;
8007 return RETURN_OK;
8008}
8009
8010//To turn on/off Band steering
8011INT wifi_setBandSteeringEnable(BOOL enable)
8012{
8013 return RETURN_OK;
8014}
8015
8016//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8017//To get Band Steering AP group
8018INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8019{
8020 if (NULL == output_ApGroup)
8021 return RETURN_ERR;
8022
8023 strcpy(output_ApGroup, "1,2");
8024 return RETURN_OK;
8025}
8026
8027//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8028//to set and read the band steering BandUtilizationThreshold parameters
8029INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8030{
8031 return RETURN_ERR;
8032}
8033
8034INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8035{
8036 return RETURN_ERR;
8037}
8038
8039//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8040//to set and read the band steering RSSIThreshold parameters
8041INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8042{
8043 return RETURN_ERR;
8044}
8045
8046INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8047{
8048 return RETURN_ERR;
8049}
8050
8051
8052//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8053//to set and read the band steering physical modulation rate threshold parameters
8054INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8055{
8056 //If chip is not support, return -1
8057 return RETURN_ERR;
8058}
8059
8060INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8061{
8062 //If chip is not support, return -1
8063 return RETURN_ERR;
8064}
8065
8066//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8067//to set and read the inactivity time (in seconds) for steering under overload condition
8068INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8069{
8070 return RETURN_ERR;
8071}
8072
8073INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8074{
8075 return RETURN_ERR;
8076}
8077
8078//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8079//to set and read the inactivity time (in seconds) for steering under Idle condition
8080INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8081{
8082 return RETURN_ERR;
8083}
8084
8085INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8086{
8087 return RETURN_ERR;
8088}
8089
8090//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8091//pClientMAC[64]
8092//pSourceSSIDIndex[64]
8093//pDestSSIDIndex[64]
8094//pSteeringReason[256]
8095INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8096{
8097 //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
8098 *pSteeringTime=time(NULL);
8099 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8100 return RETURN_OK;
8101}
8102
8103INT wifi_ifConfigDown(INT apIndex)
8104{
8105 INT status = RETURN_OK;
8106 char cmd[64];
8107
8108 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8109 printf("%s: %s\n", __func__, cmd);
8110 system(cmd);
8111
8112 return status;
8113}
8114
8115INT wifi_ifConfigUp(INT apIndex)
8116{
developerd946fd62022-12-08 18:03:28 +08008117 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008118 char cmd[128];
8119 char buf[1024];
8120
developerac6f1142022-12-20 19:26:35 +08008121 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008122 return RETURN_ERR;
8123 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008124 _syscmd(cmd, buf, sizeof(buf));
8125 return 0;
8126}
8127
8128//>> Deprecated. Replace with wifi_applyRadioSettings
8129INT wifi_pushBridgeInfo(INT apIndex)
8130{
developerd946fd62022-12-08 18:03:28 +08008131 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008132 char ip[32] = {0};
8133 char subnet[32] = {0};
8134 char bridge[32] = {0};
8135 int vlanId = 0;
8136 char cmd[128] = {0};
8137 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008138
8139 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8140 wifi_getApVlanID(apIndex,&vlanId);
8141
developerac6f1142022-12-20 19:26:35 +08008142 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008143 return RETURN_ERR;
8144 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008145 _syscmd(cmd,buf, sizeof(buf));
8146
8147 return 0;
8148}
8149
8150INT wifi_pushChannel(INT radioIndex, UINT channel)
8151{
developerd946fd62022-12-08 18:03:28 +08008152 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008153 char cmd[128];
8154 char buf[1024];
8155 int apIndex;
8156
8157 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008158 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008159 return RETURN_ERR;
8160 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008161 _syscmd(cmd,buf, sizeof(buf));
8162
8163 return 0;
8164}
8165
8166INT wifi_pushChannelMode(INT radioIndex)
8167{
8168 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8169 return RETURN_ERR;
8170}
8171
8172INT wifi_pushDefaultValues(INT radioIndex)
8173{
8174 //Apply Comcast specified default radio settings instantly
8175 //AMPDU=1
8176 //AMPDUFrames=32
8177 //AMPDULim=50000
8178 //txqueuelen=1000
8179
8180 return RETURN_ERR;
8181}
8182
8183INT wifi_pushTxChainMask(INT radioIndex)
8184{
8185 //Apply default TxChainMask instantly
8186 return RETURN_ERR;
8187}
8188
8189INT wifi_pushRxChainMask(INT radioIndex)
8190{
8191 //Apply default RxChainMask instantly
8192 return RETURN_ERR;
8193}
8194
8195INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8196{
8197 INT status;
8198
8199 status = wifi_setSSIDName(apIndex,ssid);
8200 wifi_setApEnable(apIndex,FALSE);
8201 wifi_setApEnable(apIndex,TRUE);
8202
8203 return status;
8204}
8205
8206INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8207{
8208 //Apply default Ssid Advertisement instantly
8209 return RETURN_ERR;
8210}
8211
8212INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8213{
8214 INT status = RETURN_ERR;
8215 *output = 0;
8216 return RETURN_ERR;
8217}
8218
8219INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8220{
8221 return RETURN_OK;
8222}
8223
8224INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8225{
8226 return RETURN_OK;
8227}
8228
8229//To-do
8230INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8231{
developereb199ae2022-09-13 14:04:27 +08008232 char output[16]={'\0'};
8233 char config_file[MAX_BUF_SIZE] = {0};
8234
8235 if (!output_string)
8236 return RETURN_ERR;
8237
8238 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8239 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8240
8241 if (strlen(output) == 0)
8242 snprintf(output_string, 64, "Disabled");
8243 else if (strncmp(output, "0", 1) == 0)
8244 snprintf(output_string, 64, "Disabled");
8245 else if (strncmp(output, "1", 1) == 0)
8246 snprintf(output_string, 64, "Optional");
8247 else if (strncmp(output, "2", 1) == 0)
8248 snprintf(output_string, 64, "Required");
8249 else {
8250 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8251 return RETURN_ERR;
8252 }
8253
8254 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008255 return RETURN_OK;
8256}
8257INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8258{
developereb199ae2022-09-13 14:04:27 +08008259 char str[MAX_BUF_SIZE]={'\0'};
8260 char cmd[MAX_CMD_SIZE]={'\0'};
8261 struct params params;
8262 char config_file[MAX_BUF_SIZE] = {0};
8263
8264 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8265 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8266 return RETURN_ERR;
8267
8268 params.name = "ieee80211w";
8269 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8270 params.value = "0";
8271 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8272 params.value = "1";
8273 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8274 params.value = "2";
8275 else{
8276 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8277 return RETURN_ERR;
8278 }
8279 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8280 wifi_hostapdWrite(config_file, &params, 1);
8281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008282 return RETURN_OK;
8283}
8284INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8285{
8286 char output[16]={'\0'};
8287 char config_file[MAX_BUF_SIZE] = {0};
8288
8289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8290 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8291 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8292
8293 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8294 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8295
8296 return RETURN_OK;
8297}
8298
8299INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8300{
8301 return RETURN_OK;
8302}
8303
8304INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8305{
8306 return RETURN_OK;
8307}
8308
8309INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8310{
8311 return RETURN_OK;
8312}
8313
8314INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8315{
8316 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8317 char config_file[MAX_BUF_SIZE] = {0};
8318
8319 if (NULL == output)
8320 return RETURN_ERR;
8321 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8322 wifi_hostapdRead(config_file,"hw_mode",output,64);
8323
8324 if(strcmp(output,"b")==0)
8325 sprintf(output, "%s", "1,2,5.5,11");
8326 else if (strcmp(output,"a")==0)
8327 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8328 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8329 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8330
8331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8332 return RETURN_OK;
8333}
8334
8335INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8336{
8337 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8338 char *temp;
8339 char temp_output[128];
8340 char temp_TransmitRates[128];
8341 char config_file[MAX_BUF_SIZE] = {0};
8342
8343 if (NULL == output)
8344 return RETURN_ERR;
8345
8346 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8347 wifi_hostapdRead(config_file,"supported_rates",output,64);
8348
developer5b398df2022-11-17 20:39:48 +08008349 if (strlen(output) == 0) {
8350 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8351 return RETURN_OK;
8352 }
developer06a01d92022-09-07 16:32:39 +08008353 strcpy(temp_TransmitRates,output);
8354 strcpy(temp_output,"");
8355 temp = strtok(temp_TransmitRates," ");
8356 while(temp!=NULL)
8357 {
8358 temp[strlen(temp)-1]=0;
8359 if((temp[0]=='5') && (temp[1]=='\0'))
8360 {
8361 temp="5.5";
8362 }
8363 strcat(temp_output,temp);
8364 temp = strtok(NULL," ");
8365 if(temp!=NULL)
8366 {
8367 strcat(temp_output,",");
8368 }
8369 }
8370 strcpy(output,temp_output);
8371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8372
8373 return RETURN_OK;
8374}
8375
8376INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8377{
8378 return RETURN_OK;
8379}
8380
8381
8382INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8383{
8384 int i=0;
8385 char *temp;
developeref938762022-10-19 17:21:01 +08008386 char temp1[128] = {0};
8387 char temp_output[128] = {0};
8388 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008389 struct params params={'\0'};
8390 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008391 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008392
8393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8394 if(NULL == output)
8395 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008396 strcpy(temp_TransmitRates,output);
8397
8398 for(i=0;i<strlen(temp_TransmitRates);i++)
8399 {
developeref938762022-10-19 17:21:01 +08008400 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008401 {
8402 continue;
8403 }
8404 else
8405 {
8406 return RETURN_ERR;
8407 }
8408 }
8409 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008410 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008411 while(temp!=NULL)
8412 {
8413 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008414 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008415 {
developeref938762022-10-19 17:21:01 +08008416 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008417 {
8418 return RETURN_ERR;
8419 }
8420 }
8421
8422 if(strcmp(temp,"5.5")==0)
8423 {
8424 strcpy(temp1,"55");
8425 }
8426 else
8427 {
8428 strcat(temp1,"0");
8429 }
8430 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008431 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008432 if(temp!=NULL)
8433 {
8434 strcat(temp_output," ");
8435 }
8436 }
8437 strcpy(output,temp_output);
8438
developer06a01d92022-09-07 16:32:39 +08008439 params.name = "supported_rates";
8440 params.value = output;
8441
8442 wifi_dbg_printf("\n%s:",__func__);
8443 wifi_dbg_printf("params.value=%s\n",params.value);
8444 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8445 wifi_hostapdWrite(config_file,&params,1);
8446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8447
8448 return RETURN_OK;
8449}
8450
8451
8452static char *sncopy(char *dst, int dst_sz, const char *src)
8453{
8454 if (src && dst && dst_sz > 0) {
8455 strncpy(dst, src, dst_sz);
8456 dst[dst_sz - 1] = '\0';
8457 }
8458 return dst;
8459}
8460
8461static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8462{
8463 if (0 == strcmp(ht_mode, "HT40") ||
8464 0 == strcmp(ht_mode, "HT80") ||
8465 0 == strcmp(ht_mode, "HT160")) {
8466 switch (channel) {
8467 case 1 ... 7:
8468 case 36:
8469 case 44:
8470 case 52:
8471 case 60:
8472 case 100:
8473 case 108:
8474 case 116:
8475 case 124:
8476 case 132:
8477 case 140:
8478 case 149:
8479 case 157:
8480 return 1;
8481 case 8 ... 13:
8482 case 40:
8483 case 48:
8484 case 56:
8485 case 64:
8486 case 104:
8487 case 112:
8488 case 120:
8489 case 128:
8490 case 136:
8491 case 144:
8492 case 153:
8493 case 161:
8494 return -1;
8495 default:
8496 return -EINVAL;
8497 }
8498 }
8499
8500 return -EINVAL;
8501}
8502
developerb7593de2022-10-18 09:51:57 +08008503static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8504{
8505 int idx = channel%8;
8506 if (0 == strcmp(ht_mode, "HT40") ||
8507 0 == strcmp(ht_mode, "HT80") ||
8508 0 == strcmp(ht_mode, "HT160")) {
8509 switch (idx) {
8510 case 1:
8511 return 1;
8512 case 5:
8513 return -1;
8514 default:
8515 return -EINVAL;
8516 }
8517 }
8518
8519 return -EINVAL;
8520}
developer06a01d92022-09-07 16:32:39 +08008521static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8522{
8523 if (NULL == hw_mode) return;
8524
8525 if (0 == strcmp(hw_mode, "ac"))
8526 sncopy(bw_mode, bw_mode_len, "ht vht");
8527
8528 if (0 == strcmp(hw_mode, "n"))
8529 sncopy(bw_mode, bw_mode_len, "ht");
8530
8531 return;
8532}
8533
8534static int util_chan_to_freq(int chan)
8535{
8536 if (chan == 14)
8537 return 2484;
8538 else if (chan < 14)
8539 return 2407 + chan * 5;
8540 else if (chan >= 182 && chan <= 196)
8541 return 4000 + chan * 5;
8542 else
8543 return 5000 + chan * 5;
8544 return 0;
8545}
8546
developerb7593de2022-10-18 09:51:57 +08008547static int util_6G_chan_to_freq(int chan)
8548{
8549 if (chan)
8550 return 5950 + chan * 5;
8551 else
8552 return 0;
8553
8554}
developer06a01d92022-09-07 16:32:39 +08008555const int *util_unii_5g_chan2list(int chan, int width)
8556{
8557 static const int lists[] = {
8558 // <width>, <chan1>, <chan2>..., 0,
8559 20, 36, 0,
8560 20, 40, 0,
8561 20, 44, 0,
8562 20, 48, 0,
8563 20, 52, 0,
8564 20, 56, 0,
8565 20, 60, 0,
8566 20, 64, 0,
8567 20, 100, 0,
8568 20, 104, 0,
8569 20, 108, 0,
8570 20, 112, 0,
8571 20, 116, 0,
8572 20, 120, 0,
8573 20, 124, 0,
8574 20, 128, 0,
8575 20, 132, 0,
8576 20, 136, 0,
8577 20, 140, 0,
8578 20, 144, 0,
8579 20, 149, 0,
8580 20, 153, 0,
8581 20, 157, 0,
8582 20, 161, 0,
8583 20, 165, 0,
8584 40, 36, 40, 0,
8585 40, 44, 48, 0,
8586 40, 52, 56, 0,
8587 40, 60, 64, 0,
8588 40, 100, 104, 0,
8589 40, 108, 112, 0,
8590 40, 116, 120, 0,
8591 40, 124, 128, 0,
8592 40, 132, 136, 0,
8593 40, 140, 144, 0,
8594 40, 149, 153, 0,
8595 40, 157, 161, 0,
8596 80, 36, 40, 44, 48, 0,
8597 80, 52, 56, 60, 64, 0,
8598 80, 100, 104, 108, 112, 0,
8599 80, 116, 120, 124, 128, 0,
8600 80, 132, 136, 140, 144, 0,
8601 80, 149, 153, 157, 161, 0,
8602 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8603 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8604 -1 // final delimiter
8605 };
8606 const int *start;
8607 const int *p;
8608
8609 for (p = lists; *p != -1; p++) {
8610 if (*p == width) {
8611 for (start = ++p; *p != 0; p++) {
8612 if (*p == chan)
8613 return start;
8614 }
8615 }
8616 // move to the end of channel list of given width
8617 while (*p != 0) {
8618 p++;
8619 }
8620 }
8621
8622 return NULL;
8623}
8624
8625static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8626{
8627 if (NULL == ht_mode)
8628 return 0;
8629
8630 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8631 const int *chans = util_unii_5g_chan2list(channel, width);
8632 int sum = 0;
8633 int cnt = 0;
8634
8635 if (NULL == chans)
8636 return 0;
8637
8638 while (*chans) {
8639 sum += *chans;
8640 cnt++;
8641 chans++;
8642 }
developer30423732022-12-01 16:17:49 +08008643 if (cnt == 0)
8644 return 0;
developer06a01d92022-09-07 16:32:39 +08008645 return sum / cnt;
8646}
8647
developerb7593de2022-10-18 09:51:57 +08008648static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8649{
8650 if (NULL == ht_mode)
8651 return 0;
8652
8653 int width = strtol((ht_mode + 2), NULL, 10);
8654
8655 int idx = 0 ;
8656 int centerchan = 0;
8657 int chan_ofs = 1;
8658
8659 if (width == 40){
8660 idx = ((channel/4) + chan_ofs)%2;
8661 switch (idx) {
8662 case 0:
8663 centerchan = (channel - 2);
8664 break;
8665 case 1:
8666 centerchan = (channel + 2);
8667 break;
8668 default:
8669 return -EINVAL;
8670 }
8671 }else if (width == 80){
8672 idx = ((channel/4) + chan_ofs)%4;
8673 switch (idx) {
8674 case 0:
8675 centerchan = (channel - 6);
8676 break;
8677 case 1:
8678 centerchan = (channel + 6);
8679 break;
8680 case 2:
8681 centerchan = (channel + 2);
8682 break;
8683 case 3:
8684 centerchan = (channel - 2);
8685 break;
8686 default:
8687 return -EINVAL;
8688 }
8689 }else if (width == 160){
8690 switch (channel) {
8691 case 1 ... 29:
8692 centerchan = 15;
8693 break;
8694 case 33 ... 61:
8695 centerchan = 47;
8696 break;
8697 case 65 ... 93:
8698 centerchan = 79;
8699 break;
8700 case 97 ... 125:
8701 centerchan = 111;
8702 break;
8703 case 129 ... 157:
8704 centerchan = 143;
8705 break;
8706 case 161 ... 189:
8707 centerchan = 175;
8708 break;
8709 case 193 ... 221:
8710 centerchan = 207;
8711 break;
8712 default:
8713 return -EINVAL;
8714 }
8715 }
8716 return centerchan;
8717}
developer06a01d92022-09-07 16:32:39 +08008718static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8719{
8720 BOOL onlyG, onlyN, onlyA;
8721 CHAR tmp[64];
8722 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8723 if (ret == RETURN_OK) {
8724 sncopy(hw_mode, hw_mode_size, tmp);
8725 }
8726 return ret;
8727}
8728
8729INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8730{
8731 // Sample commands:
8732 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8733 // hostapd_cli -i wifi0 chan_switch 30 2437
8734 char cmd[MAX_CMD_SIZE] = {0};
8735 char buf[MAX_BUF_SIZE] = {0};
8736 int freq = 0, ret = 0;
8737 char center_freq1_str[32] = ""; // center_freq1=%d
8738 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8739 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8740 char hw_mode[16] = ""; // n|ac
8741 char bw_mode[16] = ""; // ht|ht vht
8742 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008743 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008744 int sec_chan_offset;
8745 int width;
developer4fb0b922022-09-30 14:29:09 +08008746 char config_file[64] = {0};
8747 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008748 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008749 wifi_band band = band_invalid;
8750 int center_chan = 0;
8751 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008752
developer4fb0b922022-09-30 14:29:09 +08008753 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008754
developerac6f1142022-12-20 19:26:35 +08008755 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008756 return RETURN_ERR;
8757
developer06a01d92022-09-07 16:32:39 +08008758 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8759
developerb7593de2022-10-18 09:51:57 +08008760 band = wifi_index_to_band(radioIndex);
8761
developer5884e982022-10-06 10:52:50 +08008762 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008763
8764 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008765 if (channel){
developerb7593de2022-10-18 09:51:57 +08008766 if (band == band_6){
8767 freq = util_6G_chan_to_freq(channel);
8768 }else{
8769 freq = util_chan_to_freq(channel);
8770 }
developer5884e982022-10-06 10:52:50 +08008771 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008772
developer5884e982022-10-06 10:52:50 +08008773 // Provide bandwith if specified
8774 if (channel_width_MHz > 20) {
8775 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8776 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8777 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008778
developer5884e982022-10-06 10:52:50 +08008779 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8780 }else if (channel_width_MHz == 20){
8781 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8782 }
developer06a01d92022-09-07 16:32:39 +08008783
developerb7593de2022-10-18 09:51:57 +08008784
developer5884e982022-10-06 10:52:50 +08008785 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008786 if (band == band_6){
8787 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8788 if(center_chan){
8789 center_freq1 = util_6G_chan_to_freq(center_chan);
8790 }
8791 }else{
8792 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8793 if(center_chan){
8794 center_freq1 = util_chan_to_freq(center_chan);
8795 }
developer5884e982022-10-06 10:52:50 +08008796 }
developerb7593de2022-10-18 09:51:57 +08008797
8798 if (center_freq1)
8799 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8800
8801 }
8802
8803 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8804 if (band == band_6){
8805 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8806 }else{
8807 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008808 }
developerb7593de2022-10-18 09:51:57 +08008809 if (sec_chan_offset != -EINVAL)
8810 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008811
developer5884e982022-10-06 10:52:50 +08008812 // Only the first AP, other are hanging on the same radio
8813 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08008814 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8815 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08008816 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8817 wifi_dbg_printf("execute: '%s'\n", cmd);
8818 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08008819 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08008820
developer5884e982022-10-06 10:52:50 +08008821 ret = wifi_setRadioChannel(radioIndex, channel);
8822 if (ret != RETURN_OK) {
8823 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8824 return RETURN_ERR;
8825 }
8826
8827 if (sec_chan_offset == 1) ext_str = "Above";
8828 else if (sec_chan_offset == -1) ext_str = "Below";
8829
8830 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008831
developer5884e982022-10-06 10:52:50 +08008832 } else {
8833 if (channel_width_MHz > 20)
8834 ext_str = "Above";
8835 }
developer4fb0b922022-09-30 14:29:09 +08008836
developer06a01d92022-09-07 16:32:39 +08008837 wifi_setRadioExtChannel(radioIndex, ext_str);
8838
developer06a01d92022-09-07 16:32:39 +08008839 char mhz_str[16];
8840 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8841 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8842
8843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8844
8845 return RETURN_OK;
8846}
8847
8848INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8849{
developer615510b2022-09-27 10:14:35 +08008850 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008851 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008852 char cmd[256]={0};
8853 char buf[128]={0};
8854 char file_name[32] = {0};
8855 char filter_SSID[32] = {0};
8856 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08008857 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08008858 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008859 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008860 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008861 size_t len=0;
8862 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008863 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008864 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008865 bool filter_enable = false;
8866 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008867 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008868
developer615510b2022-09-27 10:14:35 +08008869 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008870
developer615510b2022-09-27 10:14:35 +08008871 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8872 f = fopen(file_name, "r");
8873 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08008874 fgets(buf, sizeof(file_name), f);
8875 if ((strncmp(buf, "0", 1)) != 0) {
8876 fgets(filter_SSID, sizeof(file_name), f);
8877 if (strlen(filter_SSID) != 0)
8878 filter_enable = true;
8879 }
developer615510b2022-09-27 10:14:35 +08008880 fclose(f);
8881 }
8882
developerac6f1142022-12-20 19:26:35 +08008883 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008884 return RETURN_ERR;
8885
developer033b37b2022-10-18 11:27:46 +08008886 phyId = radio_index_to_phy(radio_index);
8887
8888 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008889 _syscmd(cmd, buf, sizeof(buf));
8890 channels_num = strtol(buf, NULL, 10);
8891
developerd946fd62022-12-08 18:03:28 +08008892 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8893 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
developer615510b2022-09-27 10:14:35 +08008894 fprintf(stderr, "cmd: %s\n", cmd);
8895 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008896 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8897 return RETURN_ERR;
8898 }
developer5550e242022-09-30 09:59:32 +08008899
8900 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8901 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8902
developer615510b2022-09-27 10:14:35 +08008903 ret = fgets(line, sizeof(line), f);
8904 while (ret != NULL) {
8905 if(strstr(line, "BSS") != NULL) { // new neighbor info
8906 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8907 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8908 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8909
8910 if (!filter_BSS) {
8911 index++;
8912 wifi_neighbor_ap2_t *tmp;
8913 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8914 if (tmp == NULL) { // no more memory to use
8915 index--;
8916 wifi_dbg_printf("%s: realloc failed\n", __func__);
8917 break;
8918 }
8919 scan_array = tmp;
8920 }
8921 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008922
developer615510b2022-09-27 10:14:35 +08008923 filter_BSS = false;
8924 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8925 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8926 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8927 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8928 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008929 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008930 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008931
developer615510b2022-09-27 10:14:35 +08008932 if (freq >= 2412 && freq <= 2484) {
8933 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8934 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8935 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8936 }
8937 else if (freq >= 5160 && freq <= 5805) {
8938 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8939 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8940 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8941 }
developer06a01d92022-09-07 16:32:39 +08008942
developer615510b2022-09-27 10:14:35 +08008943 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008944 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008945 for (int i = 0; i < channels_num; i++) {
8946 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8947 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8948 break;
8949 }
8950 }
developer06a01d92022-09-07 16:32:39 +08008951 }
developer615510b2022-09-27 10:14:35 +08008952 } else if (strstr(line, "beacon interval") != NULL) {
8953 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8954 } else if (strstr(line, "signal") != NULL) {
8955 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8956 } else if (strstr(line,"SSID") != NULL) {
8957 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8958 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8959 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008960 }
developer615510b2022-09-27 10:14:35 +08008961 } else if (strstr(line, "Supported rates") != NULL) {
8962 char SRate[80] = {0}, *tmp = NULL;
8963 memset(buf, 0, sizeof(buf));
8964 strcpy(SRate, line);
8965 tmp = strtok(SRate, ":");
8966 tmp = strtok(NULL, ":");
8967 strcpy(buf, tmp);
8968 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008969
developer615510b2022-09-27 10:14:35 +08008970 tmp = strtok(buf, " \n");
8971 while (tmp != NULL) {
8972 strcat(SRate, tmp);
8973 if (SRate[strlen(SRate) - 1] == '*') {
8974 SRate[strlen(SRate) - 1] = '\0';
8975 }
8976 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008977
developer615510b2022-09-27 10:14:35 +08008978 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008979 }
developer615510b2022-09-27 10:14:35 +08008980 SRate[strlen(SRate) - 1] = '\0';
8981 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8982 } else if (strstr(line, "DTIM") != NULL) {
8983 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8984 } else if (strstr(line, "VHT capabilities") != NULL) {
8985 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8986 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8987 } else if (strstr(line, "HT capabilities") != NULL) {
8988 strcat(scan_array[index].ap_SupportedStandards, ",n");
8989 strcpy(scan_array[index].ap_OperatingStandards, "n");
8990 } else if (strstr(line, "VHT operation") != NULL) {
8991 ret = fgets(line, sizeof(line), f);
8992 sscanf(line," * channel width: %d", &vht_channel_width);
8993 if(vht_channel_width == 1) {
8994 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8995 } else {
8996 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8997 }
8998 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8999 continue;
9000 } else if (strstr(line, "HT operation") != NULL) {
9001 ret = fgets(line, sizeof(line), f);
9002 sscanf(line," * secondary channel offset: %s", &buf);
9003 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009004 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009005 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 +08009006 }
developer615510b2022-09-27 10:14:35 +08009007 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009008 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009009 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9010 } else {
9011 //20Mhz
9012 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 +08009013 }
developer615510b2022-09-27 10:14:35 +08009014 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009015 continue;
developer615510b2022-09-27 10:14:35 +08009016 } else if (strstr(line, "HE capabilities") != NULL) {
9017 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9018 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9019 ret = fgets(line, sizeof(line), f);
9020 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9021 if (strstr(line, "HE40/2.4GHz") != NULL)
9022 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9023 else
9024 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9025 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9026 if (strstr(line, "HE80/5GHz") != NULL) {
9027 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9028 ret = fgets(line, sizeof(line), f);
9029 } else
9030 continue;
9031 if (strstr(line, "HE160/5GHz") != NULL)
9032 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009033 }
developer615510b2022-09-27 10:14:35 +08009034 continue;
9035 } else if (strstr(line, "WPA") != NULL) {
9036 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9037 } else if (strstr(line, "RSN") != NULL) {
9038 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9039 } else if (strstr(line, "Group cipher") != NULL) {
9040 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9041 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9042 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009043 }
developer06a01d92022-09-07 16:32:39 +08009044 }
developer615510b2022-09-27 10:14:35 +08009045 ret = fgets(line, sizeof(line), f);
9046 }
9047
9048 if (!filter_BSS) {
9049 *output_array_size = index + 1;
9050 } else {
9051 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9052 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009053 }
developer06a01d92022-09-07 16:32:39 +08009054 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009055 pclose(f);
developer5550e242022-09-30 09:59:32 +08009056 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009057 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009058 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009059}
developer615510b2022-09-27 10:14:35 +08009060
developer06a01d92022-09-07 16:32:39 +08009061INT wifi_getApAssociatedDeviceStats(
9062 INT apIndex,
9063 mac_address_t *clientMacAddress,
9064 wifi_associated_dev_stats_t *associated_dev_stats,
9065 u64 *handle)
9066{
9067 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9068 char interface_name[50] = {0};
9069 char cmd[1024] = {0};
9070 char mac_str[18] = {0};
9071 char *key = NULL;
9072 char *val = NULL;
9073 FILE *f = NULL;
9074 char *line = NULL;
9075 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009076
9077 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9078 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9079 return RETURN_ERR;
9080 }
9081
9082 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9083 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9084 if((f = popen(cmd, "r")) == NULL) {
9085 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9086 return RETURN_ERR;
9087 }
9088
developer30423732022-12-01 16:17:49 +08009089 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009090 key = strtok(line,":");
9091 val = strtok(NULL,":");
9092
9093 if(!strncmp(key,"rx bytes",8))
9094 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9095 if(!strncmp(key,"tx bytes",8))
9096 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9097 if(!strncmp(key,"rx packets",10))
9098 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9099 if(!strncmp(key,"tx packets",10))
9100 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9101 if(!strncmp(key,"tx retries",10))
9102 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9103 if(!strncmp(key,"tx failed",9))
9104 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9105 if(!strncmp(key,"rx drop misc",13))
9106 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9107 if(!strncmp(key,"rx bitrate",10)) {
9108 val = strtok(val, " ");
9109 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9110 }
9111 if(!strncmp(key,"tx bitrate",10)) {
9112 val = strtok(val, " ");
9113 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9114 }
9115 }
9116 free(line);
9117 pclose(f);
9118 return RETURN_OK;
9119}
9120
9121INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9122{
developerd946fd62022-12-08 18:03:28 +08009123 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009124 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9125
9126 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9127 if (NULL == output_string)
9128 return RETURN_ERR;
9129
developerac6f1142022-12-20 19:26:35 +08009130 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009131 return RETURN_ERR;
9132 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08009133 _syscmd(cmd, buf, sizeof(buf));
9134
9135 //size of SSID name restricted to value less than 32 bytes
9136 snprintf(output_string, 32, "%s", buf);
9137 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9138
9139 return RETURN_OK;
9140}
9141
9142INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9143{
9144 //char cmd[MAX_CMD_SIZE] = {0};
9145 char config_file[MAX_BUF_SIZE] = {0};
9146 char buf[32] = {0};
9147
9148 if (!output_filterMode)
9149 return RETURN_ERR;
9150
9151 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9152 //_syscmd(cmd, buf, sizeof(buf));
9153 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9154 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009155 if(strlen(buf) == 0) {
9156 *output_filterMode = 0;
9157 }
9158 else {
9159 int macaddr_acl_mode = strtol(buf, NULL, 10);
9160 if (macaddr_acl_mode == 1) {
9161 *output_filterMode = 1;
9162 } else if (macaddr_acl_mode == 0) {
9163 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9164 if (strlen(buf) == 0) {
9165 *output_filterMode = 0;
9166 } else {
9167 *output_filterMode = 2;
9168 }
9169 } else {
9170 return RETURN_ERR;
9171 }
9172 }
developer06a01d92022-09-07 16:32:39 +08009173
9174 return RETURN_OK;
9175}
9176
9177INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9178{
9179 FILE *fp = NULL;
9180 char str[MAX_BUF_SIZE] = {0};
9181 int wificlientindex = 0 ;
9182 int count = 0;
9183 int signalstrength = 0;
9184 int arr[MACADDRESS_SIZE] = {0};
9185 unsigned char mac[MACADDRESS_SIZE] = {0};
9186 UINT wifi_count = 0;
9187 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9188 char pipeCmd[MAX_CMD_SIZE] = {0};
9189
9190 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9191 *output_array_size = 0;
9192 *associated_dev_array = NULL;
9193 char interface_name[50] = {0};
9194
9195 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9196 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9197 return RETURN_ERR;
9198 }
9199
9200 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9201 fp = popen(pipeCmd, "r");
9202 if (fp == NULL)
9203 {
9204 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9205 return RETURN_ERR;
9206 }
9207
9208 /* Read the output a line at a time - output it. */
9209 fgets(str, sizeof(str)-1, fp);
9210 wifi_count = (unsigned int) atoi ( str );
9211 *output_array_size = wifi_count;
9212 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9213 pclose(fp);
9214
9215 if(wifi_count == 0)
9216 {
9217 return RETURN_OK;
9218 }
9219 else
9220 {
9221 wifi_associated_dev2_t* temp = NULL;
9222 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9223 *associated_dev_array = temp;
9224 if(temp == NULL)
9225 {
9226 printf("Error Statement. Insufficient memory \n");
9227 return RETURN_ERR;
9228 }
9229
9230 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9231 system(pipeCmd);
9232
9233 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9234 if(fp == NULL)
9235 {
9236 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9237 return RETURN_ERR;
9238 }
9239 fclose(fp);
9240
developer30423732022-12-01 16:17:49 +08009241 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009242 fp = popen(pipeCmd, "r");
9243 if(fp)
9244 {
9245 for(count =0 ; count < wifi_count; count++)
9246 {
9247 fgets(str, MAX_BUF_SIZE, fp);
9248 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9249 {
9250 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9251 {
9252 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9253
9254 }
9255 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9256 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]);
9257 }
9258 temp[count].cli_AuthenticationState = 1; //TODO
9259 temp[count].cli_Active = 1; //TODO
9260 }
9261 pclose(fp);
9262 }
9263
9264 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009265 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
developer06a01d92022-09-07 16:32:39 +08009266 fp = popen(pipeCmd, "r");
9267 if(fp)
9268 {
9269 pclose(fp);
9270 }
9271 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9272 if(fp)
9273 {
9274 for(count =0 ; count < wifi_count ;count++)
9275 {
9276 fgets(str, MAX_BUF_SIZE, fp);
9277 signalstrength = atoi(str);
9278 temp[count].cli_RSSI = signalstrength;
9279 }
9280 pclose(fp);
9281 }
9282
9283
9284 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009285 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
developer06a01d92022-09-07 16:32:39 +08009286 fp = popen(pipeCmd, "r");
9287 if (fp)
9288 {
9289 pclose(fp);
9290 }
9291 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9292 if (fp)
9293 {
9294 for (count = 0; count < wifi_count; count++)
9295 {
9296 fgets(str, MAX_BUF_SIZE, fp);
9297 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9298 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9299 }
9300 pclose(fp);
9301 }
9302
9303 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009304 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
developer06a01d92022-09-07 16:32:39 +08009305 fp = popen(pipeCmd, "r");
9306 if (fp)
9307 {
9308 pclose(fp);
9309 }
9310 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9311 if (fp)
9312 {
9313 for (count = 0; count < wifi_count; count++)
9314 {
9315 fgets(str, MAX_BUF_SIZE, fp);
9316 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9317 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9318 }
9319 pclose(fp);
9320 }
9321 }
9322 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9323 return RETURN_OK;
9324
9325}
9326
9327INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9328{
9329#if 0
9330 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009331 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009332 _syscmd(cmd, buf, sizeof(buf));*/
9333
9334 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9335 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9336 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9337 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9338
9339 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.
9340 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].
9341 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].
9342 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].
9343 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9344 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9345
9346 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9347 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9348 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9349 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.
9350 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.
9351 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.
9352 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.
9353 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.
9354 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.
9355 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.
9356 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9357#endif
9358
9359 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009360 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009361 char pipeCmd[128] = {0};
9362 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009363 wifi_ssidTrafficStats2_t *out = output_struct;
9364
developerce736392022-09-13 15:24:34 +08009365 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009366 if (!output_struct)
9367 return RETURN_ERR;
9368
developerce736392022-09-13 15:24:34 +08009369 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009370 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009371 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009372 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009373
developer06a01d92022-09-07 16:32:39 +08009374 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009375 if (fp == NULL) {
9376 fprintf(stderr, "%s: popen failed\n", __func__);
9377 return RETURN_ERR;
9378 }
9379 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009380 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009381
developerce736392022-09-13 15:24:34 +08009382 if (strlen(str) == 0) // interface not exist
9383 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009384
developerce736392022-09-13 15:24:34 +08009385 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9386 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009387
developerce736392022-09-13 15:24:34 +08009388 memset(str, 0, sizeof(str));
9389 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009390 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009391 if (fp == NULL) {
9392 fprintf(stderr, "%s: popen failed\n", __func__);
9393 return RETURN_ERR;
9394 }
9395 fgets(str, sizeof(str), fp);
9396
9397 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9398 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009399 pclose(fp);
developerce736392022-09-13 15:24:34 +08009400
9401 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9402 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9403
9404 // Not supported
9405 output_struct->ssid_RetransCount = 0;
9406 output_struct->ssid_FailedRetransCount = 0;
9407 output_struct->ssid_RetryCount = 0;
9408 output_struct->ssid_MultipleRetryCount = 0;
9409 output_struct->ssid_ACKFailureCount = 0;
9410 output_struct->ssid_AggregatedPacketCount = 0;
9411
developer06a01d92022-09-07 16:32:39 +08009412 return RETURN_OK;
9413}
9414
9415//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).
9416INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9417{
9418 char output_val[16]={'\0'};
9419 char config_file[MAX_BUF_SIZE] = {0};
9420
9421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9422 if (!output)
9423 return RETURN_ERR;
9424 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9425 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9426
9427 if( strcmp(output_val,"1") == 0 )
9428 *output = TRUE;
9429 else
9430 *output = FALSE;
9431 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9432
9433 return RETURN_OK;
9434}
9435
9436INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9437{
9438 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9439 char str[MAX_BUF_SIZE]={'\0'};
9440 char string[MAX_BUF_SIZE]={'\0'};
9441 char cmd[MAX_CMD_SIZE]={'\0'};
9442 char *ch;
9443 char config_file[MAX_BUF_SIZE] = {0};
9444 struct params params;
9445
9446 if(enable == TRUE)
9447 strcpy(string,"1");
9448 else
9449 strcpy(string,"0");
9450
9451 params.name = "ap_isolate";
9452 params.value = string;
9453
9454 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9455 wifi_hostapdWrite(config_file,&params,1);
9456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9457
9458 return RETURN_OK;
9459}
9460
9461INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9462{
9463 if (NULL == output_dBm)
9464 return RETURN_ERR;
9465
9466 *output_dBm = 0;
9467 return RETURN_OK;
9468}
9469
9470INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9471{
9472 return RETURN_OK;
9473}
9474INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9475{
9476 return RETURN_OK;
9477}
9478INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9479{
9480 return RETURN_OK;
9481}
9482INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9483{
9484 return RETURN_OK;
9485}
9486INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9487{
9488 return RETURN_OK;
9489}
9490INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9491{
9492 char config_file[MAX_BUF_SIZE] = {0};
9493 struct params list;
9494
9495 list.name = "bss_transition";
9496 list.value = activate?"1":"0";
9497 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9498 wifi_hostapdWrite(config_file, &list, 1);
9499
9500 return RETURN_OK;
9501}
9502wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9503
9504void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9505{
9506 return;
9507}
9508
9509INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9510{
9511 // TODO Implement me!
9512 return RETURN_OK;
9513}
9514
9515INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9516{
developera3c68b92022-09-13 15:27:29 +08009517 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009518 FILE *f = NULL;
9519
developer72ec5572023-01-05 16:27:13 +08009520 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009521
developer72ec5572023-01-05 16:27:13 +08009522 if (essid == NULL)
9523 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009524
developer72ec5572023-01-05 16:27:13 +08009525 if (strlen(essid) == 0 || apIndex == -1) {
9526 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9527 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009528 }
9529
developer72ec5572023-01-05 16:27:13 +08009530 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9531 f = fopen(file_name, "w");
9532 if (f == NULL)
9533 return RETURN_ERR;
9534
9535 // For mode == 0 is to disable filter, just don't write ssid to the file.
9536 fprintf(f, "%d\n%s", mode, mode?essid:"");
9537 fclose(f);
9538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009539 return RETURN_OK;
9540}
9541
9542INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9543{
9544 // TODO Implement me!
9545 //Apply wifi_pushRadioChannel() instantly
9546 return RETURN_ERR;
9547}
9548
9549INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9550{
9551 // TODO Implement me!
9552 return RETURN_OK;
9553}
9554
9555#ifdef HAL_NETLINK_IMPL
9556static int tidStats_callback(struct nl_msg *msg, void *arg) {
9557 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9558 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9559 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9560 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9561 int rem , tid_index = 0;
9562
9563 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9564 wifi_associated_dev_tid_entry_t *stats_entry;
9565
9566 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9567 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9568 };
9569 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9570 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9571 };
9572
9573 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9574 genlmsg_attrlen(gnlh, 0), NULL);
9575
9576
9577 if (!tb[NL80211_ATTR_STA_INFO]) {
9578 fprintf(stderr, "station stats missing!\n");
9579 return NL_SKIP;
9580 }
9581
9582 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9583 tb[NL80211_ATTR_STA_INFO],
9584 stats_policy)) {
9585 fprintf(stderr, "failed to parse nested attributes!\n");
9586 return NL_SKIP;
9587 }
9588
9589 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9590 {
9591 stats_entry = &out->tid_array[tid_index];
9592
9593 stats_entry->tid = tid_index;
9594 stats_entry->ac = _tid_ac_index_get[tid_index];
9595
9596 if(sinfo[NL80211_STA_INFO_TID_STATS])
9597 {
9598 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9599 printf("failed to parse nested stats attributes!");
9600 return NL_SKIP;
9601 }
9602 }
9603 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9604 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9605
9606 if(tid_index < (PS_MAX_TID - 1))
9607 tid_index++;
9608 }
9609 //ToDo: sum_time_ms, ewma_time_ms
9610 return NL_SKIP;
9611}
9612#endif
9613
9614INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9615{
9616#ifdef HAL_NETLINK_IMPL
9617 Netlink nl;
9618 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009619 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009620
developerac6f1142022-12-20 19:26:35 +08009621 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009622 return RETURN_ERR;
9623
9624 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009625
9626 nl.id = initSock80211(&nl);
9627
9628 if (nl.id < 0) {
9629 fprintf(stderr, "Error initializing netlink \n");
9630 return -1;
9631 }
9632
9633 struct nl_msg* msg = nlmsg_alloc();
9634
9635 if (!msg) {
9636 fprintf(stderr, "Failed to allocate netlink message.\n");
9637 nlfree(&nl);
9638 return -2;
9639 }
9640
9641 genlmsg_put(msg,
9642 NL_AUTO_PORT,
9643 NL_AUTO_SEQ,
9644 nl.id,
9645 0,
9646 0,
9647 NL80211_CMD_GET_STATION,
9648 0);
9649
9650 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9651 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9652 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9653 nl_send_auto(nl.socket, msg);
9654 nl_recvmsgs(nl.socket, nl.cb);
9655 nlmsg_free(msg);
9656 nlfree(&nl);
9657 return RETURN_OK;
9658#else
9659//iw implementation
9660#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9661#define TOTAL_MAX_LINES 50
9662
9663 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009664 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009665 FILE *fp=NULL;
9666 char pipeCmd[1024]= {'\0'};
9667 int lines,tid_index=0;
9668 char mac_addr[20] = {'\0'};
9669
developerac6f1142022-12-20 19:26:35 +08009670 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009671 return RETURN_ERR;
9672
developer06a01d92022-09-07 16:32:39 +08009673 wifi_associated_dev_tid_entry_t *stats_entry;
9674
developer06a01d92022-09-07 16:32:39 +08009675 strcpy(mac_addr,clientMacAddress);
9676
9677 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9678 fp= popen(pipeCmd,"r");
9679 if(fp == NULL)
9680 {
9681 perror("popen for station dump failed\n");
9682 return RETURN_ERR;
9683 }
9684 pclose(fp);
9685
9686 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9687 fp=popen(pipeCmd,"r");
9688 if(fp == NULL)
9689 {
9690 perror("popen for grep station failed\n");
9691 return RETURN_ERR;
9692 }
9693 else if(fgets(buf,sizeof(buf),fp) != NULL)
9694 lines=atoi(buf);
9695 else
9696 {
9697 pclose(fp);
9698 fprintf(stderr,"No devices are connected \n");
9699 return RETURN_ERR;
9700 }
9701 pclose(fp);
9702
9703 if(lines == 1)
9704 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9705
9706 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9707 {
9708 stats_entry = &tid_stats->tid_array[tid_index];
9709 stats_entry->tid = tid_index;
9710
9711 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);
9712
9713 fp=popen(pipeCmd,"r");
9714 if(fp ==NULL)
9715 {
9716 perror("Failed to read from tid file \n");
9717 return RETURN_ERR;
9718 }
9719 else if(fgets(buf,sizeof(buf),fp) != NULL)
9720 stats_entry->num_msdus = atol(buf);
9721
9722 pclose(fp);
9723 stats_entry->ac = _tid_ac_index_get[tid_index];
9724// TODO:
9725// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9726// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9727 }
9728 return RETURN_OK;
9729#endif
9730}
9731
9732
9733INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9734{
developerd946fd62022-12-08 18:03:28 +08009735 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009736 char cmd[128]={0};
9737 char buf[128]={0};
9738 int freq = 0;
9739
9740 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9741
9742 // full mode is used to scan all channels.
9743 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9744 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9745 ieee80211_channel_to_frequency(chan_list[0], &freq);
9746
developerac6f1142022-12-20 19:26:35 +08009747 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009748 return RETURN_ERR;
9749
developer615510b2022-09-27 10:14:35 +08009750 if (freq)
developerd946fd62022-12-08 18:03:28 +08009751 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009752 else
developerd946fd62022-12-08 18:03:28 +08009753 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009754
9755 _syscmd(cmd, buf, sizeof(buf));
9756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9757
developer06a01d92022-09-07 16:32:39 +08009758 return RETURN_OK;
9759}
9760
9761
9762INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9763{
9764 // TODO Implement me!
9765 return RETURN_ERR;
9766}
9767
9768INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9769{
9770 // TODO Implement me!
9771 return RETURN_ERR;
9772}
9773
9774INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9775{
9776 // TODO Implement me!
9777 return RETURN_ERR;
9778}
9779
9780INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9781{
9782 // TODO Implement me!
9783 return RETURN_ERR;
9784}
9785
9786INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9787{
9788 // TODO Implement me!
9789 return RETURN_ERR;
9790}
9791
9792INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9793{
9794 // TODO Implement me!
9795 return RETURN_ERR;
9796}
9797
9798INT wifi_steering_eventUnregister(void)
9799{
9800 // TODO Implement me!
9801 return RETURN_ERR;
9802}
9803
9804INT wifi_delApAclDevices(INT apIndex)
9805{
9806#if 0
9807 char cmd[MAX_BUF_SIZE] = {0};
9808 char buf[MAX_BUF_SIZE] = {0};
9809
9810 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +08009811 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +08009812 if(_syscmd(cmd,buf,sizeof(buf)))
9813 return RETURN_ERR;
9814#endif
developere6aafda2022-09-13 14:59:28 +08009815 char cmd[MAX_CMD_SIZE]={0};
9816 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009817
developere6aafda2022-09-13 14:59:28 +08009818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9819 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9820 if(_syscmd(cmd, buf, sizeof(buf)))
9821 return RETURN_ERR;
9822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009823
9824 return RETURN_OK;
9825}
9826
9827#ifdef HAL_NETLINK_IMPL
9828static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9829 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9830 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9831 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9832 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9833 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9834 char mac_addr[20],dev[20];
9835
9836 nla_parse(tb,
9837 NL80211_ATTR_MAX,
9838 genlmsg_attrdata(gnlh, 0),
9839 genlmsg_attrlen(gnlh, 0),
9840 NULL);
9841
9842 if(!tb[NL80211_ATTR_STA_INFO]) {
9843 fprintf(stderr, "sta stats missing!\n");
9844 return NL_SKIP;
9845 }
9846
9847 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9848 fprintf(stderr, "failed to parse nested attributes!\n");
9849 return NL_SKIP;
9850 }
9851 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9852
9853 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9854
9855 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9856 fprintf(stderr, "failed to parse nested rate attributes!");
9857 return NL_SKIP;
9858 }
9859
9860 if(sinfo[NL80211_STA_INFO_TID_STATS])
9861 {
9862 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9863 printf("failed to parse nested stats attributes!");
9864 return NL_SKIP;
9865 }
9866 }
9867
9868 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9869 {
9870 printf("Type is VHT\n");
9871 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9872 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9873
9874 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9875 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9876 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9877 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9878 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9879 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9880 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9881 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9882 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9883 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9884 }
9885 else
9886 {
9887 printf(" OFDM or CCK \n");
9888 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9889 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9890 }
9891
9892 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9893 if(rinfo[NL80211_RATE_INFO_MCS])
9894 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9895 }
9896 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9897 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9898 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9899 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9900
9901 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9902 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9903
9904 if (sinfo[NL80211_STA_INFO_SIGNAL])
9905 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9906 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9907 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9908 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9909 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9910 //rssi_array need to be filled
9911 return NL_SKIP;
9912}
9913#endif
9914
9915INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9916{
9917#ifdef HAL_NETLINK_IMPL
9918 Netlink nl;
developerd946fd62022-12-08 18:03:28 +08009919 char if_name[32];
developerac6f1142022-12-20 19:26:35 +08009920 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009921 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009922
9923 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9924
9925 if (*output_array_size <= 0)
9926 return RETURN_OK;
9927
developer06a01d92022-09-07 16:32:39 +08009928 nl.id = initSock80211(&nl);
9929
9930 if (nl.id < 0) {
9931 fprintf(stderr, "Error initializing netlink \n");
9932 return 0;
9933 }
9934
9935 struct nl_msg* msg = nlmsg_alloc();
9936
9937 if (!msg) {
9938 fprintf(stderr, "Failed to allocate netlink message.\n");
9939 nlfree(&nl);
9940 return 0;
9941 }
9942
9943 genlmsg_put(msg,
9944 NL_AUTO_PORT,
9945 NL_AUTO_SEQ,
9946 nl.id,
9947 0,
9948 0,
9949 NL80211_CMD_GET_STATION,
9950 0);
9951
9952 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9953 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9954 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9955 nl_send_auto(nl.socket, msg);
9956 nl_recvmsgs(nl.socket, nl.cb);
9957 nlmsg_free(msg);
9958 nlfree(&nl);
9959 return RETURN_OK;
9960#else
9961 //TODO Implement me
9962 return RETURN_OK;
9963#endif
9964}
9965
9966#ifdef HAL_NETLINK_IMPL
9967static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9968 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9969 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9970 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9971 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9972 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9973 char mac_addr[20],dev[20];
9974
9975 nla_parse(tb,
9976 NL80211_ATTR_MAX,
9977 genlmsg_attrdata(gnlh, 0),
9978 genlmsg_attrlen(gnlh, 0),
9979 NULL);
9980
9981 if(!tb[NL80211_ATTR_STA_INFO]) {
9982 fprintf(stderr, "sta stats missing!\n");
9983 return NL_SKIP;
9984 }
9985
9986 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9987 fprintf(stderr, "failed to parse nested attributes!\n");
9988 return NL_SKIP;
9989 }
9990
9991 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9992
9993 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9994
9995 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9996 fprintf(stderr, "failed to parse nested rate attributes!");
9997 return NL_SKIP;
9998 }
9999
10000 if(sinfo[NL80211_STA_INFO_TID_STATS])
10001 {
10002 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10003 printf("failed to parse nested stats attributes!");
10004 return NL_SKIP;
10005 }
10006 }
10007 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10008 {
10009 printf("Type is VHT\n");
10010 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10011 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10012
10013 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10014 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10015 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10016 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10017 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10018 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10019 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10020 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10021 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10022 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10023 }
10024 else
10025 {
10026 printf(" OFDM or CCK \n");
10027 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10028 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10029 }
10030
10031 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10032 if(rinfo[NL80211_RATE_INFO_MCS])
10033 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10034 }
10035
10036 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10037 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10038 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10039 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10040
10041 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10042 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10043 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10044
10045 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10046 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10047
10048 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10049 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10050
10051 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10052 ((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]);
10053
10054 return NL_SKIP;
10055}
10056#endif
10057
10058INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10059{
10060#ifdef HAL_NETLINK_IMPL
10061 Netlink nl;
10062 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010063 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010064 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010065 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010066
10067 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10068
10069 if (*output_array_size <= 0)
10070 return RETURN_OK;
10071
developerd946fd62022-12-08 18:03:28 +080010072 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010073
10074 nl.id = initSock80211(&nl);
10075
10076 if(nl.id < 0) {
10077 fprintf(stderr, "Error initializing netlink \n");
10078 return 0;
10079 }
10080
10081 struct nl_msg* msg = nlmsg_alloc();
10082
10083 if(!msg) {
10084 fprintf(stderr, "Failed to allocate netlink message.\n");
10085 nlfree(&nl);
10086 return 0;
10087 }
10088
10089 genlmsg_put(msg,
10090 NL_AUTO_PORT,
10091 NL_AUTO_SEQ,
10092 nl.id,
10093 0,
10094 0,
10095 NL80211_CMD_GET_STATION,
10096 0);
10097
10098 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10099 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10100 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10101 nl_send_auto(nl.socket, msg);
10102 nl_recvmsgs(nl.socket, nl.cb);
10103 nlmsg_free(msg);
10104 nlfree(&nl);
10105 return RETURN_OK;
10106#else
10107 //TODO Implement me
10108 return RETURN_OK;
10109#endif
10110}
10111
10112INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10113{
10114 // TODO Implement me!
10115 char buf[MAX_BUF_SIZE] = {0};
10116 char config_file[MAX_BUF_SIZE] = {0};
10117
10118 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10119 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10120 *activate = (strncmp("1",buf,1) == 0);
10121
10122 return RETURN_OK;
10123}
10124
10125INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10126{
10127 char config_file[MAX_BUF_SIZE] = {0};
10128 struct params list;
10129
10130 list.name = "rrm_neighbor_report";
10131 list.value = activate?"1":"0";
10132 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10133 wifi_hostapdWrite(config_file, &list, 1);
10134
10135 return RETURN_OK;
10136}
10137
10138INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10139{
10140 char buf[32] = {0};
10141 char config_file[MAX_BUF_SIZE] = {0};
10142
10143 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10144 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10145 *activate = (strncmp("1",buf,1) == 0);
10146
10147 return RETURN_OK;
10148}
10149#undef HAL_NETLINK_IMPL
10150#ifdef HAL_NETLINK_IMPL
10151static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10152 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10153 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10154 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10155 char dev[20];
10156 int freq =0 ;
10157 static int i=0;
10158
10159 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10160
10161 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10162 };
10163
10164 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10165
10166 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10167
10168 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10169 fprintf(stderr, "survey data missing!\n");
10170 return NL_SKIP;
10171 }
10172
10173 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10174 {
10175 fprintf(stderr, "failed to parse nested attributes!\n");
10176 return NL_SKIP;
10177 }
10178
10179
10180 if(out[0].array_size == 1 )
10181 {
10182 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10183 {
10184 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10185 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10186 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10187
10188 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10189 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10190 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10191 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10192 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10193 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10194 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10195 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10196 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10197 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10198 if (sinfo[NL80211_SURVEY_INFO_TIME])
10199 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10200 return NL_STOP;
10201 }
10202 }
10203 else
10204 {
10205 if ( i <= out[0].array_size )
10206 {
10207 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10208 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10209 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10210
10211 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10212 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10213 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10214 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10215 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10216 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10217 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10218 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10219 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10220 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10221 if (sinfo[NL80211_SURVEY_INFO_TIME])
10222 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10223 }
10224 }
10225
10226 i++;
10227 return NL_SKIP;
10228}
10229#endif
10230
10231static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10232{
10233 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10234 FILE *fp;
10235
10236 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10237 {
10238 printf("Creating Frequency-Channel Map\n");
10239 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10240 }
10241 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10242 if((fp = popen(command, "r")))
10243 {
10244 fgets(output, sizeof(output), fp);
10245 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010246 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010247 }
10248
10249 return 0;
10250}
10251
10252static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10253{
10254 int freqMHz = -1;
10255 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010256 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010257
10258 ieee80211_channel_to_frequency(channel, &freqMHz);
10259 if (freqMHz == -1) {
10260 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10261 return -1;
10262 }
10263
developer7930d352022-12-21 17:55:42 +080010264 wifi_GetInterfaceName(radioIndex, interface_name);
10265 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010266 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10267 radioIndex, freqMHz);
10268 return -1;
10269 }
10270
10271 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10272 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10273 return -1;
10274 }
10275
10276 return 0;
10277}
10278
10279static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10280{
10281 const char *ptr = buf;
10282 char *key = NULL;
10283 char *val = NULL;
10284 char line[256] = { '\0' };
10285
10286 while (ptr = get_line_from_str_buf(ptr, line)) {
10287 if (strstr(line, "Frequency")) continue;
10288
10289 key = strtok(line, ":");
10290 val = strtok(NULL, " ");
10291 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10292
10293 if (!strcmp(key, "noise")) {
10294 sscanf(val, "%d", &stats->ch_noise);
10295 if (stats->ch_noise == 0) {
10296 // Workaround for missing noise information.
10297 // Assume -95 for 2.4G and -103 for 5G
10298 if (radioIndex == 0) stats->ch_noise = -95;
10299 if (radioIndex == 1) stats->ch_noise = -103;
10300 }
10301 }
10302 else if (!strcmp(key, "channel active time")) {
10303 sscanf(val, "%llu", &stats->ch_utilization_total);
10304 }
10305 else if (!strcmp(key, "channel busy time")) {
10306 sscanf(val, "%llu", &stats->ch_utilization_busy);
10307 }
10308 else if (!strcmp(key, "channel receive time")) {
10309 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10310 }
10311 else if (!strcmp(key, "channel transmit time")) {
10312 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10313 }
10314 };
10315
10316 return 0;
10317}
10318
10319INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10320{
10321 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10322#ifdef HAL_NETLINK_IMPL
10323 Netlink nl;
10324 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010325 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010326
10327 local[0].array_size = array_size;
10328
developerac6f1142022-12-20 19:26:35 +080010329 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010330 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010331
10332 nl.id = initSock80211(&nl);
10333
10334 if (nl.id < 0) {
10335 fprintf(stderr, "Error initializing netlink \n");
10336 return -1;
10337 }
10338
10339 struct nl_msg* msg = nlmsg_alloc();
10340
10341 if (!msg) {
10342 fprintf(stderr, "Failed to allocate netlink message.\n");
10343 nlfree(&nl);
10344 return -2;
10345 }
10346
10347 genlmsg_put(msg,
10348 NL_AUTO_PORT,
10349 NL_AUTO_SEQ,
10350 nl.id,
10351 0,
10352 NLM_F_DUMP,
10353 NL80211_CMD_GET_SURVEY,
10354 0);
10355
10356 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10357 nl_send_auto(nl.socket, msg);
10358 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10359 nl_recvmsgs(nl.socket, nl.cb);
10360 nlmsg_free(msg);
10361 nlfree(&nl);
10362 //Copying the Values
10363 for(int i=0;i<array_size;i++)
10364 {
10365 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10366 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10367 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10368 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10369 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10370 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10371 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10372 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10373 }
10374#else
10375 ULONG channel = 0;
10376 int i;
10377 int number_of_channels = array_size;
10378 char buf[512];
10379 INT ret;
10380 wifi_channelStats_t tmp_stats;
10381
10382 if (number_of_channels == 0) {
10383 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10384 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10385 return RETURN_ERR;
10386 }
10387 number_of_channels = 1;
10388 input_output_channelStats_array[0].ch_number = channel;
10389 }
10390
10391 for (i = 0; i < number_of_channels; i++) {
10392
10393 input_output_channelStats_array[i].ch_noise = 0;
10394 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10395 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10396 input_output_channelStats_array[i].ch_utilization_busy = 0;
10397 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10398 input_output_channelStats_array[i].ch_utilization_total = 0;
10399
10400 memset(buf, 0, sizeof(buf));
10401 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10402 return RETURN_ERR;
10403 }
10404 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10405 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10406 return RETURN_ERR;
10407 }
10408
10409 // XXX: fake missing 'self' counter which is not available in iw survey output
10410 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10411 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10412
10413 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10414 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10415 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10416 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10417 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10418
10419 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",
10420 __func__,
10421 input_output_channelStats_array[i].ch_number,
10422 input_output_channelStats_array[i].ch_noise,
10423 input_output_channelStats_array[i].ch_utilization_total,
10424 input_output_channelStats_array[i].ch_utilization_busy,
10425 input_output_channelStats_array[i].ch_utilization_busy_rx,
10426 input_output_channelStats_array[i].ch_utilization_busy_tx,
10427 input_output_channelStats_array[i].ch_utilization_busy_self,
10428 input_output_channelStats_array[i].ch_utilization_busy_ext);
10429 }
10430#endif
10431 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10432 return RETURN_OK;
10433}
10434#define HAL_NETLINK_IMPL
10435
10436/* Hostapd events */
10437
10438#ifndef container_of
10439#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10440#define container_of(ptr, type, member) \
10441 ((type *)((char *)ptr - offset_of(type, member)))
10442#endif /* container_of */
10443
10444struct ctrl {
10445 char sockpath[128];
10446 char sockdir[128];
10447 char bss[IFNAMSIZ];
10448 char reply[4096];
10449 int ssid_index;
10450 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10451 void (*overrun)(struct ctrl *ctrl);
10452 struct wpa_ctrl *wpa;
10453 unsigned int ovfl;
10454 size_t reply_len;
10455 int initialized;
10456 ev_timer retry;
10457 ev_timer watchdog;
10458 ev_stat stat;
10459 ev_io io;
10460};
10461static wifi_newApAssociatedDevice_callback clients_connect_cb;
10462static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10463static struct ctrl wpa_ctrl[MAX_APS];
10464static int initialized;
10465
10466static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10467{
10468 char cbuf[256] = {};
10469 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10470 struct cmsghdr *cmsg;
10471 unsigned int ovfl = ctrl->ovfl;
10472 unsigned int drop;
10473
10474 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10475 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10476 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10477 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10478
10479 drop = ovfl - ctrl->ovfl;
10480 ctrl->ovfl = ovfl;
10481
10482 return drop;
10483}
10484
10485static void ctrl_close(struct ctrl *ctrl)
10486{
10487 if (ctrl->io.cb)
10488 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10489 if (ctrl->retry.cb)
10490 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10491 if (!ctrl->wpa)
10492 return;
10493
10494 wpa_ctrl_detach(ctrl->wpa);
10495 wpa_ctrl_close(ctrl->wpa);
10496 ctrl->wpa = NULL;
10497 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10498}
10499
10500static void ctrl_process(struct ctrl *ctrl)
10501{
10502 const char *str;
10503 int drops;
10504 int level;
10505 int err;
10506
10507 /* Example events:
10508 *
10509 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10510 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10511 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10512 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10513 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10514 */
10515 if (!(str = index(ctrl->reply, '>')))
10516 return;
10517 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10518 return;
10519
10520 str++;
10521
10522 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10523 if (!(str = index(ctrl->reply, ' ')))
10524 return;
10525 wifi_associated_dev_t sta;
10526 memset(&sta, 0, sizeof(sta));
10527
10528 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10529 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10530 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10531
10532 sta.cli_Active=true;
10533
10534 (clients_connect_cb)(ctrl->ssid_index, &sta);
10535 goto handled;
10536 }
10537
10538 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10539 if (!(str = index(ctrl->reply, ' ')))
10540 return;
10541
10542 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10543 goto handled;
10544 }
10545
10546 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10547 printf("CTRL_WPA: handle TERMINATING event\n");
10548 goto retry;
10549 }
10550
10551 if (strncmp("AP-DISABLED", str, 11) == 0) {
10552 printf("CTRL_WPA: handle AP-DISABLED\n");
10553 goto retry;
10554 }
10555
10556 printf("Event not supported!!\n");
10557
10558handled:
10559
10560 if ((drops = ctrl_get_drops(ctrl))) {
10561 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10562 if (ctrl->overrun)
10563 ctrl->overrun(ctrl);
10564 }
10565
10566 return;
10567
10568retry:
10569 printf("WPA_CTRL: closing\n");
10570 ctrl_close(ctrl);
10571 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10572 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10573}
10574
10575static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10576{
10577 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10578 int err;
10579
10580 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10581 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10582 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10583 ctrl->reply[ctrl->reply_len] = 0;
10584 if (err < 0) {
10585 if (errno == EAGAIN || errno == EWOULDBLOCK)
10586 return;
10587 ctrl_close(ctrl);
10588 ev_timer_again(EV_A_ &ctrl->retry);
10589 return;
10590 }
10591
10592 ctrl_process(ctrl);
10593}
10594
10595static int ctrl_open(struct ctrl *ctrl)
10596{
10597 int fd;
10598
10599 if (ctrl->wpa)
10600 return 0;
10601
10602 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10603 if (!ctrl->wpa)
10604 goto err;
10605
10606 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10607 goto err_close;
10608
10609 fd = wpa_ctrl_get_fd(ctrl->wpa);
10610 if (fd < 0)
10611 goto err_detach;
10612
10613 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10614 goto err_detach;
10615
10616 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10617 ev_io_start(EV_DEFAULT_ &ctrl->io);
10618
10619 return 0;
10620
10621err_detach:
10622 wpa_ctrl_detach(ctrl->wpa);
10623err_close:
10624 wpa_ctrl_close(ctrl->wpa);
10625err:
10626 ctrl->wpa = NULL;
10627 return -1;
10628}
10629
10630static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10631{
10632 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10633
10634 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10635 ctrl_open(ctrl);
10636}
10637
10638static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10639{
10640 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10641
10642 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10643 if (ctrl_open(ctrl) == 0) {
10644 printf("WPA_CTRL: retry successful\n");
10645 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10646 }
10647}
10648
10649int ctrl_enable(struct ctrl *ctrl)
10650{
10651 if (ctrl->wpa)
10652 return 0;
10653
10654 if (!ctrl->stat.cb) {
10655 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10656 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10657 }
10658
10659 if (!ctrl->retry.cb) {
10660 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10661 }
10662
10663 return ctrl_open(ctrl);
10664}
10665
10666static void
10667ctrl_msg_cb(char *buf, size_t len)
10668{
10669 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10670
10671 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10672 ctrl_process(ctrl);
10673}
10674
10675static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10676{
10677 int err;
10678
10679 if (!ctrl->wpa)
10680 return -1;
10681 if (*reply_len < 2)
10682 return -1;
10683
10684 (*reply_len)--;
10685 ctrl->reply_len = sizeof(ctrl->reply);
10686 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10687 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10688 if (err < 0)
10689 return err;
10690
10691 if (ctrl->reply_len > *reply_len)
10692 ctrl->reply_len = *reply_len;
10693
10694 *reply_len = ctrl->reply_len;
10695 memcpy(reply, ctrl->reply, *reply_len);
10696 reply[*reply_len - 1] = 0;
10697 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10698 return 0;
10699}
10700
10701static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10702{
10703 const char *pong = "PONG";
10704 const char *ping = "PING";
10705 char reply[1024];
10706 size_t len = sizeof(reply);
10707 int err;
10708 ULONG s, snum;
10709 INT ret;
10710 BOOL status;
10711
10712 printf("WPA_CTRL: watchdog cb\n");
10713
10714 ret = wifi_getSSIDNumberOfEntries(&snum);
10715 if (ret != RETURN_OK) {
10716 printf("%s: failed to get SSID count", __func__);
10717 return;
10718 }
10719
10720 if (snum > MAX_APS) {
10721 printf("more ssid than supported! %lu\n", snum);
10722 return;
10723 }
10724
10725 for (s = 0; s < snum; s++) {
10726 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010727 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010728 continue;
10729 }
10730 if (status == false) continue;
10731
10732 memset(reply, 0, sizeof(reply));
10733 len = sizeof(reply);
10734 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10735 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10736 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10737 continue;
10738
10739 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10740 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010741 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010742 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10743 }
10744}
10745
10746static int init_wpa()
10747{
10748 int ret = 0, i = 0;
10749 ULONG s, snum;
10750
10751 ret = wifi_getSSIDNumberOfEntries(&snum);
10752 if (ret != RETURN_OK) {
10753 printf("%s: failed to get SSID count", __func__);
10754 return RETURN_ERR;
10755 }
10756
10757 if (snum > MAX_APS) {
10758 printf("more ssid than supported! %lu\n", snum);
10759 return RETURN_ERR;
10760 }
10761
10762 for (s = 0; s < snum; s++) {
10763 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10764 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10765 wpa_ctrl[s].ssid_index = s;
10766 ctrl_enable(&wpa_ctrl[s]);
10767 }
10768
10769 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10770 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10771
10772 initialized = 1;
10773 printf("WPA_CTRL: initialized\n");
10774
10775 return RETURN_OK;
10776}
10777
10778void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10779{
10780 clients_connect_cb = callback_proc;
10781 if (!initialized)
10782 init_wpa();
10783}
10784
10785void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10786{
10787 clients_disconnect_cb = callback_proc;
10788 if (!initialized)
10789 init_wpa();
10790}
10791
10792INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10793{
10794 // TODO Implement me!
10795 return RETURN_ERR;
10796}
10797
10798INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10799{
10800 // TODO Implement me!
10801 return RETURN_ERR;
10802}
10803
10804INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10805{
10806 int i;
developer4b102122023-02-15 10:53:03 +080010807 int phyId = -1;
10808 char cmd[256] = {0};
10809 char channel_numbers_buf[256] = {0};
10810 char dfs_state_buf[256] = {0};
10811 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080010812 const char *ptr;
developer4b102122023-02-15 10:53:03 +080010813 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080010814
developer4b102122023-02-15 10:53:03 +080010815 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080010816
developer4b102122023-02-15 10:53:03 +080010817 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
10818 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080010819
developer4b102122023-02-15 10:53:03 +080010820 snprintf(cmd, sizeof (cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v '%sno IR\\|5340\\|5480' | awk '{print $4}' | tr -d '[]'", phyId, dfs_enable?"":"radar\\|");
developer06a01d92022-09-07 16:32:39 +080010821
developer4b102122023-02-15 10:53:03 +080010822 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10823 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10824 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010825 }
10826
developer4b102122023-02-15 10:53:03 +080010827 ptr = channel_numbers_buf;
10828 i = 0;
10829 while (ptr = get_line_from_str_buf(ptr, line)) {
10830 if (i >= outputMapSize) {
10831 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10832 return RETURN_ERR;
10833 }
10834 sscanf(line, "%d", &outputMap[i].ch_number);
10835
10836 memset(cmd, 0, sizeof(cmd));
10837 // Below command should fetch string for DFS state (usable, available or unavailable)
10838 // Example line: "DFS state: usable (for 78930 sec)"
10839 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) {
10840 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080010841 return RETURN_ERR;
10842 }
10843
developer4b102122023-02-15 10:53:03 +080010844 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10845 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080010846 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10847 return RETURN_ERR;
10848 }
10849
developer4b102122023-02-15 10:53:03 +080010850 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080010851
developer4b102122023-02-15 10:53:03 +080010852 if (!strcmp(dfs_state_buf, "usable")) {
10853 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10854 } else if (!strcmp(dfs_state_buf, "available")) {
10855 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10856 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10857 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10858 } else {
10859 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080010860 }
developer4b102122023-02-15 10:53:03 +080010861 i++;
developer06a01d92022-09-07 16:32:39 +080010862 }
10863
developer4b102122023-02-15 10:53:03 +080010864 return RETURN_OK;
10865
developer06a01d92022-09-07 16:32:39 +080010866 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10867 return RETURN_ERR;
10868}
10869
10870INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10871{
10872 // TODO Implement me!
10873 return RETURN_ERR;
10874}
10875
10876INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10877{
10878 return RETURN_OK;
10879}
10880
10881INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10882{
10883 // TODO Implement me!
10884 return RETURN_ERR;
10885}
10886
10887INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10888{
10889 // TODO API refrence Implementaion is present on RPI hal
10890 return RETURN_ERR;
10891}
10892
10893INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10894{
developerd946fd62022-12-08 18:03:28 +080010895 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080010896 char cmd[128]={'\0'};
10897 char buf[128]={'\0'};
10898 char *support;
10899 int maximum_tx = 0, current_tx = 0;
10900
10901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10902 if(txpwr_pcntg == NULL)
10903 return RETURN_ERR;
10904
developerac6f1142022-12-20 19:26:35 +080010905 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010906 return RETURN_ERR;
10907
developera5005b62022-09-13 15:43:35 +080010908 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080010909 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080010910 _syscmd(cmd, buf, sizeof(buf));
10911 maximum_tx = strtol(buf, NULL, 10);
10912
10913 // Get the current tx power
10914 memset(cmd, 0, sizeof(cmd));
10915 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080010916 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080010917 _syscmd(cmd, buf, sizeof(buf));
10918 current_tx = strtol(buf, NULL, 10);
10919
10920 // Get the power supported list and find the current power percentage in supported list
10921 memset(buf, 0, sizeof(buf));
10922 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10923 support = strtok(buf, ",");
10924 while(true)
10925 {
10926 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 +080010927 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010928 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010929 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010930 }
10931 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10932 if (tmp == current_tx) {
10933 *txpwr_pcntg = strtol(support, NULL, 10);
10934 break;
10935 }
10936 support = strtok(NULL, ",");
10937 }
10938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010939 return RETURN_OK;
10940}
10941
10942INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10943{
developer58599c22022-09-13 16:40:34 +080010944 // TODO precac feature.
10945 struct params params = {0};
10946 char config_file[128] = {0};
10947
10948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10949
10950 params.name = "enable_background_radar";
10951 params.value = enable?"1":"0";
10952 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10953 wifi_hostapdWrite(config_file, &params, 1);
10954 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10955
10956 /* TODO precac feature */
10957
10958 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10959 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010960}
10961
10962INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10963{
developer58599c22022-09-13 16:40:34 +080010964 char config_file[128] = {0};
10965 char buf[64] = {0};
10966
10967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10968 if (NULL == enable || NULL == precac)
10969 return RETURN_ERR;
10970
10971 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10972 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10973 if (strncmp(enable, "1", 1) == 0)
10974 *enable = true;
10975 else
10976 *enable = false;
10977
10978 /* TODO precac feature */
10979
10980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10981 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010982}
10983
10984INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10985{
developer58599c22022-09-13 16:40:34 +080010986 *supported = TRUE;
10987 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010988}
10989
developera7149722023-01-11 11:36:21 +080010990bool check_is_hemu_vendor_new_patch() {
10991 char cmd[128] = {0};
10992 char buf[128] = {0};
10993
10994 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
10995 _syscmd(cmd, buf, sizeof(buf));
10996
10997 if (strlen(buf) > 0)
10998 return FALSE;
10999 else
11000 return TRUE;
11001}
11002
developer3e6b1692022-09-30 18:04:05 +080011003INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11004{
11005 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11006 struct params params = {0};
11007 char config_file[64] = {0};
11008 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011009 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011010 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011011 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011012 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11013
developera7149722023-01-11 11:36:21 +080011014 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011015
11016 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11017 set_mu_type &= ~0x05; // unset bit 0, 2
11018 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11019 set_mu_type |= 0x01;
11020 set_mu_type &= ~0x04;
11021 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11022 set_mu_type &= ~0x01;
11023 set_mu_type |= 0x04;
11024 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11025 set_mu_type |= 0x05; // set bit 0, 2
11026 }
11027
developera7149722023-01-11 11:36:21 +080011028 new_vendor_patch = check_is_hemu_vendor_new_patch();
11029 if (new_vendor_patch)
11030 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11031 else
11032 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11033
11034 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011035 sprintf(buf, "%u", set_mu_type);
11036 params.value = buf;
11037 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11038 wifi_hostapdWrite(config_file, &params, 1);
11039 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011040 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011041
11042 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11043 return RETURN_OK;
11044}
11045
11046INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11047{
11048 struct params params={0};
11049 char config_file[64] = {0};
11050 char buf[64] = {0};
11051 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011052 bool new_vendor_patch = FALSE;
11053 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011054
11055 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11056
11057 if (mu_type == NULL)
11058 return RETURN_ERR;
11059
developera7149722023-01-11 11:36:21 +080011060 new_vendor_patch = check_is_hemu_vendor_new_patch();
11061
11062 if (new_vendor_patch)
11063 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11064 else
11065 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11066
developer3e6b1692022-09-30 18:04:05 +080011067 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011068 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011069 get_mu_type = strtol(buf, NULL, 10);
11070
11071 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11072 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11073 else if (get_mu_type & 0x04)
11074 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11075 else if (get_mu_type & 0x01)
11076 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11077 else
11078 *mu_type = WIFI_DL_MU_TYPE_NONE;
11079
11080 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11081 return RETURN_OK;
11082}
11083
11084INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11085{
11086 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11087 struct params params={0};
11088 char config_file[64] = {0};
11089 char buf[64] = {0};
11090 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011091 bool new_vendor_patch = FALSE;
11092 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011093 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11094
developera7149722023-01-11 11:36:21 +080011095 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011096
11097 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11098 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11099 set_mu_type &= ~0x0a;
11100 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11101 set_mu_type |= 0x02;
11102 set_mu_type &= ~0x08;
11103 }
11104
developera7149722023-01-11 11:36:21 +080011105 new_vendor_patch = check_is_hemu_vendor_new_patch();
11106
11107 if (new_vendor_patch)
11108 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11109 else
11110 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11111
11112 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011113 sprintf(buf, "%u", set_mu_type);
11114 params.value = buf;
11115 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11116 wifi_hostapdWrite(config_file, &params, 1);
11117 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011118 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011119
11120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11121 return RETURN_OK;
11122}
11123
11124INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11125{
11126 struct params params={0};
11127 char config_file[64] = {0};
11128 char buf[64] = {0};
11129 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011130 bool new_vendor_patch = FALSE;
11131 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011132
11133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11134
developera7149722023-01-11 11:36:21 +080011135 new_vendor_patch = check_is_hemu_vendor_new_patch();
11136
11137 if (new_vendor_patch)
11138 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11139 else
11140 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11141
developer3e6b1692022-09-30 18:04:05 +080011142 if (mu_type == NULL)
11143 return RETURN_ERR;
11144
11145 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011146 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011147
11148 get_mu_type = strtol(buf, NULL, 10);
11149 if (get_mu_type & 0x02)
11150 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11151 else
11152 *mu_type = WIFI_DL_MU_TYPE_NONE;
11153
11154 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11155 return RETURN_OK;
11156}
11157
11158
developer454b9462022-09-13 15:29:16 +080011159INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11160{
11161 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011162 char buf[256] = {0};
11163 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011164 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011165 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011166 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011167 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011168
11169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11170
developer254882b2022-09-30 17:12:31 +080011171 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011172 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11173 return RETURN_ERR;
11174 }
developer454b9462022-09-13 15:29:16 +080011175
developer254882b2022-09-30 17:12:31 +080011176 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011177 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011178
developer254882b2022-09-30 17:12:31 +080011179 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11180 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011181 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011182 _syscmd(cmd, buf, sizeof(buf));
11183 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11184 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11185 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011186 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 +080011187 _syscmd(cmd, buf, sizeof(buf));
11188 }
11189 if (band == band_5) {
11190 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11191 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011192 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 +080011193 _syscmd(cmd, buf, sizeof(buf));
11194 }
11195 }
11196 }
11197 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011198
developer254882b2022-09-30 17:12:31 +080011199 if (guard_interval == wifi_guard_interval_400)
11200 strcpy(GI, "0.4");
11201 else if (guard_interval == wifi_guard_interval_800)
11202 strcpy(GI, "0.8");
11203 else if (guard_interval == wifi_guard_interval_1600)
11204 strcpy(GI, "1.6");
11205 else if (guard_interval == wifi_guard_interval_3200)
11206 strcpy(GI, "3.2");
11207 else if (guard_interval == wifi_guard_interval_auto)
11208 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011209 // Record GI for get GI function
11210 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11211 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011212 if (f == NULL)
11213 return RETURN_ERR;
11214 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011215 fclose(f);
11216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11217 return RETURN_OK;
11218}
11219
11220INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11221{
11222 char buf[32] = {0};
11223 char cmd[64] = {0};
11224
11225 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11226
11227 if (guard_interval == NULL)
11228 return RETURN_ERR;
11229
11230 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11231 _syscmd(cmd, buf, sizeof(buf));
11232
11233 if (strncmp(buf, "0.4", 3) == 0)
11234 *guard_interval = wifi_guard_interval_400;
11235 else if (strncmp(buf, "0.8", 3) == 0)
11236 *guard_interval = wifi_guard_interval_800;
11237 else if (strncmp(buf, "1.6", 3) == 0)
11238 *guard_interval = wifi_guard_interval_1600;
11239 else if (strncmp(buf, "3.2", 3) == 0)
11240 *guard_interval = wifi_guard_interval_3200;
11241 else
11242 *guard_interval = wifi_guard_interval_auto;
11243
11244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11245 return RETURN_OK;
11246}
11247
developer3cc61d12022-09-13 16:36:05 +080011248INT wifi_setBSSColor(INT radio_index, UCHAR color)
11249{
11250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11251 struct params params = {0};
11252 char config_file[128] = {0};
11253 char bss_color[4] ={0};
11254
11255 params.name = "he_bss_color";
11256 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11257 params.value = bss_color;
11258 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11259 wifi_hostapdWrite(config_file, &params, 1);
11260 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11261
11262 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11263 return RETURN_OK;
11264}
11265
11266INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11267{
11268 char config_file[128] = {0};
11269 char buf[64] = {0};
11270 char temp_output[128] = {'\0'};
11271
11272 wifi_dbg_printf("\nFunc=%s\n", __func__);
11273 if (NULL == color)
11274 return RETURN_ERR;
11275
11276 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11277 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11278
11279 if(strlen(buf) > 0) {
11280 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11281 } else {
11282 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11283 }
11284
11285 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11286 wifi_dbg_printf("\noutput_string=%s\n", color);
11287
11288 return RETURN_OK;
11289}
11290
developer06a01d92022-09-07 16:32:39 +080011291/* multi-psk support */
11292INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11293{
11294 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011295 char interface_name[16] = {0};
11296
developerac6f1142022-12-20 19:26:35 +080011297 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011298 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011299
developerd946fd62022-12-08 18:03:28 +080011300 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11301 interface_name,
developer06a01d92022-09-07 16:32:39 +080011302 mac[0],
11303 mac[1],
11304 mac[2],
11305 mac[3],
11306 mac[4],
11307 mac[5]
11308 );
11309 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11310 _syscmd(cmd, key->wifi_keyId, 64);
11311
11312
11313 return RETURN_OK;
11314}
11315
11316INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11317{
developerd946fd62022-12-08 18:03:28 +080011318 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011319 FILE *fd = NULL;
11320 char fname[100];
11321 char cmd[128] = {0};
11322 char out[64] = {0};
11323 wifi_key_multi_psk_t * key = NULL;
11324 if(keysNumber < 0)
11325 return RETURN_ERR;
11326
developer431128d2022-12-16 15:30:41 +080011327 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011328 fd = fopen(fname, "w");
11329 if (!fd) {
11330 return RETURN_ERR;
11331 }
11332 key= (wifi_key_multi_psk_t *) keys;
11333 for(int i=0; i<keysNumber; ++i, key++) {
11334 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11335 }
11336 fclose(fd);
11337
11338 //reload file
developerac6f1142022-12-20 19:26:35 +080011339 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011340 return RETURN_ERR;
11341 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011342 _syscmd(cmd, out, 64);
11343 return RETURN_OK;
11344}
11345
11346INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11347{
11348 FILE *fd = NULL;
11349 char fname[100];
11350 char * line = NULL;
11351 char * pos = NULL;
11352 size_t len = 0;
11353 ssize_t read = 0;
11354 INT ret = RETURN_OK;
11355 wifi_key_multi_psk_t *keys_it = NULL;
11356
11357 if (keysNumber < 1) {
11358 return RETURN_ERR;
11359 }
11360
developer431128d2022-12-16 15:30:41 +080011361 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011362 fd = fopen(fname, "r");
11363 if (!fd) {
11364 return RETURN_ERR;
11365 }
11366
11367 if (keys == NULL) {
11368 ret = RETURN_ERR;
11369 goto close;
11370 }
11371
11372 keys_it = keys;
11373 while ((read = getline(&line, &len, fd)) != -1) {
11374 //Strip trailing new line if present
11375 if (read > 0 && line[read-1] == '\n') {
11376 line[read-1] = '\0';
11377 }
11378
11379 if(strcmp(line,"keyid=")) {
11380 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11381 if (!(pos = index(line, ' '))) {
11382 ret = RETURN_ERR;
11383 goto close;
11384 }
11385 pos++;
11386 //Here should be 00:00:00:00:00:00
11387 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11388 printf("Not supported MAC: %s\n", pos);
11389 }
11390 if (!(pos = index(pos, ' '))) {
11391 ret = RETURN_ERR;
11392 goto close;
11393 }
11394 pos++;
11395
11396 //The rest is PSK
11397 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11398 keys_it++;
11399
11400 if(--keysNumber <= 0)
11401 break;
11402 }
11403 }
11404
11405close:
11406 free(line);
11407 fclose(fd);
11408 return ret;
11409}
11410/* end of multi-psk support */
11411
11412INT wifi_setNeighborReports(UINT apIndex,
11413 UINT numNeighborReports,
11414 wifi_NeighborReport_t *neighborReports)
11415{
11416 char cmd[256] = { 0 };
11417 char hex_bssid[13] = { 0 };
11418 char bssid[18] = { 0 };
11419 char nr[256] = { 0 };
11420 char ssid[256];
11421 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011422 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011423 INT ret;
11424
11425 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011426 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011427 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011428 return RETURN_ERR;
11429 sprintf(cmd, "hostapd_cli show_neighbor -i %s | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s",interface_name,interface_name);
developer06a01d92022-09-07 16:32:39 +080011430 system(cmd);
11431
11432 for(unsigned int i = 0; i < numNeighborReports; i++)
11433 {
11434 memset(ssid, 0, sizeof(ssid));
11435 ret = wifi_getSSIDName(apIndex, ssid);
11436 if (ret != RETURN_OK)
11437 return RETURN_ERR;
11438
11439 memset(hex_ssid, 0, sizeof(hex_ssid));
11440 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11441 sprintf(hex_ssid + k,"%02x", ssid[j]);
11442
11443 snprintf(hex_bssid, sizeof(hex_bssid),
11444 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11445 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11446 snprintf(bssid, sizeof(bssid),
11447 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11448 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11449
11450 snprintf(nr, sizeof(nr),
11451 "%s" // bssid
11452 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11453 "%02hhx" // operclass
11454 "%02hhx" // channel
11455 "%02hhx", // phy_mode
11456 hex_bssid,
11457 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11458 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11459 neighborReports[i].opClass,
11460 neighborReports[i].channel,
11461 neighborReports[i].phyTable);
11462
11463 snprintf(cmd, sizeof(cmd),
11464 "hostapd_cli set_neighbor "
11465 "%s " // bssid
11466 "ssid=%s " // ssid
11467 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011468 "-i %s",
11469 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011470
11471 if (WEXITSTATUS(system(cmd)) != 0)
11472 {
11473 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11474 }
11475 }
11476
11477 return RETURN_OK;
11478}
11479
11480INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11481{
11482 return RETURN_OK;
11483}
11484
11485#ifdef _WIFI_HAL_TEST_
11486int main(int argc,char **argv)
11487{
11488 int index;
11489 INT ret=0;
11490 char buf[1024]="";
11491
11492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11493 if(argc<3)
11494 {
11495 if(argc==2)
11496 {
11497 if(!strcmp(argv[1], "init"))
11498 return wifi_init();
11499 if(!strcmp(argv[1], "reset"))
11500 return wifi_reset();
11501 if(!strcmp(argv[1], "wifi_getHalVersion"))
11502 {
11503 char buffer[64];
11504 if(wifi_getHalVersion(buffer)==RETURN_OK)
11505 printf("Version: %s\n", buffer);
11506 else
11507 printf("Error in wifi_getHalVersion\n");
11508 return RETURN_OK;
11509 }
11510 }
11511 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11512 exit(-1);
11513 }
11514
11515 index = atoi(argv[2]);
11516 if(strstr(argv[1], "wifi_getApName")!=NULL)
11517 {
11518 wifi_getApName(index,buf);
11519 printf("Ap name is %s \n",buf);
11520 return 0;
11521 }
11522 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11523 {
11524 BOOL b = FALSE;
11525 BOOL *output_bool = &b;
11526 wifi_getRadioAutoChannelEnable(index,output_bool);
11527 printf("Channel enabled = %d \n",b);
11528 return 0;
11529 }
11530 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11531 {
11532 wifi_getApWpaEncryptionMode(index,buf);
11533 printf("encryption enabled = %s\n",buf);
11534 return 0;
11535 }
11536 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11537 {
11538 BOOL b = FALSE;
11539 BOOL *output_bool = &b;
11540 wifi_getApSsidAdvertisementEnable(index,output_bool);
11541 printf("advertisment enabled = %d\n",b);
11542 return 0;
11543 }
11544 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11545 {
11546 if(argc <= 3 )
11547 {
11548 printf("Insufficient arguments \n");
11549 exit(-1);
11550 }
11551
11552 char sta[20] = {'\0'};
11553 ULLONG handle= 0;
11554 strcpy(sta,argv[3]);
11555 mac_address_t st;
11556 mac_addr_aton(st,sta);
11557
11558 wifi_associated_dev_tid_stats_t tid_stats;
11559 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11560 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11561 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);
11562 }
11563
11564 if(strstr(argv[1], "getApEnable")!=NULL) {
11565 BOOL enable;
11566 ret=wifi_getApEnable(index, &enable);
11567 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11568 }
11569 else if(strstr(argv[1], "setApEnable")!=NULL) {
11570 BOOL enable = atoi(argv[3]);
11571 ret=wifi_setApEnable(index, enable);
11572 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11573 }
11574 else if(strstr(argv[1], "getApStatus")!=NULL) {
11575 char status[64];
11576 ret=wifi_getApStatus(index, status);
11577 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11578 }
11579 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11580 {
11581 wifi_getSSIDNameStatus(index,buf);
11582 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11583 return 0;
11584 }
11585 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11586 wifi_ssidTrafficStats2_t stats={0};
11587 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11588 printf("%s %d: returns %d\n", argv[1], index, ret);
11589 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11590 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11591 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11592 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11593 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11594 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11595 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11596 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11597 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11598 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11599 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11600 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11601 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11602 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11603 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11604 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11605 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11606 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11607 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11608 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11609 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11610 }
11611 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11612 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11613 UINT array_size=0;
11614 UINT i=0;
11615 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11616 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11617 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11618 printf(" neighbor %d:\n", i);
11619 printf(" ap_SSID =%s\n", pt->ap_SSID);
11620 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11621 printf(" ap_Mode =%s\n", pt->ap_Mode);
11622 printf(" ap_Channel =%d\n", pt->ap_Channel);
11623 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11624 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11625 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11626 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11627 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11628 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11629 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11630 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11631 printf(" ap_Noise =%d\n", pt->ap_Noise);
11632 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11633 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11634 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11635 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11636 }
11637 if(neighbor_ap_array)
11638 free(neighbor_ap_array); //make sure to free the list
11639 }
11640 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11641 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11642 UINT array_size=0;
11643 UINT i=0;
11644 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11645 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11646 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11647 printf(" associated_dev %d:\n", i);
11648 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11649 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11650 printf(" cli_SNR =%d\n", pt->cli_SNR);
11651 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11652 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11653 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11654 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11655 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11656 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11657 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11658 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11659 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11660 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11661 }
11662 if(associated_dev_array)
11663 free(associated_dev_array); //make sure to free the list
11664 }
11665
11666 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11667 {
11668#define MAX_ARRAY_SIZE 64
11669 int i, array_size;
11670 char *p, *ch_str;
11671 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11672
11673 if(argc != 5)
11674 {
11675 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11676 exit(-1);
11677 }
11678 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11679
11680 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11681 {
11682 strtok_r(ch_str, ",", &p);
11683 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11684 }
11685 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11686 if(!array_size)
11687 array_size=1;//Need to print current channel statistics
11688 for(i=0; i<array_size; i++)
11689 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11690 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11691 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11692 input_output_channelStats_array[i].ch_number,\
11693 input_output_channelStats_array[i].ch_noise,\
11694 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11695 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11696 input_output_channelStats_array[i].ch_utilization_busy,\
11697 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11698 input_output_channelStats_array[i].ch_utilization_total);
11699 }
11700
11701 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11702 {
11703 if(argc <= 3 )
11704 {
11705 printf("Insufficient arguments \n");
11706 exit(-1);
11707 }
11708 char mac_addr[20] = {'\0'};
11709 wifi_device_t output_struct;
11710 int dev_index = atoi(argv[3]);
11711
11712 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11713 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11714 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);
11715 }
11716
11717 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11718 {
11719 if (argc <= 3)
11720 {
11721 printf("Insufficient arguments\n");
11722 exit(-1);
11723 }
11724 char args[256];
11725 wifi_NeighborReport_t *neighborReports;
11726
11727 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11728 if (!neighborReports)
11729 {
11730 printf("Failed to allocate memory");
11731 exit(-1);
11732 }
11733
11734 for (int i = 3; i < argc; ++i)
11735 {
11736 char *val;
11737 int j = 0;
11738 memset(args, 0, sizeof(args));
11739 strncpy(args, argv[i], sizeof(args));
11740 val = strtok(args, ";");
11741 while (val != NULL)
11742 {
11743 if (j == 0)
11744 {
11745 mac_addr_aton(neighborReports[i - 3].bssid, val);
11746 } else if (j == 1)
11747 {
11748 neighborReports[i - 3].info = strtol(val, NULL, 16);
11749 } else if (j == 2)
11750 {
11751 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11752 } else if (j == 3)
11753 {
11754 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11755 } else if (j == 4)
11756 {
11757 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11758 } else {
11759 printf("Insufficient arguments]n\n");
11760 exit(-1);
11761 }
11762 val = strtok(NULL, ";");
11763 j++;
11764 }
11765 }
11766
11767 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11768 if (ret != RETURN_OK)
11769 {
11770 printf("wifi_setNeighborReports ret = %d", ret);
11771 exit(-1);
11772 }
11773 }
11774 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11775 {
11776 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11777 printf("%s.\n", buf);
11778 else
11779 printf("Error returned\n");
11780 }
11781 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11782 {
11783 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11784 printf("%s.\n", buf);
11785 else
11786 printf("Error returned\n");
11787 }
11788 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11789 {
11790 if (argc <= 2)
11791 {
11792 printf("Insufficient arguments\n");
11793 exit(-1);
11794 }
11795 char buf[64]= {'\0'};
11796 wifi_getRadioOperatingChannelBandwidth(index,buf);
11797 printf("Current bandwidth is %s \n",buf);
11798 return 0;
11799 }
11800 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11801 {
11802 if (argc <= 5)
11803 {
11804 printf("Insufficient arguments\n");
11805 exit(-1);
11806 }
11807 UINT channel = atoi(argv[3]);
11808 UINT width = atoi(argv[4]);
11809 UINT beacon = atoi(argv[5]);
11810 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11811 printf("Result = %d", ret);
11812 }
11813
11814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11815 return 0;
11816}
11817
11818#endif
11819
11820#ifdef WIFI_HAL_VERSION_3
11821
developer1e5aa162022-09-13 16:06:24 +080011822INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11823{
11824 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11825 if (bitMap & WIFI_BITRATE_1MBPS)
11826 strcat(BasicRate, "1,");
11827 if (bitMap & WIFI_BITRATE_2MBPS)
11828 strcat(BasicRate, "2,");
11829 if (bitMap & WIFI_BITRATE_5_5MBPS)
11830 strcat(BasicRate, "5.5,");
11831 if (bitMap & WIFI_BITRATE_6MBPS)
11832 strcat(BasicRate, "6,");
11833 if (bitMap & WIFI_BITRATE_9MBPS)
11834 strcat(BasicRate, "9,");
11835 if (bitMap & WIFI_BITRATE_11MBPS)
11836 strcat(BasicRate, "11,");
11837 if (bitMap & WIFI_BITRATE_12MBPS)
11838 strcat(BasicRate, "12,");
11839 if (bitMap & WIFI_BITRATE_18MBPS)
11840 strcat(BasicRate, "18,");
11841 if (bitMap & WIFI_BITRATE_24MBPS)
11842 strcat(BasicRate, "24,");
11843 if (bitMap & WIFI_BITRATE_36MBPS)
11844 strcat(BasicRate, "36,");
11845 if (bitMap & WIFI_BITRATE_48MBPS)
11846 strcat(BasicRate, "48,");
11847 if (bitMap & WIFI_BITRATE_54MBPS)
11848 strcat(BasicRate, "54,");
11849 if (strlen(BasicRate) != 0) // remove last comma
11850 BasicRate[strlen(BasicRate) - 1] = '\0';
11851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11852 return RETURN_OK;
11853}
11854
11855INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11856{
11857 UINT BitMap = 0;
11858 char *rate;
11859
11860 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11861 rate = strtok(BasicRatesList, ",");
11862 while(rate != NULL)
11863 {
11864 if (strcmp(rate, "1") == 0)
11865 BitMap |= WIFI_BITRATE_1MBPS;
11866 else if (strcmp(rate, "2") == 0)
11867 BitMap |= WIFI_BITRATE_2MBPS;
11868 else if (strcmp(rate, "5.5") == 0)
11869 BitMap |= WIFI_BITRATE_5_5MBPS;
11870 else if (strcmp(rate, "6") == 0)
11871 BitMap |= WIFI_BITRATE_6MBPS;
11872 else if (strcmp(rate, "9") == 0)
11873 BitMap |= WIFI_BITRATE_9MBPS;
11874 else if (strcmp(rate, "11") == 0)
11875 BitMap |= WIFI_BITRATE_11MBPS;
11876 else if (strcmp(rate, "12") == 0)
11877 BitMap |= WIFI_BITRATE_12MBPS;
11878 else if (strcmp(rate, "18") == 0)
11879 BitMap |= WIFI_BITRATE_18MBPS;
11880 else if (strcmp(rate, "24") == 0)
11881 BitMap |= WIFI_BITRATE_24MBPS;
11882 else if (strcmp(rate, "36") == 0)
11883 BitMap |= WIFI_BITRATE_36MBPS;
11884 else if (strcmp(rate, "48") == 0)
11885 BitMap |= WIFI_BITRATE_48MBPS;
11886 else if (strcmp(rate, "54") == 0)
11887 BitMap |= WIFI_BITRATE_54MBPS;
11888 rate = strtok(NULL, ",");
11889 }
11890 *basicRateBitMap = BitMap;
11891 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11892 return RETURN_OK;
11893}
11894
11895// 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 +080011896INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11897{
developer1e5aa162022-09-13 16:06:24 +080011898 char buf[128] = {0};
11899 char cmd[128] = {0};
11900 char config_file[64] = {0};
11901 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011902 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011903 wifi_radio_operationParam_t current_param;
11904
11905 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11906
11907 multiple_set = TRUE;
11908 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11909 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11910 return RETURN_ERR;
11911 }
11912 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11913 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11914 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11915 return RETURN_ERR;
11916 }
11917 }
developer5884e982022-10-06 10:52:50 +080011918
11919 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11920 bandwidth = 20;
11921 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11922 bandwidth = 40;
11923 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11924 bandwidth = 80;
11925 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11926 bandwidth = 160;
11927 if (operationParam->autoChannelEnabled){
11928 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11929 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11930 return RETURN_ERR;
11931 }
11932 }else{
developer1e5aa162022-09-13 16:06:24 +080011933 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11934 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11935 return RETURN_ERR;
11936 }
11937 }
developer5884e982022-10-06 10:52:50 +080011938
developer1e5aa162022-09-13 16:06:24 +080011939 if (current_param.variant != operationParam->variant) {
11940 // Two different definition bit map, so need to check every bit.
11941 if (operationParam->variant & WIFI_80211_VARIANT_A)
11942 set_mode |= WIFI_MODE_A;
11943 if (operationParam->variant & WIFI_80211_VARIANT_B)
11944 set_mode |= WIFI_MODE_B;
11945 if (operationParam->variant & WIFI_80211_VARIANT_G)
11946 set_mode |= WIFI_MODE_G;
11947 if (operationParam->variant & WIFI_80211_VARIANT_N)
11948 set_mode |= WIFI_MODE_N;
11949 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11950 set_mode |= WIFI_MODE_AC;
11951 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11952 set_mode |= WIFI_MODE_AX;
11953 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11954 memset(buf, 0, sizeof(buf));
11955 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11956 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11957 return RETURN_ERR;
11958 }
11959 }
11960 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11961 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11962 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11963 return RETURN_ERR;
11964 }
11965 }
11966 if (current_param.beaconInterval != operationParam->beaconInterval) {
11967 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11968 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11969 return RETURN_ERR;
11970 }
11971 }
11972 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11973 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11974 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11975 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11976 return RETURN_ERR;
11977 }
11978 }
11979 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11980 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11981 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11982 return RETURN_ERR;
11983 }
11984 }
11985 if (current_param.guardInterval != operationParam->guardInterval) {
11986 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11987 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11988 return RETURN_ERR;
11989 }
11990 }
11991 if (current_param.transmitPower != operationParam->transmitPower) {
11992 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11993 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11994 return RETURN_ERR;
11995 }
11996 }
11997 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11998 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11999 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12000 return RETURN_ERR;
12001 }
12002 }
12003 if (current_param.obssCoex != operationParam->obssCoex) {
12004 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12005 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12006 return RETURN_ERR;
12007 }
12008 }
12009 if (current_param.stbcEnable != operationParam->stbcEnable) {
12010 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12011 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12012 return RETURN_ERR;
12013 }
12014 }
12015 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12016 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12017 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12018 return RETURN_ERR;
12019 }
12020 }
12021
12022 // if enable is true, then restart the radio
12023 wifi_setRadioEnable(index, FALSE);
12024 if (operationParam->enable == TRUE)
12025 wifi_setRadioEnable(index, TRUE);
12026 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12027
developer06a01d92022-09-07 16:32:39 +080012028 return RETURN_OK;
12029}
12030
12031INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12032{
developer1e5aa162022-09-13 16:06:24 +080012033 char band[64] = {0};
12034 char buf[256] = {0};
12035 char config_file[64] = {0};
12036 char cmd[128] = {0};
12037 int ret = RETURN_ERR;
12038 int mode = 0;
12039 ULONG channel = 0;
12040 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012041
12042 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12043 printf("Entering %s index = %d\n", __func__, (int)index);
12044
developer1e5aa162022-09-13 16:06:24 +080012045 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12046 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12047 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012048 {
developer1e5aa162022-09-13 16:06:24 +080012049 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012050 return RETURN_ERR;
12051 }
12052 operationParam->enable = enabled;
12053
12054 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012055 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012056 {
developer1e5aa162022-09-13 16:06:24 +080012057 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012058 return RETURN_ERR;
12059 }
12060
12061 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012062 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012063 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012064 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012065 else if (!strcmp(band, "6GHz"))
12066 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012067 else
12068 {
developer1e5aa162022-09-13 16:06:24 +080012069 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012070 band);
12071 }
12072
developer1e5aa162022-09-13 16:06:24 +080012073 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12074 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12075 operationParam->channel = 0;
12076 operationParam->autoChannelEnabled = TRUE;
12077 } else {
12078 operationParam->channel = strtol(buf, NULL, 10);
12079 operationParam->autoChannelEnabled = FALSE;
12080 }
12081
developer06a01d92022-09-07 16:32:39 +080012082 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012083 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12084 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12085 return RETURN_ERR;
12086 }
developer06a01d92022-09-07 16:32:39 +080012087 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12088 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12089 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012090 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer06a01d92022-09-07 16:32:39 +080012091 else
12092 {
developer1e5aa162022-09-13 16:06:24 +080012093 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12094 return false;
developer06a01d92022-09-07 16:32:39 +080012095 }
12096
developer1e5aa162022-09-13 16:06:24 +080012097 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12098 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12099 return RETURN_ERR;
12100 }
12101 // Two different definition bit map, so need to check every bit.
12102 if (mode & WIFI_MODE_A)
12103 operationParam->variant |= WIFI_80211_VARIANT_A;
12104 if (mode & WIFI_MODE_B)
12105 operationParam->variant |= WIFI_80211_VARIANT_B;
12106 if (mode & WIFI_MODE_G)
12107 operationParam->variant |= WIFI_80211_VARIANT_G;
12108 if (mode & WIFI_MODE_N)
12109 operationParam->variant |= WIFI_80211_VARIANT_N;
12110 if (mode & WIFI_MODE_AC)
12111 operationParam->variant |= WIFI_80211_VARIANT_AC;
12112 if (mode & WIFI_MODE_AX)
12113 operationParam->variant |= WIFI_80211_VARIANT_AX;
12114 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12115 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12116 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012117 }
developer1e5aa162022-09-13 16:06:24 +080012118 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12119 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12120 return RETURN_ERR;
12121 }
12122 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12123 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12124 return RETURN_ERR;
12125 }
developer06a01d92022-09-07 16:32:39 +080012126
developer1e5aa162022-09-13 16:06:24 +080012127 memset(buf, 0, sizeof(buf));
12128 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12129 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12130 return RETURN_ERR;
12131 }
12132 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12133
12134 memset(buf, 0, sizeof(buf));
12135 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12136 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12137 return RETURN_ERR;
12138 }
12139 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12140
12141 memset(buf, 0, sizeof(buf));
12142 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12143 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12144
12145 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12146 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12147 return RETURN_ERR;
12148 }
12149 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12150 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12151 return RETURN_ERR;
12152 }
12153
12154 memset(buf, 0, sizeof(buf));
12155 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12156 if (strcmp(buf, "-1") == 0) {
12157 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12158 operationParam->ctsProtection = FALSE;
12159 } else {
12160 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12161 operationParam->ctsProtection = TRUE;
12162 }
12163
12164 memset(buf, 0, sizeof(buf));
12165 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12166 if (strcmp(buf, "0") == 0)
12167 operationParam->obssCoex = FALSE;
12168 else
12169 operationParam->obssCoex = TRUE;
12170
12171 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12172 _syscmd(cmd, buf, sizeof(buf));
12173 if (strlen(buf) != 0)
12174 operationParam->stbcEnable = TRUE;
12175 else
12176 operationParam->stbcEnable = FALSE;
12177
12178 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12179 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12180 return RETURN_ERR;
12181 }
12182
12183 // Below value is hardcoded
12184
12185 operationParam->numSecondaryChannels = 0;
12186 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12187 operationParam->channelSecondary[i] = 0;
12188 }
12189 operationParam->csa_beacon_count = 15;
12190 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012191
12192 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12193 return RETURN_OK;
12194}
12195
12196static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12197{
developerc086fb72022-10-04 10:18:22 +080012198 int max_radio_num = 0;
12199
12200 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012201 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012202 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12203 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012204 }
12205
developerc086fb72022-10-04 10:18:22 +080012206 return (arrayIndex * max_radio_num) + radioIndex;
12207}
developer06a01d92022-09-07 16:32:39 +080012208
developerc086fb72022-10-04 10:18:22 +080012209wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12210 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12211 return WIFI_BITRATE_1MBPS;
12212 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12213 return WIFI_BITRATE_2MBPS;
12214 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12215 return WIFI_BITRATE_5_5MBPS;
12216 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12217 return WIFI_BITRATE_6MBPS;
12218 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12219 return WIFI_BITRATE_9MBPS;
12220 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12221 return WIFI_BITRATE_11MBPS;
12222 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12223 return WIFI_BITRATE_12MBPS;
12224 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12225 return WIFI_BITRATE_18MBPS;
12226 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12227 return WIFI_BITRATE_24MBPS;
12228 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12229 return WIFI_BITRATE_36MBPS;
12230 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12231 return WIFI_BITRATE_48MBPS;
12232 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12233 return WIFI_BITRATE_54MBPS;
12234 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012235}
12236
developer1d57d002022-10-12 18:03:15 +080012237INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12238{
12239 if (beacon == WIFI_BITRATE_1MBPS)
12240 strcpy(beacon_str, "1Mbps");
12241 else if (beacon == WIFI_BITRATE_2MBPS)
12242 strcpy(beacon_str, "2Mbps");
12243 else if (beacon == WIFI_BITRATE_5_5MBPS)
12244 strcpy(beacon_str, "5.5Mbps");
12245 else if (beacon == WIFI_BITRATE_6MBPS)
12246 strcpy(beacon_str, "6Mbps");
12247 else if (beacon == WIFI_BITRATE_9MBPS)
12248 strcpy(beacon_str, "9Mbps");
12249 else if (beacon == WIFI_BITRATE_11MBPS)
12250 strcpy(beacon_str, "11Mbps");
12251 else if (beacon == WIFI_BITRATE_12MBPS)
12252 strcpy(beacon_str, "12Mbps");
12253 else if (beacon == WIFI_BITRATE_18MBPS)
12254 strcpy(beacon_str, "18Mbps");
12255 else if (beacon == WIFI_BITRATE_24MBPS)
12256 strcpy(beacon_str, "24Mbps");
12257 else if (beacon == WIFI_BITRATE_36MBPS)
12258 strcpy(beacon_str, "36Mbps");
12259 else if (beacon == WIFI_BITRATE_48MBPS)
12260 strcpy(beacon_str, "48Mbps");
12261 else if (beacon == WIFI_BITRATE_54MBPS)
12262 strcpy(beacon_str, "54Mbps");
12263 return RETURN_OK;
12264}
12265
developer06a01d92022-09-07 16:32:39 +080012266INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12267{
developerc086fb72022-10-04 10:18:22 +080012268 INT mode = 0;
12269 INT ret = -1;
12270 INT output = 0;
12271 int i = 0;
12272 int vap_index = 0;
12273 BOOL enabled = FALSE;
12274 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012275 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012276
developer06a01d92022-09-07 16:32:39 +080012277
12278 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12279 printf("Entering %s index = %d\n", __func__, (int)index);
12280
developera77d84b2023-02-22 16:10:50 +080012281 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012282 {
developerc086fb72022-10-04 10:18:22 +080012283 map->vap_array[i].radio_index = index;
12284
developer06a01d92022-09-07 16:32:39 +080012285 vap_index = array_index_to_vap_index(index, i);
12286 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012287 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012288
developerc086fb72022-10-04 10:18:22 +080012289 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012290
12291 map->vap_array[i].vap_index = vap_index;
12292
12293 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012294 ret = wifi_getApName(vap_index, buf);
12295 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012296 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12297
developerc086fb72022-10-04 10:18:22 +080012298 return RETURN_ERR;
12299 }
12300 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12301
12302 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012303 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012304 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012305 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012306 return RETURN_ERR;
12307 }
12308 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 +080012309
12310 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012311 if (ret != RETURN_OK) {
12312 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012313 return RETURN_ERR;
12314 }
12315 map->vap_array[i].u.bss_info.enabled = enabled;
12316
developerc086fb72022-10-04 10:18:22 +080012317 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12318 if (ret != RETURN_OK) {
12319 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12320 return RETURN_ERR;
12321 }
developer06a01d92022-09-07 16:32:39 +080012322 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012323
12324 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12325 if (ret != RETURN_OK) {
12326 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12327 return RETURN_ERR;
12328 }
12329 map->vap_array[i].u.bss_info.isolation = enabled;
12330
12331 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12332 if (ret != RETURN_OK) {
12333 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12334 return RETURN_ERR;
12335 }
12336 map->vap_array[i].u.bss_info.bssMaxSta = output;
12337
12338 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12339 if (ret != RETURN_OK) {
12340 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12341 return RETURN_ERR;
12342 }
12343 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012344
developerc086fb72022-10-04 10:18:22 +080012345 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12346 if (ret != RETURN_OK) {
12347 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12348 return RETURN_ERR;
12349 }
12350 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012351
developerc086fb72022-10-04 10:18:22 +080012352 ret = wifi_getApSecurity(vap_index, &security);
12353 if (ret != RETURN_OK) {
12354 printf("%s: wifi_getApSecurity return error\n", __func__);
12355 return RETURN_ERR;
12356 }
12357 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012358
developerc086fb72022-10-04 10:18:22 +080012359 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12360 if (ret != RETURN_OK) {
12361 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12362 return RETURN_ERR;
12363 }
12364 if (mode == 0)
12365 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12366 else
12367 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12368 if (mode == 1)
12369 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12370 else if (mode == 2)
12371 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012372
developerc086fb72022-10-04 10:18:22 +080012373 ret = wifi_getApWmmEnable(vap_index, &enabled);
12374 if (ret != RETURN_OK) {
12375 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12376 return RETURN_ERR;
12377 }
12378 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012379
developerc086fb72022-10-04 10:18:22 +080012380 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12381 if (ret != RETURN_OK) {
12382 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012383 return RETURN_ERR;
12384 }
developerc086fb72022-10-04 10:18:22 +080012385 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012386
12387 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012388 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012389 if (ret != RETURN_OK) {
12390 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12391 return RETURN_ERR;
12392 }
12393 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012394
developerc086fb72022-10-04 10:18:22 +080012395 memset(buf, 0, sizeof(buf));
12396 ret = wifi_getBaseBSSID(vap_index, buf);
12397 if (ret != RETURN_OK) {
12398 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12399 return RETURN_ERR;
12400 }
12401 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12402 &map->vap_array[i].u.bss_info.bssid[0],
12403 &map->vap_array[i].u.bss_info.bssid[1],
12404 &map->vap_array[i].u.bss_info.bssid[2],
12405 &map->vap_array[i].u.bss_info.bssid[3],
12406 &map->vap_array[i].u.bss_info.bssid[4],
12407 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012408 // 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]);
12409
12410 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12411 if (ret != RETURN_OK) {
12412 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12413 return RETURN_ERR;
12414 }
12415 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developera77d84b2023-02-22 16:10:50 +080012416 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012417 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012418 }
12419 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12420 return RETURN_OK;
12421}
12422
developer431128d2022-12-16 15:30:41 +080012423void checkVapStatus(int apIndex, bool *enable)
12424{
12425 char if_name[16] = {0};
12426 char cmd[128] = {0};
12427 char buf[128] = {0};
12428
12429 *enable = FALSE;
developerac6f1142022-12-20 19:26:35 +080012430 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
developer431128d2022-12-16 15:30:41 +080012431 return;
12432
12433 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12434 _syscmd(cmd, buf, sizeof(buf));
12435 if (strlen(buf) > 0)
12436 *enable = TRUE;
12437 return;
12438}
12439
developerd946fd62022-12-08 18:03:28 +080012440static int prepareInterface(UINT apIndex, char *new_interface)
12441{
12442 char cur_interface[16] = {0};
12443 char config_file[128] = {0};
12444 char cmd[128] = {0};
12445 char buf[16] = {0};
12446 int max_radio_num = 0;
12447 int radioIndex = -1;
12448 int phyIndex = -1;
12449
12450 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12451 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12452
12453 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12454 wifi_getMaxRadioNumber(&max_radio_num);
12455 radioIndex = apIndex % max_radio_num;
12456 phyIndex = radio_index_to_phy(radioIndex);
12457 // disable and del old interface, then add new interface
12458 wifi_setApEnable(apIndex, FALSE);
developer431128d2022-12-16 15:30:41 +080012459 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
developerd946fd62022-12-08 18:03:28 +080012460 _syscmd(cmd, buf, sizeof(buf));
12461 }
developer431128d2022-12-16 15:30:41 +080012462 // update the vap status file
12463 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12464 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012465 return RETURN_OK;
12466}
12467
developer06a01d92022-09-07 16:32:39 +080012468INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12469{
developerd946fd62022-12-08 18:03:28 +080012470 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012471 unsigned int i;
12472 wifi_vap_info_t *vap_info = NULL;
12473 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012474 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012475 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012476 char buf[256] = {0};
12477 char cmd[128] = {0};
12478 char config_file[64] = {0};
12479 char bssid[32] = {0};
12480 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012481 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012482
12483 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12484 printf("Entering %s index = %d\n", __func__, (int)index);
12485 for (i = 0; i < map->num_vaps; i++)
12486 {
developer1d57d002022-10-12 18:03:15 +080012487 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012488 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012489
12490 // Check vap status file to enable multiple ap if the system boot.
12491 checkVapStatus(vap_info->vap_index, &enable);
12492 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012493 continue;
developer06a01d92022-09-07 16:32:39 +080012494
developer1d57d002022-10-12 18:03:15 +080012495 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12496
developer431128d2022-12-16 15:30:41 +080012497 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12498 enable = FALSE;
12499
12500 // multi-ap first up need to copy current radio config
12501 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012502 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12503 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012504 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12505 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12506 } else {
12507 // Check whether the interface name is valid or this ap change it.
12508 int apIndex = -1;
12509 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12510 if (apIndex != -1 && apIndex != vap_info->vap_index)
12511 continue;
12512 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012513 }
developer06a01d92022-09-07 16:32:39 +080012514
developer1d57d002022-10-12 18:03:15 +080012515 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012516 params[0].name = "interface";
12517 params[0].value = vap_info->vap_name;
12518 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12519 params[1].name = "bssid";
12520 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012521 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012522 params[2].name = "wpa_psk_file";
12523 params[2].value = psk_file;
12524
12525 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12526 wifi_hostapdWrite(config_file, params, 3);
12527
12528 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12529 _syscmd(cmd, buf, sizeof(buf));
12530
12531 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12532 if (ret != RETURN_OK) {
12533 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12534 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012535 }
developer1d57d002022-10-12 18:03:15 +080012536
12537 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12538 if (ret != RETURN_OK) {
12539 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12540 return RETURN_ERR;
12541 }
12542
12543 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12544 if (ret != RETURN_OK) {
12545 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12546 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012547 }
12548
developer1d57d002022-10-12 18:03:15 +080012549 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12550 if (ret != RETURN_OK) {
12551 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12552 return RETURN_ERR;
12553 }
developer06a01d92022-09-07 16:32:39 +080012554
developer1d57d002022-10-12 18:03:15 +080012555 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12556 if (ret != RETURN_OK) {
12557 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12558 return RETURN_ERR;
12559 }
developer06a01d92022-09-07 16:32:39 +080012560
developer1d57d002022-10-12 18:03:15 +080012561 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12562 if (ret != RETURN_OK) {
12563 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12564 return RETURN_ERR;
12565 }
12566
developer804c64f2022-10-19 13:54:40 +080012567 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012568 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012569 }else {
12570 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012571 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012572 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12573 _syscmd(cmd, buf, sizeof(buf));
12574 }else{
developer1d57d002022-10-12 18:03:15 +080012575 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012576 }
developer1d57d002022-10-12 18:03:15 +080012577 }
12578
12579 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12580 if (ret != RETURN_OK) {
12581 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12582 return RETURN_ERR;
12583 }
12584
12585 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12586 if (ret != RETURN_OK) {
12587 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12588 return RETURN_ERR;
12589 }
12590
12591 memset(buf, 0, sizeof(buf));
12592 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12593 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12594 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12595 if (ret != RETURN_OK) {
12596 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12597 return RETURN_ERR;
12598 }
12599
12600 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12601 if (ret != RETURN_OK) {
12602 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12603 return RETURN_ERR;
12604 }
12605
developer1d57d002022-10-12 18:03:15 +080012606 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12607 if (ret != RETURN_OK) {
12608 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12609 return RETURN_ERR;
12610 }
12611
developer23e71282023-01-18 10:25:19 +080012612 wifi_setApEnable(vap_info->vap_index, FALSE);
12613 wifi_setApEnable(vap_info->vap_index, TRUE);
12614 multiple_set = FALSE;
12615
12616 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer1d57d002022-10-12 18:03:15 +080012617 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12618 if (ret != RETURN_OK) {
12619 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12620 return RETURN_ERR;
12621 }
developer06a01d92022-09-07 16:32:39 +080012622
developer1d57d002022-10-12 18:03:15 +080012623 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012624 }
12625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12626 return RETURN_OK;
12627}
12628
12629int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12630{
12631 char *token, *next;
12632 const char s[2] = ",";
12633 int count =0;
12634
12635 /* get the first token */
12636 token = strtok_r(pchannels, s, &next);
12637
12638 /* walk through other tokens */
12639 while( token != NULL && count < MAX_CHANNELS) {
12640 chlistptr->channels_list[count++] = atoi(token);
12641 token = strtok_r(NULL, s, &next);
12642 }
12643
12644 return count;
12645}
12646
12647static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12648{
12649 INT status;
12650 wifi_channels_list_t *chlistp;
12651 CHAR output_string[64];
12652 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080012653 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080012654 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080012655
12656 if(rcap == NULL)
12657 {
12658 return RETURN_ERR;
12659 }
12660
12661 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012662 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012663
developer1e5aa162022-09-13 16:06:24 +080012664 if (band == band_2_4)
12665 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12666 else if (band == band_5)
12667 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12668 else if (band == band_6)
12669 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012670
12671 chlistp = &(rcap->channel_list[0]);
12672 memset(pchannels, 0, sizeof(pchannels));
12673
12674 /* possible number of radio channels */
12675 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12676 {
12677 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12678 }
12679 /* Number of channels and list*/
12680 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12681
12682 /* autoChannelSupported */
12683 /* always ON with wifi_getRadioAutoChannelSupported */
12684 rcap->autoChannelSupported = TRUE;
12685
12686 /* DCSSupported */
12687 /* always ON with wifi_getRadioDCSSupported */
12688 rcap->DCSSupported = TRUE;
12689
12690 /* zeroDFSSupported - TBD */
12691 rcap->zeroDFSSupported = FALSE;
12692
12693 /* Supported Country List*/
12694 memset(output_string, 0, sizeof(output_string));
12695 status = wifi_getRadioCountryCode(radioIndex, output_string);
12696 if( status != 0 ) {
12697 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12698 return RETURN_ERR;
12699 } else {
12700 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12701 }
12702 if(!strcmp(output_string,"US")){
12703 rcap->countrySupported[0] = wifi_countrycode_US;
12704 rcap->countrySupported[1] = wifi_countrycode_CA;
12705 } else if (!strcmp(output_string,"CA")) {
12706 rcap->countrySupported[0] = wifi_countrycode_CA;
12707 rcap->countrySupported[1] = wifi_countrycode_US;
12708 } else {
12709 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12710 }
12711
12712 rcap->numcountrySupported = 2;
12713
12714 /* csi */
12715 rcap->csi.maxDevices = 8;
12716 rcap->csi.soudingFrameSupported = TRUE;
12717
developer7930d352022-12-21 17:55:42 +080012718 wifi_GetInterfaceName(radioIndex, interface_name);
12719 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080012720
12721 /* channelWidth - all supported bandwidths */
12722 int i=0;
12723 rcap->channelWidth[i] = 0;
12724 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12725 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12726 WIFI_CHANNELBANDWIDTH_40MHZ);
12727
12728 }
developer1e5aa162022-09-13 16:06:24 +080012729 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012730 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12731 WIFI_CHANNELBANDWIDTH_40MHZ |
12732 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12733 }
12734
12735
12736 /* mode - all supported variants */
12737 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12738 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012739 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 +080012740 }
12741 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012742 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12743 }
12744 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12745 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012746 }
12747 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12748 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12749
12750 /* supportedBitRate - all supported bitrates */
12751 rcap->supportedBitRate[i] = 0;
12752 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12753 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12754 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12755 }
developer1e5aa162022-09-13 16:06:24 +080012756 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012757 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12758 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12759 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12760 }
12761
12762
12763 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12764 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12765 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12766 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12767 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12768 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12769 rcap->cipherSupported = 0;
12770 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12771 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12772
12773 return RETURN_OK;
12774}
12775
12776INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12777{
developer30423732022-12-01 16:17:49 +080012778 INT status = 0, radioIndex = 0;
12779 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080012780 int iter = 0;
developer30423732022-12-01 16:17:49 +080012781 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080012782 int max_num_radios;
developer30423732022-12-01 16:17:49 +080012783 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080012784
12785 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12786
12787 memset(cap, 0, sizeof(wifi_hal_capability_t));
12788
12789 /* version */
12790 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12791 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12792
12793 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080012794 wifi_getMaxRadioNumber(&max_num_radios);
12795 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080012796
12797 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12798 {
12799 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12800 if (status != 0) {
12801 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12802 return RETURN_ERR;
12803 }
12804
12805 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12806 {
developer804c64f2022-10-19 13:54:40 +080012807 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012808 {
12809 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12810 return RETURN_ERR;
12811 }
12812 iface_info = &cap->wifi_prop.interface_map[iter];
12813 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12814 iface_info->rdk_radio_index = radioIndex;
12815 memset(output, 0, sizeof(output));
12816 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12817 {
12818 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12819 }
12820 // TODO: bridge name
12821 // TODO: vlan id
12822 // TODO: primary
12823 iface_info->index = array_index_to_vap_index(radioIndex, j);
12824 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080012825 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012826 {
12827 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12828 }
12829 iter++;
12830 }
12831 }
12832
12833 cap->BandSteeringSupported = FALSE;
12834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12835 return RETURN_OK;
12836}
12837
developer9df4e652022-10-11 11:27:38 +080012838INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12839{
12840 struct params h_config={0};
12841 char config_file[64] = {0};
12842
12843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12844
12845 h_config.name = "okc";
12846 h_config.value = okc_enable?"1":"0";
12847
12848 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12849 wifi_hostapdWrite(config_file, &h_config, 1);
12850 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12851
12852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12853 return RETURN_OK;
12854}
12855
12856INT wifi_setSAEMFP(int ap_index, BOOL enable)
12857{
12858 struct params h_config={0};
12859 char config_file[64] = {0};
12860 char buf[128] = {0};
12861
12862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12863
12864 h_config.name = "sae_require_mfp";
12865 h_config.value = enable?"1":"0";
12866
12867 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12868 wifi_hostapdWrite(config_file, &h_config, 1);
12869 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12870
12871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12872 return RETURN_OK;
12873}
12874
12875INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12876{
12877 struct params h_config={0};
12878 char config_file[64] = {0};
12879 char buf[128] = {0};
12880
12881 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12882
12883 h_config.name = "sae_pwe";
12884 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12885 h_config.value = buf;
12886
12887 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12888 wifi_hostapdWrite(config_file, &h_config, 1);
12889 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12890
12891 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12892 return RETURN_OK;
12893}
12894
12895INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12896{
12897 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12898 struct params h_config={0};
12899 char config_file[64] = {0};
12900
12901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12902
12903 h_config.name = "wpa_disable_eapol_key_retries";
12904 h_config.value = disable_EAPOL_retries?"1":"0";
12905
12906 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12907 wifi_hostapdWrite(config_file, &h_config, 1);
12908 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12909
12910 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12911 return RETURN_OK;
12912}
12913
developer06a01d92022-09-07 16:32:39 +080012914INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12915{
developer587c1b62022-09-27 15:58:59 +080012916 char buf[128] = {0};
12917 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080012918 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080012919 char password[64] = {0};
12920 char mfp[32] = {0};
12921 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012922 BOOL okc_enable = FALSE;
12923 BOOL sae_MFP = FALSE;
12924 BOOL disable_EAPOL_retries = TRUE;
12925 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012926 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012927 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012928
12929 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12930
12931 multiple_set = TRUE;
12932 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12933 if (security->mode == wifi_security_mode_none) {
12934 strcpy(wpa_mode, "None");
12935 } else if (security->mode == wifi_security_mode_wpa_personal)
12936 strcpy(wpa_mode, "WPA-Personal");
12937 else if (security->mode == wifi_security_mode_wpa2_personal)
12938 strcpy(wpa_mode, "WPA2-Personal");
12939 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12940 strcpy(wpa_mode, "WPA-WPA2-Personal");
12941 else if (security->mode == wifi_security_mode_wpa_enterprise)
12942 strcpy(wpa_mode, "WPA-Enterprise");
12943 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12944 strcpy(wpa_mode, "WPA2-Enterprise");
12945 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12946 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012947 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012948 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012949 okc_enable = TRUE;
12950 sae_MFP = TRUE;
12951 sae_pwe = 2;
12952 disable_EAPOL_retries = FALSE;
12953 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012954 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012955 okc_enable = TRUE;
12956 sae_MFP = TRUE;
12957 sae_pwe = 2;
12958 disable_EAPOL_retries = FALSE;
12959 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012960 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012961 sae_MFP = TRUE;
12962 sae_pwe = 2;
12963 disable_EAPOL_retries = FALSE;
developer5c9fee82023-01-13 14:44:16 +080012964 } else if (security->mode == wifi_security_mode_owe) {
12965 strcpy(wpa_mode, "OWE");
12966 sae_MFP = TRUE;
12967 sae_pwe = 2;
12968 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080012969 }
12970
12971 band = wifi_index_to_band(ap_index);
12972 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12973 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12974 return RETURN_ERR;
12975 }
developer587c1b62022-09-27 15:58:59 +080012976
12977 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012978 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012979 wifi_setSAEMFP(ap_index, sae_MFP);
12980 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012981 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012982
developer23e71282023-01-18 10:25:19 +080012983 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_owe) {
developer4b102122023-02-15 10:53:03 +080012984 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_pass || security->u.key.type == wifi_security_key_type_psk_sae) {
12985 int key_len = strlen(security->u.key.key);
12986 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
12987 if (key_len == 64) { // set wpa_psk
12988 strncpy(password, security->u.key.key, 64); // 64 characters
12989 password[64] = '\0';
12990 wifi_setApSecurityPreSharedKey(ap_index, password);
12991 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
12992 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
12993 strncpy(password, security->u.key.key, 63);
12994 password[63] = '\0';
12995 wifi_setApSecurityKeyPassphrase(ap_index, password);
12996 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
12997 } else
12998 return RETURN_ERR;
12999 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013000 }
13001 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13002 params.name = "sae_password";
13003 params.value = security->u.key.key;
13004 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013005 } else { // remove sae_password
13006 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13007 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013008 }
13009 }
developer587c1b62022-09-27 15:58:59 +080013010
13011 if (security->mode != wifi_security_mode_none) {
13012 memset(&params, 0, sizeof(params));
13013 params.name = "wpa_pairwise";
13014 if (security->encr == wifi_encryption_tkip)
13015 params.value = "TKIP";
13016 else if (security->encr == wifi_encryption_aes)
13017 params.value = "CCMP";
13018 else if (security->encr == wifi_encryption_aes_tkip)
13019 params.value = "TKIP CCMP";
13020 wifi_hostapdWrite(config_file, &params, 1);
13021 }
13022
13023 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013024 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013025 else if (security->mfp == wifi_mfp_cfg_optional)
13026 strcpy(mfp, "Optional");
13027 else if (security->mfp == wifi_mfp_cfg_required)
13028 strcpy(mfp, "Required");
13029 wifi_setApSecurityMFPConfig(ap_index, mfp);
13030
13031 memset(&params, 0, sizeof(params));
13032 params.name = "transition_disable";
13033 if (security->wpa3_transition_disable == TRUE)
13034 params.value = "0x01";
13035 else
13036 params.value = "0x00";
13037 wifi_hostapdWrite(config_file, &params, 1);
13038
13039 memset(&params, 0, sizeof(params));
13040 params.name = "wpa_group_rekey";
13041 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13042 params.value = buf;
13043 wifi_hostapdWrite(config_file, &params, 1);
13044
13045 memset(&params, 0, sizeof(params));
13046 params.name = "wpa_strict_rekey";
13047 params.value = security->strict_rekey?"1":"0";
13048 wifi_hostapdWrite(config_file, &params, 1);
13049
13050 memset(&params, 0, sizeof(params));
13051 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013052 if (security->eapol_key_retries == 0)
13053 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013054 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13055 params.value = buf;
13056 wifi_hostapdWrite(config_file, &params, 1);
13057
13058 memset(&params, 0, sizeof(params));
13059 params.name = "disable_pmksa_caching";
13060 params.value = security->disable_pmksa_caching?"1":"0";
13061 wifi_hostapdWrite(config_file, &params, 1);
13062
developer23e71282023-01-18 10:25:19 +080013063 if (multiple_set == FALSE) {
13064 wifi_setApEnable(ap_index, FALSE);
13065 wifi_setApEnable(ap_index, TRUE);
13066 }
developer587c1b62022-09-27 15:58:59 +080013067
13068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13069
developer06a01d92022-09-07 16:32:39 +080013070 return RETURN_OK;
13071}
13072
13073INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13074{
developer9df4e652022-10-11 11:27:38 +080013075 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013076 char config_file[128] = {0};
13077 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013078 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013079
13080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13081 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13082 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13083 security->mode = wifi_security_mode_none;
13084 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013085 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013086 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013087 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013088 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013089 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013090 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013091 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013092 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013093 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013094 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013095 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013096 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013097 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013098 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013099 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013100 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013101 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013102 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013103 else if (!strcmp(buf, "OWE"))
13104 security->mode = wifi_security_mode_owe;
developer587c1b62022-09-27 15:58:59 +080013105 }
13106
13107 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13108 if (security->mode == wifi_security_mode_none)
13109 security->encr = wifi_encryption_none;
13110 else {
13111 if (strcmp(buf, "TKIP") == 0)
13112 security->encr = wifi_encryption_tkip;
13113 else if (strcmp(buf, "CCMP") == 0)
13114 security->encr = wifi_encryption_aes;
13115 else
13116 security->encr = wifi_encryption_aes_tkip;
13117 }
13118
developer9df4e652022-10-11 11:27:38 +080013119 if (security->mode != wifi_encryption_none) {
13120 memset(buf, 0, sizeof(buf));
13121 // wpa3 can use one or both configs as password, so we check sae_password first.
13122 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013123 if (strlen(buf) != 0) {
13124 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13125 security->u.key.type = wifi_security_key_type_sae;
13126 set_sae = TRUE;
13127 strncpy(security->u.key.key, buf, sizeof(buf));
13128 }
13129 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13130 if (strlen(buf) != 0){
13131 if (set_sae == TRUE)
13132 security->u.key.type = wifi_security_key_type_psk_sae;
13133 else if (strlen(buf) == 64)
13134 security->u.key.type = wifi_security_key_type_psk;
13135 else
13136 security->u.key.type = wifi_security_key_type_pass;
13137 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013138 }
developer9df4e652022-10-11 11:27:38 +080013139 security->u.key.key[255] = '\0';
13140 }
13141
developer587c1b62022-09-27 15:58:59 +080013142 memset(buf, 0, sizeof(buf));
13143 wifi_getApSecurityMFPConfig(ap_index, buf);
13144 if (strcmp(buf, "Disabled") == 0)
13145 security->mfp = wifi_mfp_cfg_disabled;
13146 else if (strcmp(buf, "Optional") == 0)
13147 security->mfp = wifi_mfp_cfg_optional;
13148 else if (strcmp(buf, "Required") == 0)
13149 security->mfp = wifi_mfp_cfg_required;
13150
13151 memset(buf, 0, sizeof(buf));
13152 security->wpa3_transition_disable = FALSE;
13153 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13154 disable = strtol(buf, NULL, 16);
13155 if (disable != 0)
13156 security->wpa3_transition_disable = TRUE;
13157
13158 memset(buf, 0, sizeof(buf));
13159 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13160 if (strlen(buf) == 0)
13161 security->rekey_interval = 86400;
13162 else
13163 security->rekey_interval = strtol(buf, NULL, 10);
13164
13165 memset(buf, 0, sizeof(buf));
13166 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13167 if (strlen(buf) == 0)
13168 security->strict_rekey = 1;
13169 else
13170 security->strict_rekey = strtol(buf, NULL, 10);
13171
13172 memset(buf, 0, sizeof(buf));
13173 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13174 if (strlen(buf) == 0)
13175 security->eapol_key_retries = 4;
13176 else
13177 security->eapol_key_retries = strtol(buf, NULL, 10);
13178
13179 memset(buf, 0, sizeof(buf));
13180 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13181 if (strlen(buf) == 0)
13182 security->disable_pmksa_caching = FALSE;
13183 else
13184 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13185
13186 /* TODO
13187 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13188 */
13189 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13190 security->eap_identity_req_timeout = 0;
13191 security->eap_identity_req_retries = 0;
13192 security->eap_req_timeout = 0;
13193 security->eap_req_retries = 0;
13194 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013195 return RETURN_OK;
13196}
13197
13198#endif /* WIFI_HAL_VERSION_3 */
13199
13200#ifdef WIFI_HAL_VERSION_3_PHASE2
13201INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13202{
developerd946fd62022-12-08 18:03:28 +080013203 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013204 char cmd[128] = {0};
13205 char buf[128] = {0};
13206 char *mac_addr = NULL;
13207 BOOL status = FALSE;
13208 size_t len = 0;
13209
13210 if(ap_index > MAX_APS)
13211 return RETURN_ERR;
13212
13213 *output_numDevices = 0;
13214 wifi_getApEnable(ap_index, &status);
13215 if (status == FALSE)
13216 return RETURN_OK;
13217
developerac6f1142022-12-20 19:26:35 +080013218 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013219 return RETURN_ERR;
13220 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013221 _syscmd(cmd, buf, sizeof(buf));
13222
13223 mac_addr = strtok(buf, "\n");
13224 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13225 *output_numDevices = i + 1;
13226 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13227 addr_ptr = output_deviceMacAddressArray[i];
13228 mac_addr_aton(addr_ptr, mac_addr);
13229 mac_addr = strtok(NULL, "\n");
13230 }
13231
13232 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013233}
13234#else
13235INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13236{
developerd946fd62022-12-08 18:03:28 +080013237 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013238 char cmd[128];
13239 BOOL status = false;
13240
13241 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13242 return RETURN_ERR;
13243
13244 output_buf[0] = '\0';
13245
13246 wifi_getApEnable(ap_index,&status);
13247 if (!status)
13248 return RETURN_OK;
13249
developerac6f1142022-12-20 19:26:35 +080013250 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013251 return RETURN_ERR;
13252 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013253 _syscmd(cmd, output_buf, output_buf_size);
13254
13255 return RETURN_OK;
13256}
13257#endif
developer2f513ab2022-09-13 14:26:06 +080013258
13259INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13260{
13261 char output[16]={'\0'};
13262 char config_file[MAX_BUF_SIZE] = {0};
13263
13264 if (!enable)
13265 return RETURN_ERR;
13266
13267 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13268 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13269
13270 if (strlen(output) == 0)
13271 *enable = FALSE;
13272 else if (strncmp(output, "1", 1) == 0)
13273 *enable = TRUE;
13274 else
13275 *enable = FALSE;
13276
13277 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13278 return RETURN_OK;
13279}
developer2d9c30f2022-09-13 15:06:14 +080013280
13281INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13282{
developer804c64f2022-10-19 13:54:40 +080013283 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013284 return RETURN_ERR;
13285 *output_enable=TRUE;
13286 return RETURN_OK;
13287}
developerfd7d2892022-09-13 16:44:53 +080013288
13289INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13290{
13291 char cmd[128] = {0};
13292 char buf[128] = {0};
13293 char line[128] = {0};
13294 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013295 FILE *f = NULL;
13296 int index = 0;
13297 int exp = 0;
13298 int mantissa = 0;
13299 int duration = 0;
13300 int radio_index = 0;
13301 int max_radio_num = 0;
13302 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013303 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13305
13306 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013307
developerfd7d2892022-09-13 16:44:53 +080013308 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013309
13310 phyId = radio_index_to_phy(radio_index);
13311 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013312 _syscmd(cmd, buf, sizeof(buf));
13313 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13314 if (*numSessionReturned > maxNumberSessions)
13315 *numSessionReturned = maxNumberSessions;
13316 else if (*numSessionReturned < 1) {
13317 *numSessionReturned = 0;
13318 return RETURN_OK;
13319 }
13320
developer033b37b2022-10-18 11:27:46 +080013321 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 +080013322 if ((f = popen(cmd, "r")) == NULL) {
13323 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13324 return RETURN_ERR;
13325 }
13326
13327 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013328 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013329 char *tmp = NULL;
13330 strcpy(buf, line);
13331 tmp = strtok(buf, " ");
13332 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13333 tmp = strtok(NULL, " ");
13334 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13335 tmp = strtok(NULL, " ");
13336 if (strstr(tmp, "t")) {
13337 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13338 }
13339 if (strstr(tmp, "a")) {
13340 twtSessions[index].twtParameters.operation.announced = TRUE;
13341 }
13342 tmp = strtok(NULL, " ");
13343 exp = strtol(tmp, NULL, 10);
13344 tmp = strtok(NULL, " ");
13345 mantissa = strtol(tmp, NULL, 10);
13346 tmp = strtok(NULL, " ");
13347 duration = strtol(tmp, NULL, 10);
13348
13349 // only implicit supported
13350 twtSessions[index].twtParameters.operation.implicit = TRUE;
13351 // only individual agreement supported
13352 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13353
13354 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13355 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013356 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013357 // Overflow handling
13358 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13359 } else {
13360 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13361 }
13362 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13363 index++;
13364 }
13365
13366 pclose(f);
13367 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13368 return RETURN_OK;
13369}