blob: 41125941d18f63c7f572e81659a4d06e4cacf87f [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>
developerefb790a2023-12-26 18:58:32 +080064#include <pthread.h>
65
developer06a01d92022-09-07 16:32:39 +080066#define MAC_ALEN 6
67
developer7930d352022-12-21 17:55:42 +080068#define MAX_BUF_SIZE 256
69#define MAX_CMD_SIZE 256
70#define IF_NAME_SIZE 16
developer06a01d92022-09-07 16:32:39 +080071#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080072#define ACL_PREFIX "/nvram/hostapd-acl"
73#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080074//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
75#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080076#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080077#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080078#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080079#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080080#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080081#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080082#define PSK_FILE "/nvram/hostapd"
developerf49437e2022-09-29 19:58:21 +080083#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080084#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080085
developer81bf2ed2022-09-13 15:31:14 +080086#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080087
88/*
89 MAX_APS - Number of all AP available in system
90 2x Home AP
91 2x Backhaul AP
92 2x Guest AP
93 2x Secure Onboard AP
94 2x Service AP
95
96*/
developer06a01d92022-09-07 16:32:39 +080097
developer033b37b2022-10-18 11:27:46 +080098
developera77d84b2023-02-22 16:10:50 +080099#define MAX_APS ((MAX_NUM_RADIOS)*(MAX_NUM_VAP_PER_RADIO))
developer06a01d92022-09-07 16:32:39 +0800100#ifndef AP_PREFIX
101#define AP_PREFIX "wifi"
102#endif
103
104#ifndef RADIO_PREFIX
105#define RADIO_PREFIX "wlan"
106#endif
107
developer89df4502023-02-16 20:45:02 +0800108#define MAX_ASSOCIATED_STA_NUM 2007 // hostapd default
developer06a01d92022-09-07 16:32:39 +0800109
110//Uncomment to enable debug logs
111//#define WIFI_DEBUG
112
113#ifdef WIFI_DEBUG
114#define wifi_dbg_printf printf
115#define WIFI_ENTRY_EXIT_DEBUG printf
116#else
117#define wifi_dbg_printf(format, args...) printf("")
118#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
119#endif
120
121#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
122#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
123#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
124#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
125#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
126#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
127#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
128#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
129#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
130#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
131
developer4fb0b922022-09-30 14:29:09 +0800132#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800133
134#define BW_FNAME "/nvram/bw_file.txt"
135
136#define PS_MAX_TID 16
137
138static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
139 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
140 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
141 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
142 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
143 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
144 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
145 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
146 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
148 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
149 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
150 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
151 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
152 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
153 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
154 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
155};
156
157typedef unsigned long long u64;
158
159/* Enum to define WiFi Bands */
160typedef enum
161{
162 band_invalid = -1,
163 band_2_4 = 0,
164 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800165 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800166} wifi_band;
167
developerdb744382022-09-13 15:34:54 +0800168typedef enum {
169 WIFI_MODE_A = 0x01,
170 WIFI_MODE_B = 0x02,
171 WIFI_MODE_G = 0x04,
172 WIFI_MODE_N = 0x08,
173 WIFI_MODE_AC = 0x10,
174 WIFI_MODE_AX = 0x20,
developer7c4cd202023-03-01 10:56:29 +0800175 WIFI_MODE_BE = 0x40,
developerdb744382022-09-13 15:34:54 +0800176} wifi_ieee80211_Mode;
177
developer06a01d92022-09-07 16:32:39 +0800178#ifdef WIFI_HAL_VERSION_3
179
180// Return number of elements in array
181#ifndef ARRAY_SIZE
182#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
183#endif /* ARRAY_SIZE */
184
185#ifndef ARRAY_AND_SIZE
186#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
187#endif /* ARRAY_AND_SIZE */
188
189#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
190
191typedef struct {
192 int32_t value;
193 int32_t param;
194 intptr_t key;
195 intptr_t data;
196} wifi_secur_list;
197
developerfa41b1f2023-01-06 10:25:51 +0800198static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
199static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800200static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800201wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
202wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
203char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800204static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800205
206static wifi_secur_list map_security[] =
207{
208 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
209 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800218 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800219 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800220};
221
developerefb790a2023-12-26 18:58:32 +0800222typedef struct {
223 char ssid[MAX_BUF_SIZE];
224 char wpa[MAX_BUF_SIZE];
225 char wpa_key_mgmt[MAX_BUF_SIZE];
226 char wpa_passphrase[MAX_BUF_SIZE];
227 char ap_isolate[MAX_BUF_SIZE];
228 char macaddr_acl[MAX_BUF_SIZE];
229 char bss_transition[MAX_BUF_SIZE];
230 char ignore_broadcast_ssid[MAX_BUF_SIZE];
231 char max_sta[MAX_BUF_SIZE];
232} __attribute__((packed)) wifi_vap_cfg_t;
233
234pthread_t pthread_id;
235int result = 0, tflag = 0;
236wifi_vap_cfg_t vap_info[MAX_NUM_RADIOS*MAX_NUM_VAP_PER_RADIO];
237int syn_flag = 0;
238
developer06a01d92022-09-07 16:32:39 +0800239wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
240{
241 wifi_secur_list *item;
242 int i;
243
244 for (item = list,i = 0;i < list_sz; item++, i++) {
245 if ((int)(item->key) == key) {
246 return item;
247 }
248 }
249
250 return NULL;
251}
252
253char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
254{
255 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
256
257 if (!item) {
258 return "";
259 }
260
261 return (char *)(item->data);
262}
263
264wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
265{
266 wifi_secur_list *item;
267 int i;
268
269 for (item = list,i = 0;i < list_sz; item++, i++) {
270 if (strcmp((char *)(item->data), str) == 0) {
271 return item;
272 }
273 }
274
275 return NULL;
276}
277#endif /* WIFI_HAL_VERSION_3 */
278
279#ifdef HAL_NETLINK_IMPL
280typedef struct {
281 int id;
282 struct nl_sock* socket;
283 struct nl_cb* cb;
284} Netlink;
285
286static int mac_addr_aton(unsigned char *mac_addr, char *arg)
287{
288 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800289 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 +0800290 mac_addr[0] = mac_addr_int[0];
291 mac_addr[1] = mac_addr_int[1];
292 mac_addr[2] = mac_addr_int[2];
293 mac_addr[3] = mac_addr_int[3];
294 mac_addr[4] = mac_addr_int[4];
295 mac_addr[5] = mac_addr_int[5];
296 return 0;
297}
298
299static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
300{
301 unsigned int mac_addr_int[6]={};
302 mac_addr_int[0] = arg[0];
303 mac_addr_int[1] = arg[1];
304 mac_addr_int[2] = arg[2];
305 mac_addr_int[3] = arg[3];
306 mac_addr_int[4] = arg[4];
307 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800308 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 +0800309 return;
310}
311
312static int ieee80211_frequency_to_channel(int freq)
313{
developerf5745ee2022-10-05 16:09:53 +0800314 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800315 if (freq == 2484)
316 return 14;
developerf5745ee2022-10-05 16:09:53 +0800317 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
318 else if (freq == 5935)
319 return 2;
developer06a01d92022-09-07 16:32:39 +0800320 else if (freq < 2484)
321 return (freq - 2407) / 5;
322 else if (freq >= 4910 && freq <= 4980)
323 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800324 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800325 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800326 else if (freq <= 45000) /* DMG band lower limit */
327 /* see 802.11ax D6.1 27.3.23.2 */
328 return (freq - 5950) / 5;
329 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800330 return (freq - 56160) / 2160;
331 else
332 return 0;
333}
334
335static int initSock80211(Netlink* nl) {
336 nl->socket = nl_socket_alloc();
337 if (!nl->socket) {
338 fprintf(stderr, "Failing to allocate the sock\n");
339 return -ENOMEM;
340 }
341
342 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
343
344 if (genl_connect(nl->socket)) {
345 fprintf(stderr, "Failed to connect\n");
346 nl_close(nl->socket);
347 nl_socket_free(nl->socket);
348 return -ENOLINK;
349 }
350
351 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
352 if (nl->id< 0) {
353 fprintf(stderr, "interface not found.\n");
354 nl_close(nl->socket);
355 nl_socket_free(nl->socket);
356 return -ENOENT;
357 }
358
359 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
360 if ((!nl->cb)) {
361 fprintf(stderr, "Failed to allocate netlink callback.\n");
362 nl_close(nl->socket);
363 nl_socket_free(nl->socket);
364 return ENOMEM;
365 }
366
367 return nl->id;
368}
369
370static int nlfree(Netlink *nl)
371{
372 nl_cb_put(nl->cb);
373 nl_close(nl->socket);
374 nl_socket_free(nl->socket);
375 return 0;
376}
377
378static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
379 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
380 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
381 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
382};
383
384static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
385};
386
387static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
388};
389
390typedef struct _wifi_channelStats_loc {
391 INT array_size;
392 INT ch_number;
393 BOOL ch_in_pool;
394 INT ch_noise;
395 BOOL ch_radar_noise;
396 INT ch_max_80211_rssi;
397 INT ch_non_80211_noise;
398 INT ch_utilization;
399 ULLONG ch_utilization_total;
400 ULLONG ch_utilization_busy;
401 ULLONG ch_utilization_busy_tx;
402 ULLONG ch_utilization_busy_rx;
403 ULLONG ch_utilization_busy_self;
404 ULLONG ch_utilization_busy_ext;
405} wifi_channelStats_t_loc;
406
407typedef struct wifi_device_info {
408 INT wifi_devIndex;
409 UCHAR wifi_devMacAddress[6];
410 CHAR wifi_devIPAddress[64];
411 BOOL wifi_devAssociatedDeviceAuthentiationState;
412 INT wifi_devSignalStrength;
413 INT wifi_devTxRate;
414 INT wifi_devRxRate;
415} wifi_device_info_t;
416
417#endif
418
419//For 5g Alias Interfaces
420static BOOL priv_flag = TRUE;
421static BOOL pub_flag = TRUE;
422static BOOL Radio_flag = TRUE;
423//wifi_setApBeaconRate(1, beaconRate);
424
developer1e5aa162022-09-13 16:06:24 +0800425BOOL multiple_set = FALSE;
426
developer06a01d92022-09-07 16:32:39 +0800427struct params
428{
429 char * name;
430 char * value;
431};
432
433static int _syscmd(char *cmd, char *retBuf, int retBufSize)
434{
435 FILE *f;
436 char *ptr = retBuf;
437 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
438
439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
440 if((f = popen(cmd, "r")) == NULL) {
441 fprintf(stderr,"\npopen %s error\n", cmd);
442 return RETURN_ERR;
443 }
444
445 while(!feof(f))
446 {
447 *ptr = 0;
448 if(bufSize>=128) {
449 bufbytes=128;
450 } else {
451 bufbytes=bufSize-1;
452 }
453
454 fgets(ptr,bufbytes,f);
455 readbytes=strlen(ptr);
456
457 if(!readbytes)
458 break;
459
460 bufSize-=readbytes;
461 ptr += readbytes;
462 }
463 cmd_ret = pclose(f);
464 retBuf[retBufSize-1]=0;
465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
466
467 return cmd_ret >> 8;
468}
469
developer033b37b2022-10-18 11:27:46 +0800470INT radio_index_to_phy(int radioIndex)
471{
472 char cmd[128] = {0};
473 char buf[64] = {0};
474 int phyIndex = 0;
475 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
476 _syscmd(cmd, buf, sizeof(buf));
477
478 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800479 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800480 return RETURN_ERR;
481 }
482 sscanf(buf, "phy%d", &phyIndex);
483
484 return phyIndex;
485}
developer026ac9e2022-11-07 13:46:24 +0800486
developer431128d2022-12-16 15:30:41 +0800487INT wifi_getMaxRadioNumber(INT *max_radio_num)
488{
489 char cmd[64] = {0};
490 char buf[4] = {0};
491
492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
493
494 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
495 _syscmd(cmd, buf, sizeof(buf));
496 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
497
498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
499
500 return RETURN_OK;
501}
502
developer59ff6de2023-02-08 17:58:14 +0800503static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
504{
505 char cmd[MAX_CMD_SIZE]={'\0'};
506 char buf[MAX_BUF_SIZE]={'\0'};
507 int ret = 0;
508
509 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
510 ret = _syscmd(cmd, buf, sizeof(buf));
511 if ((ret != 0) && (strlen(buf) == 0))
512 return -1;
513 snprintf(output, output_size, "%s", buf);
514
515 return 0;
516}
517
518static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
519{
520 char cmd[MAX_CMD_SIZE]={'\0'};
521 char buf[MAX_BUF_SIZE]={'\0'};
522
523 for(int i=0;i<item_count;i++)
524 {
525 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
526 if (strlen(buf) == 0) //Insert
527 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
528 else //Update
529 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
530
531 if(_syscmd(cmd, buf, sizeof(buf)))
532 return -1;
533 }
534
535 return 0;
536}
537
developer431128d2022-12-16 15:30:41 +0800538wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800539{
540 char cmd[128] = {0};
541 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800542 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800543 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800544 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800545 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800546 int radioIndex = 0;
547 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800548 wifi_band band = band_invalid;
549
550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800551
developer431128d2022-12-16 15:30:41 +0800552 wifi_getMaxRadioNumber(&max_radio_num);
553 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800554 phyIndex = radio_index_to_phy(radioIndex);
developer59ff6de2023-02-08 17:58:14 +0800555 snprintf(cmd, sizeof(cmd), "cat /sys/class/ieee80211/phy%d/device/device 2> /dev/null", phyIndex);
556 _syscmd(cmd, buf, sizeof(buf));
557 if (strncmp(buf, "0x7915", 6) == 0) { // harrier have two bands, consider as a special case.
558 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
559 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
560 if (strncmp(buf, "a", 1) == 0)
561 return band_5;
562 else
563 return band_2_4;
564 }
developer5884e982022-10-06 10:52:50 +0800565 while(i < 10){
developer59ff6de2023-02-08 17:58:14 +0800566 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800567 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800568 nl80211_band = strtol(buf, NULL, 10);
569 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800570 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800571 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800572 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800573 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800574 band = band_6;
575
576 if(band != band_invalid)
577 break;
578
579 i++;
580 sleep(1);
581 }
developerc707e972022-09-13 15:38:02 +0800582
583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
584 return band;
585}
586
developerd946fd62022-12-08 18:03:28 +0800587//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800588static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800589{
590 char config_file[128] = {0};
591
592 if (interface_name == NULL)
593 return RETURN_ERR;
594
595 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerefb790a2023-12-26 18:58:32 +0800596#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +0800597 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
598 wifi_hostapdRead(config_file, "interface", interface_name, 16);
599 if (strlen(interface_name) == 0)
600 return RETURN_ERR;
developerefb790a2023-12-26 18:58:32 +0800601#else
602 sprintf(interface_name, "%s%d",AP_PREFIX, apIndex);
603#endif
developerd946fd62022-12-08 18:03:28 +0800604 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
605 return RETURN_OK;
606}
607
developerac6f1142022-12-20 19:26:35 +0800608// wifi agent will call this function, do not change the parameter
609void GetInterfaceName(char *interface_name, char *conf_file)
610{
611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
612 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
613 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
614}
615
developer06a01d92022-09-07 16:32:39 +0800616static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
617{
developerd946fd62022-12-08 18:03:28 +0800618 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800619 if (multiple_set == TRUE)
620 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800621 char cmd[MAX_CMD_SIZE]="", output[32]="";
622 FILE *fp;
623 int i;
624 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800625 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800626 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800627 for(i=0; i<item_count; i++, list++)
628 {
developerd946fd62022-12-08 18:03:28 +0800629 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800630 if((fp = popen(cmd, "r"))==NULL)
631 {
632 perror("popen failed");
633 return -1;
634 }
635 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
636 {
637 pclose(fp);
638 perror("fgets failed");
639 return -1;
640 }
641 pclose(fp);
642 }
643 return 0;
644}
645
646static int wifi_reloadAp(int apIndex)
647{
developerd946fd62022-12-08 18:03:28 +0800648 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800649 if (multiple_set == TRUE)
650 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800651 char cmd[MAX_CMD_SIZE]="";
652 char buf[MAX_BUF_SIZE]="";
653
developerac6f1142022-12-20 19:26:35 +0800654 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800655 return RETURN_ERR;
656 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800657 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
658 return RETURN_ERR;
659
developerd946fd62022-12-08 18:03:28 +0800660 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800661 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
662 return RETURN_ERR;
663
developerd946fd62022-12-08 18:03:28 +0800664 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800665 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
666 return RETURN_ERR;
667
668 return RETURN_OK;
669}
670
developer06a01d92022-09-07 16:32:39 +0800671INT File_Reading(CHAR *file, char *Value)
672{
673 FILE *fp = NULL;
674 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
675 int count = 0;
676
677 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
678 fp = popen(file,"r");
679 if(fp == NULL)
680 return RETURN_ERR;
681
682 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
683 {
684 for(count=0;buf[count]!='\n';count++)
685 copy_buf[count]=buf[count];
686 copy_buf[count]='\0';
687 }
688 strcpy(Value,copy_buf);
689 pclose(fp);
690 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
691
692 return RETURN_OK;
693}
694
695void wifi_RestartHostapd_2G()
696{
697 int Public2GApIndex = 4;
698
699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
700 wifi_setApEnable(Public2GApIndex, FALSE);
701 wifi_setApEnable(Public2GApIndex, TRUE);
702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
703}
704
705void wifi_RestartHostapd_5G()
706{
707 int Public5GApIndex = 5;
708
709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
710 wifi_setApEnable(Public5GApIndex, FALSE);
711 wifi_setApEnable(Public5GApIndex, TRUE);
712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
713}
714
715void wifi_RestartPrivateWifi_2G()
716{
717 int PrivateApIndex = 0;
718
719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
720 wifi_setApEnable(PrivateApIndex, FALSE);
721 wifi_setApEnable(PrivateApIndex, TRUE);
722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
723}
724
725void wifi_RestartPrivateWifi_5G()
726{
727 int Private5GApIndex = 1;
728
729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
730 wifi_setApEnable(Private5GApIndex, FALSE);
731 wifi_setApEnable(Private5GApIndex, TRUE);
732 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
733}
734
735static int writeBandWidth(int radioIndex,char *bw_value)
736{
737 char buf[MAX_BUF_SIZE];
738 char cmd[MAX_CMD_SIZE];
739
740 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
741 if(_syscmd(cmd, buf, sizeof(buf)))
742 {
743 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
744 _syscmd(cmd, buf, sizeof(buf));
745 return RETURN_OK;
746 }
747
748 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
749 _syscmd(cmd,buf,sizeof(buf));
750 return RETURN_OK;
751}
752
753static int readBandWidth(int radioIndex,char *bw_value)
754{
developer30423732022-12-01 16:17:49 +0800755 char buf[MAX_BUF_SIZE] = {0};
756 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800757 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
758 _syscmd(cmd,buf,sizeof(buf));
759 if(NULL!=strstr(buf,"20MHz"))
developer06a01d92022-09-07 16:32:39 +0800760 strcpy(bw_value,"20MHz");
developer06a01d92022-09-07 16:32:39 +0800761 else if(NULL!=strstr(buf,"40MHz"))
developer06a01d92022-09-07 16:32:39 +0800762 strcpy(bw_value,"40MHz");
developer06a01d92022-09-07 16:32:39 +0800763 else if(NULL!=strstr(buf,"80MHz"))
developer06a01d92022-09-07 16:32:39 +0800764 strcpy(bw_value,"80MHz");
developer57fa24a2023-03-15 17:25:07 +0800765 else if(NULL!=strstr(buf,"160MHz"))
766 strcpy(bw_value,"160MHz");
767 else if(NULL!=strstr(buf,"320MHz"))
768 strcpy(bw_value,"320MHz");
developer06a01d92022-09-07 16:32:39 +0800769 else
developer06a01d92022-09-07 16:32:39 +0800770 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800771 return RETURN_OK;
772}
773
developer264159b2022-11-02 09:41:35 +0800774// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800775INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
776{
developer5f222492022-09-13 15:21:52 +0800777 struct params params={'\0'};
778 char config_file[MAX_BUF_SIZE] = {0};
779 char buf[MAX_BUF_SIZE] = {'\0'};
780
781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800782 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800783 if (strlen (beaconRate) >= 5) {
784 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
785 buf[strlen(beaconRate) - 4] = '\0';
786 } else if (strlen(beaconRate) > 0)
787 strcpy(buf, beaconRate);
788 else
789 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800790
791 params.name = "beacon_rate";
792 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
793 if (strncmp(buf, "5.5", 3) == 0) {
794 snprintf(buf, sizeof(buf), "55");
795 params.value = buf;
796 } else {
797 strcat(buf, "0");
798 params.value = buf;
799 }
800
801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
802 wifi_hostapdWrite(config_file, &params, 1);
803 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
804 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
805
806 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800807}
808
809INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
810{
developer1d57d002022-10-12 18:03:15 +0800811 char config_file[128] = {'\0'};
812 char temp_output[128] = {'\0'};
813 char buf[128] = {'\0'};
814 char cmd[128] = {'\0'};
815 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800816 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800817
818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
819 if (NULL == beaconRate)
820 return RETURN_ERR;
821
822 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
823 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800824 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800825 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
826 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800827 if (strncmp(buf, "55", 2) == 0)
828 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
829 else {
830 rate = strtol(buf, NULL, 10)/10;
831 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
832 }
developer5f222492022-09-13 15:21:52 +0800833 } else {
developer1d57d002022-10-12 18:03:15 +0800834 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800835 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 +0800836 _syscmd(cmd, buf, sizeof(buf));
837 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800838 }
839 strncpy(beaconRate, temp_output, sizeof(temp_output));
840 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
841
842 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800843}
844
845INT wifi_setLED(INT radioIndex, BOOL enable)
846{
847 return 0;
848}
849INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
850{
851 return RETURN_OK;
852}
853/**********************************************************************************
854 *
855 * Wifi Subsystem level function prototypes
856 *
857**********************************************************************************/
858//---------------------------------------------------------------------------------------------------
859//Wifi system api
860//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
861INT wifi_getHalVersion(CHAR *output_string) //RDKB
862{
863 if(!output_string)
864 return RETURN_ERR;
865 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
866
867 return RETURN_OK;
868}
869
870
871/* wifi_factoryReset() function */
872/**
873* @description Clears internal variables to implement a factory reset of the Wi-Fi
874* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
875*
876* @param None
877*
878* @return The status of the operation.
879* @retval RETURN_OK if successful.
880* @retval RETURN_ERR if any error is detected
881*
882* @execution Synchronous
883* @sideeffect None
884*
885* @note This function must not suspend and must not invoke any blocking system
886* calls. It should probably just send a message to a driver event handler task.
887*
888*/
889INT wifi_factoryReset()
890{
891 char cmd[128];
892
893 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800894 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
895 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800896 system(cmd);
897 system("systemctl restart hostapd.service");
898
899 return RETURN_OK;
900}
901
902/* wifi_factoryResetRadios() function */
903/**
904* @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.
905*
906* @param None
907* @return The status of the operation
908* @retval RETURN_OK if successful
909* @retval RETURN_ERR if any error is detected
910*
911* @execution Synchronous
912*
913* @sideeffect None
914*
915* @note This function must not suspend and must not invoke any blocking system
916* calls. It should probably just send a message to a driver event handler task.
917*
918*/
919INT wifi_factoryResetRadios()
920{
developer72ec5572023-01-05 16:27:13 +0800921 int max_radio_num = 0;
922 wifi_getMaxRadioNumber(&max_radio_num);
923 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
924 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800925
developer72ec5572023-01-05 16:27:13 +0800926 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800927}
928
929
930/* wifi_factoryResetRadio() function */
931/**
932* @description Restore selected radio parameters without touching access point parameters
933*
934* @param radioIndex - Index of Wi-Fi Radio channel
935*
936* @return The status of the operation.
937* @retval RETURN_OK if successful.
938* @retval RETURN_ERR if any error is detected
939*
940* @execution Synchronous.
941* @sideeffect None.
942*
943* @note This function must not suspend and must not invoke any blocking system
944* calls. It should probably just send a message to a driver event handler task.
945*
946*/
947INT wifi_factoryResetRadio(int radioIndex) //RDKB
948{
developer72ec5572023-01-05 16:27:13 +0800949 char cmd[128] = {0};
950 char buf[128] = {0};
951 int max_radio_num = 0;
952
953 wifi_getMaxRadioNumber(&max_radio_num);
954 if (radioIndex < 0 || radioIndex > max_radio_num)
955 return RETURN_ERR;
956
957 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
958 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800959
developer06a01d92022-09-07 16:32:39 +0800960 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800961 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
962 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800963
developer72ec5572023-01-05 16:27:13 +0800964 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
965 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800966 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
967 return RETURN_OK;
968}
969
970/* wifi_initRadio() function */
971/**
972* Description: This function call initializes the specified radio.
973* Implementation specifics may dictate the functionality since
974* different hardware implementations may have different initilization requirements.
975* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
976*
977* @return The status of the operation.
978* @retval RETURN_OK if successful.
979* @retval RETURN_ERR if any error is detected
980*
981* @execution Synchronous.
982* @sideeffect None.
983*
984* @note This function must not suspend and must not invoke any blocking system
985* calls. It should probably just send a message to a driver event handler task.
986*
987*/
988INT wifi_initRadio(INT radioIndex)
989{
990 //TODO: Initializes the wifi subsystem (for specified radio)
991 return RETURN_OK;
992}
993void macfilter_init()
994{
995 char count[4]={'\0'};
996 char buf[253]={'\0'};
997 char tmp[19]={'\0'};
998 int dev_count,block,mac_entry=0;
999 char res[4]={'\0'};
1000 char acl_file_path[64] = {'\0'};
1001 FILE *fp = NULL;
1002 int index=0;
1003 char iface[10]={'\0'};
1004 char config_file[MAX_BUF_SIZE] = {0};
1005
1006
1007 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1008
1009 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +08001010 if (fp == NULL) {
1011 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
1012 return RETURN_ERR;
1013 }
developer06a01d92022-09-07 16:32:39 +08001014 sprintf(buf,"#!/bin/sh \n");
1015 fprintf(fp,"%s\n",buf);
1016
1017 system("chmod 0777 /tmp/mac_filter.sh");
1018
1019 for(index=0;index<=1;index++)
1020 {
1021 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1022 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1023 sprintf(buf,"syscfg get %dcountfilter",index);
1024 _syscmd(buf,count,sizeof(count));
1025 mac_entry=atoi(count);
1026
1027 sprintf(buf,"syscfg get %dblockall",index);
1028 _syscmd(buf,res,sizeof(res));
1029 block = atoi(res);
1030
1031 //Allow only those macs mentioned in ACL
1032 if(block==1)
1033 {
1034 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1035 fprintf(fp,"%s\n",buf);
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 Allowed *%s* ###########\n",tmp);
1041 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1042 fprintf(fp,"%s\n",buf);
1043 }
1044 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1045 fprintf(fp,"%s\n",buf);
1046 }
1047
1048 //Block all the macs mentioned in ACL
1049 else if(block==2)
1050 {
1051 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1052 fprintf(fp,"%s\n",buf);
1053
1054 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1055 {
1056 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1057 _syscmd(buf,tmp,sizeof(tmp));
1058 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1059 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1060 fprintf(fp,"%s\n",buf);
1061 }
1062 }
1063 }
1064 fclose(fp);
1065}
1066
1067// Initializes the wifi subsystem (all radios)
1068INT wifi_init() //RDKB
1069{
1070 char interface[MAX_BUF_SIZE]={'\0'};
1071 char bridge_name[MAX_BUF_SIZE]={'\0'};
1072 INT len=0;
1073
1074 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1075 //Not intitializing macfilter for Turris-Omnia Platform for now
1076 //macfilter_init();
1077
1078 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001079 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001080 sleep(2);//sleep to wait for hostapd to start
1081
1082 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1083
1084 return RETURN_OK;
1085}
1086
1087/* wifi_reset() function */
1088/**
1089* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1090* Implementation specifics may dictate what is actualy reset since
1091* different hardware implementations may have different requirements.
1092* Parameters : None
1093*
1094* @return The status of the operation.
1095* @retval RETURN_OK if successful.
1096* @retval RETURN_ERR if any error is detected
1097*
1098* @execution Synchronous.
1099* @sideeffect None.
1100*
1101* @note This function must not suspend and must not invoke any blocking system
1102* calls. It should probably just send a message to a driver event handler task.
1103*
1104*/
1105INT wifi_reset()
1106{
1107 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001108 system("systemctl stop hostapd.service");
1109 sleep(2);
1110 system("systemctl start hostapd.service");
1111 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001112 return RETURN_OK;
1113}
1114
1115/* wifi_down() function */
1116/**
1117* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1118* Implementation specifics may dictate some functionality since
1119* different hardware implementations may have different requirements.
1120*
1121* @param None
1122*
1123* @return The status of the operation
1124* @retval RETURN_OK if successful
1125* @retval RETURN_ERR if any error is detected
1126*
1127* @execution Synchronous
1128* @sideeffect None
1129*
1130* @note This function must not suspend and must not invoke any blocking system
1131* calls. It should probably just send a message to a driver event handler task.
1132*
1133*/
1134INT wifi_down()
1135{
1136 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001137 int max_num_radios = 0;
1138 wifi_getMaxRadioNumber(&max_num_radios);
1139 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1140 wifi_setRadioEnable(radioIndex, FALSE);
1141
developer06a01d92022-09-07 16:32:39 +08001142 return RETURN_OK;
1143}
1144
1145
1146/* wifi_createInitialConfigFiles() function */
1147/**
1148* @description This function creates wifi configuration files. The format
1149* and content of these files are implementation dependent. This function call is
1150* used to trigger this task if necessary. Some implementations may not need this
1151* function. If an implementation does not need to create config files the function call can
1152* do nothing and return RETURN_OK.
1153*
1154* @param None
1155*
1156* @return The status of the operation
1157* @retval RETURN_OK if successful
1158* @retval RETURN_ERR if any error is detected
1159*
1160* @execution Synchronous
1161* @sideeffect None
1162*
1163* @note This function must not suspend and must not invoke any blocking system
1164* calls. It should probably just send a message to a driver event handler task.
1165*
1166*/
1167INT wifi_createInitialConfigFiles()
1168{
1169 //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)
1170 return RETURN_OK;
1171}
1172
1173// outputs the country code to a max 64 character string
1174INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1175{
developerd946fd62022-12-08 18:03:28 +08001176 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001177 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001178 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001179 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001180
developerac6f1142022-12-20 19:26:35 +08001181 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001182 return RETURN_ERR;
1183 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001184 _syscmd(cmd, buf, sizeof(buf));
1185 if(strlen(buf) > 0)
1186 snprintf(output_string, 64, "%s", buf);
1187 else
1188 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001189
1190 return RETURN_OK;
1191}
1192
1193INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1194{
1195 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001196 char str[MAX_BUF_SIZE]={'\0'};
1197 char cmd[MAX_CMD_SIZE]={'\0'};
1198 struct params params;
1199 char config_file[MAX_BUF_SIZE] = {0};
1200
1201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1202 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1203 return RETURN_ERR;
1204
developerb86c6f32022-10-07 14:34:58 +08001205 if (strlen(CountryCode) == 0)
1206 strcpy(CountryCode, "US");
1207
developer7543b3b2022-09-13 13:47:17 +08001208 params.name = "country_code";
1209 params.value = CountryCode;
1210 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1211 int ret = wifi_hostapdWrite(config_file, &params, 1);
1212 if (ret) {
1213 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1214 ,__func__, ret);
1215 }
1216
1217 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1218 if (ret) {
1219 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1220 ,__func__, ret);
1221 }
developer7543b3b2022-09-13 13:47:17 +08001222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1223
developer06a01d92022-09-07 16:32:39 +08001224 return RETURN_OK;
1225}
1226
developera748dcf2022-09-13 15:56:48 +08001227INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1228{
developerd946fd62022-12-08 18:03:28 +08001229 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001230 char channel_util_file[64] = {0};
1231 char cmd[128] = {0};
1232 char buf[128] = {0};
1233 char line[128] = {0};
1234 char *param = NULL, *value = NULL;
1235 int read = 0;
1236 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1237 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1238 size_t len = 0;
1239 FILE *f = NULL;
1240
1241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1242
developerac6f1142022-12-20 19:26:35 +08001243 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001244 return RETURN_ERR;
1245 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001246 _syscmd(cmd, buf, sizeof(buf));
1247 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1248
1249 memset(cmd, 0, sizeof(cmd));
1250 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001251 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001252 if ((f = popen(cmd, "r")) == NULL) {
1253 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1254 return RETURN_ERR;
1255 }
1256
1257 read = getline(&line, &len, f);
1258 while (read != -1) {
1259 param = strtok(line, ":\t");
1260 value = strtok(NULL, " ");
1261 if(strstr(param, "frequency") != NULL) {
1262 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1263 }
1264 if(strstr(param, "noise") != NULL) {
1265 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1266 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1267 }
1268 if(strstr(param, "channel active time") != NULL) {
1269 ActiveTime = strtol(value, NULL, 10);
1270 }
1271 if(strstr(param, "channel busy time") != NULL) {
1272 BusyTime = strtol(value, NULL, 10);
1273 }
1274 if(strstr(param, "channel transmit time") != NULL) {
1275 TransmitTime = strtol(value, NULL, 10);
1276 }
1277 read = getline(&line, &len, f);
1278 }
1279 pclose(f);
1280
1281 // The file should store the last active, busy and transmit time
1282 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1283 f = fopen(channel_util_file, "r");
1284 if (f != NULL) {
1285 read = getline(&line, &len, f);
1286 preActiveTime = strtol(line, NULL, 10);
1287 read = getline(&line, &len, f);
1288 preBusyTime = strtol(line, NULL, 10);
1289 read = getline(&line, &len, f);
1290 preTransmitTime = strtol(line, NULL, 10);
1291 fclose(f);
1292 }
1293
1294 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1295 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1296
1297 f = fopen(channel_util_file, "w");
1298 if (f != NULL) {
1299 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1300 fclose(f);
1301 }
1302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1303 return RETURN_OK;
1304}
1305
developer06a01d92022-09-07 16:32:39 +08001306/**********************************************************************************
1307 *
1308 * Wifi radio level function prototypes
1309 *
1310**********************************************************************************/
1311
1312//Get the total number of radios in this wifi subsystem
1313INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1314{
1315 if (NULL == output)
1316 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001317 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001318
1319 return RETURN_OK;
1320}
1321
1322//Get the total number of SSID entries in this wifi subsystem
1323INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1324{
1325 if (NULL == output)
1326 return RETURN_ERR;
1327 *output = MAX_APS;
1328
1329 return RETURN_OK;
1330}
1331
1332//Get the Radio enable config parameter
1333INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1334{
developerd946fd62022-12-08 18:03:28 +08001335 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001336 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001337 int apIndex;
1338 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001339
1340 if (NULL == output_bool)
1341 return RETURN_ERR;
1342
1343 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001344
1345 wifi_getMaxRadioNumber(&max_radio_num);
1346
1347 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001348 return RETURN_ERR;
1349
developera77d84b2023-02-22 16:10:50 +08001350 /* loop all interface in radio, if any is enable, reture true, else return false */
1351 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1352 {
developer643b28f2023-04-04 10:26:01 +08001353 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developera77d84b2023-02-22 16:10:50 +08001354 continue;
1355 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1356 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001357
developera77d84b2023-02-22 16:10:50 +08001358 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1359 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1360 /* return true if any interface is eanble */
1361 *output_bool = TRUE;
1362 break;
1363 }
1364 }
developer06a01d92022-09-07 16:32:39 +08001365 return RETURN_OK;
1366}
1367
1368INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1369{
developerd946fd62022-12-08 18:03:28 +08001370 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001371 char cmd[MAX_CMD_SIZE] = {0};
1372 char buf[MAX_CMD_SIZE] = {0};
1373 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001374 int max_radio_num = 0;
1375 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001376
1377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001378
1379 phyId = radio_index_to_phy(radioIndex);
1380
1381 wifi_getMaxRadioNumber(&max_radio_num);
1382
developer06a01d92022-09-07 16:32:39 +08001383 if(enable==FALSE)
1384 {
developera77d84b2023-02-22 16:10:50 +08001385 /* disable from max apindex to min, to avoid fail in mbss case */
1386 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001387 {
developer1e125222022-12-29 09:35:25 +08001388 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001389 continue;
developer1e125222022-12-29 09:35:25 +08001390
developer06a01d92022-09-07 16:32:39 +08001391 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001392 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001393 _syscmd(cmd, buf, sizeof(buf));
1394 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001395 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001396
developer2f18b9f2023-03-17 19:32:57 +08001397 if (!(apIndex/max_radio_num)) {
1398 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1399 _syscmd(cmd, buf, sizeof(buf));
1400 }
developer06a01d92022-09-07 16:32:39 +08001401 }
developer06a01d92022-09-07 16:32:39 +08001402 }
1403 else
1404 {
developer033b37b2022-10-18 11:27:46 +08001405 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001406 {
developer1e125222022-12-29 09:35:25 +08001407 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001408 continue;
developer1e125222022-12-29 09:35:25 +08001409
developer643b28f2023-04-04 10:26:01 +08001410 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001411 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001412 if(*buf == '1') {
developer2f18b9f2023-03-17 19:32:57 +08001413 if (!(apIndex/max_radio_num)) {
1414 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1415 ret = _syscmd(cmd, buf, sizeof(buf));
1416 if ( ret == RETURN_ERR) {
1417 fprintf(stderr, "VAP interface creation failed\n");
1418 continue;
1419 }
developera77d84b2023-02-22 16:10:50 +08001420 }
developer06a01d92022-09-07 16:32:39 +08001421 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001422 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001423 _syscmd(cmd, buf, sizeof(buf));
1424 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001425 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001426 }
1427 }
1428 }
1429
1430 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1431 return RETURN_OK;
1432}
1433
1434//Get the Radio enable status
1435INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1436{
1437 if (NULL == output_bool)
1438 return RETURN_ERR;
1439
1440 return wifi_getRadioEnable(radioIndex, output_bool);
1441}
1442
1443//Get the Radio Interface name from platform, eg "wlan0"
1444INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1445{
developer804c64f2022-10-19 13:54:40 +08001446 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001447 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001448 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001449}
1450
1451//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1452//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.
1453INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1454{
developerbcc556a2022-09-22 20:02:45 +08001455 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1456 // For max bit rate, we should always choose the best MCS
1457 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001458 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001459 char *tmp = NULL;
1460 UINT mode_map = 0;
1461 UINT num_subcarrier = 0;
1462 UINT code_bits = 0;
1463 float code_rate = 0; // use max code rate
1464 int NSS = 0;
1465 UINT Symbol_duration = 0;
1466 UINT GI_duration = 0;
1467 wifi_band band = band_invalid;
1468 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1469 BOOL enable = FALSE;
1470 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001471
1472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1473 if (NULL == output_string)
1474 return RETURN_ERR;
1475
developerbcc556a2022-09-22 20:02:45 +08001476 wifi_getRadioEnable(radioIndex, &enable);
1477 if (enable == FALSE) {
1478 snprintf(output_string, 64, "0 Mb/s");
1479 return RETURN_OK;
1480 }
1481
1482 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1483 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1484 return RETURN_ERR;
1485 }
1486
1487 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1488 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1489 return RETURN_ERR;
1490 }
1491
1492 if (gi == wifi_guard_interval_3200)
1493 GI_duration = 32;
1494 else if (gi == wifi_guard_interval_1600)
1495 GI_duration = 16;
1496 else if (gi == wifi_guard_interval_800)
1497 GI_duration = 8;
1498 else // auto, 400
1499 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001500
developerbcc556a2022-09-22 20:02:45 +08001501 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1502 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1503 return RETURN_ERR;
1504 }
1505
1506 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1507 strcpy(channel_bandwidth_str, "160");
1508
1509 if (mode_map & WIFI_MODE_AX) {
1510 if (strstr(channel_bandwidth_str, "160") != NULL)
1511 num_subcarrier = 1960;
1512 else if (strstr(channel_bandwidth_str, "80") != NULL)
1513 num_subcarrier = 980;
1514 else if (strstr(channel_bandwidth_str, "40") != NULL)
1515 num_subcarrier = 468;
1516 else if (strstr(channel_bandwidth_str, "20") != NULL)
1517 num_subcarrier = 234;
1518 code_bits = 10;
1519 code_rate = (float)5/6;
1520 Symbol_duration = 128;
1521 } else if (mode_map & WIFI_MODE_AC) {
1522 if (strstr(channel_bandwidth_str, "160") != NULL)
1523 num_subcarrier = 468;
1524 else if (strstr(channel_bandwidth_str, "80") != NULL)
1525 num_subcarrier = 234;
1526 else if (strstr(channel_bandwidth_str, "40") != NULL)
1527 num_subcarrier = 108;
1528 else if (strstr(channel_bandwidth_str, "20") != NULL)
1529 num_subcarrier = 52;
1530 code_bits = 8;
1531 code_rate = (float)5/6;
1532 Symbol_duration = 32;
1533 } else if (mode_map & WIFI_MODE_N) {
1534 if (strstr(channel_bandwidth_str, "160") != NULL)
1535 num_subcarrier = 468;
1536 else if (strstr(channel_bandwidth_str, "80") != NULL)
1537 num_subcarrier = 234;
1538 else if (strstr(channel_bandwidth_str, "40") != NULL)
1539 num_subcarrier = 108;
1540 else if (strstr(channel_bandwidth_str, "20") != NULL)
1541 num_subcarrier = 52;
1542 code_bits = 6;
1543 code_rate = (float)3/4;
1544 Symbol_duration = 32;
1545 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1546 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1547 snprintf(output_string, 64, "65 Mb/s");
1548 return RETURN_OK;
1549 } else {
1550 snprintf(output_string, 64, "0 Mb/s");
1551 return RETURN_OK;
1552 }
developer06a01d92022-09-07 16:32:39 +08001553
developerbcc556a2022-09-22 20:02:45 +08001554 // Spatial streams
1555 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1556 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1557 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001558 }
developerbcc556a2022-09-22 20:02:45 +08001559
1560 // multiple 10 is to align duration unit (0.1 us)
1561 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1562 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1563
developer06a01d92022-09-07 16:32:39 +08001564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1565
1566 return RETURN_OK;
1567}
1568#if 0
1569INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1570{
1571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1572 char cmd[64];
1573 char buf[1024];
1574 int apIndex;
1575
1576 if (NULL == output_string)
1577 return RETURN_ERR;
1578
1579 apIndex=(radioIndex==0)?0:1;
1580
developerd946fd62022-12-08 18:03:28 +08001581 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001582 _syscmd(cmd,buf, sizeof(buf));
1583
1584 snprintf(output_string, 64, "%s", buf);
1585 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1586 return RETURN_OK;
1587}
1588#endif
1589
1590
1591//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1592//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.
1593INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1594{
developer963da0c2022-09-13 15:58:27 +08001595 wifi_band band = band_invalid;
1596
developer06a01d92022-09-07 16:32:39 +08001597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1598 if (NULL == output_string)
1599 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001600
1601 band = wifi_index_to_band(radioIndex);
1602
1603 memset(output_string, 0, 10);
1604 if (band == band_2_4)
1605 strcpy(output_string, "2.4GHz");
1606 else if (band == band_5)
1607 strcpy(output_string, "5GHz");
1608 else if (band == band_6)
1609 strcpy(output_string, "6GHz");
1610 else
1611 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1613
1614 return RETURN_OK;
1615#if 0
1616 char buf[MAX_BUF_SIZE]={'\0'};
1617 char str[MAX_BUF_SIZE]={'\0'};
1618 char cmd[MAX_CMD_SIZE]={'\0'};
1619 char *ch=NULL;
1620 char *ch2=NULL;
1621
1622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1623 if (NULL == output_string)
1624 return RETURN_ERR;
1625
1626
1627 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1628
1629 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1630 {
1631 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1632 return RETURN_ERR;
1633 }
1634 ch=strchr(buf,'\n');
1635 *ch='\0';
1636 ch=strchr(buf,'=');
1637 if(ch==NULL)
1638 return RETURN_ERR;
1639
1640
1641 ch++;
1642
1643 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1644 strcpy(buf,"0");
1645 if(strlen(ch) == 1)
1646 ch=strcat(buf,ch);
1647
1648
1649 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1650
1651 if(_syscmd(cmd,str,64) == RETURN_ERR)
1652 {
1653 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1654 return RETURN_ERR;
1655 }
1656
1657
1658 ch2=strchr(str,'\n');
1659 //replace \n with \0
1660 *ch2='\0';
1661 ch2=strchr(str,'=');
1662 if(ch2==NULL)
1663 {
1664 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1665 return RETURN_ERR;
1666 }
1667 else
1668 wifi_dbg_printf("%s",ch2+1);
1669
1670
1671 ch2++;
1672
1673
1674 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1675
1676 memset(buf,'\0',sizeof(buf));
1677 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1678 {
1679 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1680 return RETURN_ERR;
1681 }
1682 if (strstr(buf,"2.4") != NULL )
1683 strcpy(output_string,"2.4GHz");
1684 else if(strstr(buf,"5.") != NULL )
1685 strcpy(output_string,"5GHz");
1686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1687
1688 return RETURN_OK;
1689#endif
1690}
1691
1692//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1693//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.
1694INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1695{
developerb7593de2022-10-18 09:51:57 +08001696 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1698 if (NULL == output_string)
1699 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001700 band = wifi_index_to_band(radioIndex);
1701
1702 if (band == band_2_4)
1703 snprintf(output_string, 64, "2.4GHz");
1704 else if (band == band_5)
1705 snprintf(output_string, 64, "5GHz");
1706 else if (band == band_6)
1707 snprintf(output_string, 64, "6GHz");
1708
developer06a01d92022-09-07 16:32:39 +08001709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1710
1711 return RETURN_OK;
1712#if 0
1713 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1714 char buf[MAX_BUF_SIZE]={'\0'};
1715 char str[MAX_BUF_SIZE]={'\0'};
1716 char cmd[MAX_CMD_SIZE]={'\0'};
1717 char *ch=NULL;
1718 char *ch2=NULL;
1719 char ch1[5]="0";
1720
1721 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1722
1723 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1724 {
1725 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1726 return RETURN_ERR;
1727 }
1728
1729 ch=strchr(buf,'\n');
1730 *ch='\0';
1731 ch=strchr(buf,'=');
1732 if(ch==NULL)
1733 return RETURN_ERR;
1734 ch++;
1735
1736 if(strlen(ch)==1)
1737 {
1738 strcat(ch1,ch);
1739
1740 }
1741 else
1742 {
1743 strcpy(ch1,ch);
1744 }
1745
1746
1747
1748 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1749 if(_syscmd(cmd,str,64) == RETURN_ERR)
1750 {
1751 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1752 return RETURN_ERR;
1753 }
1754
1755
1756 ch2=strchr(str,'\n');
1757 //replace \n with \0
1758 *ch2='\0';
1759 ch2=strchr(str,'=');
1760 if(ch2==NULL)
1761 {
1762 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1763 return RETURN_ERR;
1764 }
1765 else
1766 wifi_dbg_printf("%s",ch2+1);
1767 ch2++;
1768
1769
1770 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1771 memset(buf,'\0',sizeof(buf));
1772 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1773 {
1774 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1775 return RETURN_ERR;
1776 }
1777
1778
1779 if(strstr(buf,"2.4")!=NULL)
1780 {
1781 strcpy(output_string,"2.4GHz");
1782 }
1783 if(strstr(buf,"5.")!=NULL)
1784 {
1785 strcpy(output_string,"5GHz");
1786 }
1787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1788 return RETURN_OK;
1789#endif
1790}
1791
1792//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1793//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.
1794INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1795{
developer963da0c2022-09-13 15:58:27 +08001796 char cmd[128]={0};
1797 char buf[128]={0};
1798 char temp_output[128] = {0};
1799 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001800 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001801
1802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001803 if (NULL == output_string)
1804 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001805
1806 band = wifi_index_to_band(radioIndex);
1807 if (band == band_2_4) {
1808 strcat(temp_output, "b,g,");
1809 } else if (band == band_5) {
1810 strcat(temp_output, "a,");
1811 }
developer033b37b2022-10-18 11:27:46 +08001812 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001813 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001814 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 +08001815 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001816 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001817 strcat(temp_output, "n,");
1818 }
developer06a01d92022-09-07 16:32:39 +08001819
developer963da0c2022-09-13 15:58:27 +08001820 // vht capabilities
1821 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001822 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 +08001823 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001824 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001825 strcat(temp_output, "ac,");
1826 }
1827 }
1828
1829 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001830 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 +08001831 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001832 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001833 strcat(temp_output, "ax,");
1834 }
1835
developer7c4cd202023-03-01 10:56:29 +08001836 // eht capabilities
1837 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'EHT MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
1838 _syscmd(cmd, buf, sizeof(buf));
1839 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1840 strcat(temp_output, "be,");
1841 }
1842
developer963da0c2022-09-13 15:58:27 +08001843 // Remove the last comma
1844 if (strlen(temp_output) != 0)
1845 temp_output[strlen(temp_output)-1] = '\0';
1846 strncpy(output_string, temp_output, strlen(temp_output));
1847 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001848 return RETURN_OK;
1849}
1850
1851//Get the radio operating mode, and pure mode flag. eg: "ac"
1852//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.
1853INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1854{
1855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1856 if (NULL == output_string)
1857 return RETURN_ERR;
1858
1859 if (radioIndex == 0) {
1860 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1861 *gOnly = FALSE;
1862 *nOnly = TRUE;
1863 *acOnly = FALSE;
1864 } else {
1865 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1866 *gOnly = FALSE;
1867 *nOnly = FALSE;
1868 *acOnly = FALSE;
1869 }
1870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1871
1872 return RETURN_OK;
1873#if 0
1874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1875 char buf[64] = {0};
1876 char config_file[MAX_BUF_SIZE] = {0};
1877
1878 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1879 return RETURN_ERR;
1880
1881 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1882 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1883
1884 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1885 if (strlen(buf) == 0)
1886 {
1887 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1888 return RETURN_ERR;
1889 }
1890 if(strcmp(buf,"g")==0)
1891 {
1892 wifi_dbg_printf("\nG\n");
1893 *gOnly=TRUE;
1894 *nOnly=FALSE;
1895 *acOnly=FALSE;
1896 }
1897 else if(strcmp(buf,"n")==0)
1898 {
1899 wifi_dbg_printf("\nN\n");
1900 *gOnly=FALSE;
1901 *nOnly=TRUE;
1902 *acOnly=FALSE;
1903 }
1904 else if(strcmp(buf,"ac")==0)
1905 {
1906 wifi_dbg_printf("\nac\n");
1907 *gOnly=FALSE;
1908 *nOnly=FALSE;
1909 *acOnly=TRUE;
1910 }
1911 /* hostapd-5G.conf has "a" as hw_mode */
1912 else if(strcmp(buf,"a")==0)
1913 {
1914 wifi_dbg_printf("\na\n");
1915 *gOnly=FALSE;
1916 *nOnly=FALSE;
1917 *acOnly=FALSE;
1918 }
1919 else
1920 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1921
1922 //for a,n mode
1923 if(radioIndex == 1)
1924 {
1925 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1926 if(strcmp(buf,"1")==0)
1927 {
1928 strncpy(output_string, "n", 1);
1929 *nOnly=FALSE;
1930 }
1931 }
1932
1933 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1935 return RETURN_OK;
1936#endif
1937}
1938
developerdb744382022-09-13 15:34:54 +08001939INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1940{
1941 char cmd[128] = {0};
1942 char buf[64] = {0};
1943 char config_file[64] = {0};
1944 wifi_band band;
1945
1946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1947 if(NULL == output_string || NULL == pureMode)
1948 return RETURN_ERR;
1949
1950 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001951 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001952 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | sed \"s/ieee80211\\.*/\1/\"", config_file);
developerdb744382022-09-13 15:34:54 +08001953 _syscmd(cmd, buf, sizeof(buf));
1954
1955 band = wifi_index_to_band(radioIndex);
1956 // puremode is a bit map
1957 *pureMode = 0;
1958 if (band == band_2_4) {
1959 strcat(output_string, "b,g");
1960 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1961 if (strstr(buf, "n") != NULL) {
1962 strcat(output_string, ",n");
1963 *pureMode |= WIFI_MODE_N;
1964 }
1965 if (strstr(buf, "ax") != NULL) {
1966 strcat(output_string, ",ax");
1967 *pureMode |= WIFI_MODE_AX;
1968 }
developer7c4cd202023-03-01 10:56:29 +08001969 if (strstr(buf, "be") != NULL) {
1970 strcat(output_string, ",be");
1971 *pureMode |= WIFI_MODE_BE;
1972 }
developerdb744382022-09-13 15:34:54 +08001973 } else if (band == band_5) {
1974 strcat(output_string, "a");
1975 *pureMode |= WIFI_MODE_A;
1976 if (strstr(buf, "n") != NULL) {
1977 strcat(output_string, ",n");
1978 *pureMode |= WIFI_MODE_N;
1979 }
1980 if (strstr(buf, "ac") != NULL) {
1981 strcat(output_string, ",ac");
1982 *pureMode |= WIFI_MODE_AC;
1983 }
1984 if (strstr(buf, "ax") != NULL) {
1985 strcat(output_string, ",ax");
1986 *pureMode |= WIFI_MODE_AX;
1987 }
developer7c4cd202023-03-01 10:56:29 +08001988 if (strstr(buf, "be") != NULL) {
1989 strcat(output_string, ",be");
1990 *pureMode |= WIFI_MODE_BE;
1991 }
developerdb744382022-09-13 15:34:54 +08001992 } else if (band == band_6) {
1993 if (strstr(buf, "ax") != NULL) {
1994 strcat(output_string, "ax");
1995 *pureMode |= WIFI_MODE_AX;
1996 }
developer7c4cd202023-03-01 10:56:29 +08001997 if (strstr(buf, "be") != NULL) {
1998 strcat(output_string, ",be");
1999 *pureMode |= WIFI_MODE_BE;
2000 }
developerdb744382022-09-13 15:34:54 +08002001 }
2002
2003 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2004 return RETURN_OK;
2005}
2006
2007// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08002008INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2009{
2010 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
2011 if (strcmp (channelMode,"11A") == 0)
2012 {
2013 writeBandWidth(radioIndex,"20MHz");
2014 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2015 printf("\nChannel Mode is 802.11a (5GHz)\n");
2016 }
2017 else if (strcmp (channelMode,"11NAHT20") == 0)
2018 {
2019 writeBandWidth(radioIndex,"20MHz");
2020 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2021 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2022 }
2023 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2024 {
2025 writeBandWidth(radioIndex,"40MHz");
2026 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2027 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2028 }
2029 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2030 {
2031 writeBandWidth(radioIndex,"40MHz");
2032 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2033 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2034 }
2035 else if (strcmp (channelMode,"11ACVHT20") == 0)
2036 {
2037 writeBandWidth(radioIndex,"20MHz");
2038 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2039 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2040 }
2041 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2042 {
2043 writeBandWidth(radioIndex,"40MHz");
2044 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2045 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2046 }
2047 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2048 {
2049 writeBandWidth(radioIndex,"40MHz");
2050 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2051 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2052 }
2053 else if (strcmp (channelMode,"11ACVHT80") == 0)
2054 {
2055 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2056 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2057 }
2058 else if (strcmp (channelMode,"11ACVHT160") == 0)
2059 {
2060 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2061 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2062 }
2063 else if (strcmp (channelMode,"11B") == 0)
2064 {
2065 writeBandWidth(radioIndex,"20MHz");
2066 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2067 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2068 }
2069 else if (strcmp (channelMode,"11G") == 0)
2070 {
2071 writeBandWidth(radioIndex,"20MHz");
2072 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2073 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2074 }
2075 else if (strcmp (channelMode,"11NGHT20") == 0)
2076 {
2077 writeBandWidth(radioIndex,"20MHz");
2078 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2079 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2080 }
2081 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2082 {
2083 writeBandWidth(radioIndex,"40MHz");
2084 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2085 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2086 }
2087 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2088 {
2089 writeBandWidth(radioIndex,"40MHz");
2090 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2091 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2092 }
2093 else
2094 {
2095 return RETURN_ERR;
2096 }
2097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2098
2099 return RETURN_OK;
2100}
2101
developerdb744382022-09-13 15:34:54 +08002102// Set the radio operating mode, and pure mode flag.
2103INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2104{
developer7c4cd202023-03-01 10:56:29 +08002105 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002106 struct params list[num_hostapd_support_mode];
2107 char config_file[64] = {0};
2108 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002109 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002110 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002111 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002112
2113 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2114 // Set radio mode
2115 list[0].name = "ieee80211n";
2116 list[1].name = "ieee80211ac";
2117 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002118 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002119 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2120
2121 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002122 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002123 list[0].value = "1";
2124 else
2125 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002126 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002127 list[1].value = "1";
2128 else
2129 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002130 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002131 list[2].value = "1";
2132 else
2133 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002134 if (pureMode & WIFI_MODE_BE)
2135 list[3].value = "1";
2136 else
2137 list[3].value = "0";
2138
2139 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2140 if (strstr(supported_mode, "be") != NULL)
2141 eht_support = TRUE;
2142
2143 if (eht_support)
2144 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2145 else
2146 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002147
2148 if (channelMode == NULL || strlen(channelMode) == 0)
2149 return RETURN_OK;
2150 // Set bandwidth
2151 if (strstr(channelMode, "40") != NULL)
2152 strcpy(bandwidth, "40MHz");
2153 else if (strstr(channelMode, "80") != NULL)
2154 strcpy(bandwidth, "80MHz");
2155 else if (strstr(channelMode, "160") != NULL)
2156 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002157 else if (strstr(channelMode, "320") != NULL)
2158 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002159 else // 11A, 11B, 11G....
2160 strcpy(bandwidth, "20MHz");
2161
2162 writeBandWidth(radioIndex, bandwidth);
2163 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2164
2165 wifi_reloadAp(radioIndex);
2166 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2167
2168 return RETURN_OK;
2169}
2170
developer1d12ebf2022-10-04 15:13:38 +08002171INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2172
2173 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002174 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002175 struct params params = {0};
2176 wifi_band band = band_invalid;
2177
2178 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2179
2180 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002181
2182 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002183 return RETURN_ERR;
2184 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2185 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002186 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2187 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002188
2189 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2190 params.name = "hw_mode";
2191 params.value = hw_mode;
2192 wifi_hostapdWrite(config_file, &params, 1);
2193 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2194
developeref938762022-10-19 17:21:01 +08002195 if (band == band_2_4) {
2196 if (strncmp(hw_mode, "b", 1) == 0) {
2197 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2198 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2199 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2200 snprintf(buf, sizeof(buf), "%s", "1,2");
2201 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2202 } else {
2203 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2204
2205 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2206 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2207 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2208 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2209 }
2210 }
2211
developer1d12ebf2022-10-04 15:13:38 +08002212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2213 return RETURN_OK;
2214}
2215
developere8988ba2022-10-18 17:42:30 +08002216INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2217{
2218 char config_file[64] = {0};
2219 struct params params = {0};
2220 wifi_band band = band_invalid;
2221
2222 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2223
2224 band = wifi_index_to_band(radioIndex);
2225
2226 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2227 params.name = "noscan";
2228 params.value = noscan;
2229 wifi_hostapdWrite(config_file, &params, 1);
2230 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2231
2232 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2233 return RETURN_OK;
2234}
2235
developer06a01d92022-09-07 16:32:39 +08002236//Get the list of supported channel. eg: "1-11"
2237//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.
2238INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2239{
developer6318ed52022-09-13 15:17:58 +08002240 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002241 if (NULL == output_string)
2242 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002243 char cmd[256] = {0};
2244 char buf[128] = {0};
2245 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002246 int phyId = 0;
2247
developer6318ed52022-09-13 15:17:58 +08002248 // Parse possible channel number and separate them with commas.
2249 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002250 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002251 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002252 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002253 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 +08002254 else
developer033b37b2022-10-18 11:27:46 +08002255 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 +08002256
2257 _syscmd(cmd,buf,sizeof(buf));
2258 strncpy(output_string, buf, sizeof(buf));
2259
2260 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2261 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002262}
2263
2264//Get the list for used channel. eg: "1,6,9,11"
2265//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.
2266INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2267{
developerd946fd62022-12-08 18:03:28 +08002268 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002269 char cmd[128] = {0};
2270 char buf[128] = {0};
2271 char config_file[64] = {0};
2272 int channel = 0;
2273 int freq = 0;
2274 int bandwidth = 0;
2275 int center_freq = 0;
2276 int center_channel = 0;
2277 int channel_delta = 0;
2278 wifi_band band = band_invalid;
2279
2280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2281
developer06a01d92022-09-07 16:32:39 +08002282 if (NULL == output_string)
2283 return RETURN_ERR;
2284
developerac6f1142022-12-20 19:26:35 +08002285 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002286 return RETURN_ERR;
2287 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002288 _syscmd(cmd, buf, sizeof(buf));
2289 if (strlen(buf) == 0) {
2290 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2291 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002292 }
developerf5745ee2022-10-05 16:09:53 +08002293 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2294
2295 if (bandwidth == 20) {
2296 snprintf(output_string, 256, "%d", channel);
2297 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002298 }
developerf5745ee2022-10-05 16:09:53 +08002299
2300 center_channel = ieee80211_frequency_to_channel(center_freq);
2301
2302 band = wifi_index_to_band(radioIndex);
2303 if (band == band_2_4 && bandwidth == 40) {
2304 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2305 memset(buf, 0, sizeof(buf));
2306 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2307
developerf22724d2022-12-22 17:24:14 +08002308 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002309 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002310 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002311 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2312 } else {
2313 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2314 return RETURN_ERR;
2315 }
2316 } else if (band == band_5 || band == band_6){
2317 // 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 +08002318 // 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 +08002319 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002320 memset(output_string, 0, 256);
2321 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2322 // If i is not the last channel, we add a comma.
2323 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2324 strncat(output_string, buf, strlen(buf));
2325 }
developerf5745ee2022-10-05 16:09:53 +08002326 } else
2327 return RETURN_ERR;
2328
2329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002330 return RETURN_OK;
2331}
2332
2333//Get the running channel number
2334INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2335{
developer5b398df2022-11-17 20:39:48 +08002336 char channel_str[16] = {0};
2337 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002338
developer5b398df2022-11-17 20:39:48 +08002339 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002340 return RETURN_ERR;
2341
developer5b398df2022-11-17 20:39:48 +08002342 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2343 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002344
developer5b398df2022-11-17 20:39:48 +08002345 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002346
developer06a01d92022-09-07 16:32:39 +08002347 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002348}
2349
2350
2351INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2352{
2353 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002354 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002355
2356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2357 if (NULL == output_ulong)
2358 return RETURN_ERR;
2359
developer06a01d92022-09-07 16:32:39 +08002360 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002361 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2362 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002363 _syscmd(cmd,buf,sizeof(buf));
2364 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2365 if (*output_ulong == 0) {
2366 return RETURN_ERR;
2367 }
2368
2369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2370 return RETURN_OK;
2371}
2372
2373//Storing the previous channel value
2374INT wifi_storeprevchanval(INT radioIndex)
2375{
2376 char buf[256] = {0};
2377 char output[4]={'\0'};
2378 char config_file[MAX_BUF_SIZE] = {0};
2379 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2380 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2381 if(radioIndex == 0)
2382 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2383 else if(radioIndex == 1)
2384 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2385 system(buf);
2386 Radio_flag = FALSE;
2387 return RETURN_OK;
2388}
2389
2390//Set the running channel number
2391INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2392{
developer76989232022-10-04 14:13:19 +08002393 // We only write hostapd config here
2394 char str_channel[8]={0};
2395 char *list_channel;
2396 char config_file[128] = {0};
2397 char possible_channels[256] = {0};
2398 int max_radio_num = 0;
2399 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002400
developer76989232022-10-04 14:13:19 +08002401 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002402
developer76989232022-10-04 14:13:19 +08002403 // Check valid
2404 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002405
developer76989232022-10-04 14:13:19 +08002406 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2407 list_channel = strtok(possible_channels, ",");
2408 while(true)
developer06a01d92022-09-07 16:32:39 +08002409 {
developer76989232022-10-04 14:13:19 +08002410 if(list_channel == NULL) { // input not in the list
2411 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2412 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002413 }
developer76989232022-10-04 14:13:19 +08002414 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2415 break;
2416 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002417 }
2418
developer76989232022-10-04 14:13:19 +08002419 list.name = "channel";
2420 list.value = str_channel;
2421 wifi_getMaxRadioNumber(&max_radio_num);
2422 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002423 {
developer76989232022-10-04 14:13:19 +08002424 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2425 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002426 }
2427
developer76989232022-10-04 14:13:19 +08002428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002429 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002430}
developer06a01d92022-09-07 16:32:39 +08002431
2432INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2433{
developer7c4cd202023-03-01 10:56:29 +08002434 struct params list[3];
2435 char str_idx[16] = {0};
2436 char supported_mode[32] = {0};
2437 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002438 int max_num_radios = 0;
2439 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002440 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002441
2442 band = wifi_index_to_band(radioIndex);
2443 if (band == band_2_4)
2444 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002445
developer7c4cd202023-03-01 10:56:29 +08002446 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2447 if (strstr(supported_mode, "be") != NULL)
2448 eht_support = TRUE;
2449
developer30423732022-12-01 16:17:49 +08002450 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002451 list[0].name = "vht_oper_centr_freq_seg0_idx";
2452 list[0].value = str_idx;
2453 list[1].name = "he_oper_centr_freq_seg0_idx";
2454 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002455 list[2].name = "eht_oper_centr_freq_seg0_idx";
2456 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002457
developer76989232022-10-04 14:13:19 +08002458 wifi_getMaxRadioNumber(&max_num_radios);
2459 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002460 {
developer76989232022-10-04 14:13:19 +08002461 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002462 if (eht_support)
2463 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002464 else
2465 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002466 }
2467
2468 return RETURN_OK;
2469}
2470
2471//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2472//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2473INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2474{
2475 //Set to wifi config only. Wait for wifi reset to apply.
2476 char buf[256] = {0};
2477 char str_channel[256] = {0};
2478 int count = 0;
2479 ULONG Value = 0;
2480 FILE *fp = NULL;
2481 if(enable == TRUE)
2482 {
developer06a01d92022-09-07 16:32:39 +08002483 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002484 }
developer5884e982022-10-06 10:52:50 +08002485 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002486}
2487
developer0b246d12022-09-30 15:24:20 +08002488INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2489{
2490 if (output_bool == NULL)
2491 return RETURN_ERR;
2492
2493 *output_bool = TRUE;
2494
2495 return RETURN_OK;
2496}
2497
developer06a01d92022-09-07 16:32:39 +08002498INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2499{
2500 if (NULL == output_bool)
2501 return RETURN_ERR;
2502 *output_bool=FALSE;
2503 return RETURN_OK;
2504}
2505
2506INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2507{
2508 if (NULL == output_bool)
2509 return RETURN_ERR;
2510 *output_bool=FALSE;
2511 return RETURN_OK;
2512}
2513
2514INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2515{
2516 //Set to wifi config only. Wait for wifi reset to apply.
2517 return RETURN_OK;
2518}
2519
2520INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2521{
2522 return RETURN_OK;
2523}
2524
2525INT wifi_factoryResetAP(int apIndex)
2526{
developer838cca92022-10-03 13:19:57 +08002527 char ap_config_file[64] = {0};
2528 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002529 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002530 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002531
developer06a01d92022-09-07 16:32:39 +08002532 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002533
2534 wifi_setApEnable(apIndex, FALSE);
2535 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2536 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002537 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002538 wifi_getMaxRadioNumber(&max_radio_num);
2539 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2540 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002541
developer06a01d92022-09-07 16:32:39 +08002542 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002543
developer06a01d92022-09-07 16:32:39 +08002544 return RETURN_OK;
2545}
2546
2547//To set Band Steering AP group
2548//To-do
2549INT wifi_setBandSteeringApGroup(char *ApGroup)
2550{
2551 return RETURN_OK;
2552}
2553
developer1e5aa162022-09-13 16:06:24 +08002554INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2555{
2556 char config_file[128] = {'\0'};
2557 char buf[128] = {'\0'};
2558
2559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2560 if (dtimInterval == NULL)
2561 return RETURN_ERR;
2562
2563 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2564 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2565
2566 if (strlen(buf) == 0) {
2567 *dtimInterval = 2;
2568 } else {
2569 *dtimInterval = strtoul(buf, NULL, 10);
2570 }
2571
2572 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2573 return RETURN_OK;
2574}
2575
developer06a01d92022-09-07 16:32:39 +08002576INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2577{
developer5f222492022-09-13 15:21:52 +08002578 struct params params={0};
2579 char config_file[MAX_BUF_SIZE] = {'\0'};
2580 char buf[MAX_BUF_SIZE] = {'\0'};
2581
2582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2583 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002584 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002585 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002586 }
2587
2588 params.name = "dtim_period";
2589 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2590 params.value = buf;
2591
2592 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2593 wifi_hostapdWrite(config_file, &params, 1);
2594 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2595
2596 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2597 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002598}
2599
2600//Check if the driver support the Dfs
2601INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2602{
developer78a15382022-11-02 10:57:40 +08002603 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002604 if (NULL == output_bool)
2605 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002606 *output_bool=FALSE;
2607
2608 band = wifi_index_to_band(radioIndex);
2609 if (band == band_5)
2610 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002611 return RETURN_OK;
2612}
2613
2614//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.
2615//The value of this parameter is a comma seperated list of channel number
2616INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2617{
2618 if (NULL == output_pool)
2619 return RETURN_ERR;
2620 if (radioIndex==1)
2621 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2622 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2623
2624 return RETURN_OK;
2625}
2626
2627INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2628{
2629 //Set to wifi config. And apply instantly.
2630 return RETURN_OK;
2631}
2632
2633INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2634{
2635 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2636 return RETURN_ERR;
2637 *output_interval_seconds=1800;
2638 *output_dwell_milliseconds=40;
2639
2640 return RETURN_OK;
2641}
2642
2643INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2644{
2645 //Set to wifi config. And apply instantly.
2646 return RETURN_OK;
2647}
2648
developerbfc18512022-10-05 17:54:28 +08002649INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2650{
2651 if (output_bool == NULL)
2652 return RETURN_ERR;
2653 *output_bool = true;
2654 return RETURN_OK;
2655}
2656
2657INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2658{
2659 return RETURN_OK;
2660}
2661
developer06a01d92022-09-07 16:32:39 +08002662//Get the Dfs enable status
2663INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2664{
developer9964b5b2022-09-13 15:59:34 +08002665 char buf[16] = {0};
2666 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002667
2668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2669
developer30423732022-12-01 16:17:49 +08002670 if (output_bool == NULL)
2671 return RETURN_ERR;
2672
developer9964b5b2022-09-13 15:59:34 +08002673 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002674 f = fopen(DFS_ENABLE_FILE, "r");
2675 if (f != NULL) {
2676 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002677 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002678 *output_bool = FALSE;
2679 fclose(f);
2680 }
2681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002682 return RETURN_OK;
2683}
2684
2685//Set the Dfs enable status
2686INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2687{
developer9964b5b2022-09-13 15:59:34 +08002688 char config_file[128] = {0};
2689 FILE *f = NULL;
2690 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002691
2692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2693
developer9964b5b2022-09-13 15:59:34 +08002694 f = fopen(DFS_ENABLE_FILE, "w");
2695 if (f == NULL)
2696 return RETURN_ERR;
2697 fprintf(f, "%d", enable);
2698 fclose(f);
2699
2700 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002701 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002702 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2703 wifi_hostapdWrite(config_file, &params, 1);
2704 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2705
2706 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2707
developer9964b5b2022-09-13 15:59:34 +08002708 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002709 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002710}
2711
2712//Check if the driver support the AutoChannelRefreshPeriod
2713INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2714{
2715 if (NULL == output_bool)
2716 return RETURN_ERR;
2717 *output_bool=FALSE; //not support
2718
2719 return RETURN_OK;
2720}
2721
2722//Get the ACS refresh period in seconds
2723INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2724{
2725 if (NULL == output_ulong)
2726 return RETURN_ERR;
2727 *output_ulong=300;
2728
2729 return RETURN_OK;
2730}
2731
2732//Set the ACS refresh period in seconds
2733INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2734{
2735 return RETURN_ERR;
2736}
2737
developer7c4cd202023-03-01 10:56:29 +08002738INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2739{
2740 int center_channel = 0;
2741 char config_file[32] = {0};
2742 char buf[32] = {0};
2743
2744 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2745 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2746
2747 center_channel = strtoul(buf, NULL, 10);
2748 center_channel += 1; // Add 1 to become muiltiple of 16
2749 if (center_channel % 64 == 32)
2750 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2751 else if (center_channel % 64 == 0)
2752 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2753 else
2754 return RETURN_ERR;
2755 return RETURN_OK;
2756}
2757
developer06a01d92022-09-07 16:32:39 +08002758//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2759//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.
2760INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2761{
developer72ec5572023-01-05 16:27:13 +08002762 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002763 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002764 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002765 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002766 wifi_band band;
developer70490032022-09-13 15:45:20 +08002767
2768 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2769
developer06a01d92022-09-07 16:32:39 +08002770 if (NULL == output_string)
2771 return RETURN_ERR;
2772
developer70490032022-09-13 15:45:20 +08002773 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2774 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002775
developer70490032022-09-13 15:45:20 +08002776 if (radio_enable != TRUE)
2777 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002778
developerfa41b1f2023-01-06 10:25:51 +08002779 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002780 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002781 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002782 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2783 snprintf(output_string, 64, "20MHz");
2784 else
2785 snprintf(output_string, 64, "40MHz");
2786
2787 } else {
2788 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2789 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2790 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2791 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2792 if (strncmp(buf, "0", 1) == 0)
2793 snprintf(output_string, 64, "20MHz");
2794 else
2795 snprintf(output_string, 64, "40MHz");
2796
2797 } else if (strncmp(buf, "1", 1) == 0)
2798 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002799 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002800 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002801 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2802 if (strncmp(buf, "9", 1) == 0) {
2803 int BandwidthSet = 0;
2804 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2805 return RETURN_ERR;
2806 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2807 snprintf(output_string, 64, "320-1MHz");
2808 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2809 snprintf(output_string, 64, "320-2MHz");
2810 }
2811 }
developer06a01d92022-09-07 16:32:39 +08002812 }
developer72ec5572023-01-05 16:27:13 +08002813
developer06a01d92022-09-07 16:32:39 +08002814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002815
2816 return RETURN_OK;
2817}
2818
2819//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002820INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002821{
developerf7a466e2022-09-29 11:55:56 +08002822 char config_file[128];
2823 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002824 char supported_mode[32] = {0};
2825 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002826 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002827 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002828
developer06a01d92022-09-07 16:32:39 +08002829 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002830
developerf7a466e2022-09-29 11:55:56 +08002831 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002832 return RETURN_ERR;
2833
developer7c4cd202023-03-01 10:56:29 +08002834 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002835 strcpy(set_value, "2");
2836 else if(strstr(bandwidth,"80") != NULL)
2837 strcpy(set_value, "1");
2838 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2839 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002840 else if (strstr(bandwidth, "Auto") != NULL)
2841 return RETURN_OK;
2842 else {
developerf7a466e2022-09-29 11:55:56 +08002843 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002844 return RETURN_ERR;
2845 }
2846
developer7c4cd202023-03-01 10:56:29 +08002847 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2848 if (strstr(supported_mode, "be") != NULL)
2849 eht_support = TRUE;
2850
developerf7a466e2022-09-29 11:55:56 +08002851 params[0].name = "vht_oper_chwidth";
2852 params[0].value = set_value;
2853 params[1].name = "he_oper_chwidth";
2854 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002855 params[2].name = "eht_oper_chwidth";
2856 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2857 params[2].value = "9";
2858 else
2859 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002860
developerf7a466e2022-09-29 11:55:56 +08002861 wifi_getMaxRadioNumber(&max_radio_num);
2862 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002863 {
developer7c4cd202023-03-01 10:56:29 +08002864 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2865 if (eht_support == TRUE)
2866 wifi_hostapdWrite(config_file, params, 3);
2867 else
2868 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002869 }
2870
2871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2872 return RETURN_OK;
2873}
2874
2875//Getting current radio extension channel
2876INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2877{
2878 CHAR buf[150] = {0};
2879 CHAR cmd[150] = {0};
2880 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2881 _syscmd(cmd, buf, sizeof(buf));
2882 if(NULL != strstr(buf,"HT40+"))
2883 strcpy(Value,"AboveControlChannel");
2884 else if(NULL != strstr(buf,"HT40-"))
2885 strcpy(Value,"BelowControlChannel");
2886 return RETURN_OK;
2887}
2888
2889//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2890//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.
2891INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2892{
developerfa41b1f2023-01-06 10:25:51 +08002893 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002894 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002895
2896 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002897 return RETURN_ERR;
2898
developerfa41b1f2023-01-06 10:25:51 +08002899 band = wifi_index_to_band(radioIndex);
2900 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002901 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002902
2903 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2904
2905 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002906 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002907
2908 return RETURN_OK;
2909}
2910
developer57fa24a2023-03-15 17:25:07 +08002911// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2912INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2913{
2914 struct params params={0};
2915 char config_file[64] = {0};
2916 char ht_capab[128]={0};
2917 char buf[128] = {0};
2918 char cmd[128] = {0};
2919 int max_radio_num =0;
2920 bool stbcEnable = FALSE;
2921
2922 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2923 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2924 _syscmd(cmd, buf, sizeof(buf));
2925 if (strlen(buf) != 0)
2926 stbcEnable = TRUE;
2927
2928 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2929 params.value = ht_capab;
2930 params.name = "ht_capab";
2931
2932 wifi_getMaxRadioNumber(&max_radio_num);
2933 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2934 {
2935 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2936 wifi_hostapdWrite(config_file, &params, 1);
developer57fa24a2023-03-15 17:25:07 +08002937 }
developer8d7d0862023-05-18 16:50:23 +08002938 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer57fa24a2023-03-15 17:25:07 +08002939 return RETURN_OK;
2940}
2941
developer06a01d92022-09-07 16:32:39 +08002942//Set the extension channel.
2943INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002944{
developer06a01d92022-09-07 16:32:39 +08002945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002946 struct params params={0};
2947 char config_file[64] = {0};
2948 char ext_channel[128]={0};
2949 char buf[128] = {0};
2950 char cmd[128] = {0};
2951 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002952 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002953 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002954 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002955 wifi_band band;
2956
2957 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2958 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2959 _syscmd(cmd, buf, sizeof(buf));
2960 if (strlen(buf) != 0)
2961 stbcEnable = TRUE;
developer57fa24a2023-03-15 17:25:07 +08002962
2963 // readBandWidth get empty file will return error, that means we don't set new bandwidth
2964 if (readBandWidth(radioIndex, buf) != RETURN_OK) {
2965 // Get current bandwidth
2966 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2967 return RETURN_ERR;
2968 }
developerfa41b1f2023-01-06 10:25:51 +08002969 bandwidth = strtol(buf, NULL, 10);
2970 // TDK expected to get error with 20MHz
developer57fa24a2023-03-15 17:25:07 +08002971 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developerfa41b1f2023-01-06 10:25:51 +08002972 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2973 return RETURN_ERR;
2974
2975 band = wifi_index_to_band(radioIndex);
2976 if (band == band_invalid)
2977 return RETURN_ERR;
2978
2979 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2980 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002981
developer72ec5572023-01-05 16:27:13 +08002982 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2983 ret = util_get_sec_chan_offset(channel, buf);
2984 if (ret == -EINVAL)
2985 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002986
2987 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002988 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2989 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002990 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002991 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08002992 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
2993 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002994 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002995 } else {
developer57fa24a2023-03-15 17:25:07 +08002996 fprintf(stderr, "%s: unknow extchannel %s\n", __func__, string);
2997 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002998 }
developer06a01d92022-09-07 16:32:39 +08002999
3000 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08003001
3002 wifi_getMaxRadioNumber(&max_radio_num);
3003 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08003004 {
developer033b37b2022-10-18 11:27:46 +08003005 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08003006 wifi_hostapdWrite(config_file, &params, 1);
3007 }
developer8d7d0862023-05-18 16:50:23 +08003008 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer06a01d92022-09-07 16:32:39 +08003009
3010 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3011 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3012 return RETURN_OK;
3013}
3014
3015//Get the guard interval value. eg "400nsec" or "800nsec"
3016//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.
3017INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3018{
developer454b9462022-09-13 15:29:16 +08003019 wifi_guard_interval_t GI;
3020
3021 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3022
3023 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08003024 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08003025
3026 if (GI == wifi_guard_interval_400)
3027 strcpy(output_string, "400nsec");
3028 else if (GI == wifi_guard_interval_800)
3029 strcpy(output_string, "800nsec");
3030 else if (GI == wifi_guard_interval_1600)
3031 strcpy(output_string, "1600nsec");
3032 else if (GI == wifi_guard_interval_3200)
3033 strcpy(output_string, "3200nsec");
3034 else
developer78a15382022-11-02 10:57:40 +08003035 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08003036
developer454b9462022-09-13 15:29:16 +08003037 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003038 return RETURN_OK;
3039}
3040
3041//Set the guard interval value.
3042INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3043{
developer454b9462022-09-13 15:29:16 +08003044 wifi_guard_interval_t GI;
3045 int ret = 0;
3046
3047 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3048
3049 if (strcmp(string, "400nsec") == 0)
3050 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08003051 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08003052 GI = wifi_guard_interval_800;
3053 else if (strcmp(string , "1600nsec") == 0)
3054 GI = wifi_guard_interval_1600;
3055 else if (strcmp(string , "3200nsec") == 0)
3056 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08003057 else
3058 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003059
3060 ret = wifi_setGuardInterval(radioIndex, GI);
3061
3062 if (ret == RETURN_ERR) {
3063 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3064 return RETURN_ERR;
3065 }
3066
3067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3068 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003069}
3070
3071//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3072INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3073{
developerf49437e2022-09-29 19:58:21 +08003074 char buf[32]={0};
3075 char mcs_file[64] = {0};
3076 char cmd[64] = {0};
3077 int mode_bitmap = 0;
3078
3079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3080 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003081 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003082 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3083
3084 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3085 _syscmd(cmd, buf, sizeof(buf));
3086 if (strlen(buf) > 0)
3087 *output_int = strtol(buf, NULL, 10);
3088 else {
3089 // output the max MCS for the current radio mode
3090 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3091 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3092 return RETURN_ERR;
3093 }
3094 if (mode_bitmap & WIFI_MODE_AX) {
3095 *output_int = 11;
3096 } else if (mode_bitmap & WIFI_MODE_AC) {
3097 *output_int = 9;
3098 } else if (mode_bitmap & WIFI_MODE_N) {
3099 *output_int = 7;
3100 }
3101 }
3102 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003103
3104 return RETURN_OK;
3105}
3106
3107//Set the Modulation Coding Scheme index
3108INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3109{
developerf49437e2022-09-29 19:58:21 +08003110 // 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).
3111 char config_file[64] = {0};
3112 char set_value[16] = {0};
3113 char mcs_file[32] = {0};
3114 wifi_band band = band_invalid;
3115 struct params set_config = {0};
3116 FILE *f = NULL;
3117
3118 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3119
3120 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3121
developer78a15382022-11-02 10:57:40 +08003122 // -1 means auto
3123 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003124 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3125 return RETURN_ERR;
3126 }
3127
developer78a15382022-11-02 10:57:40 +08003128 if (MCS > 9 || MCS == -1)
3129 strcpy(set_value, "2");
3130 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003131 strcpy(set_value, "1");
3132 else
developer78a15382022-11-02 10:57:40 +08003133 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003134
3135 set_config.name = "he_basic_mcs_nss_set";
3136 set_config.value = set_value;
3137
3138 wifi_hostapdWrite(config_file, &set_config, 1);
3139 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3140
3141 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3142 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3143 f = fopen(mcs_file, "w");
3144 if (f == NULL) {
3145 fprintf(stderr, "%s: fopen failed\n", __func__);
3146 return RETURN_ERR;
3147 }
3148 fprintf(f, "%d", MCS);
3149 fclose(f);
3150
3151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3152 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003153}
3154
3155//Get supported Transmit Power list, eg : "0,25,50,75,100"
3156//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.
3157INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3158{
3159 if (NULL == output_list)
3160 return RETURN_ERR;
developer5c97d532023-09-28 11:19:30 +08003161 snprintf(output_list, 64,"0,12,25,50,75,100");
developer06a01d92022-09-07 16:32:39 +08003162 return RETURN_OK;
3163}
3164
developer5c97d532023-09-28 11:19:30 +08003165// Get current Transmit Power in percent
developer06a01d92022-09-07 16:32:39 +08003166INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3167{
developer5c97d532023-09-28 11:19:30 +08003168 char cmd[128]={'\0'};
3169 char buf[128]={'\0'};
3170 int phyIndex = -1;
3171 bool enabled = false;
3172 int cur_tx_dbm = 0;
3173
developera5005b62022-09-13 15:43:35 +08003174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003175
developera5005b62022-09-13 15:43:35 +08003176 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003177 return RETURN_ERR;
3178
developer5c97d532023-09-28 11:19:30 +08003179 phyIndex = radio_index_to_phy(radioIndex);
3180
3181 // Get the maximum tx power of the device
3182 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
3183 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developer06a01d92022-09-07 16:32:39 +08003184 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003185 if (strcmp(buf, "enable") == 0)
3186 enabled = true;
developer06a01d92022-09-07 16:32:39 +08003187
developer5c97d532023-09-28 11:19:30 +08003188 if (!enabled) {
3189 *output_ulong = 100;
3190 return RETURN_OK;
3191 }
developera5005b62022-09-13 15:43:35 +08003192
developer5c97d532023-09-28 11:19:30 +08003193 memset(cmd, 0, sizeof(cmd));
3194 memset(buf, 0, sizeof(buf));
3195 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
3196 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
3197 _syscmd(cmd, buf, sizeof(buf));
3198 cur_tx_dbm = strtol(buf, NULL, 10);
3199
3200 switch (cur_tx_dbm) {
3201 case 0:
3202 *output_ulong = 100; // range 91-100
3203 break;
3204 case 1:
3205 *output_ulong = 75; // range 61-90
3206 break;
3207 case 3:
3208 *output_ulong = 50; // range 31-60
3209 break;
3210 case 6:
3211 *output_ulong = 25; // range 16-30
3212 break;
3213 case 9:
3214 *output_ulong = 12; // range 10-15
3215 break;
3216 case 12:
3217 *output_ulong = 6; // range 1-9
3218 break;
3219 default:
3220 *output_ulong = 100; // 0
3221 }
3222
developer06a01d92022-09-07 16:32:39 +08003223 return RETURN_OK;
3224}
3225
developer5c97d532023-09-28 11:19:30 +08003226// TransmitPower: the the percentage relative to the maximum power,
3227// only support 0,12,25,50,75,100, But 0 means disable Power limit,
3228// so the power is 100%
developer06a01d92022-09-07 16:32:39 +08003229INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3230{
developerd946fd62022-12-08 18:03:28 +08003231 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003232 char *support;
developer06a01d92022-09-07 16:32:39 +08003233 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003234 char buf[128]={0};
3235 char txpower_str[64] = {0};
developer033b37b2022-10-18 11:27:46 +08003236 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003237
3238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003239
developerac6f1142022-12-20 19:26:35 +08003240 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003241 return RETURN_ERR;
developera5005b62022-09-13 15:43:35 +08003242
3243 // Get the Tx power supported list and check that is the input in the list
3244 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3245 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3246 support = strtok(buf, ",");
3247 while(true)
3248 {
3249 if(support == NULL) { // input not in the list
3250 wifi_dbg_printf("Input value is invalid.\n");
3251 return RETURN_ERR;
3252 }
3253 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3254 break;
3255 }
3256 support = strtok(NULL, ",");
3257 }
developer5c97d532023-09-28 11:19:30 +08003258
developer033b37b2022-10-18 11:27:46 +08003259 phyId = radio_index_to_phy(radioIndex);
developer5c97d532023-09-28 11:19:30 +08003260 snprintf(cmd, sizeof(cmd), "echo %lu > /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_level",
3261 TransmitPower, phyId);
developera5005b62022-09-13 15:43:35 +08003262 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003263
developera5005b62022-09-13 15:43:35 +08003264 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003265
3266 return RETURN_OK;
3267}
3268
3269//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3270INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3271{
3272 if (NULL == Supported)
3273 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003274 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003275
3276 return RETURN_OK;
3277}
3278
3279//Get 80211h feature enable
3280INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3281{
developer3885fec2022-09-13 15:13:47 +08003282 char buf[64]={'\0'};
3283 char config_file[64] = {'\0'};
3284
3285 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3286 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003287 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003288
3289 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3290 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003291
developer3885fec2022-09-13 15:13:47 +08003292 if (strncmp(buf, "1", 1) == 0)
3293 *enable = TRUE;
3294 else
3295 *enable = FALSE;
3296
3297 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003298 return RETURN_OK;
3299}
3300
3301//Set 80211h feature enable
3302INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3303{
developer3885fec2022-09-13 15:13:47 +08003304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3305 struct params params={'\0'};
3306 char config_file[MAX_BUF_SIZE] = {0};
3307
3308 params.name = "ieee80211h";
3309
3310 if (enable) {
3311 params.value = "1";
3312 } else {
3313 params.value = "0";
3314 }
3315
3316 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3317 wifi_hostapdWrite(config_file, &params, 1);
3318
3319 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3321 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003322}
3323
3324//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.
3325INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3326{
3327 if (NULL == output)
3328 return RETURN_ERR;
3329 *output=100;
3330
3331 return RETURN_OK;
3332}
3333
3334//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.
3335INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3336{
3337 if (NULL == output)
3338 return RETURN_ERR;
3339 *output = -99;
3340
3341 return RETURN_OK;
3342}
3343
3344INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3345{
3346 return RETURN_ERR;
3347}
3348
3349
3350//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3351INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3352{
developerd946fd62022-12-08 18:03:28 +08003353 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003354 char cmd[MAX_BUF_SIZE]={'\0'};
3355 char buf[MAX_CMD_SIZE]={'\0'};
3356
3357 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3358 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003359 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003360
developerac6f1142022-12-20 19:26:35 +08003361 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003362 return RETURN_ERR;
3363 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 +08003364 _syscmd(cmd, buf, sizeof(buf));
3365 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003366
developer5f222492022-09-13 15:21:52 +08003367 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003368 return RETURN_OK;
3369}
3370
3371INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3372{
developer5f222492022-09-13 15:21:52 +08003373 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3374 struct params params={'\0'};
3375 char buf[MAX_BUF_SIZE] = {'\0'};
3376 char config_file[MAX_BUF_SIZE] = {'\0'};
3377
developer5b398df2022-11-17 20:39:48 +08003378 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3379 return RETURN_ERR;
3380
developer5f222492022-09-13 15:21:52 +08003381 params.name = "beacon_int";
3382 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3383 params.value = buf;
3384
3385 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3386 wifi_hostapdWrite(config_file, &params, 1);
3387
3388 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3390 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003391}
3392
3393//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.
3394INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3395{
developer06a01d92022-09-07 16:32:39 +08003396 //TODO: need to revisit below implementation
3397 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003398 char temp_output[128] = {0};
3399 char temp_TransmitRates[64] = {0};
3400 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003401
3402 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3403 if (NULL == output)
3404 return RETURN_ERR;
3405 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003406 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3407
3408 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3409 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3410 } else {
3411 temp = strtok(temp_TransmitRates," ");
3412 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003413 {
developere9d0abd2022-09-13 15:40:57 +08003414 // Convert 100 kbps to Mbps
3415 temp[strlen(temp)-1]=0;
3416 if((temp[0]=='5') && (temp[1]=='\0'))
3417 {
3418 temp="5.5";
3419 }
3420 strcat(temp_output,temp);
3421 temp = strtok(NULL," ");
3422 if(temp!=NULL)
3423 {
3424 strcat(temp_output,",");
3425 }
developer06a01d92022-09-07 16:32:39 +08003426 }
developere9d0abd2022-09-13 15:40:57 +08003427 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003428 }
developer06a01d92022-09-07 16:32:39 +08003429 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003430 return RETURN_OK;
3431}
3432
3433INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3434{
3435 char *temp;
3436 char temp1[128];
3437 char temp_output[128];
3438 char temp_TransmitRates[128];
3439 char set[128];
3440 char sub_set[128];
3441 int set_count=0,subset_count=0;
3442 int set_index=0,subset_index=0;
3443 char *token;
3444 int flag=0, i=0;
3445 struct params params={'\0'};
3446 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003447 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003448
3449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3450 if(NULL == TransmitRates)
3451 return RETURN_ERR;
3452 strcpy(sub_set,TransmitRates);
3453
3454 //Allow only supported Data transmit rate to be set
3455 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3456 token = strtok(sub_set,",");
3457 while( token != NULL ) /* split the basic rate to be set, by comma */
3458 {
3459 sub_set[subset_count]=atoi(token);
3460 subset_count++;
3461 token=strtok(NULL,",");
3462 }
3463 token=strtok(set,",");
3464 while(token!=NULL) /* split the supported rate by comma */
3465 {
3466 set[set_count]=atoi(token);
3467 set_count++;
3468 token=strtok(NULL,",");
3469 }
3470 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3471 {
3472 for(set_index=0;set_index < set_count;set_index++)
3473 {
3474 flag=0;
3475 if(sub_set[subset_index]==set[set_index])
3476 break;
3477 else
3478 flag=1; /* No match found */
3479 }
3480 if(flag==1)
3481 return RETURN_ERR; //If value not found return Error
3482 }
3483 strcpy(temp_TransmitRates,TransmitRates);
3484
3485 for(i=0;i<strlen(temp_TransmitRates);i++)
3486 {
3487 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003488 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003489 {
3490 continue;
3491 }
3492 else
3493 {
3494 return RETURN_ERR;
3495 }
3496 }
3497 strcpy(temp_output,"");
3498 temp = strtok(temp_TransmitRates,",");
3499 while(temp!=NULL)
3500 {
3501 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003502 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003503 {
developeref938762022-10-19 17:21:01 +08003504 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003505 {
3506 return RETURN_ERR;
3507 }
3508 }
3509
3510 if(strcmp(temp,"5.5")==0)
3511 {
3512 strcpy(temp1,"55");
3513 }
3514 else
3515 {
3516 strcat(temp1,"0");
3517 }
3518 strcat(temp_output,temp1);
3519 temp = strtok(NULL,",");
3520 if(temp!=NULL)
3521 {
3522 strcat(temp_output," ");
3523 }
3524 }
3525 strcpy(TransmitRates,temp_output);
3526
3527 params.name= "basic_rates";
3528 params.value =TransmitRates;
3529
3530 wifi_dbg_printf("\n%s:",__func__);
3531 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3532 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3533 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3534 wifi_hostapdWrite(config_file,&params,1);
3535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3536 return RETURN_OK;
3537}
3538
3539//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003540INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003541{
3542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3543 FILE *fp = NULL;
3544 char path[256] = {0}, output_string[256] = {0};
3545 int count = 0;
3546 char *interface = NULL;
3547
3548 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3549 if (fp == NULL)
3550 {
3551 printf("Failed to run command in Function %s\n", __FUNCTION__);
3552 return RETURN_ERR;
3553 }
3554 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3555 {
3556 interface = strchr(path, '=');
3557
3558 if (interface != NULL)
3559 {
3560 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003561 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003562 interface_name[count] = output_string[count];
3563
3564 interface_name[count] = '\0';
3565 }
3566 }
3567 pclose(fp);
3568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3569 return RETURN_OK;
3570}
3571
3572INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3573{
3574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3575 output_struct->radio_BytesSent = 0;
3576 output_struct->radio_BytesReceived = 0;
3577 output_struct->radio_PacketsSent = 0;
3578 output_struct->radio_PacketsReceived = 0;
3579 output_struct->radio_ErrorsSent = 0;
3580 output_struct->radio_ErrorsReceived = 0;
3581 output_struct->radio_DiscardPacketsSent = 0;
3582 output_struct->radio_DiscardPacketsReceived = 0;
3583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3584 return RETURN_OK;
3585}
3586
3587
3588INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3589{
3590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer214b0592023-10-31 10:59:05 +08003591 CHAR buf[MAX_CMD_SIZE] = {0};
3592 CHAR Value[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08003593 FILE *fp = NULL;
3594
3595 if (ifname == NULL || strlen(ifname) <= 1)
3596 return RETURN_OK;
3597
developer214b0592023-10-31 10:59:05 +08003598 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
developer06a01d92022-09-07 16:32:39 +08003599 system(buf);
3600
3601 fp = fopen("/tmp/Radio_Stats.txt", "r");
3602 if(fp == NULL)
3603 {
3604 printf("/tmp/Radio_Stats.txt not exists \n");
3605 return RETURN_ERR;
3606 }
3607 fclose(fp);
3608
developer214b0592023-10-31 10:59:05 +08003609 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3610 File_Reading(buf, Value);
3611 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003612
developer214b0592023-10-31 10:59:05 +08003613 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3614 File_Reading(buf, Value);
3615 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003616
developer214b0592023-10-31 10:59:05 +08003617 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3618 File_Reading(buf, Value);
3619 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003620
developer214b0592023-10-31 10:59:05 +08003621 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3622 File_Reading(buf, Value);
3623 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003624
developer214b0592023-10-31 10:59:05 +08003625 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3626 File_Reading(buf, Value);
3627 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003628
developer214b0592023-10-31 10:59:05 +08003629 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3630 File_Reading(buf, Value);
3631 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003632
developer214b0592023-10-31 10:59:05 +08003633 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3634 File_Reading(buf, Value);
3635 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003636
developer214b0592023-10-31 10:59:05 +08003637 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3638 File_Reading(buf, Value);
3639 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003640
3641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3642 return RETURN_OK;
3643}
3644
3645INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3646{
3647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3648 CHAR buf[MAX_CMD_SIZE] = {0};
3649 FILE *fp = NULL;
3650 INT count = 0;
3651
3652 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3653 {
3654 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3655 File_Reading(buf, status);
3656 }
3657 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3658 return RETURN_OK;
3659}
3660
3661//Get detail radio traffic static info
3662INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3663{
3664
3665#if 0
3666 //ifconfig radio_x
3667 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3668 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3669 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3670 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3671
3672 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3673 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3674 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.
3675 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.
3676
3677 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3678 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].
3679 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3680 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.
3681 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
3682 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
3683 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
3684 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
3685 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
3686
3687 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
3688 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
3689 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
3690 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.
3691
3692 return RETURN_OK;
3693#endif
3694
developera91d99f2022-09-29 15:59:10 +08003695 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003696 BOOL iface_status = FALSE;
3697 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer7c4c40e2023-10-25 10:17:04 +08003698 INT max_radio_num = 0, apIndex = 0;
developer06a01d92022-09-07 16:32:39 +08003699
3700 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3701 if (NULL == output_struct)
3702 return RETURN_ERR;
3703
developer7c4c40e2023-10-25 10:17:04 +08003704 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08003705
developer7c4c40e2023-10-25 10:17:04 +08003706 memset(output_struct, 0, sizeof(wifi_radioTrafficStats2_t));
developer06a01d92022-09-07 16:32:39 +08003707
developer7c4c40e2023-10-25 10:17:04 +08003708 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
3709 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3710 continue;
3711 wifi_getApEnable(radioIndex, &iface_status);
3712
3713 if (iface_status == TRUE)
3714 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3715 else
3716 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003717
developer7c4c40e2023-10-25 10:17:04 +08003718 output_struct->radio_BytesSent += radioTrafficStats.radio_BytesSent;
3719 output_struct->radio_BytesReceived += radioTrafficStats.radio_BytesReceived;
3720 output_struct->radio_PacketsSent += radioTrafficStats.radio_PacketsSent;
3721 output_struct->radio_PacketsReceived += radioTrafficStats.radio_PacketsReceived;
3722 output_struct->radio_ErrorsSent += radioTrafficStats.radio_ErrorsSent;
3723 output_struct->radio_ErrorsReceived += radioTrafficStats.radio_ErrorsReceived;
3724 output_struct->radio_DiscardPacketsSent += radioTrafficStats.radio_DiscardPacketsSent;
3725 output_struct->radio_DiscardPacketsReceived += radioTrafficStats.radio_DiscardPacketsReceived;
3726 }
developer06a01d92022-09-07 16:32:39 +08003727
3728 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3729 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].
3730 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3731 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.
3732 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
3733 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
3734 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
3735 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
3736 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
3737
3738 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
3739 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
3740 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
3741 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.
3742
3743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3744
3745 return RETURN_OK;
3746}
3747
3748//Set radio traffic static Measureing rules
3749INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3750{
3751 //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
3752 // Else, save the MeasuringRate and MeasuringInterval for future usage
3753
3754 return RETURN_OK;
3755}
3756
3757//To start or stop RadioTrafficStats
3758INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3759{
3760 //zqiu: If the RadioTrafficStats process running
3761 // if(enable)
3762 // return RETURN_OK.
3763 // else
3764 // Stop RadioTrafficStats process
3765 // Else
3766 // if(enable)
3767 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3768 // else
3769 // return RETURN_OK.
3770
3771 return RETURN_OK;
3772}
3773
3774//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
3775INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3776{
3777 //zqiu: Please ignor signalIndex.
3778 if (NULL == SignalLevel)
3779 return RETURN_ERR;
3780 *SignalLevel=(radioIndex==0)?-19:-19;
3781
3782 return RETURN_OK;
3783}
3784
3785//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3786INT wifi_applyRadioSettings(INT radioIndex)
3787{
3788 return RETURN_OK;
3789}
3790
3791//Get the radio index assocated with this SSID entry
3792INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3793{
developer5b398df2022-11-17 20:39:48 +08003794 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003795 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003796 int max_radio_num = 0;
3797 wifi_getMaxRadioNumber(&max_radio_num);
3798 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003799 return RETURN_OK;
3800}
3801
3802//Device.WiFi.SSID.{i}.Enable
3803//Get SSID enable configuration parameters (not the SSID enable status)
3804INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3805{
3806 if (NULL == output_bool)
3807 return RETURN_ERR;
3808
developer06a01d92022-09-07 16:32:39 +08003809 return wifi_getApEnable(ssidIndex, output_bool);
3810}
3811
3812//Device.WiFi.SSID.{i}.Enable
3813//Set SSID enable configuration parameters
3814INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3815{
developer06a01d92022-09-07 16:32:39 +08003816 return wifi_setApEnable(ssidIndex, enable);
3817}
3818
3819//Device.WiFi.SSID.{i}.Status
3820//Get the SSID enable status
3821INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3822{
3823 char cmd[MAX_CMD_SIZE]={0};
3824 char buf[MAX_BUF_SIZE]={0};
3825 BOOL output_bool;
3826
3827 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3828 if (NULL == output_string)
3829 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003830
developer06a01d92022-09-07 16:32:39 +08003831 wifi_getApEnable(ssidIndex,&output_bool);
3832 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3833
3834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3835 return RETURN_OK;
3836}
3837
3838// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3839INT wifi_getSSIDName(INT apIndex, CHAR *output)
3840{
3841 char config_file[MAX_BUF_SIZE] = {0};
3842
3843 if (NULL == output)
3844 return RETURN_ERR;
3845
developerefb790a2023-12-26 18:58:32 +08003846 if (!syn_flag) {
3847 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3848 wifi_hostapdRead(config_file,"ssid",output,32);
3849 } else
developer07ded1f2024-01-10 10:30:15 +08003850 snprintf(output, 32, "%s", vap_info[apIndex].ssid);
developer06a01d92022-09-07 16:32:39 +08003851
3852 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3853 return RETURN_OK;
3854}
3855
3856// Set a max 32 byte string and sets an internal variable to the SSID name
3857INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3858{
3859 char str[MAX_BUF_SIZE]={'\0'};
3860 char cmd[MAX_CMD_SIZE]={'\0'};
3861 struct params params;
3862 char config_file[MAX_BUF_SIZE] = {0};
3863
3864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003865 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003866 return RETURN_ERR;
3867
3868 params.name = "ssid";
3869 params.value = ssid_string;
3870 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3871 wifi_hostapdWrite(config_file, &params, 1);
3872 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3874
3875 return RETURN_OK;
3876}
3877
3878//Get the BSSID
3879INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3880{
3881 char cmd[MAX_CMD_SIZE]="";
3882
3883 if (NULL == output_string)
3884 return RETURN_ERR;
3885
3886 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3887 {
developer1d57d002022-10-12 18:03:15 +08003888 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 +08003889 _syscmd(cmd, output_string, 64);
3890 return RETURN_OK;
3891 }
3892 strncpy(output_string, "\0", 1);
3893
3894 return RETURN_ERR;
3895}
3896
3897//Get the MAC address associated with this Wifi SSID
3898INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3899{
3900 wifi_getBaseBSSID(ssidIndex,output_string);
3901 return RETURN_OK;
3902}
3903
3904//Get the basic SSID traffic static info
3905//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3906//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3907INT wifi_applySSIDSettings(INT ssidIndex)
3908{
developerd946fd62022-12-08 18:03:28 +08003909 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003910 BOOL status = false;
3911 char cmd[MAX_CMD_SIZE] = {0};
3912 char buf[MAX_CMD_SIZE] = {0};
3913 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003914 int max_radio_num = 0;
3915 int radioIndex = 0;
3916
3917 wifi_getMaxRadioNumber(&max_radio_num);
3918
3919 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003920
3921 wifi_getApEnable(ssidIndex,&status);
3922 // Do not apply when ssid index is disabled
3923 if (status == false)
3924 return RETURN_OK;
3925
3926 /* Doing full remove and add for ssid Index
3927 * Not all hostapd options are supported with reload
3928 * for example macaddr_acl
3929 */
3930 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3931 return RETURN_ERR;
3932
3933 ret = wifi_setApEnable(ssidIndex,true);
3934
3935 /* Workaround for hostapd issue with multiple bss definitions
3936 * when first created interface will be removed
3937 * then all vaps other vaps on same phy are removed
3938 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003939 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003940 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003941 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003942 continue;
developer643b28f2023-04-04 10:26:01 +08003943 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003944 _syscmd(cmd, buf, sizeof(buf));
3945 if(*buf == '1')
3946 wifi_setApEnable(apIndex, true);
3947 }
3948
3949 return ret;
3950}
3951
developera3c68b92022-09-13 15:27:29 +08003952struct channels_noise {
3953 int channel;
3954 int noise;
3955};
3956
3957// Return noise array for each channel
3958int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3959{
developerd946fd62022-12-08 18:03:28 +08003960 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003961 FILE *f = NULL;
3962 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003963 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003964 size_t len = 0;
3965 ssize_t read = 0;
3966 int tmp = 0, arr_index = -1;
3967
developerac6f1142022-12-20 19:26:35 +08003968 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003969 return RETURN_ERR;
3970 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003971
3972 if ((f = popen(cmd, "r")) == NULL) {
3973 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3974 return RETURN_ERR;
3975 }
developer5550e242022-09-30 09:59:32 +08003976
3977 while(fgets(line, sizeof(line), f) != NULL) {
3978 if(arr_index < channels_num){
3979 sscanf(line, "%d", &tmp);
3980 if (tmp > 0) { // channel frequency, the first line must be frequency
3981 arr_index++;
3982 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3983 } else { // noise
3984 channels_noise_arr[arr_index].noise = tmp;
3985 }
3986 }else{
3987 break;
developera3c68b92022-09-13 15:27:29 +08003988 }
3989 }
developera3c68b92022-09-13 15:27:29 +08003990 pclose(f);
3991 return RETURN_OK;
3992}
3993
developer06a01d92022-09-07 16:32:39 +08003994//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3995//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3996INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3997{
developera3c68b92022-09-13 15:27:29 +08003998 int index = -1;
3999 wifi_neighbor_ap2_t *scan_array = NULL;
4000 char cmd[256]={0};
4001 char buf[128]={0};
4002 char file_name[32] = {0};
4003 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08004004 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004005 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08004006 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08004007 int freq=0;
4008 FILE *f = NULL;
4009 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08004010 int channels_num = 0;
4011 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08004012 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08004013 bool filter_enable = false;
4014 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08004015 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004016
developer615510b2022-09-27 10:14:35 +08004017 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004018
developerac6f1142022-12-20 19:26:35 +08004019 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004020 return RETURN_ERR;
4021
developera3c68b92022-09-13 15:27:29 +08004022 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4023 f = fopen(file_name, "r");
4024 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08004025 fgets(buf, sizeof(file_name), f);
4026 if ((strncmp(buf, "0", 1)) != 0) {
4027 fgets(filter_SSID, sizeof(file_name), f);
4028 if (strlen(filter_SSID) != 0)
4029 filter_enable = true;
4030 }
developera3c68b92022-09-13 15:27:29 +08004031 fclose(f);
4032 }
4033
developer033b37b2022-10-18 11:27:46 +08004034 phyId = radio_index_to_phy(radioIndex);
4035 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08004036 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08004037 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004038
developer5550e242022-09-30 09:59:32 +08004039
developer06a01d92022-09-07 16:32:39 +08004040
developerd946fd62022-12-08 18:03:28 +08004041 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4042 // 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 +08004043 fprintf(stderr, "cmd: %s\n", cmd);
4044 if ((f = popen(cmd, "r")) == NULL) {
4045 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4046 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004047 }
developer5550e242022-09-30 09:59:32 +08004048
4049 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4050 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4051
developer615510b2022-09-27 10:14:35 +08004052 ret = fgets(line, sizeof(line), f);
4053 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08004054 if(strstr(line, "BSS") != NULL) { // new neighbor info
4055 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4056 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4057 // 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 +08004058
developera3c68b92022-09-13 15:27:29 +08004059 if (!filter_BSS) {
4060 index++;
4061 wifi_neighbor_ap2_t *tmp;
4062 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4063 if (tmp == NULL) { // no more memory to use
4064 index--;
4065 wifi_dbg_printf("%s: realloc failed\n", __func__);
4066 break;
4067 }
4068 scan_array = tmp;
4069 }
4070 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4071
4072 filter_BSS = false;
4073 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4074 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4075 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4076 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4077 } else if (strstr(line, "freq") != NULL) {
4078 sscanf(line," freq: %d", &freq);
4079 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4080
4081 if (freq >= 2412 && freq <= 2484) {
4082 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4083 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4084 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4085 }
4086 else if (freq >= 5160 && freq <= 5805) {
4087 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4088 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4089 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4090 }
4091
4092 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004093 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004094 for (int i = 0; i < channels_num; i++) {
4095 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4096 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4097 break;
4098 }
4099 }
4100 }
4101 } else if (strstr(line, "beacon interval") != NULL) {
4102 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4103 } else if (strstr(line, "signal") != NULL) {
4104 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4105 } else if (strstr(line,"SSID") != NULL) {
4106 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4107 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4108 filter_BSS = true;
4109 }
4110 } else if (strstr(line, "Supported rates") != NULL) {
4111 char SRate[80] = {0}, *tmp = NULL;
4112 memset(buf, 0, sizeof(buf));
4113 strcpy(SRate, line);
4114 tmp = strtok(SRate, ":");
4115 tmp = strtok(NULL, ":");
4116 strcpy(buf, tmp);
4117 memset(SRate, 0, sizeof(SRate));
4118
4119 tmp = strtok(buf, " \n");
4120 while (tmp != NULL) {
4121 strcat(SRate, tmp);
4122 if (SRate[strlen(SRate) - 1] == '*') {
4123 SRate[strlen(SRate) - 1] = '\0';
4124 }
4125 strcat(SRate, ",");
4126
4127 tmp = strtok(NULL, " \n");
4128 }
4129 SRate[strlen(SRate) - 1] = '\0';
4130 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4131 } else if (strstr(line, "DTIM") != NULL) {
4132 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4133 } else if (strstr(line, "VHT capabilities") != NULL) {
4134 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4135 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4136 } else if (strstr(line, "HT capabilities") != NULL) {
4137 strcat(scan_array[index].ap_SupportedStandards, ",n");
4138 strcpy(scan_array[index].ap_OperatingStandards, "n");
4139 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004140 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004141 sscanf(line," * channel width: %d", &vht_channel_width);
4142 if(vht_channel_width == 1) {
4143 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4144 } else {
4145 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4146 }
4147 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4148 continue;
4149 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004150 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004151 sscanf(line," * secondary channel offset: %s", &buf);
4152 if (!strcmp(buf, "above")) {
4153 //40Mhz +
4154 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4155 }
4156 else if (!strcmp(buf, "below")) {
4157 //40Mhz -
4158 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4159 } else {
4160 //20Mhz
4161 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4162 }
4163 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4164 continue;
4165 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004166 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4167 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4168 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004169 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4170 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004171 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004172 else
developer615510b2022-09-27 10:14:35 +08004173 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004174 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004175 if (strstr(line, "HE80/5GHz") != NULL) {
4176 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4177 ret = fgets(line, sizeof(line), f);
4178 } else
4179 continue;
developera3c68b92022-09-13 15:27:29 +08004180 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004181 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004182 }
developer615510b2022-09-27 10:14:35 +08004183 continue;
developera3c68b92022-09-13 15:27:29 +08004184 } else if (strstr(line, "WPA") != NULL) {
4185 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4186 } else if (strstr(line, "RSN") != NULL) {
4187 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4188 } else if (strstr(line, "Group cipher") != NULL) {
4189 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4190 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4191 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4192 }
4193 }
developer615510b2022-09-27 10:14:35 +08004194 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004195 }
4196
4197 if (!filter_BSS) {
4198 *output_array_size = index + 1;
4199 } else {
4200 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4201 *output_array_size = index;
4202 }
4203 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004204 pclose(f);
developer5550e242022-09-30 09:59:32 +08004205 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004207 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004208}
4209
4210//>> Deprecated: used for old RDKB code.
4211INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4212{
4213 INT status = RETURN_ERR;
4214
4215 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4216 output_struct->wifi_PLCPErrorCount = 0;
4217 output_struct->wifi_FCSErrorCount = 0;
4218 output_struct->wifi_InvalidMACCount = 0;
4219 output_struct->wifi_PacketsOtherReceived = 0;
4220 output_struct->wifi_Noise = 0;
4221 status = RETURN_OK;
4222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4223 return status;
4224}
4225
4226INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4227{
developerd946fd62022-12-08 18:03:28 +08004228 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004229 char cmd[128] = {0};
4230 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004231 char *pos = NULL;
4232
4233 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4234 if (NULL == output_struct)
4235 return RETURN_ERR;
4236
developerac6f1142022-12-20 19:26:35 +08004237 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004238 return RETURN_ERR;
4239
developer06a01d92022-09-07 16:32:39 +08004240 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4241
developerd946fd62022-12-08 18:03:28 +08004242 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004243 _syscmd(cmd, buf, sizeof(buf));
4244
4245 pos = buf;
4246 if ((pos = strstr(pos, "RX packets:")) == NULL)
4247 return RETURN_ERR;
4248 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4249
4250 if ((pos = strstr(pos, "TX packets:")) == NULL)
4251 return RETURN_ERR;
4252 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4253
4254 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4255 return RETURN_ERR;
4256 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4257
4258 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4259 return RETURN_ERR;
4260 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4261
developerd946fd62022-12-08 18:03:28 +08004262 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004263 _syscmd(cmd, buf, sizeof(buf));
4264 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4265
4266#if 0
4267 //TODO: need to revisit below implementation
4268 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4269 char interface_name[MAX_BUF_SIZE] = {0};
4270 char interface_status[MAX_BUF_SIZE] = {0};
4271 char Value[MAX_BUF_SIZE] = {0};
4272 char buf[MAX_CMD_SIZE] = {0};
4273 char cmd[MAX_CMD_SIZE] = {0};
4274 FILE *fp = NULL;
4275
4276 if (NULL == output_struct) {
4277 return RETURN_ERR;
4278 }
4279
4280 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4281
4282 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4283 {
4284 if(apIndex == 0) //private_wifi for 2.4G
4285 {
developerac6f1142022-12-20 19:26:35 +08004286 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004287 }
4288 else if(apIndex == 1) //private_wifi for 5G
4289 {
developerac6f1142022-12-20 19:26:35 +08004290 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004291 }
4292 else if(apIndex == 4) //public_wifi for 2.4G
4293 {
4294 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4295 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4296 {
4297 return RETURN_ERR;
4298 }
4299 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004300 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004301 else//tenda
developerac6f1142022-12-20 19:26:35 +08004302 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004303 }
4304 else if(apIndex == 5) //public_wifi for 5G
4305 {
developerac6f1142022-12-20 19:26:35 +08004306 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004307 }
4308
4309 GetIfacestatus(interface_name, interface_status);
4310
4311 if(0 != strcmp(interface_status, "1"))
4312 return RETURN_ERR;
4313
4314 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4315 system(cmd);
4316
4317 fp = fopen("/tmp/SSID_Stats.txt", "r");
4318 if(fp == NULL)
4319 {
4320 printf("/tmp/SSID_Stats.txt not exists \n");
4321 return RETURN_ERR;
4322 }
4323 fclose(fp);
4324
4325 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4326 File_Reading(buf, Value);
4327 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4328
4329 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4330 File_Reading(buf, Value);
4331 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4332
4333 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4334 File_Reading(buf, Value);
4335 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4336
4337 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4338 File_Reading(buf, Value);
4339 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4340
4341 /* There is no specific parameter from caller to associate the value wifi_Associations */
4342 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4343 //_syscmd(cmd, buf, sizeof(buf));
4344 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4345 }
4346#endif
4347 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4348 return RETURN_OK;
4349}
4350
4351INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4352{
4353 char interface_name[MAX_BUF_SIZE] = {0};
4354 char interface_status[MAX_BUF_SIZE] = {0};
4355 char Value[MAX_BUF_SIZE] = {0};
4356 char buf[MAX_CMD_SIZE] = {0};
4357 char cmd[MAX_CMD_SIZE] = {0};
4358 FILE *fp = NULL;
4359
4360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4361 if (NULL == output_struct)
4362 return RETURN_ERR;
4363
4364 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4365
developerac6f1142022-12-20 19:26:35 +08004366 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004367 return RETURN_ERR;
4368 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004369
developerd946fd62022-12-08 18:03:28 +08004370 if(0 != strcmp(interface_status, "1"))
4371 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004372
developerd946fd62022-12-08 18:03:28 +08004373 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4374 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004375
developerd946fd62022-12-08 18:03:28 +08004376 fp = fopen("/tmp/SSID_Stats.txt", "r");
4377 if(fp == NULL)
4378 {
4379 printf("/tmp/SSID_Stats.txt not exists \n");
4380 return RETURN_ERR;
4381 }
4382 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004383
developerd946fd62022-12-08 18:03:28 +08004384 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4385 File_Reading(buf, Value);
4386 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004387
developerd946fd62022-12-08 18:03:28 +08004388 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4389 File_Reading(buf, Value);
4390 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004391
developerd946fd62022-12-08 18:03:28 +08004392 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4393 File_Reading(buf, Value);
4394 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004395
developerd946fd62022-12-08 18:03:28 +08004396 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4397 File_Reading(buf, Value);
4398 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004399
4400 output_struct->wifi_UnicastPacketsSent = 0;
4401 output_struct->wifi_UnicastPacketsReceived = 0;
4402 output_struct->wifi_MulticastPacketsSent = 0;
4403 output_struct->wifi_MulticastPacketsReceived = 0;
4404 output_struct->wifi_BroadcastPacketsSent = 0;
4405 output_struct->wifi_BroadcastPacketsRecevied = 0;
4406 output_struct->wifi_UnknownPacketsReceived = 0;
4407
4408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4409 return RETURN_OK;
4410}
4411
4412INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4413{
4414 INT status = RETURN_ERR;
4415
4416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4417 //Below values should get updated from hal
4418 output_struct->wifi_RetransCount=0;
4419 output_struct->wifi_FailedRetransCount=0;
4420 output_struct->wifi_RetryCount=0;
4421 output_struct->wifi_MultipleRetryCount=0;
4422 output_struct->wifi_ACKFailureCount=0;
4423 output_struct->wifi_AggregatedPacketCount=0;
4424
4425 status = RETURN_OK;
4426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4427
4428 return status;
4429}
4430
4431INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4432{
4433 INT status = RETURN_ERR;
4434 UINT index;
4435 wifi_neighbor_ap_t *pt=NULL;
4436
4437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4438 *output_array_size=2;
4439 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4440 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4441 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4442 strcpy(pt->ap_Radio,"");
4443 strcpy(pt->ap_SSID,"");
4444 strcpy(pt->ap_BSSID,"");
4445 strcpy(pt->ap_Mode,"");
4446 pt->ap_Channel=1;
4447 pt->ap_SignalStrength=0;
4448 strcpy(pt->ap_SecurityModeEnabled,"");
4449 strcpy(pt->ap_EncryptionMode,"");
4450 strcpy(pt->ap_OperatingFrequencyBand,"");
4451 strcpy(pt->ap_SupportedStandards,"");
4452 strcpy(pt->ap_OperatingStandards,"");
4453 strcpy(pt->ap_OperatingChannelBandwidth,"");
4454 pt->ap_BeaconPeriod=1;
4455 pt->ap_Noise=0;
4456 strcpy(pt->ap_BasicDataTransferRates,"");
4457 strcpy(pt->ap_SupportedDataTransferRates,"");
4458 pt->ap_DTIMPeriod=1;
4459 pt->ap_ChannelUtilization = 1;
4460 }
4461
4462 status = RETURN_OK;
4463 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4464
4465 return status;
4466}
4467
4468//----------------- AP HAL -------------------------------
4469
4470//>> Deprecated: used for old RDKB code.
4471INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4472{
4473 if (NULL == output_ulong || NULL == output_struct)
4474 return RETURN_ERR;
4475 *output_ulong = 0;
4476 *output_struct = NULL;
4477 return RETURN_OK;
4478}
4479
4480#ifdef HAL_NETLINK_IMPL
4481static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4482 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4483 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4484 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4485 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4486 char mac_addr[20];
4487 static int count=0;
4488 int rate=0;
4489
4490 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4491
4492 nla_parse(tb,
4493 NL80211_ATTR_MAX,
4494 genlmsg_attrdata(gnlh, 0),
4495 genlmsg_attrlen(gnlh, 0),
4496 NULL);
4497
4498 if(!tb[NL80211_ATTR_STA_INFO]) {
4499 fprintf(stderr, "sta stats missing!\n");
4500 return NL_SKIP;
4501 }
4502
4503
4504 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4505 fprintf(stderr, "failed to parse nested attributes!\n");
4506 return NL_SKIP;
4507 }
4508
4509 //devIndex starts from 1
4510 if( ++count == out->wifi_devIndex )
4511 {
4512 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4513 //Getting the mac addrress
4514 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4515
4516 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4517 fprintf(stderr, "failed to parse nested rate attributes!");
4518 return NL_SKIP;
4519 }
4520
4521 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4522 if(rinfo[NL80211_RATE_INFO_BITRATE])
4523 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4524 out->wifi_devTxRate = rate/10;
4525 }
4526
4527 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4528 fprintf(stderr, "failed to parse nested rate attributes!");
4529 return NL_SKIP;
4530 }
4531
4532 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4533 if(rinfo[NL80211_RATE_INFO_BITRATE])
4534 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4535 out->wifi_devRxRate = rate/10;
4536 }
4537 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4538 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4539
4540 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4541 count = 0; //starts the count for next cycle
4542 return NL_STOP;
4543 }
4544
4545 return NL_SKIP;
4546
4547}
4548#endif
4549
4550INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4551{
4552#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004553 Netlink nl = {0};
4554 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004555 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004556
developer30423732022-12-01 16:17:49 +08004557 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004558 info.wifi_devIndex = devIndex;
4559
developerac6f1142022-12-20 19:26:35 +08004560 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004561 return RETURN_ERR;
4562
4563 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004564
4565 nl.id = initSock80211(&nl);
4566
4567 if (nl.id < 0) {
4568 fprintf(stderr, "Error initializing netlink \n");
4569 return -1;
4570 }
4571
4572 struct nl_msg* msg = nlmsg_alloc();
4573
4574 if (!msg) {
4575 fprintf(stderr, "Failed to allocate netlink message.\n");
4576 nlfree(&nl);
4577 return -2;
4578 }
4579
4580 genlmsg_put(msg,
4581 NL_AUTO_PORT,
4582 NL_AUTO_SEQ,
4583 nl.id,
4584 0,
4585 NLM_F_DUMP,
4586 NL80211_CMD_GET_STATION,
4587 0);
4588
4589 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4590 nl_send_auto(nl.socket, msg);
4591 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4592 nl_recvmsgs(nl.socket, nl.cb);
4593 nlmsg_free(msg);
4594 nlfree(&nl);
4595
4596 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4597 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4598 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4599 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4600 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4601 return RETURN_OK;
4602#else
4603 //iw utility to retrieve station information
4604#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4605#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4606#define MACFILE "/tmp/wifi_AssoMac.txt"
4607#define TXRATEFILE "/tmp/wifi_txrate.txt"
4608#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4609 FILE *file = NULL;
4610 char if_name[10] = {'\0'};
4611 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004612 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004613 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004614 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004615
developerac6f1142022-12-20 19:26:35 +08004616 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004617 return RETURN_ERR;
4618
4619 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004620
4621 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4622 file = popen(pipeCmd, "r");
4623
4624 if(file == NULL)
4625 return RETURN_ERR; //popen failed
4626
4627 fgets(line, sizeof line, file);
4628 device = atoi(line);
4629 pclose(file);
4630
4631 if(device == 0)
4632 return RETURN_ERR; //No devices are connected
4633
4634 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4635 system(pipeCmd);
4636
4637 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4638
4639 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4640
4641 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4642
4643 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4644
4645 //devIndex starts from 1, ++count
4646 if((file = fopen(SIGNALFILE, "r")) != NULL )
4647 {
4648 for(count =0;fgets(line, sizeof line, file) != NULL;)
4649 {
4650 if (++count == devIndex)
4651 {
4652 output_struct->wifi_devSignalStrength = atoi(line);
4653 break;
4654 }
4655 }
4656 fclose(file);
4657 }
4658 else
4659 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4660
4661 if((file = fopen(MACFILE, "r")) != NULL )
4662 {
4663 for(count =0;fgets(line, sizeof line, file) != NULL;)
4664 {
4665 if (++count == devIndex)
4666 {
4667 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]);
4668 break;
4669 }
4670 }
4671 fclose(file);
4672 }
4673 else
4674 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4675
4676 if((file = fopen(TXRATEFILE, "r")) != NULL )
4677 {
4678 for(count =0;fgets(line, sizeof line, file) != NULL;)
4679 {
4680 if (++count == devIndex)
4681 {
4682 output_struct->wifi_devTxRate = atoi(line);
4683 break;
4684 }
4685 }
4686 fclose(file);
4687 }
4688 else
4689 fprintf(stderr,"fopen wifi_txrate.txt failed");
4690
4691 if((file = fopen(RXRATEFILE, "r")) != NULL)
4692 {
4693 for(count =0;fgets(line, sizeof line, file) != NULL;)
4694 {
4695 if (++count == devIndex)
4696 {
4697 output_struct->wifi_devRxRate = atoi(line);
4698 break;
4699 }
4700 }
4701 fclose(file);
4702 }
4703 else
4704 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4705
4706 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4707
4708 return RETURN_OK;
4709#endif
4710}
4711
4712INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4713{
4714 if (NULL == device)
4715 return RETURN_ERR;
4716 return RETURN_OK;
4717}
4718//<<
4719
4720
4721//--------------wifi_ap_hal-----------------------------
4722//enables CTS protection for the radio used by this AP
4723INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4724{
4725 //save config and Apply instantly
4726 return RETURN_ERR;
4727}
4728
4729// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4730INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4731{
developer463d39a2022-09-13 15:32:51 +08004732 char config_file[64] = {'\0'};
4733 char buf[64] = {'\0'};
4734 struct params list;
4735
4736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4737 list.name = "ht_coex";
4738 snprintf(buf, sizeof(buf), "%d", enable);
4739 list.value = buf;
4740
4741 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4742 wifi_hostapdWrite(config_file, &list, 1);
4743 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4744
4745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4746
4747 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004748}
4749
4750//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4751INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4752{
developerea4bcce2022-09-13 15:26:13 +08004753 char config_file[MAX_BUF_SIZE] = {'\0'};
4754 char buf[MAX_BUF_SIZE] = {'\0'};
4755 struct params list;
4756
4757 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4758 if (threshold < 256 || threshold > 2346 )
4759 return RETURN_ERR;
4760 list.name = "fragm_threshold";
4761 snprintf(buf, sizeof(buf), "%d", threshold);
4762 list.value = buf;
4763
4764 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4765 wifi_hostapdWrite(config_file, &list, 1);
4766 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004767
developerea4bcce2022-09-13 15:26:13 +08004768 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004769
4770 return RETURN_OK;
4771}
4772
4773// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4774INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4775{
developer51a927d2022-09-13 15:42:22 +08004776 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004777 char cmd[512] = {'\0'};
4778 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004779 char stbc_config[16] = {'\0'};
4780 wifi_band band;
4781 int iterator = 0;
4782 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004783 int ant_count = 0;
4784 int ant_bitmap = 0;
4785 struct params list;
developer51a927d2022-09-13 15:42:22 +08004786
4787 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4788
4789 band = wifi_index_to_band(radioIndex);
4790 if (band == band_invalid)
4791 return RETURN_ERR;
4792
4793 if (band == band_2_4)
4794 iterator = 1;
4795 else if (band == band_5)
4796 iterator = 2;
4797 else
4798 return RETURN_OK;
4799
developer110b8a32022-12-26 15:56:44 +08004800 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4801 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4802 ant_count += ant_bitmap & 1;
4803
4804 if (ant_count == 1 && STBC_Enable == TRUE) {
4805 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4806 return RETURN_OK;
4807 }
4808
developer51a927d2022-09-13 15:42:22 +08004809 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4810
4811 // set ht and vht config
4812 for (int i = 0; i < iterator; i++) {
4813 memset(stbc_config, 0, sizeof(stbc_config));
4814 memset(cmd, 0, sizeof(cmd));
4815 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004816 list.name = (i == 0)?"ht_capab":"vht_capab";
4817 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004818 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4819 _syscmd(cmd, buf, sizeof(buf));
4820 if (strlen(buf) != 0)
4821 current_stbc = TRUE;
4822 if (current_stbc == STBC_Enable)
4823 continue;
4824
4825 if (STBC_Enable == TRUE) {
4826 // Append the STBC flags in capab config
4827 memset(cmd, 0, sizeof(cmd));
4828 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004829 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004830 else
developer6372c2b2022-10-27 17:39:51 +08004831 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 +08004832 _syscmd(cmd, buf, sizeof(buf));
4833 } else if (STBC_Enable == FALSE) {
4834 // Remove the STBC flags and remain other flags in capab
4835 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004836 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004837 _syscmd(cmd, buf, sizeof(buf));
4838 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004839 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004840 _syscmd(cmd, buf, sizeof(buf));
4841 }
developer110b8a32022-12-26 15:56:44 +08004842 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4843 list.value = buf;
4844 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004845 }
4846
4847 wifi_reloadAp(radioIndex);
4848
4849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4850 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004851}
4852
4853// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4854INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4855{
developerfe7aefc2022-12-23 17:13:37 +08004856 char cmd[128] = {0};
4857 char buf[128] = {0};
4858 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004859
4860 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4861
4862 if(output_bool == NULL)
4863 return RETURN_ERR;
4864
developerfe7aefc2022-12-23 17:13:37 +08004865 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4866 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004867
developerfe7aefc2022-12-23 17:13:37 +08004868 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4869 _syscmd(cmd, buf, sizeof(buf));
4870
4871 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004872 *output_bool = TRUE;
4873 else
4874 *output_bool = FALSE;
4875
4876 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4877 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004878}
4879
4880// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4881INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4882{
developerfe7aefc2022-12-23 17:13:37 +08004883 char config_file[128] = {0};
4884 struct params list = {0};
4885 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004886
4887 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4888
developerfe7aefc2022-12-23 17:13:37 +08004889 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004890 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004891
developerfe7aefc2022-12-23 17:13:37 +08004892 if (amsduEnable == enable)
4893 return RETURN_OK;
4894
4895 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4896 list.name = "amsdu";
4897 list.value = amsduEnable? "1":"0";
4898 wifi_hostapdWrite(config_file, &list, 1);
4899 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4900 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004901
4902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4903 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004904}
4905
4906//P2 // outputs the number of Tx streams
4907INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4908{
developer2de97692022-09-26 14:00:03 +08004909 char buf[8] = {0};
4910 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004911 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004912
4913 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4914
developer033b37b2022-10-18 11:27:46 +08004915 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004916 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004917 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004918
developer110b8a32022-12-26 15:56:44 +08004919 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004920
4921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4922
4923 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004924}
4925
developer110b8a32022-12-26 15:56:44 +08004926INT fitChainMask(INT radioIndex, int antcount)
4927{
4928 char buf[128] = {0};
4929 char cmd[128] = {0};
4930 char config_file[64] = {0};
4931 wifi_band band;
4932 struct params list[2] = {0};
4933
4934 band = wifi_index_to_band(radioIndex);
4935 if (band == band_invalid)
4936 return RETURN_ERR;
4937
4938 list[0].name = "he_mu_beamformer";
4939 list[1].name = "he_su_beamformer";
4940
4941 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4942 if (antcount == 1) {
4943 // remove config about multiple antennas
4944 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4945 _syscmd(cmd, buf, sizeof(buf));
4946
4947 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4948 _syscmd(cmd, buf, sizeof(buf));
4949
4950 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4951 _syscmd(cmd, buf, sizeof(buf));
4952
4953 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4954 _syscmd(cmd, buf, sizeof(buf));
4955
4956 list[0].value = "0";
4957 list[1].value = "0";
4958 } else {
4959 // 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.
4960 if (band == band_2_4 || band == band_5) {
4961 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4962 _syscmd(cmd, buf, sizeof(buf));
4963 if (strlen(buf) > 0) {
4964 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4965 _syscmd(cmd, buf, sizeof(buf));
4966 }
4967 }
4968 if (band == band_5) {
4969 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4970 _syscmd(cmd, buf, sizeof(buf));
4971 if (strlen(buf) > 0) {
4972 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4973 _syscmd(cmd, buf, sizeof(buf));
4974 }
4975 }
4976
4977 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4978 _syscmd(cmd, buf, sizeof(buf));
4979 if (strlen(buf) == 0) {
4980 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4981 _syscmd(cmd, buf, sizeof(buf));
4982 }
4983
4984 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4985 _syscmd(cmd, buf, sizeof(buf));
4986 if (strlen(buf) == 0) {
4987 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4988 _syscmd(cmd, buf, sizeof(buf));
4989 }
4990
4991 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4992 _syscmd(cmd, buf, sizeof(buf));
4993 if (strlen(buf) == 0) {
4994 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4995 } else {
4996 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4997 }
4998 _syscmd(cmd, buf, sizeof(buf));
4999
5000 list[0].value = "1";
5001 list[1].value = "1";
5002 }
5003 wifi_hostapdWrite(config_file, list, 2);
5004}
5005
developer06a01d92022-09-07 16:32:39 +08005006//P2 // sets the number of Tx streams to an enviornment variable
5007INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5008{
developer2de97692022-09-26 14:00:03 +08005009 char cmd[128] = {0};
5010 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08005011 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08005012 int cur_mask = 0;
5013 int antcount = 0;
5014 wifi_band band;
developer2de97692022-09-26 14:00:03 +08005015
5016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5017
developer110b8a32022-12-26 15:56:44 +08005018 if (numStreams <= 0) {
5019 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08005020 return RETURN_ERR;
5021 }
developer110b8a32022-12-26 15:56:44 +08005022
5023 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5024 if (cur_mask == numStreams)
5025 return RETURN_OK;
5026
developer2de97692022-09-26 14:00:03 +08005027 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08005028
5029 phyId = radio_index_to_phy(radioIndex);
5030 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08005031 _syscmd(cmd, buf, sizeof(buf));
5032
5033 if (strlen(buf) > 0) {
5034 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5035 return RETURN_ERR;
5036 }
developer2de97692022-09-26 14:00:03 +08005037
developer110b8a32022-12-26 15:56:44 +08005038 // if chain mask changed, we need to make the hostapd config valid.
5039 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5040 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08005041 }
developer110b8a32022-12-26 15:56:44 +08005042 fitChainMask(radioIndex, antcount);
5043
5044 wifi_setRadioEnable(radioIndex, TRUE);
5045
developer2de97692022-09-26 14:00:03 +08005046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5047 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005048}
5049
5050//P2 // outputs the number of Rx streams
5051INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5052{
developer110b8a32022-12-26 15:56:44 +08005053 char buf[8] = {0};
5054 char cmd[128] = {0};
5055 int phyId = 0;
5056
developer2de97692022-09-26 14:00:03 +08005057 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005058
5059 phyId = radio_index_to_phy(radioIndex);
5060 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5061 _syscmd(cmd, buf, sizeof(buf));
5062
5063 *output_int = (INT)strtol(buf, NULL, 16);
5064
developer2de97692022-09-26 14:00:03 +08005065 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005066
developer06a01d92022-09-07 16:32:39 +08005067 return RETURN_OK;
5068}
5069
5070//P2 // sets the number of Rx streams to an enviornment variable
5071INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5072{
developer2de97692022-09-26 14:00:03 +08005073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5074 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5075 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5076 return RETURN_ERR;
5077 }
5078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005079 return RETURN_ERR;
5080}
5081
5082//Get radio RDG enable setting
5083INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5084{
5085 if (NULL == output_bool)
5086 return RETURN_ERR;
5087 *output_bool = TRUE;
5088 return RETURN_OK;
5089}
5090
5091//Get radio RDG enable setting
5092INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5093{
5094 if (NULL == output_bool)
5095 return RETURN_ERR;
5096 *output_bool = TRUE;
5097 return RETURN_OK;
5098}
5099
5100//Set radio RDG enable setting
5101INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5102{
5103 return RETURN_ERR;
5104}
5105
5106//Get radio ADDBA enable setting
5107INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5108{
5109 if (NULL == output_bool)
5110 return RETURN_ERR;
5111 *output_bool = TRUE;
5112 return RETURN_OK;
5113}
5114
5115//Set radio ADDBA enable setting
5116INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5117{
5118 return RETURN_ERR;
5119}
5120
5121//Get radio auto block ack enable setting
5122INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5123{
5124 if (NULL == output_bool)
5125 return RETURN_ERR;
5126 *output_bool = TRUE;
5127 return RETURN_OK;
5128}
5129
5130//Set radio auto block ack enable setting
5131INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5132{
5133 return RETURN_ERR;
5134}
5135
5136//Get radio 11n pure mode enable support
5137INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5138{
5139 if (NULL == output_bool)
5140 return RETURN_ERR;
5141 *output_bool = TRUE;
5142 return RETURN_OK;
5143}
5144
5145//Get radio 11n pure mode enable setting
5146INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5147{
5148 if (NULL == output_bool)
5149 return RETURN_ERR;
5150 *output_bool = TRUE;
5151 return RETURN_OK;
5152}
5153
5154//Set radio 11n pure mode enable setting
5155INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5156{
5157 return RETURN_ERR;
5158}
5159
5160//Get radio IGMP snooping enable setting
5161INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5162{
developerd946fd62022-12-08 18:03:28 +08005163 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005164 char cmd[128]={0};
5165 char buf[4]={0};
5166 bool bridge = FALSE, mac80211 = FALSE;
5167 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5168
5169 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005170 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005171
5172 *output_bool = FALSE;
5173
5174 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5175 _syscmd(cmd, buf, sizeof(buf));
5176 if (strncmp(buf, "1", 1) == 0)
5177 bridge = TRUE;
5178
developerac6f1142022-12-20 19:26:35 +08005179 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005180 return RETURN_ERR;
5181 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 +08005182 _syscmd(cmd, buf, sizeof(buf));
5183 if (strncmp(buf, "1", 1) == 0)
5184 mac80211 = TRUE;
5185
5186 if (bridge && mac80211)
5187 *output_bool = TRUE;
5188
5189 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005190 return RETURN_OK;
5191}
5192
5193//Set radio IGMP snooping enable setting
5194INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5195{
developerd946fd62022-12-08 18:03:28 +08005196 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005197 char cmd[128]={0};
5198 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005199 int max_num_radios = 0;
5200 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5202
5203 // bridge
developerfb09ba62023-06-09 17:03:21 +08005204 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005205 _syscmd(cmd, buf, sizeof(buf));
5206
developer804c64f2022-10-19 13:54:40 +08005207 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005208 // mac80211
developer894affa2023-05-10 18:13:19 +08005209 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5210 apIndex = radioIndex + i*max_num_radios;
5211 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5212 continue;
developerfb09ba62023-06-09 17:03:21 +08005213 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 +08005214 _syscmd(cmd, buf, sizeof(buf));
5215 }
5216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5217 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005218}
5219
5220//Get the Reset count of radio
5221INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5222{
5223 if (NULL == output_int)
5224 return RETURN_ERR;
5225 *output_int = (radioIndex==0)? 1: 3;
5226
5227 return RETURN_OK;
5228}
5229
5230
5231//---------------------------------------------------------------------------------------------------
5232//
5233// Additional Wifi AP level APIs used for Access Point devices
5234//
5235//---------------------------------------------------------------------------------------------------
5236
5237// creates a new ap and pushes these parameters to the hardware
5238INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5239{
developer7930d352022-12-21 17:55:42 +08005240 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005241 return RETURN_OK;
5242}
5243
5244// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5245INT wifi_deleteAp(INT apIndex)
5246{
developerd946fd62022-12-08 18:03:28 +08005247 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005248 char buf[128] = {0};
5249 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005250
developerac6f1142022-12-20 19:26:35 +08005251 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005252 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005253
developer89df4502023-02-16 20:45:02 +08005254 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5255 return RETURN_ERR;
5256
developer7930d352022-12-21 17:55:42 +08005257 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005258 _syscmd(cmd, buf, sizeof(buf));
5259
5260 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005261 return RETURN_OK;
5262}
5263
5264// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5265INT wifi_getApName(INT apIndex, CHAR *output_string)
5266{
developerd946fd62022-12-08 18:03:28 +08005267 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005268 if(NULL == output_string)
5269 return RETURN_ERR;
5270
developerac6f1142022-12-20 19:26:35 +08005271 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005272 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005273 else
5274 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005275 return RETURN_OK;
5276}
5277
5278// Outputs the index number in that corresponds to the SSID string
5279INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5280{
developerd946fd62022-12-08 18:03:28 +08005281 char cmd [128] = {0};
5282 char buf[32] = {0};
5283 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005284 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005285
developerefb790a2023-12-26 18:58:32 +08005286#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +08005287 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5288 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005289
developerac6f1142022-12-20 19:26:35 +08005290 if (strlen(buf) != 0) {
5291 apIndex_str = strtok(buf, "\n");
5292 *output_int = strtoul(apIndex_str, NULL, 10);
5293 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005294 }
developerefb790a2023-12-26 18:58:32 +08005295#endif
developer67b8ee92022-12-20 10:48:43 +08005296 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5297 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5298 if (apIndex_str) {
5299 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5300 return RETURN_OK;
5301 }
developerd946fd62022-12-08 18:03:28 +08005302 *output_int = -1;
5303 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005304}
5305
5306INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5307{
5308 return wifi_getIndexFromName(inputSsidString, output_int);
5309}
5310
5311// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5312INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5313{
5314 char buf[MAX_BUF_SIZE] = {0};
5315 char cmd[MAX_CMD_SIZE] = {0};
5316 char config_file[MAX_BUF_SIZE] = {0};
5317
5318 if(NULL == output_string)
5319 return RETURN_ERR;
5320
5321 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005322 if (!syn_flag)
5323 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5324 else
developer07ded1f2024-01-10 10:30:15 +08005325 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005326 if((strcmp(buf,"3")==0))
5327 snprintf(output_string, 32, "WPAand11i");
5328 else if((strcmp(buf,"2")==0))
5329 snprintf(output_string, 32, "11i");
5330 else if((strcmp(buf,"1")==0))
5331 snprintf(output_string, 32, "WPA");
5332 else
5333 snprintf(output_string, 32, "None");
5334
5335 return RETURN_OK;
5336}
5337
5338// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5339INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5340{
5341 char config_file[MAX_BUF_SIZE] = {0};
5342 struct params list;
5343
5344 if (NULL == beaconTypeString)
5345 return RETURN_ERR;
5346 list.name = "wpa";
5347 list.value = "0";
5348
5349 if((strcmp(beaconTypeString,"WPAand11i")==0))
5350 list.value="3";
5351 else if((strcmp(beaconTypeString,"11i")==0))
5352 list.value="2";
5353 else if((strcmp(beaconTypeString,"WPA")==0))
5354 list.value="1";
5355
5356 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5357 wifi_hostapdWrite(config_file, &list, 1);
5358 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developerefb790a2023-12-26 18:58:32 +08005359 snprintf(vap_info[apIndex].wpa, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08005360 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5361 return RETURN_OK;
5362}
5363
5364// sets the beacon interval on the hardware for this AP
5365INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5366{
developer5f222492022-09-13 15:21:52 +08005367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5368 struct params params={'\0'};
5369 char buf[MAX_BUF_SIZE] = {'\0'};
5370 char config_file[MAX_BUF_SIZE] = {'\0'};
5371
5372 params.name = "beacon_int";
5373 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5374 params.value = buf;
5375
5376 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5377 wifi_hostapdWrite(config_file, &params, 1);
5378
5379 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5381 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005382}
5383
5384INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5385{
developer5b398df2022-11-17 20:39:48 +08005386 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5387 return RETURN_ERR;
5388 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005389}
5390
5391// Get the packet size threshold supported.
5392INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5393{
5394 //save config and apply instantly
5395 if (NULL == output_bool)
5396 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005397 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005398 return RETURN_OK;
5399}
5400
5401// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5402INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5403{
developer514406b2022-12-05 17:20:21 +08005404 char buf[16] = {0};
5405 char config_file[128] = {0};
5406 struct params param = {0};
5407
5408 if (threshold > 65535) {
5409 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5410 return RETURN_ERR;
5411 }
developer06a01d92022-09-07 16:32:39 +08005412
developer23e71282023-01-18 10:25:19 +08005413 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005414 snprintf(buf, sizeof(buf), "%u", threshold);
5415 param.name = "rts_threshold";
5416 param.value = buf;
5417 wifi_hostapdWrite(config_file, &param, 1);
5418 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5419 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005420
5421 return RETURN_OK;
5422}
5423
5424// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5425INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5426{
5427 if (NULL == output_string)
5428 return RETURN_ERR;
5429 snprintf(output_string, 32, "TKIPandAESEncryption");
5430 return RETURN_OK;
5431
5432}
5433
5434// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5435INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5436{
5437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005438 char *param_name = NULL;
5439 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005440
5441 if(NULL == output_string)
5442 return RETURN_ERR;
5443
5444 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005445 if (!syn_flag)
5446 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5447 else
developer07ded1f2024-01-10 10:30:15 +08005448 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005449
5450 if(strcmp(buf,"0")==0)
5451 {
5452 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5453 snprintf(output_string, 32, "None");
5454 return RETURN_OK;
5455 }
5456 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5457 param_name = "rsn_pairwise";
5458 else if((strcmp(buf,"1")==0))
5459 param_name = "wpa_pairwise";
5460 else
5461 return RETURN_ERR;
5462 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005463 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005464 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5465 param_name = "wpa_pairwise";
5466 memset(output_string, '\0', 32);
5467 wifi_hostapdRead(config_file, param_name, output_string, 32);
5468 }
developer06a01d92022-09-07 16:32:39 +08005469 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5470
developer72ec5572023-01-05 16:27:13 +08005471 if(strcmp(output_string,"TKIP CCMP") == 0)
5472 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5473 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005474 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5475 else if(strcmp(output_string,"CCMP") == 0)
5476 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005477
5478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5479 return RETURN_OK;
5480}
5481
5482// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5483INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5484{
5485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5486 struct params params={'\0'};
5487 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005488 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005489
5490 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005491 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005492
5493 if(strcmp(encMode, "TKIPEncryption") == 0)
5494 params.value = "TKIP";
5495 else if(strcmp(encMode,"AESEncryption") == 0)
5496 params.value = "CCMP";
5497 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5498 params.value = "TKIP CCMP";
5499
5500 if((strcmp(output_string,"WPAand11i")==0))
5501 {
5502 params.name = "wpa_pairwise";
5503 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5504 wifi_hostapdWrite(config_file, &params, 1);
5505 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5506
developer30423732022-12-01 16:17:49 +08005507 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005508 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5509 wifi_hostapdWrite(config_file, &params, 1);
5510 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5511
5512 return RETURN_OK;
5513 }
5514 else if((strcmp(output_string,"11i")==0))
5515 {
5516 params.name = "rsn_pairwise";
5517 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5518 wifi_hostapdWrite(config_file, &params, 1);
5519 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5520 return RETURN_OK;
5521 }
5522 else if((strcmp(output_string,"WPA")==0))
5523 {
5524 params.name = "wpa_pairwise";
5525 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5526 wifi_hostapdWrite(config_file, &params, 1);
5527 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5528 return RETURN_OK;
5529 }
5530
5531 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5532 return RETURN_OK;
5533}
5534
5535// deletes internal security varable settings for this ap
5536INT wifi_removeApSecVaribles(INT apIndex)
5537{
5538 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005539 //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 +08005540 //_syscmd(cmd, buf, sizeof(buf));
5541
developerd946fd62022-12-08 18:03:28 +08005542 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005543 //_syscmd(cmd, buf, sizeof(buf));
5544 return RETURN_ERR;
5545}
5546
5547// changes the hardware settings to disable encryption on this ap
5548INT wifi_disableApEncryption(INT apIndex)
5549{
5550 //Apply instantly
5551 return RETURN_ERR;
5552}
5553
5554// set the authorization mode on this ap
5555// mode mapping as: 1: open, 2: shared, 4:auto
5556INT wifi_setApAuthMode(INT apIndex, INT mode)
5557{
developeraf95c502022-09-13 16:18:22 +08005558 struct params params={0};
5559 char config_file[64] = {0};
5560 int ret;
5561
5562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5563
5564 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5565 params.name = "auth_algs";
5566
developer72ec5572023-01-05 16:27:13 +08005567 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005568 params.value = "3";
5569 else if (mode & 2)
5570 params.value = "2";
5571 else if (mode & 1)
5572 params.value = "1";
5573 else
5574 params.value = "0";
5575
5576 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5577 wifi_hostapdWrite(config_file, &params, 1);
5578 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005579 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5581
5582 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005583}
5584
5585// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5586INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5587{
5588 //save to wifi config, and wait for wifi restart to apply
5589 struct params params={'\0'};
5590 char config_file[MAX_BUF_SIZE] = {0};
5591 int ret;
5592
5593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5594 if(authMode == NULL)
5595 return RETURN_ERR;
5596
5597 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5598 params.name = "wpa_key_mgmt";
5599
5600 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5601 params.value = "WPA-PSK";
5602 else if(strcmp(authMode,"EAPAuthentication") == 0)
5603 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005604 else if (strcmp(authMode, "SAEAuthentication") == 0)
5605 params.value = "SAE";
5606 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5607 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005608 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5609 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005610 else if (strcmp(authMode, "Enhanced_Open") == 0)
5611 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005612 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5613 return RETURN_OK; //This is taken careof in beaconType
5614
5615 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5616 ret=wifi_hostapdWrite(config_file,&params,1);
5617 if(!ret)
5618 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
developerefb790a2023-12-26 18:58:32 +08005619 snprintf(vap_info[apIndex].wpa_key_mgmt, MAX_BUF_SIZE, "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08005620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5621
5622 return ret;
5623}
5624
5625// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5626INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5627{
5628 //save to wifi config, and wait for wifi restart to apply
5629 char BeaconType[50] = {0};
5630 char config_file[MAX_BUF_SIZE] = {0};
5631
5632 *authMode = 0;
5633 wifi_getApBeaconType(apIndex,BeaconType);
5634 printf("%s____%s \n",__FUNCTION__,BeaconType);
5635
5636 if(strcmp(BeaconType,"None") == 0)
5637 strcpy(authMode,"None");
5638 else
5639 {
5640 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005641 if (!syn_flag)
5642 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5643 else
developer07ded1f2024-01-10 10:30:15 +08005644 snprintf(authMode, 32, "%s", vap_info[apIndex].wpa_key_mgmt);
developer06a01d92022-09-07 16:32:39 +08005645 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5646 if(strcmp(authMode,"WPA-PSK") == 0)
5647 strcpy(authMode,"SharedAuthentication");
5648 else if(strcmp(authMode,"WPA-EAP") == 0)
5649 strcpy(authMode,"EAPAuthentication");
5650 }
5651
5652 return RETURN_OK;
5653}
5654
5655// Outputs the number of stations associated per AP
5656INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5657{
developerd946fd62022-12-08 18:03:28 +08005658 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005659 char cmd[128]={0};
5660 char buf[128]={0};
5661 BOOL status = false;
5662
5663 if(apIndex > MAX_APS)
5664 return RETURN_ERR;
5665
5666 wifi_getApEnable(apIndex,&status);
5667 if (!status)
5668 return RETURN_OK;
5669
developerd946fd62022-12-08 18:03:28 +08005670 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005671 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005672 return RETURN_ERR;
5673 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005674 _syscmd(cmd, buf, sizeof(buf));
5675 sscanf(buf,"%lu", output_ulong);
5676
5677 return RETURN_OK;
5678}
5679
5680// manually removes any active wi-fi association with the device specified on this ap
5681INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5682{
developerd946fd62022-12-08 18:03:28 +08005683 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005684 char buf[126]={'\0'};
5685
developerac6f1142022-12-20 19:26:35 +08005686 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005687 return RETURN_ERR;
5688 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005689 system(buf);
5690
5691 return RETURN_OK;
5692}
5693
5694// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5695INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5696{
5697 if(NULL == output_int)
5698 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005699 int max_radio_num = 0;
5700 wifi_getMaxRadioNumber(&max_radio_num);
5701 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005702 return RETURN_OK;
5703}
5704
5705// sets the radio index for the specific ap
5706INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5707{
5708 //set to config only and wait for wifi reset to apply settings
5709 return RETURN_ERR;
5710}
5711
5712// Get the ACL MAC list per AP
5713INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5714{
developerd946fd62022-12-08 18:03:28 +08005715 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005716 char cmd[MAX_CMD_SIZE]={'\0'};
5717 int ret = 0;
5718
developerac6f1142022-12-20 19:26:35 +08005719 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005720 return RETURN_ERR;
5721 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005722 ret = _syscmd(cmd,macArray,buf_size);
5723 if (ret != 0)
5724 return RETURN_ERR;
5725
5726 return RETURN_OK;
5727}
5728
developere6aafda2022-09-13 14:59:28 +08005729INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5730{
developerd946fd62022-12-08 18:03:28 +08005731 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005732 char cmd[MAX_CMD_SIZE]={'\0'};
5733 int ret = 0;
5734
developerac6f1142022-12-20 19:26:35 +08005735 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005736 return RETURN_ERR;
5737 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005738 ret = _syscmd(cmd,macArray,buf_size);
5739 if (ret != 0)
5740 return RETURN_ERR;
5741
5742 return RETURN_OK;
5743}
5744
developer06a01d92022-09-07 16:32:39 +08005745// Get the list of stations associated per AP
5746INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5747{
developerd946fd62022-12-08 18:03:28 +08005748 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005749 char cmd[128];
5750
5751 if(apIndex > 3) //Currently supporting apIndex upto 3
5752 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005753 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005754 return RETURN_ERR;
5755 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5756 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005757 _syscmd(cmd, macArray, buf_size);
5758
5759 return RETURN_OK;
5760}
5761
developer2f995fb2023-02-24 10:40:44 +08005762INT getAddressControlMode(INT apIndex, INT *mode)
5763{
5764 char buf [16] = {0};
5765 char config_file[64] = {0};
5766
5767 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08005768 if (!syn_flag)
5769 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5770 else
developer07ded1f2024-01-10 10:30:15 +08005771 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer2f995fb2023-02-24 10:40:44 +08005772
5773 *mode = -1;
5774 // 0 use deny file, 1 use accept file
5775 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5776 *mode = (INT)strtol(buf, NULL, 10);
5777
5778 return RETURN_OK;
5779}
5780
developer06a01d92022-09-07 16:32:39 +08005781// adds the mac address to the filter list
5782//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5783INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5784{
5785 char cmd[MAX_CMD_SIZE]={'\0'};
5786 char buf[MAX_BUF_SIZE]={'\0'};
5787
developer2f995fb2023-02-24 10:40:44 +08005788 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005789 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005790
developer06a01d92022-09-07 16:32:39 +08005791 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5792 if(_syscmd(cmd,buf,sizeof(buf)))
5793 return RETURN_ERR;
5794
5795 return RETURN_OK;
5796}
5797
developer2f995fb2023-02-24 10:40:44 +08005798INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5799{
5800 char cmd[MAX_CMD_SIZE]={'\0'};
5801 char buf[MAX_BUF_SIZE]={'\0'};
5802
5803 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5804 return RETURN_ERR;
5805
5806 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5807 if(_syscmd(cmd,buf,sizeof(buf)))
5808 return RETURN_ERR;
5809
5810 return RETURN_OK;
5811}
5812
developer06a01d92022-09-07 16:32:39 +08005813// deletes the mac address from the filter list
5814//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5815INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5816{
5817 char cmd[MAX_CMD_SIZE]={'\0'};
5818 char buf[MAX_BUF_SIZE]={'\0'};
5819
5820#if 0
developerd946fd62022-12-08 18:03:28 +08005821 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005822 if(_syscmd(cmd,buf,sizeof(buf)))
5823 return RETURN_ERR;
5824
5825#endif
developer2f995fb2023-02-24 10:40:44 +08005826 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005827 if(_syscmd(cmd,buf,sizeof(buf)))
5828 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005829 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5830 if(_syscmd(cmd,buf,sizeof(buf)))
5831 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005832
5833 return RETURN_OK;
5834}
5835
5836// outputs the number of devices in the filter list
5837INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5838{
developere6aafda2022-09-13 14:59:28 +08005839 char cmd[MAX_BUF_SIZE]={0};
5840 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005841 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005842
5843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5844 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005845 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005846
developer2f995fb2023-02-24 10:40:44 +08005847 getAddressControlMode(apIndex, &mode);
5848 if (mode == -1)
5849 return RETURN_OK;
5850
5851 if (mode == 0)
5852 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5853 else if (mode == 1)
5854 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005855 _syscmd(cmd, buf, sizeof(buf));
5856
developer2f995fb2023-02-24 10:40:44 +08005857 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005858
5859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5860 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005861}
5862
5863INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5864{
5865 char cmd[128]={'\0'};
5866 char buf[128]={'\0'};
5867
5868 if(strcmp(action,"DENY")==0)
5869 {
5870 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5871 system(buf);
5872 return RETURN_OK;
5873 }
5874
5875 if(strcmp(action,"ALLOW")==0)
5876 {
5877 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5878 system(buf);
5879 return RETURN_OK;
5880 }
5881
5882 return RETURN_ERR;
5883
5884}
5885
5886// enable kick for devices on acl black list
5887INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5888{
5889 char aclArray[512] = {0}, *acl = NULL;
5890 char assocArray[512] = {0}, *asso = NULL;
5891
developere6aafda2022-09-13 14:59:28 +08005892 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005893 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5894
5895 // if there are no devices connected there is nothing to do
5896 if (strlen(assocArray) < 17)
5897 return RETURN_OK;
5898
5899 if (enable == TRUE)
5900 {
5901 //kick off the MAC which is in ACL array (deny list)
5902 acl = strtok(aclArray, "\r\n");
5903 while (acl != NULL) {
5904 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5905 wifi_kickApAssociatedDevice(apIndex, acl);
5906
5907 acl = strtok(NULL, "\r\n");
5908 }
developere6aafda2022-09-13 14:59:28 +08005909 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005910 }
5911 else
5912 {
developere6aafda2022-09-13 14:59:28 +08005913 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005914 }
5915
5916#if 0
5917 //TODO: need to revisit below implementation
5918 char aclArray[512]={0}, *acl=NULL;
5919 char assocArray[512]={0}, *asso=NULL;
5920 char buf[256]={'\0'};
5921 char action[10]={'\0'};
5922 FILE *fr=NULL;
5923 char interface[10]={'\0'};
5924 char config_file[MAX_BUF_SIZE] = {0};
5925
5926 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5927 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5928 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5929 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5930
5931 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5932 system(buf);
5933 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5934 system(buf);
5935 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5936 system(buf);
5937 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5938 system(buf);
5939 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5940 system(buf);
5941
5942 if ( enable == TRUE )
5943 {
5944 int device_count=0;
5945 strcpy(action,"DENY");
5946 //kick off the MAC which is in ACL array (deny list)
5947 acl = strtok (aclArray,",");
5948 while (acl != NULL) {
5949 if(strlen(acl)>=17)
5950 {
5951 apply_rules(apIndex, acl,action,interface);
5952 device_count++;
5953 //Register mac to be blocked ,in syscfg.db persistent storage
5954 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5955 system(buf);
5956 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5957 system(buf);
5958 system("syscfg commit");
5959
5960 wifi_kickApAssociatedDevice(apIndex, acl);
5961 }
5962 acl = strtok (NULL, ",");
5963 }
5964 }
5965 else
5966 {
5967 int device_count=0;
5968 char cmdmac[20]={'\0'};
5969 strcpy(action,"ALLOW");
5970 //kick off the MAC which is not in ACL array (allow list)
5971 acl = strtok (aclArray,",");
5972 while (acl != NULL) {
5973 if(strlen(acl)>=17)
5974 {
5975 apply_rules(apIndex, acl,action,interface);
5976 device_count++;
5977 //Register mac to be Allowed ,in syscfg.db persistent storage
5978 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5979 system(buf);
5980 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5981 system(buf);
5982 sprintf(cmdmac,"%s",acl);
5983 }
5984 acl = strtok (NULL, ",");
5985 }
5986 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5987 system(buf);
5988
5989 //Disconnect the mac which is not in ACL
5990 asso = strtok (assocArray,",");
5991 while (asso != NULL) {
5992 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5993 wifi_kickApAssociatedDevice(apIndex, asso);
5994 asso = strtok (NULL, ",");
5995 }
5996 }
5997#endif
5998 return RETURN_OK;
5999}
6000
6001INT wifi_setPreferPrivateConnection(BOOL enable)
6002{
developer06a01d92022-09-07 16:32:39 +08006003 return RETURN_OK;
6004}
6005
6006// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6007INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6008{
developerd946fd62022-12-08 18:03:28 +08006009 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006010 int items = 1;
6011 struct params list[2];
6012 char buf[MAX_BUF_SIZE] = {0};
6013 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08006014 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08006015
6016 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08006017
developer10adcc12022-09-13 14:39:17 +08006018 if (filterMode == 0) {
6019 sprintf(buf, "%d", 0);
6020 list[0].value = buf;
6021
developer2f995fb2023-02-24 10:40:44 +08006022 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08006023 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006024 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08006025 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
6026 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006027 memset(cmd,0,sizeof(cmd));
6028 // Delete deny_mac_file in hostapd configuration
6029 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08006030 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006031 }
6032 else if (filterMode == 1) {
6033 sprintf(buf, "%d", filterMode);
6034 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08006035 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
6036 list[1].name = "accept_mac_file";
6037 list[1].value = acl_file;
6038 items = 2;
developer10adcc12022-09-13 14:39:17 +08006039 } else if (filterMode == 2) {
6040 //TODO: deny_mac_file
6041 sprintf(buf, "%d", 0);
6042 list[0].value = buf;
6043 list[1].name = "deny_mac_file";
6044 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6045 list[1].value = deny_file;
6046 items = 2;
6047 } else {
6048 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006049 }
developer10adcc12022-09-13 14:39:17 +08006050
developer06a01d92022-09-07 16:32:39 +08006051 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6052 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08006053 if (multiple_set == FALSE) {
6054 wifi_setApEnable(apIndex, FALSE);
6055 wifi_setApEnable(apIndex, TRUE);
6056 }
developerefb790a2023-12-26 18:58:32 +08006057 snprintf(vap_info[apIndex].macaddr_acl, MAX_BUF_SIZE, "%s", list[0].value);
developer06a01d92022-09-07 16:32:39 +08006058
6059 return RETURN_OK;
6060
6061#if 0
6062 if(apIndex==0 || apIndex==1)
6063 {
6064 //set the filtermode
6065 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6066 system(buf);
6067 system("syscfg commit");
6068
6069 if(filterMode==0)
6070 {
6071 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6072 system(buf);
6073 return RETURN_OK;
6074 }
6075 }
6076 return RETURN_OK;
6077#endif
6078}
6079
6080// 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.
6081INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6082{
6083 return RETURN_ERR;
6084}
6085
6086// gets the vlan ID for this ap from an internal enviornment variable
6087INT wifi_getApVlanID(INT apIndex, INT *output_int)
6088{
developer30423732022-12-01 16:17:49 +08006089 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006090 {
6091 *output_int=100;
6092 return RETURN_OK;
6093 }
6094
6095 return RETURN_ERR;
6096}
6097
6098// sets the vlan ID for this ap to an internal enviornment variable
6099INT wifi_setApVlanID(INT apIndex, INT vlanId)
6100{
6101 //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)
6102 return RETURN_ERR;
6103}
6104
6105// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6106INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6107{
6108 snprintf(bridgeName, 32, "brlan0");
6109 snprintf(IP, 32, "10.0.0.1");
6110 snprintf(subnet, 32, "255.255.255.0");
6111
6112 return RETURN_OK;
6113}
6114
6115//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6116INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6117{
6118 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6119 return RETURN_ERR;
6120}
6121
6122// reset the vlan configuration for this ap
6123INT wifi_resetApVlanCfg(INT apIndex)
6124{
developerf5fef612022-09-20 19:38:26 +08006125 char original_config_file[64] = {0};
6126 char current_config_file[64] = {0};
6127 char buf[64] = {0};
6128 char cmd[64] = {0};
6129 char vlan_file[64] = {0};
6130 char vlan_tagged_interface[16] = {0};
6131 char vlan_bridge[16] = {0};
6132 char vlan_naming[16] = {0};
6133 struct params list[4] = {0};
6134 wifi_band band;
6135
6136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6137
6138 band = wifi_index_to_band(apIndex);
6139 if (band == band_2_4)
6140 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006141 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006142 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006143 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006144 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6145
6146 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6147
6148 if (strlen(vlan_file) == 0)
6149 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006150
developerf5fef612022-09-20 19:38:26 +08006151 // The file should exist or this vap would not work.
6152 if (access(vlan_file, F_OK) != 0) {
6153 sprintf(cmd, "touch %s", vlan_file);
6154 _syscmd(cmd, buf, sizeof(buf));
6155 }
6156 list[0].name = "vlan_file";
6157 list[0].value = vlan_file;
6158
6159 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6160 list[1].name = "vlan_tagged_interface";
6161 list[1].value = vlan_tagged_interface;
6162
6163 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6164 list[2].name = "vlan_bridge";
6165 list[2].value = vlan_bridge;
6166
6167 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6168 list[3].name = "vlan_naming";
6169 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006170
developerf5fef612022-09-20 19:38:26 +08006171 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6172 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006173 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006174 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006175
developerf5fef612022-09-20 19:38:26 +08006176 // restart this ap
6177 wifi_setApEnable(apIndex, FALSE);
6178 wifi_setApEnable(apIndex, TRUE);
6179
6180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6181
6182 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006183}
6184
6185// 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.
6186INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6187{
6188 return RETURN_ERR;
6189}
6190
6191// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6192INT wifi_startHostApd()
6193{
6194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6195 system("systemctl start hostapd.service");
6196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6197 return RETURN_OK;
6198 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6199}
6200
6201// stops hostapd
6202INT wifi_stopHostApd()
6203{
6204 char cmd[128] = {0};
6205 char buf[128] = {0};
6206
6207 sprintf(cmd,"systemctl stop hostapd");
6208 _syscmd(cmd, buf, sizeof(buf));
6209
6210 return RETURN_OK;
6211}
6212
6213// restart hostapd dummy function
6214INT wifi_restartHostApd()
6215{
6216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6217 system("systemctl restart hostapd-global");
6218 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6219
6220 return RETURN_OK;
6221}
6222
6223static int align_hostapd_config(int index)
6224{
6225 ULONG lval;
6226 wifi_getRadioChannel(index%2, &lval);
6227 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006228 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006229}
6230
6231// sets the AP enable status variable for the specified ap.
6232INT wifi_setApEnable(INT apIndex, BOOL enable)
6233{
developerd946fd62022-12-08 18:03:28 +08006234 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006235 char config_file[MAX_BUF_SIZE] = {0};
6236 char cmd[MAX_CMD_SIZE] = {0};
6237 char buf[MAX_BUF_SIZE] = {0};
6238 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006239 int max_radio_num = 0;
6240 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006241
6242 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006243
6244 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006245 if (enable == status)
6246 return RETURN_OK;
6247
developerac6f1142022-12-20 19:26:35 +08006248 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006249 return RETURN_ERR;
6250
developer06a01d92022-09-07 16:32:39 +08006251 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006252 int radioIndex = apIndex % max_radio_num;
6253 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006254 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6255 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006256 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006257 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006258 if (!(apIndex/max_radio_num)) {
6259 sprintf(cmd, "iw %s del", interface_name);
6260 _syscmd(cmd, buf, sizeof(buf));
6261 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6262 _syscmd(cmd, buf, sizeof(buf));
6263 }
developer033b37b2022-10-18 11:27:46 +08006264 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006265 _syscmd(cmd, buf, sizeof(buf));
6266 }
6267 else {
developerd946fd62022-12-08 18:03:28 +08006268 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006269 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006270 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006271 _syscmd(cmd, buf, sizeof(buf));
6272 }
developera77d84b2023-02-22 16:10:50 +08006273
developer431128d2022-12-16 15:30:41 +08006274 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006275 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006276 _syscmd(cmd, buf, sizeof(buf));
6277 //Wait for wifi up/down to apply
6278 return RETURN_OK;
6279}
6280
6281// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6282INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6283{
developerd946fd62022-12-08 18:03:28 +08006284 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006285 char cmd[MAX_CMD_SIZE] = {'\0'};
6286 char buf[MAX_BUF_SIZE] = {'\0'};
6287
6288 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6289 return RETURN_ERR;
6290
6291 *output_bool = 0;
6292
6293 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6294 {
developerac6f1142022-12-20 19:26:35 +08006295 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006296 *output_bool = FALSE;
6297 return RETURN_OK;
6298 }
6299 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006300 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6301 }
6302
6303 return RETURN_OK;
6304}
6305
6306// Outputs the AP "Enabled" "Disabled" status from driver
6307INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6308{
6309 char cmd[128] = {0};
6310 char buf[128] = {0};
6311 BOOL output_bool;
6312
6313 if ( NULL == output_string)
6314 return RETURN_ERR;
6315 wifi_getApEnable(apIndex,&output_bool);
6316
6317 if(output_bool == 1)
6318 snprintf(output_string, 32, "Up");
6319 else
6320 snprintf(output_string, 32, "Disable");
6321
6322 return RETURN_OK;
6323}
6324
6325//Indicates whether or not beacons include the SSID name.
6326// outputs a 1 if SSID on the AP is enabled, else outputs 0
6327INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6328{
6329 //get the running status
6330 char config_file[MAX_BUF_SIZE] = {0};
6331 char buf[16] = {0};
6332
6333 if (!output)
6334 return RETURN_ERR;
6335
6336 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006337 if (!syn_flag)
6338 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6339 else
developer07ded1f2024-01-10 10:30:15 +08006340 snprintf(buf, sizeof(buf), "%s",vap_info[apIndex].ignore_broadcast_ssid);
developer1d57d002022-10-12 18:03:15 +08006341 // default is enable
6342 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6343 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006344
6345 return RETURN_OK;
6346}
6347
6348// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6349INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6350{
6351 //store the config, apply instantly
6352 char config_file[MAX_BUF_SIZE] = {0};
6353 struct params list;
6354
6355 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6356 list.name = "ignore_broadcast_ssid";
6357 list.value = enable?"0":"1";
6358
6359 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6360 wifi_hostapdWrite(config_file, &list, 1);
6361 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6362 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006363 wifi_reloadAp(apIndex);
developerefb790a2023-12-26 18:58:32 +08006364 snprintf(vap_info[apIndex].ignore_broadcast_ssid, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08006365 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6366
6367 return RETURN_OK;
6368}
6369
6370//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6371INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6372{
6373 //get the running status
6374 if(!output_uint)
6375 return RETURN_ERR;
6376 *output_uint=16;
6377 return RETURN_OK;
6378}
6379
6380INT wifi_setApRetryLimit(INT apIndex, UINT number)
6381{
6382 //apply instantly
6383 return RETURN_ERR;
6384}
6385
6386//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6387INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6388{
6389 if(!output)
6390 return RETURN_ERR;
6391 *output=TRUE;
6392 return RETURN_OK;
6393}
6394
6395//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6396INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6397{
6398 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006399 char cmd[128] = {0};
6400 char buf[128] = {0};
6401 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006402 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006403
developer0b246d12022-09-30 15:24:20 +08006404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006405
developer0b246d12022-09-30 15:24:20 +08006406 wifi_getMaxRadioNumber(&max_radio_num);
6407 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006408 phyId = radio_index_to_phy(radioIndex);
6409 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006410 _syscmd(cmd,buf, sizeof(buf));
6411
6412 if (strlen(buf) > 0)
6413 *output = true;
6414
6415 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006416
developer06a01d92022-09-07 16:32:39 +08006417 return RETURN_OK;
6418}
6419
6420//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6421INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6422{
6423 //get the running status from driver
6424 if(!output)
6425 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006426
6427 char config_file[MAX_BUF_SIZE] = {0};
6428 char buf[16] = {0};
6429
6430 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6431 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006432 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006433 *output = TRUE;
6434 else
6435 *output = FALSE;
6436
developer06a01d92022-09-07 16:32:39 +08006437 return RETURN_OK;
6438}
6439
6440// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6441INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6442{
6443 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006444 char config_file[MAX_BUF_SIZE] = {0};
6445 struct params list;
6446
6447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6448 list.name = "wmm_enabled";
6449 list.value = enable?"1":"0";
6450
6451 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6452 wifi_hostapdWrite(config_file, &list, 1);
6453 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6454 wifi_reloadAp(apIndex);
6455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6456
6457 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006458}
6459
6460//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.
6461INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6462{
6463 //get the running status from driver
6464 if(!output)
6465 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006466
6467 char config_file[128] = {0};
6468 char buf[16] = {0};
6469
6470 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6471 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6472 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6473 *output = TRUE;
6474 else
6475 *output = FALSE;
6476
developer06a01d92022-09-07 16:32:39 +08006477 return RETURN_OK;
6478}
6479
6480// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6481INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6482{
6483 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006484 char config_file[MAX_BUF_SIZE] = {0};
6485 struct params list;
6486
6487 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6488 list.name = "uapsd_advertisement_enabled";
6489 list.value = enable?"1":"0";
6490
6491 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6492 wifi_hostapdWrite(config_file, &list, 1);
6493 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6494 wifi_reloadAp(apIndex);
6495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6496
6497 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006498}
6499
developer6daeb3f2022-09-30 13:36:39 +08006500// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006501INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6502{
developerd946fd62022-12-08 18:03:28 +08006503 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006504 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6505 char cmd[128] = {0};
6506 char buf[128] = {0};
6507 char ack_filepath[128] = {0};
6508 uint16_t bitmap = 0;
6509 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6510 FILE *f = NULL;
6511
6512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6513
6514 // Get current setting
6515 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6516 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6517 _syscmd(cmd, buf, sizeof(buf));
6518 if (strlen(buf) > 0)
6519 bitmap = strtoul(buf, NULL, 10);
6520
6521 bitmap = strtoul(buf, NULL, 10);
6522
6523 if (ackPolicy == TRUE) { // True, unset this class
6524 bitmap &= ~class_map[class];
6525 } else { // False, set this class
6526 bitmap |= class_map[class];
6527 }
6528
6529 f = fopen(ack_filepath, "w");
6530 if (f == NULL) {
6531 fprintf(stderr, "%s: fopen failed\n", __func__);
6532 return RETURN_ERR;
6533 }
6534 fprintf(f, "%hu", bitmap);
6535 fclose(f);
6536
developerac6f1142022-12-20 19:26:35 +08006537 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006538 return RETURN_ERR;
6539 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006540 _syscmd(cmd, buf, sizeof(buf));
6541
6542 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6543 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006544}
6545
6546//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.
6547INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6548{
6549 //get the running status from driver
6550 if(!output_uint)
6551 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006552
6553 char output[16]={'\0'};
6554 char config_file[MAX_BUF_SIZE] = {0};
6555
6556 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006557 if (!syn_flag)
6558 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6559 else
developer07ded1f2024-01-10 10:30:15 +08006560 snprintf(output, sizeof(output), "%s", vap_info[apIndex].max_sta);
developer0947e1a2022-09-13 14:15:25 +08006561 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6562 else {
6563 int device_num = atoi(output);
6564 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6565 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6566 return RETURN_ERR;
6567 }
6568 else {
6569 *output_uint = device_num;
6570 }
6571 }
6572
developer06a01d92022-09-07 16:32:39 +08006573 return RETURN_OK;
6574}
6575
6576INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6577{
6578 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006579 char str[MAX_BUF_SIZE]={'\0'};
6580 char cmd[MAX_CMD_SIZE]={'\0'};
6581 struct params params;
6582 char config_file[MAX_BUF_SIZE] = {0};
6583
6584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006585 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006586 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006587 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006588 }
6589 sprintf(str, "%d", number);
6590 params.name = "max_num_sta";
6591 params.value = str;
6592
6593 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6594 int ret = wifi_hostapdWrite(config_file, &params, 1);
6595 if (ret) {
6596 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6597 ,__func__, ret);
6598 }
6599
6600 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6601 if (ret) {
6602 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6603 ,__func__, ret);
6604 }
6605 wifi_reloadAp(apIndex);
6606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6607
6608 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006609}
6610
6611//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.
6612INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6613{
6614 //get the current threshold
6615 if(!output_uint)
6616 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006617 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6618 if (*output_uint == 0)
6619 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006620 return RETURN_OK;
6621}
6622
6623INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6624{
6625 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006626 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6627 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006628 return RETURN_ERR;
6629}
6630
6631//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.
6632INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6633{
6634 if(!output_uint)
6635 return RETURN_ERR;
6636 *output_uint = 3;
6637 return RETURN_OK;
6638}
6639
6640//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6641INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6642{
6643 if(!output_uint)
6644 return RETURN_ERR;
6645 *output_uint = 3;
6646 return RETURN_OK;
6647}
6648
6649//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.
6650INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6651{
6652 if(!output_in_seconds)
6653 return RETURN_ERR;
6654 *output_in_seconds = 0;
6655 return RETURN_OK;
6656}
6657
6658//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
6659INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6660{
6661 if(!output || apIndex>=MAX_APS)
6662 return RETURN_ERR;
6663 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006664 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006665 return RETURN_OK;
6666}
6667
6668//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6669INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6670{
developer587c1b62022-09-27 15:58:59 +08006671 char config_file[128] = {0};
6672 char wpa[16] = {0};
6673 char key_mgmt[64] = {0};
6674 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006675 if (!output)
6676 return RETURN_ERR;
6677
6678 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006679 if (!syn_flag)
6680 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6681 else
developer07ded1f2024-01-10 10:30:15 +08006682 snprintf(wpa, sizeof(wpa), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006683
developer587c1b62022-09-27 15:58:59 +08006684 strcpy(output, "None");//Copying "None" to output string for default case
developerefb790a2023-12-26 18:58:32 +08006685 if (!syn_flag)
6686 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6687 else
developer07ded1f2024-01-10 10:30:15 +08006688 snprintf(key_mgmt, sizeof(key_mgmt), "%s", vap_info[apIndex].wpa_key_mgmt);
developer4a359672022-10-13 15:30:46 +08006689 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006690 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006691 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006692 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006693 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006694 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006695 snprintf(output, 32, "WPA-WPA2-Personal");
6696
developer72ec5572023-01-05 16:27:13 +08006697 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6698 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006699 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006700 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006701 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006702 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006703 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006704 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006705 snprintf(output, 32, "WPA-WPA2-Enterprise");
6706 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006707 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006708 snprintf(output, 32, "WPA3-Personal");
6709 else
developer4a359672022-10-13 15:30:46 +08006710 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006711 }
developer06a01d92022-09-07 16:32:39 +08006712
6713 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6714 return RETURN_OK;
6715#if 0
6716 //TODO: need to revisit below implementation
6717 char securityType[32], authMode[32];
6718 int enterpriseMode=0;
6719
6720 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6721 if(!output)
6722 return RETURN_ERR;
6723
6724 wifi_getApBeaconType(apIndex, securityType);
6725 strcpy(output,"None");//By default, copying "None" to output string
6726 if (strncmp(securityType,"None", strlen("None")) == 0)
6727 return RETURN_OK;
6728
6729 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6730 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6731
6732 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6733 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6734 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6735 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6736 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6737 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6739
6740 return RETURN_OK;
6741#endif
6742}
6743
6744INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6745{
6746 char securityType[32];
6747 char authMode[32];
6748
6749 //store settings and wait for wifi up to apply
6750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6751 if(!encMode)
6752 return RETURN_ERR;
6753
developer06a01d92022-09-07 16:32:39 +08006754 if (strcmp(encMode, "None")==0)
6755 {
6756 strcpy(securityType,"None");
6757 strcpy(authMode,"None");
6758 }
6759 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6760 {
6761 strcpy(securityType,"WPAand11i");
6762 strcpy(authMode,"PSKAuthentication");
6763 }
6764 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6765 {
6766 strcpy(securityType,"WPAand11i");
6767 strcpy(authMode,"EAPAuthentication");
6768 }
6769 else if (strcmp(encMode, "WPA-Personal")==0)
6770 {
6771 strcpy(securityType,"WPA");
6772 strcpy(authMode,"PSKAuthentication");
6773 }
6774 else if (strcmp(encMode, "WPA-Enterprise")==0)
6775 {
6776 strcpy(securityType,"WPA");
6777 strcpy(authMode,"EAPAuthentication");
6778 }
6779 else if (strcmp(encMode, "WPA2-Personal")==0)
6780 {
6781 strcpy(securityType,"11i");
6782 strcpy(authMode,"PSKAuthentication");
6783 }
6784 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6785 {
6786 strcpy(securityType,"11i");
6787 strcpy(authMode,"EAPAuthentication");
6788 }
developer587c1b62022-09-27 15:58:59 +08006789 else if (strcmp(encMode, "WPA3-Personal") == 0)
6790 {
6791 strcpy(securityType,"11i");
6792 strcpy(authMode,"SAEAuthentication");
6793 }
developer4a359672022-10-13 15:30:46 +08006794 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006795 {
6796 strcpy(securityType, "11i");
6797 strcpy(authMode, "PSK-SAEAuthentication");
6798 }
developer587c1b62022-09-27 15:58:59 +08006799 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6800 {
6801 strcpy(securityType,"11i");
6802 strcpy(authMode,"EAP_192-bit_Authentication");
6803 }
developer5c9fee82023-01-13 14:44:16 +08006804 else if (strcmp(encMode, "OWE") == 0)
6805 {
6806 strcpy(securityType,"11i");
6807 strcpy(authMode,"Enhanced_Open");
6808 }
developer06a01d92022-09-07 16:32:39 +08006809 else
6810 {
6811 strcpy(securityType,"None");
6812 strcpy(authMode,"None");
6813 }
6814 wifi_setApBeaconType(apIndex, securityType);
6815 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6816 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6817
6818 return RETURN_OK;
6819}
6820
6821
developer4b102122023-02-15 10:53:03 +08006822// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006823//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006824INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6825{
developer30423732022-12-01 16:17:49 +08006826 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006827 char config_file[MAX_BUF_SIZE] = {0};
6828
6829 if(output_string==NULL)
6830 return RETURN_ERR;
6831
6832 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006833 if (!syn_flag)
6834 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6835 else
developer07ded1f2024-01-10 10:30:15 +08006836 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006837 if(strcmp(buf,"0")==0)
6838 {
6839 printf("wpa_mode is %s ......... \n",buf);
6840 return RETURN_ERR;
6841 }
6842
6843 wifi_dbg_printf("\nFunc=%s\n",__func__);
6844 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006845 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006846 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6847
6848 return RETURN_OK;
6849}
6850
developer4b102122023-02-15 10:53:03 +08006851// Set PreSharedKey associated with a Access Point.
6852// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006853INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6854{
6855 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6856 struct params params={'\0'};
6857 int ret;
6858 char config_file[MAX_BUF_SIZE] = {0};
6859
6860 if(NULL == preSharedKey)
6861 return RETURN_ERR;
6862
developer4b102122023-02-15 10:53:03 +08006863 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006864
developer4b102122023-02-15 10:53:03 +08006865 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006866 {
developer4b102122023-02-15 10:53:03 +08006867 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006868 return RETURN_ERR;
6869 }
6870 params.value = preSharedKey;
6871 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6872 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006873 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006874 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006875 wifi_reloadAp(apIndex);
6876 }
developer06a01d92022-09-07 16:32:39 +08006877 return ret;
6878 //TODO: call hostapd_cli for dynamic_config_control
6879}
6880
6881//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6882// outputs the passphrase, maximum 63 characters
6883INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6884{
6885 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6886
6887 wifi_dbg_printf("\nFunc=%s\n",__func__);
6888 if (NULL == output_string)
6889 return RETURN_ERR;
6890
6891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006892 if (!syn_flag)
6893 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6894 else
developer07ded1f2024-01-10 10:30:15 +08006895 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006896 if(strcmp(buf,"0")==0)
6897 {
6898 printf("wpa_mode is %s ......... \n",buf);
6899 return RETURN_ERR;
6900 }
6901
developerefb790a2023-12-26 18:58:32 +08006902 if (!syn_flag)
6903 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6904 else
developer07ded1f2024-01-10 10:30:15 +08006905 snprintf(output_string, 64, "%s", vap_info[apIndex].wpa_passphrase);
developer06a01d92022-09-07 16:32:39 +08006906 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6907
6908 return RETURN_OK;
6909}
6910
6911// sets the passphrase enviornment variable, max 63 characters
6912INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6913{
6914 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6915 struct params params={'\0'};
6916 char config_file[MAX_BUF_SIZE] = {0};
6917 int ret;
6918
6919 if(NULL == passPhrase)
6920 return RETURN_ERR;
6921
6922 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6923 {
6924 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6925 return RETURN_ERR;
6926 }
6927 params.name = "wpa_passphrase";
6928 params.value = passPhrase;
6929 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6930 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006931 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006932 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006933 wifi_reloadAp(apIndex);
6934 }
developerefb790a2023-12-26 18:58:32 +08006935 snprintf(vap_info[apIndex].wpa_passphrase, MAX_BUF_SIZE, "%s", passPhrase);
developer06a01d92022-09-07 16:32:39 +08006936
6937 return ret;
6938}
6939
6940//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.
6941INT wifi_setApSecurityReset(INT apIndex)
6942{
developer8d583982022-09-20 11:28:22 +08006943 char original_config_file[64] = {0};
6944 char current_config_file[64] = {0};
6945 char buf[64] = {0};
6946 char cmd[64] = {0};
6947 char wpa[4] = {0};
6948 char wpa_psk[64] = {0};
6949 char wpa_passphrase[64] = {0};
6950 char wpa_psk_file[128] = {0};
6951 char wpa_key_mgmt[64] = {0};
6952 char wpa_pairwise[32] = {0};
6953 wifi_band band;
6954 struct params list[6];
6955
6956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6957
6958 band = wifi_index_to_band(apIndex);
6959 if (band == band_2_4)
6960 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006961 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006962 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006963 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006964 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6965 else
6966 return RETURN_ERR;
6967
6968 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6969 list[0].name = "wpa";
6970 list[0].value = wpa;
6971
6972 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6973 list[1].name = "wpa_psk";
6974 list[1].value = wpa_psk;
6975
6976 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6977 list[2].name = "wpa_passphrase";
6978 list[2].value = wpa_passphrase;
6979
6980 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6981
6982 if (strlen(wpa_psk_file) == 0)
6983 strcpy(wpa_psk_file, PSK_FILE);
6984
6985 if (access(wpa_psk_file, F_OK) != 0) {
6986 sprintf(cmd, "touch %s", wpa_psk_file);
6987 _syscmd(cmd, buf, sizeof(buf));
6988 }
6989 list[3].name = "wpa_psk_file";
6990 list[3].value = wpa_psk_file;
6991
6992 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6993 list[4].name = "wpa_key_mgmt";
6994 list[4].value = wpa_key_mgmt;
6995
6996 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6997 list[5].name = "wpa_pairwise";
6998 list[5].value = wpa_pairwise;
6999
7000 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7001 wifi_hostapdWrite(current_config_file, list, 6);
7002
7003 wifi_setApEnable(apIndex, FALSE);
7004 wifi_setApEnable(apIndex, TRUE);
7005
7006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7007 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007008}
7009
7010//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).
7011INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7012{
developer8f2ddd52022-09-13 15:39:24 +08007013 char config_file[64] = {0};
7014 char buf[64] = {0};
7015 char cmd[256] = {0};
7016
7017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7018
developer06a01d92022-09-07 16:32:39 +08007019 if(!IP_output || !Port_output || !RadiusSecret_output)
7020 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08007021
developer8f2ddd52022-09-13 15:39:24 +08007022 // Read the first matched config
7023 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7024 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7025 _syscmd(cmd, buf, sizeof(buf));
7026 strncpy(IP_output, buf, 64);
7027
7028 memset(buf, 0, sizeof(buf));
7029 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7030 _syscmd(cmd, buf, sizeof(buf));
7031 *Port_output = atoi(buf);
7032
7033 memset(buf, 0, sizeof(buf));
7034 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7035 _syscmd(cmd, buf, sizeof(buf));
7036 strncpy(RadiusSecret_output, buf, 64);
7037
7038 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007039 return RETURN_OK;
7040}
7041
7042INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7043{
developer8f2ddd52022-09-13 15:39:24 +08007044 char config_file[64] = {0};
7045 char port_str[8] = {0};
7046 char cmd[256] = {0};
7047 char buf[128] = {0};
7048
7049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007050 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7051 return RETURN_ERR;
7052
7053 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7054 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007055
7056 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7057
7058 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7059 _syscmd(cmd, buf, sizeof(buf));
7060 memset(cmd, 0, sizeof(cmd));
7061
7062 snprintf(port_str, sizeof(port_str), "%d", port);
7063 if (strlen(buf) == 0)
7064 // Append
7065 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7066 "auth_server_addr=%s\\n"
7067 "auth_server_port=%s\\n"
7068 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7069 else {
7070 // Delete the three lines setting after the "# radius 1" comment
7071 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7072 _syscmd(cmd, buf, sizeof(buf));
7073 memset(cmd, 0, sizeof(cmd));
7074 // Use "# radius 1" comment to find the location to insert the radius setting
7075 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7076 "# radius 1\\n"
7077 "auth_server_addr=%s\\n"
7078 "auth_server_port=%s\\n"
7079 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7080 }
7081 if(_syscmd(cmd, buf, sizeof(buf))) {
7082 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7083 return RETURN_ERR;
7084 }
7085
7086 wifi_reloadAp(apIndex);
7087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7088 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007089}
7090
7091INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7092{
developer8f2ddd52022-09-13 15:39:24 +08007093 char config_file[64] = {0};
7094 char buf[64] = {0};
7095 char cmd[256] = {0};
7096
7097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7098
developer06a01d92022-09-07 16:32:39 +08007099 if(!IP_output || !Port_output || !RadiusSecret_output)
7100 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007101
7102 // Read the second matched config
7103 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7104 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7105 _syscmd(cmd, buf, sizeof(buf));
7106 strncpy(IP_output, buf, 64);
7107
7108 memset(buf, 0, sizeof(buf));
7109 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7110 _syscmd(cmd, buf, sizeof(buf));
7111 *Port_output = atoi(buf);
7112
7113 memset(buf, 0, sizeof(buf));
7114 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7115 _syscmd(cmd, buf, sizeof(buf));
7116 strncpy(RadiusSecret_output, buf, 64);
7117
7118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007119 return RETURN_OK;
7120}
7121
7122INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7123{
developer8f2ddd52022-09-13 15:39:24 +08007124 char config_file[64] = {0};
7125 char port_str[8] = {0};
7126 char cmd[256] = {0};
7127 char buf[128] = {0};
7128
7129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007130 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7131 return RETURN_ERR;
7132
7133 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7134 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007135
7136 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7137
7138 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7139 _syscmd(cmd, buf, sizeof(buf));
7140 memset(cmd, 0, sizeof(cmd));
7141
7142 snprintf(port_str, sizeof(port_str), "%d", port);
7143 if (strlen(buf) == 0)
7144 // Append
7145 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7146 "auth_server_addr=%s\\n"
7147 "auth_server_port=%s\\n"
7148 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7149 else {
7150 // Delete the three lines setting after the "# radius 2" comment
7151 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7152 _syscmd(cmd, buf, sizeof(buf));
7153 memset(cmd, 0, sizeof(cmd));
7154 // Use "# radius 2" comment to find the location to insert the radius setting
7155 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7156 "# radius 2\\n"
7157 "auth_server_addr=%s\\n"
7158 "auth_server_port=%s\\n"
7159 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7160 }
7161 if(_syscmd(cmd, buf, sizeof(buf))) {
7162 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7163 return RETURN_ERR;
7164 }
7165
7166 wifi_reloadAp(apIndex);
7167 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7168 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007169}
7170
7171//RadiusSettings
7172INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7173{
7174 if(!output)
7175 return RETURN_ERR;
7176
7177 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7178 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7179 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7180 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7181 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7182 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.
7183 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7184 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7185 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7186 //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.
7187
7188 return RETURN_OK;
7189}
7190
7191INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7192{
7193 //store the paramters, and apply instantly
7194 return RETURN_ERR;
7195}
7196
7197//Device.WiFi.AccessPoint.{i}.WPS.Enable
7198//Enables or disables WPS functionality for this access point.
7199// outputs the WPS enable state of this ap in output_bool
7200INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7201{
developerd946fd62022-12-08 18:03:28 +08007202 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007203 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007204
7205 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007206 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007207 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007208 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007209 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007210 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007211 _syscmd(cmd, buf, sizeof(buf));
7212 if(strstr(buf, "configured"))
7213 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007214
7215 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007216}
developer06a01d92022-09-07 16:32:39 +08007217
7218//Device.WiFi.AccessPoint.{i}.WPS.Enable
7219// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7220INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7221{
7222 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007223 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007224 struct params params;
7225
developer06a01d92022-09-07 16:32:39 +08007226 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7227 //store the paramters, and wait for wifi up to apply
7228 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007229 if (enable == TRUE) {
7230 wifi_getApBeaconType(apIndex, buf);
7231 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7232 params.value = "1";
7233 else // If ap set encryption
7234 params.value = "2";
7235 } else {
7236 params.value = "0";
7237 }
developer06a01d92022-09-07 16:32:39 +08007238
7239 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7240 wifi_hostapdWrite(config_file, &params, 1);
7241 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7242 wifi_reloadAp(apIndex);
7243
7244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7245 return RETURN_OK;
7246}
7247
7248//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
7249INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7250{
7251 if(!output)
7252 return RETURN_ERR;
7253 snprintf(output, 128, "PushButton,PIN");
7254 return RETURN_OK;
7255}
7256
7257//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7258//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.
7259// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7260INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7261{
7262 if(!output)
7263 return RETURN_ERR;
7264 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7265
7266 return RETURN_OK;
7267}
7268
7269//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7270// 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
7271INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7272{
7273 //apply instantly. No setting need to be stored.
7274 char methods[MAX_BUF_SIZE], *token, *next_token;
7275 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7276 struct params params;
7277
developer5b398df2022-11-17 20:39:48 +08007278 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007279 return RETURN_ERR;
7280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7281 //store the paramters, and wait for wifi up to apply
7282
7283 snprintf(methods, sizeof(methods), "%s", methodString);
7284 for(token=methods; *token; token=next_token)
7285 {
7286 strtok_r(token, ",", &next_token);
7287 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7288 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7289 else if(*token=='E')
7290 {
7291 if(!strcmp(methods, "Ethernet"))
7292 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7293 else if(!strcmp(methods, "ExternalNFCToken"))
7294 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7295 else
7296 printf("%s: Unknown WpsConfigMethod\n", __func__);
7297 }
7298 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7299 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7300 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7301 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7302 else if(*token=='P' )
7303 {
7304 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007305 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007306 else if(!strcmp(token, "PIN"))
7307 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7308 else
7309 printf("%s: Unknown WpsConfigMethod\n", __func__);
7310 }
7311 else
7312 printf("%s: Unknown WpsConfigMethod\n", __func__);
7313 }
7314 params.name = "config_methods";
7315 params.value = config_methods;
7316 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7317 wifi_hostapdWrite(config_file, &params, 1);
7318 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7319 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7320
7321 return RETURN_OK;
7322}
7323
7324// outputs the pin value, ulong_pin must be allocated by the caller
7325INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7326{
7327 char buf[MAX_BUF_SIZE] = {0};
7328 char cmd[MAX_CMD_SIZE] = {0};
7329
developer5b398df2022-11-17 20:39:48 +08007330 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007331 return RETURN_ERR;
7332 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7333 _syscmd(cmd, buf, sizeof(buf));
7334 if(strlen(buf) > 0)
7335 *output_ulong=strtoul(buf, NULL, 10);
7336
7337 return RETURN_OK;
7338}
7339
7340// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7341INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7342{
7343 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7344 char ap_pin[16] = {0};
7345 char buf[MAX_BUF_SIZE] = {0};
7346 char config_file[MAX_BUF_SIZE] = {0};
7347 ULONG prev_pin = 0;
7348 struct params params;
7349
developer06a01d92022-09-07 16:32:39 +08007350 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7351 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7352 params.name = "ap_pin";
7353 params.value = ap_pin;
7354 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7355 wifi_hostapdWrite(config_file, &params, 1);
7356 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7358
7359 return RETURN_OK;
7360}
7361
7362// Output string is either Not configured or Configured, max 32 characters
7363INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7364{
developerd946fd62022-12-08 18:03:28 +08007365 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007366 char cmd[MAX_CMD_SIZE];
7367 char buf[MAX_BUF_SIZE]={0};
7368
developer5b398df2022-11-17 20:39:48 +08007369 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007370 return RETURN_ERR;
7371 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7372 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007373 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007374 return RETURN_ERR;
7375 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007376 _syscmd(cmd, buf, sizeof(buf));
7377
developer348e3d92022-09-13 14:48:41 +08007378 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007379 snprintf(output_string, 32, "Configured");
7380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7381
7382 return RETURN_OK;
7383}
7384
7385// sets the WPS pin for this AP
7386INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7387{
developerd946fd62022-12-08 18:03:28 +08007388 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007389 char cmd[MAX_CMD_SIZE];
7390 char buf[MAX_BUF_SIZE]={0};
7391 BOOL enable;
7392
developer06a01d92022-09-07 16:32:39 +08007393 wifi_getApEnable(apIndex, &enable);
7394 if (!enable)
7395 return RETURN_ERR;
7396 wifi_getApWpsEnable(apIndex, &enable);
7397 if (!enable)
7398 return RETURN_ERR;
7399
developerac6f1142022-12-20 19:26:35 +08007400 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007401 return RETURN_ERR;
7402 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007403 _syscmd(cmd, buf, sizeof(buf));
7404 if((strstr(buf, "OK"))!=NULL)
7405 return RETURN_OK;
7406
7407 return RETURN_ERR;
7408}
7409
7410// This function is called when the WPS push button has been pressed for this AP
7411INT wifi_setApWpsButtonPush(INT apIndex)
7412{
7413 char cmd[MAX_CMD_SIZE];
7414 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007415 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007416 BOOL enable=FALSE;
7417
developer06a01d92022-09-07 16:32:39 +08007418 wifi_getApEnable(apIndex, &enable);
7419 if (!enable)
7420 return RETURN_ERR;
7421
7422 wifi_getApWpsEnable(apIndex, &enable);
7423 if (!enable)
7424 return RETURN_ERR;
7425
developerac6f1142022-12-20 19:26:35 +08007426 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007427 return RETURN_ERR;
7428
developer900e2b72023-05-23 10:23:48 +08007429 snprintf(cmd, sizeof(cmd), "sleep 1 && hostapd_cli -i%s wps_cancel && hostapd_cli -i%s wps_pbc", interface_name, interface_name);
developer06a01d92022-09-07 16:32:39 +08007430 _syscmd(cmd, buf, sizeof(buf));
7431
7432 if((strstr(buf, "OK"))!=NULL)
7433 return RETURN_OK;
7434 return RETURN_ERR;
7435}
7436
7437// cancels WPS mode for this AP
7438INT wifi_cancelApWPS(INT apIndex)
7439{
developerd946fd62022-12-08 18:03:28 +08007440 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007441 char cmd[MAX_CMD_SIZE];
7442 char buf[MAX_BUF_SIZE]={0};
7443
developerac6f1142022-12-20 19:26:35 +08007444 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007445 return RETURN_ERR;
7446 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007447 _syscmd(cmd,buf, sizeof(buf));
7448
7449 if((strstr(buf, "OK"))!=NULL)
7450 return RETURN_OK;
7451 return RETURN_ERR;
7452}
7453
7454//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7455//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7456INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7457{
developerd946fd62022-12-08 18:03:28 +08007458 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007459 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007460 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007461 char cmd[256] = {0}, buf[2048] = {0};
7462 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007463 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007464 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007465 wifi_associated_dev_t *dev=NULL;
7466
7467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7468 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007469 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007470 return RETURN_ERR;
7471 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007472 _syscmd(cmd,buf,sizeof(buf));
7473 *output_array_size = atoi(buf);
7474
7475 if (*output_array_size <= 0)
7476 return RETURN_OK;
7477
7478 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7479 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007480 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007481 _syscmd(cmd,buf,sizeof(buf));
7482 f = fopen("/tmp/connected_devices.txt", "r");
7483 if (f==NULL)
7484 {
7485 *output_array_size=0;
7486 return RETURN_ERR;
7487 }
developer30423732022-12-01 16:17:49 +08007488 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007489 {
7490 param = strtok(line,"=");
7491 value = strtok(NULL,"=");
7492
7493 if( strcmp("flags",param) == 0 )
7494 {
7495 value[strlen(value)-1]='\0';
7496 if(strstr (value,"AUTHORIZED") != NULL )
7497 {
7498 dev[auth_temp].cli_AuthenticationState = 1;
7499 dev[auth_temp].cli_Active = 1;
7500 auth_temp++;
7501 read_flag=1;
7502 }
7503 }
7504 if(read_flag==1)
7505 {
7506 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7507 {
7508 value[strlen(value)-1]='\0';
7509 sscanf(value, "%x:%x:%x:%x:%x:%x",
7510 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7511 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7512 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7513 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7514 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7515 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7516 mac_temp++;
7517 read_flag=0;
7518 }
7519 }
7520 }
7521 *output_array_size = auth_temp;
7522 auth_temp=0;
7523 mac_temp=0;
7524 free(line);
7525 fclose(f);
7526 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7527 return RETURN_OK;
7528}
7529
7530#define MACADDRESS_SIZE 6
7531
7532INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7533{
7534 FILE *fp = NULL;
7535 char str[MAX_BUF_SIZE] = {0};
7536 int wificlientindex = 0 ;
7537 int count = 0;
7538 int signalstrength = 0;
7539 int arr[MACADDRESS_SIZE] = {0};
7540 unsigned char mac[MACADDRESS_SIZE] = {0};
7541 UINT wifi_count = 0;
7542 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7543 char pipeCmd[MAX_CMD_SIZE] = {0};
7544
7545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7546 *output_array_size = 0;
7547 *associated_dev_array = NULL;
7548
7549 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7550 fp = popen(pipeCmd, "r");
7551 if (fp == NULL)
7552 {
7553 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7554 return RETURN_ERR;
7555 }
7556
7557 /* Read the output a line at a time - output it. */
7558 fgets(str, sizeof(str)-1, fp);
7559 wifi_count = (unsigned int) atoi ( str );
7560 *output_array_size = wifi_count;
7561 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7562 pclose(fp);
7563
7564 if(wifi_count == 0)
7565 {
7566 return RETURN_OK;
7567 }
7568 else
7569 {
7570 wifi_associated_dev3_t* temp = NULL;
7571 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7572 if(temp == NULL)
7573 {
7574 printf("Error Statement. Insufficient memory \n");
7575 return RETURN_ERR;
7576 }
7577
7578 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7579 system(pipeCmd);
7580 memset(pipeCmd,0,sizeof(pipeCmd));
7581 if(apIndex == 0)
7582 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7583 else if(apIndex == 1)
7584 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7585 system(pipeCmd);
7586
7587 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7588 if(fp == NULL)
7589 {
7590 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007591 free(temp);
developer06a01d92022-09-07 16:32:39 +08007592 return RETURN_ERR;
7593 }
7594 fclose(fp);
7595
developer30423732022-12-01 16:17:49 +08007596 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007597 fp = popen(pipeCmd, "r");
7598 if(fp)
7599 {
7600 for(count =0 ; count < wifi_count; count++)
7601 {
7602 fgets(str, MAX_BUF_SIZE, fp);
7603 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7604 {
7605 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7606 {
7607 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7608
7609 }
7610 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7611 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]);
7612 }
7613 temp[count].cli_AuthenticationState = 1; //TODO
7614 temp[count].cli_Active = 1; //TODO
7615 }
7616 pclose(fp);
7617 }
7618
developer30423732022-12-01 16:17:49 +08007619 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 +08007620 fp = popen(pipeCmd, "r");
7621 if(fp)
7622 {
7623 pclose(fp);
7624 }
7625 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7626 if(fp)
7627 {
7628 for(count =0 ; count < wifi_count ;count++)
7629 {
7630 fgets(str, MAX_BUF_SIZE, fp);
7631 signalstrength = atoi(str);
7632 temp[count].cli_SignalStrength = signalstrength;
7633 temp[count].cli_RSSI = signalstrength;
7634 temp[count].cli_SNR = signalstrength + 95;
7635 }
7636 pclose(fp);
7637 }
7638
7639
7640 if((apIndex == 0) || (apIndex == 4))
7641 {
7642 for(count =0 ; count < wifi_count ;count++)
7643 {
7644 strcpy(temp[count].cli_OperatingStandard,"g");
7645 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7646 }
7647
7648 //BytesSent
developer30423732022-12-01 16:17:49 +08007649 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 +08007650 fp = popen(pipeCmd, "r");
7651 if(fp)
7652 {
7653 pclose(fp);
7654 }
7655 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7656 if(fp)
7657 {
7658 for (count = 0; count < wifi_count; count++)
7659 {
7660 fgets(str, MAX_BUF_SIZE, fp);
7661 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7662 }
7663 pclose(fp);
7664 }
7665
7666 //BytesReceived
developer30423732022-12-01 16:17:49 +08007667 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 +08007668 fp = popen(pipeCmd, "r");
7669 if (fp)
7670 {
7671 pclose(fp);
7672 }
7673 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7674 if (fp)
7675 {
7676 for (count = 0; count < wifi_count; count++)
7677 {
7678 fgets(str, MAX_BUF_SIZE, fp);
7679 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7680 }
7681 pclose(fp);
7682 }
7683
7684 //PacketsSent
developer30423732022-12-01 16:17:49 +08007685 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 +08007686 fp = popen(pipeCmd, "r");
7687 if (fp)
7688 {
7689 pclose(fp);
7690 }
7691
7692 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7693 if (fp)
7694 {
7695 for (count = 0; count < wifi_count; count++)
7696 {
7697 fgets(str, MAX_BUF_SIZE, fp);
7698 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7699 }
7700 pclose(fp);
7701 }
7702
7703 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007704 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 +08007705 fp = popen(pipeCmd, "r");
7706 if (fp)
7707 {
7708 pclose(fp);
7709 }
7710 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7711 if (fp)
7712 {
7713 for (count = 0; count < wifi_count; count++)
7714 {
7715 fgets(str, MAX_BUF_SIZE, fp);
7716 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7717 }
7718 pclose(fp);
7719 }
7720
7721 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007722 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 +08007723 fp = popen(pipeCmd, "r");
7724 if (fp)
7725 {
7726 pclose(fp);
7727 }
7728 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7729 if (fp)
7730 {
7731 for (count = 0; count < wifi_count; count++)
7732 {
7733 fgets(str, MAX_BUF_SIZE, fp);
7734 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7735 }
7736 pclose(fp);
7737 }
7738
7739 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007740 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 +08007741 fp = popen(pipeCmd, "r");
7742 if (fp)
7743 {
7744 pclose(fp);
7745 }
7746 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7747 if (fp)
7748 {
7749 for (count = 0; count < wifi_count; count++)
7750 {
7751 fgets(str, MAX_BUF_SIZE, fp);
7752 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7753 }
7754 pclose(fp);
7755 }
7756
7757 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007758 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 +08007759 fp = popen(pipeCmd, "r");
7760 if (fp)
7761 {
7762 pclose(fp);
7763 }
7764 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7765 if (fp)
7766 {
7767 for (count = 0; count < wifi_count; count++)
7768 {
7769 fgets(str, MAX_BUF_SIZE, fp);
7770 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7771 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7772 }
7773 pclose(fp);
7774 }
7775
7776 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007777 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 +08007778 fp = popen(pipeCmd, "r");
7779 if (fp)
7780 {
7781 pclose(fp);
7782 }
7783 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7784 if (fp)
7785 {
7786 for (count = 0; count < wifi_count; count++)
7787 {
7788 fgets(str, MAX_BUF_SIZE, fp);
7789 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7790 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7791 }
7792 pclose(fp);
7793 }
7794
7795 }
7796 else if ((apIndex == 1) || (apIndex == 5))
7797 {
7798 for (count = 0; count < wifi_count; count++)
7799 {
7800 strcpy(temp[count].cli_OperatingStandard, "a");
7801 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7802 temp[count].cli_BytesSent = 0;
7803 temp[count].cli_BytesReceived = 0;
7804 temp[count].cli_LastDataUplinkRate = 0;
7805 temp[count].cli_LastDataDownlinkRate = 0;
7806 temp[count].cli_PacketsSent = 0;
7807 temp[count].cli_PacketsReceived = 0;
7808 temp[count].cli_ErrorsSent = 0;
7809 }
7810 }
7811
7812 for (count = 0; count < wifi_count; count++)
7813 {
7814 temp[count].cli_Retransmissions = 0;
7815 temp[count].cli_DataFramesSentAck = 0;
7816 temp[count].cli_DataFramesSentNoAck = 0;
7817 temp[count].cli_MinRSSI = 0;
7818 temp[count].cli_MaxRSSI = 0;
7819 strncpy(temp[count].cli_InterferenceSources, "", 64);
7820 memset(temp[count].cli_IPAddress, 0, 64);
7821 temp[count].cli_RetransCount = 0;
7822 temp[count].cli_FailedRetransCount = 0;
7823 temp[count].cli_RetryCount = 0;
7824 temp[count].cli_MultipleRetryCount = 0;
7825 }
7826 *associated_dev_array = temp;
7827 }
7828 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7829 return RETURN_OK;
7830}
7831
7832int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7833{
7834 FILE *fp = NULL;
7835 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7836 char cmd[MAX_CMD_SIZE];
7837 int count = 0;
7838
7839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7840 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7841 fp = popen(cmd,"r");
7842 if(fp == NULL)
7843 {
7844 printf("Failed to run command in Function %s\n",__FUNCTION__);
7845 return 0;
7846 }
7847 if(fgets(path, sizeof(path)-1, fp) != NULL)
7848 {
7849 for(count=0;path[count]!='\n';count++)
7850 status[count]=path[count];
7851 status[count]='\0';
7852 }
7853 strcpy(wifi_status,status);
7854 pclose(fp);
7855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7856 return RETURN_OK;
7857}
7858
7859/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7860struct hostapd_sta_param {
7861 char key[50];
7862 char value[100];
7863}
7864
7865static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7866 int i = 0;
7867
7868 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7869 if (strncmp(params[i].key,key,50) == 0){
7870 return &params[i].value;
7871 }
7872 i++;
7873 }
7874 return NULL;
7875
7876} */
7877
7878static unsigned int count_occurences(const char *buf, const char *word)
7879{
7880 unsigned int n = 0;
7881 char *ptr = strstr(buf, word);
7882
7883 while (ptr++) {
7884 n++;
7885 ptr = strstr(ptr, word);
7886 }
7887
7888 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7889 return n;
7890}
7891
7892static const char *get_line_from_str_buf(const char *buf, char *line)
7893{
7894 int i;
7895 int n = strlen(buf);
7896
7897 for (i = 0; i < n; i++) {
7898 line[i] = buf[i];
7899 if (buf[i] == '\n') {
7900 line[i] = '\0';
7901 return &buf[i + 1];
7902 }
7903 }
7904
7905 return NULL;
7906}
7907
developer9a9f46e2023-11-09 09:22:42 +08007908static INT wifi_getAssocConnectMode(INT apIndex, CHAR *input_string, CHAR *OperatingStandard)
7909{
7910 wifi_band band;
7911 int ieee80211_mode = 0;
7912
7913 if (!input_string || !OperatingStandard)
7914 return RETURN_ERR;
7915
7916 band = wifi_index_to_band(apIndex);
7917
7918 if (strstr(input_string, "HE"))
7919 ieee80211_mode = WIFI_MODE_AX;
7920 else if (strstr(input_string, "VHT"))
7921 ieee80211_mode = WIFI_MODE_AC;
7922 else if (strstr(input_string, "EHT"))
7923 ieee80211_mode = WIFI_MODE_BE;
7924
7925 switch (ieee80211_mode) {
7926 case WIFI_MODE_AC:
7927 strncpy(OperatingStandard, "ac", 2);
7928 break;
7929 case WIFI_MODE_AX:
7930 strncpy(OperatingStandard, "ax", 2);
7931 break;
7932 case WIFI_MODE_BE:
7933 strncpy(OperatingStandard, "be", 2);
7934 break;
7935 default:
7936 if(band == band_2_4)
7937 strncpy(OperatingStandard,"b,g,n", 5);
7938 else if(band == band_5)
7939 strncpy(OperatingStandard,"a,n", 3);
7940 else if(band == band_6)
7941 strncpy(OperatingStandard,"ax", 2);
7942 else {
7943 wifi_dbg_printf("%s: failed to parse band %d\n", __FUNCTION__, band);
7944 return RETURN_ERR;
7945 }
7946 }
7947
7948
7949 return RETURN_OK;
7950}
7951
developer06a01d92022-09-07 16:32:39 +08007952INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7953{
7954 unsigned int assoc_cnt = 0;
7955 char interface_name[50] = {0};
7956 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7957 char cmd[MAX_CMD_SIZE] = {'\0'};
7958 char line[256] = {'\0'};
7959 int i = 0;
7960 int ret = 0;
7961 const char *ptr = NULL;
7962 char *key = NULL;
7963 char *val = NULL;
7964 wifi_associated_dev3_t *temp = NULL;
7965 int rssi;
7966
7967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7968
7969 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7970 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7971 return RETURN_ERR;
7972 }
7973
7974 // Example filtered output of 'iw dev' command:
7975 // Station 0a:69:72:10:d2:fa (on wifi0)
7976 // signal avg:-67 [-71, -71] dBm
7977 // Station 28:c2:1f:25:5f:99 (on wifi0)
7978 // signal avg:-67 [-71, -70] dBm
developer9a9f46e2023-11-09 09:22:42 +08007979 if (sprintf(cmd,"iw dev %s station dump | tr -d '\t' | grep -E 'Station|signal avg"
7980 "|tx bitrate|rx bitrate'", interface_name) < 0) {
7981 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
developer06a01d92022-09-07 16:32:39 +08007982 return RETURN_ERR;
7983 }
7984
7985 ret = _syscmd(cmd, buf, sizeof(buf));
7986 if (ret == RETURN_ERR) {
7987 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7988 return RETURN_ERR;
7989 }
7990
7991 *output_array_size = count_occurences(buf, "Station");
7992 if (*output_array_size == 0) return RETURN_OK;
7993
7994 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7995 if (temp == NULL) {
7996 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7997 return RETURN_ERR;
7998 }
7999 *associated_dev_array = temp;
8000
8001 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8002 ptr = get_line_from_str_buf(buf, line);
8003 i = -1;
8004 while (ptr) {
8005 if (strstr(line, "Station")) {
8006 i++;
8007 key = strtok(line, " ");
8008 val = strtok(NULL, " ");
8009 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8010 &temp[i].cli_MACAddress[0],
8011 &temp[i].cli_MACAddress[1],
8012 &temp[i].cli_MACAddress[2],
8013 &temp[i].cli_MACAddress[3],
8014 &temp[i].cli_MACAddress[4],
8015 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8016 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8017 free(*associated_dev_array);
8018 return RETURN_ERR;
8019 }
8020 }
8021 else if (i < 0) {
developer9a9f46e2023-11-09 09:22:42 +08008022 wifi_dbg_printf("%s: not find station\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +08008023 ptr = get_line_from_str_buf(ptr, line);
8024 continue; // We didn't detect 'station' entry yet
8025 }
8026 else if (strstr(line, "signal avg")) {
8027 key = strtok(line, ":");
8028 val = strtok(NULL, " ");
8029 if (sscanf(val, "%d", &rssi) <= 0 ) {
8030 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8031 free(*associated_dev_array);
8032 return RETURN_ERR;
8033 }
8034 temp[i].cli_RSSI = rssi;
8035 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8036 }
developer9a9f46e2023-11-09 09:22:42 +08008037 else if (strstr(line, "tx bitrate")) {
8038 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8039 if (ret == RETURN_ERR) {
8040 wifi_dbg_printf("%s: failed to execute tx get assoc connect mode command.\n", __FUNCTION__);
8041 return ret;
8042 }
8043 }
8044 else if (strstr(line, "rx bitrate")) {
8045 /* if tx get ac, ax, be mode, need not get mode from rx */
8046 if (strncmp(temp[i].cli_OperatingStandard,"ac", 2) &&
8047 strncmp(temp[i].cli_OperatingStandard,"ax", 2) &&
8048 strncmp(temp[i].cli_OperatingStandard,"be", 2)) {
8049 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8050 if (ret == RETURN_ERR) {
8051 wifi_dbg_printf("%s: failed to execute rx get assoc connect mode command.\n", __FUNCTION__);
8052 return ret;
8053 }
8054 }
8055 }
developer06a01d92022-09-07 16:32:39 +08008056 // Here other fields can be parsed if added to filter of 'iw dev' command
developer06a01d92022-09-07 16:32:39 +08008057 ptr = get_line_from_str_buf(ptr, line);
developer9a9f46e2023-11-09 09:22:42 +08008058 }
developer06a01d92022-09-07 16:32:39 +08008059
8060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008061 return RETURN_OK;
8062}
8063
8064#if 0
8065//To-do
8066INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8067{
8068 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8069
8070 //Using different approach to get required WiFi Parameters from system available commands
8071#if 0
8072 FILE *f;
8073 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8074 char cmd[256], buf[2048];
8075 char *param , *value, *line=NULL;
8076 size_t len = 0;
8077 ssize_t nread;
8078 wifi_associated_dev3_t *dev=NULL;
8079 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08008080 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08008081 _syscmd(cmd,buf,sizeof(buf));
8082 *output_array_size = atoi(buf);
8083
8084 if (*output_array_size <= 0)
8085 return RETURN_OK;
8086
8087 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8088 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08008089 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08008090 _syscmd(cmd,buf,sizeof(buf));
8091 f = fopen("/tmp/connected_devices.txt", "r");
8092 if (f==NULL)
8093 {
8094 *output_array_size=0;
8095 return RETURN_ERR;
8096 }
8097 while ((nread = getline(&line, &len, f)) != -1)
8098 {
8099 param = strtok(line,"=");
8100 value = strtok(NULL,"=");
8101
8102 if( strcmp("flags",param) == 0 )
8103 {
8104 value[strlen(value)-1]='\0';
8105 if(strstr (value,"AUTHORIZED") != NULL )
8106 {
8107 dev[auth_temp].cli_AuthenticationState = 1;
8108 dev[auth_temp].cli_Active = 1;
8109 auth_temp++;
8110 read_flag=1;
8111 }
8112 }
8113 if(read_flag==1)
8114 {
8115 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8116 {
8117 value[strlen(value)-1]='\0';
8118 sscanf(value, "%x:%x:%x:%x:%x:%x",
8119 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8120 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8121 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8122 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8123 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8124 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8125
8126 }
8127 else if( strcmp("rx_packets",param) == 0 )
8128 {
8129 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8130 }
8131
8132 else if( strcmp("tx_packets",param) == 0 )
8133 {
8134 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8135 }
8136
8137 else if( strcmp("rx_bytes",param) == 0 )
8138 {
8139 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8140 }
8141
8142 else if( strcmp("tx_bytes",param) == 0 )
8143 {
8144 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8145 mac_temp++;
8146 read_flag=0;
8147 }
8148 }
8149 }
8150
8151 *output_array_size = auth_temp;
8152 auth_temp=0;
8153 mac_temp=0;
8154 free(line);
8155 fclose(f);
8156#endif
8157 char interface_name[MAX_BUF_SIZE] = {0};
8158 char wifi_status[MAX_BUF_SIZE] = {0};
8159 char hostapdconf[MAX_BUF_SIZE] = {0};
8160
8161 wifi_associated_dev3_t *dev_array = NULL;
8162 ULONG wifi_count = 0;
8163
8164 *associated_dev_array = NULL;
8165 *output_array_size = 0;
8166
8167 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8168 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8169 {
8170 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8171
developerac6f1142022-12-20 19:26:35 +08008172 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008173
8174 if(strlen(interface_name) > 1)
8175 {
8176 wifihal_interfacestatus(wifi_status,interface_name);
8177 if(strcmp(wifi_status,"RUNNING") == 0)
8178 {
8179 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8180
8181 *associated_dev_array = dev_array;
8182 *output_array_size = wifi_count;
8183 }
8184 else
8185 {
8186 *associated_dev_array = NULL;
8187 }
8188 }
8189 }
8190
8191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8192 return RETURN_OK;
8193}
8194#endif
8195
8196/* getIPAddress function */
8197/**
8198* @description Returning IpAddress of the Matched String
8199*
8200* @param
8201* @str Having MacAddress
8202* @ipaddr Having ipaddr
8203* @return The status of the operation
8204* @retval RETURN_OK if successful
8205* @retval RETURN_ERR if any error is detected
8206*
8207*/
8208
8209INT getIPAddress(char *str,char *ipaddr)
8210{
8211 FILE *fp = NULL;
8212 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8213 int LeaseTime = 0,ret = 0;
8214 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8215 {
8216 return RETURN_ERR;
8217 }
8218
8219 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8220 {
8221 /*
8222 Sample:sss
8223 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8224 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8225 */
8226 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008227 &(LeaseTime),
8228 phyAddr,
8229 ipAddr,
8230 hostName
8231 );
developer06a01d92022-09-07 16:32:39 +08008232 if(ret != 4)
8233 continue;
8234 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008235 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008236 }
developerd946fd62022-12-08 18:03:28 +08008237 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008238 return RETURN_OK;
8239}
8240
8241/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8242/**
8243* @description Returning Inactive wireless connected clients informations
8244*
8245* @param
8246* @filename Holding private_wifi 2g/5g content files
8247* @associated_dev_array Having inactiv wireless clients informations
8248* @output_array_size Returning Inactive wireless counts
8249* @return The status of the operation
8250* @retval RETURN_OK if successful
8251* @retval RETURN_ERR if any error is detected
8252*
8253*/
8254
8255INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8256{
8257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8258 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8259 FILE *fp = NULL;
8260 int arr[MACADDRESS_SIZE] = {0};
8261 unsigned char mac[MACADDRESS_SIZE] = {0};
8262 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8263 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8264 fp = popen(buf,"r");
8265 if(fp == NULL)
8266 return RETURN_ERR;
8267 else
8268 {
8269 fgets(path,sizeof(path),fp);
8270 maccount = atoi(path);
8271 }
8272 pclose(fp);
8273 *output_array_size = maccount;
8274 wifi_associated_dev3_t* temp = NULL;
8275 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8276 *associated_dev_array = temp;
8277 if(temp == NULL)
8278 {
8279 printf("Error Statement. Insufficient memory \n");
8280 return RETURN_ERR;
8281 }
8282 memset(buf,0,sizeof(buf));
8283 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8284 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008285 if (fp == NULL) {
8286 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8287 return RETURN_ERR;
8288 }
developer06a01d92022-09-07 16:32:39 +08008289 for(count = 0; count < maccount ; count++)
8290 {
8291 fgets(path,sizeof(path),fp);
8292 for(i = 0; path[i]!='\n';i++)
8293 str[i]=path[i];
8294 str[i]='\0';
8295 getIPAddress(str,ipaddr);
8296 memset(buf,0,sizeof(buf));
8297 if(strlen(ipaddr) > 0)
8298 {
8299 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8300 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8301 {
8302 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8303 {
8304 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8305 {
8306 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8307
8308 }
8309 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8310 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]);
8311 }
8312 temp[count].cli_AuthenticationState = 0; //TODO
8313 temp[count].cli_Active = 0; //TODO
8314 temp[count].cli_SignalStrength = 0;
8315 }
8316 else //Active wireless clients info
8317 {
8318 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8319 {
8320 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8321 {
8322 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8323
8324 }
8325 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8326 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]);
8327 }
8328 temp[count].cli_Active = 1;
8329 }
8330 }
8331 memset(ipaddr,0,sizeof(ipaddr));
8332 }
8333 pclose(fp);
8334 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8335 return RETURN_OK;
8336}
8337//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8338//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8339//To get Band Steering Capability
8340INT wifi_getBandSteeringCapability(BOOL *support)
8341{
8342 *support = FALSE;
8343 return RETURN_OK;
8344}
8345
8346
8347//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8348//To get Band Steering enable status
8349INT wifi_getBandSteeringEnable(BOOL *enable)
8350{
8351 *enable = FALSE;
8352 return RETURN_OK;
8353}
8354
8355//To turn on/off Band steering
8356INT wifi_setBandSteeringEnable(BOOL enable)
8357{
8358 return RETURN_OK;
8359}
8360
8361//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8362//To get Band Steering AP group
8363INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8364{
8365 if (NULL == output_ApGroup)
8366 return RETURN_ERR;
8367
8368 strcpy(output_ApGroup, "1,2");
8369 return RETURN_OK;
8370}
8371
8372//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8373//to set and read the band steering BandUtilizationThreshold parameters
8374INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8375{
8376 return RETURN_ERR;
8377}
8378
8379INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8380{
8381 return RETURN_ERR;
8382}
8383
8384//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8385//to set and read the band steering RSSIThreshold parameters
8386INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8387{
8388 return RETURN_ERR;
8389}
8390
8391INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8392{
8393 return RETURN_ERR;
8394}
8395
8396
8397//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8398//to set and read the band steering physical modulation rate threshold parameters
8399INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8400{
8401 //If chip is not support, return -1
8402 return RETURN_ERR;
8403}
8404
8405INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8406{
8407 //If chip is not support, return -1
8408 return RETURN_ERR;
8409}
8410
8411//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8412//to set and read the inactivity time (in seconds) for steering under overload condition
8413INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8414{
8415 return RETURN_ERR;
8416}
8417
8418INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8419{
8420 return RETURN_ERR;
8421}
8422
8423//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8424//to set and read the inactivity time (in seconds) for steering under Idle condition
8425INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8426{
8427 return RETURN_ERR;
8428}
8429
8430INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8431{
8432 return RETURN_ERR;
8433}
8434
8435//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8436//pClientMAC[64]
8437//pSourceSSIDIndex[64]
8438//pDestSSIDIndex[64]
8439//pSteeringReason[256]
8440INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8441{
8442 //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
8443 *pSteeringTime=time(NULL);
8444 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8445 return RETURN_OK;
8446}
8447
8448INT wifi_ifConfigDown(INT apIndex)
8449{
8450 INT status = RETURN_OK;
8451 char cmd[64];
8452
8453 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8454 printf("%s: %s\n", __func__, cmd);
8455 system(cmd);
8456
8457 return status;
8458}
8459
8460INT wifi_ifConfigUp(INT apIndex)
8461{
developerd946fd62022-12-08 18:03:28 +08008462 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008463 char cmd[128];
8464 char buf[1024];
8465
developerac6f1142022-12-20 19:26:35 +08008466 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008467 return RETURN_ERR;
8468 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008469 _syscmd(cmd, buf, sizeof(buf));
8470 return 0;
8471}
8472
8473//>> Deprecated. Replace with wifi_applyRadioSettings
8474INT wifi_pushBridgeInfo(INT apIndex)
8475{
developerd946fd62022-12-08 18:03:28 +08008476 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008477 char ip[32] = {0};
8478 char subnet[32] = {0};
8479 char bridge[32] = {0};
8480 int vlanId = 0;
8481 char cmd[128] = {0};
8482 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008483
8484 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8485 wifi_getApVlanID(apIndex,&vlanId);
8486
developerac6f1142022-12-20 19:26:35 +08008487 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008488 return RETURN_ERR;
8489 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008490 _syscmd(cmd,buf, sizeof(buf));
8491
8492 return 0;
8493}
8494
8495INT wifi_pushChannel(INT radioIndex, UINT channel)
8496{
developerd946fd62022-12-08 18:03:28 +08008497 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008498 char cmd[128];
8499 char buf[1024];
8500 int apIndex;
8501
8502 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008503 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008504 return RETURN_ERR;
8505 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008506 _syscmd(cmd,buf, sizeof(buf));
8507
8508 return 0;
8509}
8510
8511INT wifi_pushChannelMode(INT radioIndex)
8512{
8513 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8514 return RETURN_ERR;
8515}
8516
8517INT wifi_pushDefaultValues(INT radioIndex)
8518{
8519 //Apply Comcast specified default radio settings instantly
8520 //AMPDU=1
8521 //AMPDUFrames=32
8522 //AMPDULim=50000
8523 //txqueuelen=1000
8524
8525 return RETURN_ERR;
8526}
8527
8528INT wifi_pushTxChainMask(INT radioIndex)
8529{
8530 //Apply default TxChainMask instantly
8531 return RETURN_ERR;
8532}
8533
8534INT wifi_pushRxChainMask(INT radioIndex)
8535{
8536 //Apply default RxChainMask instantly
8537 return RETURN_ERR;
8538}
8539
8540INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8541{
8542 INT status;
8543
8544 status = wifi_setSSIDName(apIndex,ssid);
8545 wifi_setApEnable(apIndex,FALSE);
8546 wifi_setApEnable(apIndex,TRUE);
8547
8548 return status;
8549}
8550
8551INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8552{
8553 //Apply default Ssid Advertisement instantly
8554 return RETURN_ERR;
8555}
8556
8557INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8558{
8559 INT status = RETURN_ERR;
8560 *output = 0;
8561 return RETURN_ERR;
8562}
8563
8564INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8565{
8566 return RETURN_OK;
8567}
8568
8569INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8570{
8571 return RETURN_OK;
8572}
8573
8574//To-do
8575INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8576{
developereb199ae2022-09-13 14:04:27 +08008577 char output[16]={'\0'};
8578 char config_file[MAX_BUF_SIZE] = {0};
8579
8580 if (!output_string)
8581 return RETURN_ERR;
8582
8583 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8584 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8585
8586 if (strlen(output) == 0)
8587 snprintf(output_string, 64, "Disabled");
8588 else if (strncmp(output, "0", 1) == 0)
8589 snprintf(output_string, 64, "Disabled");
8590 else if (strncmp(output, "1", 1) == 0)
8591 snprintf(output_string, 64, "Optional");
8592 else if (strncmp(output, "2", 1) == 0)
8593 snprintf(output_string, 64, "Required");
8594 else {
8595 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8596 return RETURN_ERR;
8597 }
8598
8599 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008600 return RETURN_OK;
8601}
8602INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8603{
developereb199ae2022-09-13 14:04:27 +08008604 char str[MAX_BUF_SIZE]={'\0'};
8605 char cmd[MAX_CMD_SIZE]={'\0'};
8606 struct params params;
8607 char config_file[MAX_BUF_SIZE] = {0};
8608
8609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8610 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8611 return RETURN_ERR;
8612
8613 params.name = "ieee80211w";
8614 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8615 params.value = "0";
8616 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8617 params.value = "1";
8618 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8619 params.value = "2";
8620 else{
8621 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8622 return RETURN_ERR;
8623 }
8624 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8625 wifi_hostapdWrite(config_file, &params, 1);
8626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008627 return RETURN_OK;
8628}
8629INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8630{
8631 char output[16]={'\0'};
8632 char config_file[MAX_BUF_SIZE] = {0};
8633
8634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8635 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8636 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8637
8638 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8639 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8640
8641 return RETURN_OK;
8642}
8643
8644INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8645{
8646 return RETURN_OK;
8647}
8648
8649INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8650{
8651 return RETURN_OK;
8652}
8653
8654INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8655{
8656 return RETURN_OK;
8657}
8658
8659INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8660{
8661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8662 char config_file[MAX_BUF_SIZE] = {0};
8663
8664 if (NULL == output)
8665 return RETURN_ERR;
8666 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8667 wifi_hostapdRead(config_file,"hw_mode",output,64);
8668
8669 if(strcmp(output,"b")==0)
8670 sprintf(output, "%s", "1,2,5.5,11");
8671 else if (strcmp(output,"a")==0)
8672 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8673 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8674 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8675
8676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8677 return RETURN_OK;
8678}
8679
8680INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8681{
8682 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8683 char *temp;
8684 char temp_output[128];
8685 char temp_TransmitRates[128];
8686 char config_file[MAX_BUF_SIZE] = {0};
8687
8688 if (NULL == output)
8689 return RETURN_ERR;
8690
8691 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8692 wifi_hostapdRead(config_file,"supported_rates",output,64);
8693
developer5b398df2022-11-17 20:39:48 +08008694 if (strlen(output) == 0) {
8695 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8696 return RETURN_OK;
8697 }
developer06a01d92022-09-07 16:32:39 +08008698 strcpy(temp_TransmitRates,output);
8699 strcpy(temp_output,"");
8700 temp = strtok(temp_TransmitRates," ");
8701 while(temp!=NULL)
8702 {
8703 temp[strlen(temp)-1]=0;
8704 if((temp[0]=='5') && (temp[1]=='\0'))
8705 {
8706 temp="5.5";
8707 }
8708 strcat(temp_output,temp);
8709 temp = strtok(NULL," ");
8710 if(temp!=NULL)
8711 {
8712 strcat(temp_output,",");
8713 }
8714 }
8715 strcpy(output,temp_output);
8716 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8717
8718 return RETURN_OK;
8719}
8720
8721INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8722{
8723 return RETURN_OK;
8724}
8725
8726
8727INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8728{
8729 int i=0;
8730 char *temp;
developeref938762022-10-19 17:21:01 +08008731 char temp1[128] = {0};
8732 char temp_output[128] = {0};
8733 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008734 struct params params={'\0'};
8735 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008736 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008737
8738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8739 if(NULL == output)
8740 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008741 strcpy(temp_TransmitRates,output);
8742
8743 for(i=0;i<strlen(temp_TransmitRates);i++)
8744 {
developeref938762022-10-19 17:21:01 +08008745 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008746 {
8747 continue;
8748 }
8749 else
8750 {
8751 return RETURN_ERR;
8752 }
8753 }
8754 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008755 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008756 while(temp!=NULL)
8757 {
8758 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008759 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008760 {
developeref938762022-10-19 17:21:01 +08008761 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008762 {
8763 return RETURN_ERR;
8764 }
8765 }
8766
8767 if(strcmp(temp,"5.5")==0)
8768 {
8769 strcpy(temp1,"55");
8770 }
8771 else
8772 {
8773 strcat(temp1,"0");
8774 }
8775 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008776 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008777 if(temp!=NULL)
8778 {
8779 strcat(temp_output," ");
8780 }
8781 }
8782 strcpy(output,temp_output);
8783
developer06a01d92022-09-07 16:32:39 +08008784 params.name = "supported_rates";
8785 params.value = output;
8786
8787 wifi_dbg_printf("\n%s:",__func__);
8788 wifi_dbg_printf("params.value=%s\n",params.value);
8789 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8790 wifi_hostapdWrite(config_file,&params,1);
8791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8792
8793 return RETURN_OK;
8794}
8795
8796
8797static char *sncopy(char *dst, int dst_sz, const char *src)
8798{
8799 if (src && dst && dst_sz > 0) {
8800 strncpy(dst, src, dst_sz);
8801 dst[dst_sz - 1] = '\0';
8802 }
8803 return dst;
8804}
8805
8806static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8807{
8808 if (0 == strcmp(ht_mode, "HT40") ||
8809 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008810 0 == strcmp(ht_mode, "HT160") ||
8811 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008812 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008813 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008814 case 36:
8815 case 44:
8816 case 52:
8817 case 60:
8818 case 100:
8819 case 108:
8820 case 116:
8821 case 124:
8822 case 132:
8823 case 140:
8824 case 149:
8825 case 157:
8826 return 1;
8827 case 8 ... 13:
8828 case 40:
8829 case 48:
8830 case 56:
8831 case 64:
8832 case 104:
8833 case 112:
8834 case 120:
8835 case 128:
8836 case 136:
8837 case 144:
8838 case 153:
8839 case 161:
8840 return -1;
8841 default:
8842 return -EINVAL;
8843 }
8844 }
8845
8846 return -EINVAL;
8847}
8848
developerb7593de2022-10-18 09:51:57 +08008849static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8850{
8851 int idx = channel%8;
8852 if (0 == strcmp(ht_mode, "HT40") ||
8853 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008854 0 == strcmp(ht_mode, "HT160") ||
8855 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008856 switch (idx) {
8857 case 1:
8858 return 1;
8859 case 5:
8860 return -1;
8861 default:
8862 return -EINVAL;
8863 }
8864 }
8865
8866 return -EINVAL;
8867}
developer06a01d92022-09-07 16:32:39 +08008868static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8869{
8870 if (NULL == hw_mode) return;
8871
8872 if (0 == strcmp(hw_mode, "ac"))
8873 sncopy(bw_mode, bw_mode_len, "ht vht");
8874
8875 if (0 == strcmp(hw_mode, "n"))
8876 sncopy(bw_mode, bw_mode_len, "ht");
8877
8878 return;
8879}
8880
8881static int util_chan_to_freq(int chan)
8882{
8883 if (chan == 14)
8884 return 2484;
8885 else if (chan < 14)
8886 return 2407 + chan * 5;
8887 else if (chan >= 182 && chan <= 196)
8888 return 4000 + chan * 5;
8889 else
8890 return 5000 + chan * 5;
8891 return 0;
8892}
8893
developerb7593de2022-10-18 09:51:57 +08008894static int util_6G_chan_to_freq(int chan)
8895{
8896 if (chan)
8897 return 5950 + chan * 5;
8898 else
8899 return 0;
8900
8901}
developer06a01d92022-09-07 16:32:39 +08008902const int *util_unii_5g_chan2list(int chan, int width)
8903{
8904 static const int lists[] = {
8905 // <width>, <chan1>, <chan2>..., 0,
8906 20, 36, 0,
8907 20, 40, 0,
8908 20, 44, 0,
8909 20, 48, 0,
8910 20, 52, 0,
8911 20, 56, 0,
8912 20, 60, 0,
8913 20, 64, 0,
8914 20, 100, 0,
8915 20, 104, 0,
8916 20, 108, 0,
8917 20, 112, 0,
8918 20, 116, 0,
8919 20, 120, 0,
8920 20, 124, 0,
8921 20, 128, 0,
8922 20, 132, 0,
8923 20, 136, 0,
8924 20, 140, 0,
8925 20, 144, 0,
8926 20, 149, 0,
8927 20, 153, 0,
8928 20, 157, 0,
8929 20, 161, 0,
8930 20, 165, 0,
8931 40, 36, 40, 0,
8932 40, 44, 48, 0,
8933 40, 52, 56, 0,
8934 40, 60, 64, 0,
8935 40, 100, 104, 0,
8936 40, 108, 112, 0,
8937 40, 116, 120, 0,
8938 40, 124, 128, 0,
8939 40, 132, 136, 0,
8940 40, 140, 144, 0,
8941 40, 149, 153, 0,
8942 40, 157, 161, 0,
8943 80, 36, 40, 44, 48, 0,
8944 80, 52, 56, 60, 64, 0,
8945 80, 100, 104, 108, 112, 0,
8946 80, 116, 120, 124, 128, 0,
8947 80, 132, 136, 140, 144, 0,
8948 80, 149, 153, 157, 161, 0,
8949 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8950 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8951 -1 // final delimiter
8952 };
8953 const int *start;
8954 const int *p;
8955
8956 for (p = lists; *p != -1; p++) {
8957 if (*p == width) {
8958 for (start = ++p; *p != 0; p++) {
8959 if (*p == chan)
8960 return start;
8961 }
8962 }
8963 // move to the end of channel list of given width
8964 while (*p != 0) {
8965 p++;
8966 }
8967 }
8968
8969 return NULL;
8970}
8971
8972static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8973{
8974 if (NULL == ht_mode)
8975 return 0;
8976
8977 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8978 const int *chans = util_unii_5g_chan2list(channel, width);
8979 int sum = 0;
8980 int cnt = 0;
8981
8982 if (NULL == chans)
8983 return 0;
8984
8985 while (*chans) {
8986 sum += *chans;
8987 cnt++;
8988 chans++;
8989 }
developer30423732022-12-01 16:17:49 +08008990 if (cnt == 0)
8991 return 0;
developer06a01d92022-09-07 16:32:39 +08008992 return sum / cnt;
8993}
8994
developerb7593de2022-10-18 09:51:57 +08008995static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8996{
8997 if (NULL == ht_mode)
8998 return 0;
8999
9000 int width = strtol((ht_mode + 2), NULL, 10);
9001
9002 int idx = 0 ;
9003 int centerchan = 0;
9004 int chan_ofs = 1;
9005
9006 if (width == 40){
9007 idx = ((channel/4) + chan_ofs)%2;
9008 switch (idx) {
9009 case 0:
9010 centerchan = (channel - 2);
9011 break;
9012 case 1:
9013 centerchan = (channel + 2);
9014 break;
9015 default:
9016 return -EINVAL;
9017 }
9018 }else if (width == 80){
9019 idx = ((channel/4) + chan_ofs)%4;
9020 switch (idx) {
9021 case 0:
9022 centerchan = (channel - 6);
9023 break;
9024 case 1:
9025 centerchan = (channel + 6);
9026 break;
9027 case 2:
9028 centerchan = (channel + 2);
9029 break;
9030 case 3:
9031 centerchan = (channel - 2);
9032 break;
9033 default:
9034 return -EINVAL;
9035 }
9036 }else if (width == 160){
9037 switch (channel) {
9038 case 1 ... 29:
9039 centerchan = 15;
9040 break;
9041 case 33 ... 61:
9042 centerchan = 47;
9043 break;
9044 case 65 ... 93:
9045 centerchan = 79;
9046 break;
9047 case 97 ... 125:
9048 centerchan = 111;
9049 break;
9050 case 129 ... 157:
9051 centerchan = 143;
9052 break;
9053 case 161 ... 189:
9054 centerchan = 175;
9055 break;
9056 case 193 ... 221:
9057 centerchan = 207;
9058 break;
9059 default:
9060 return -EINVAL;
9061 }
developer7c4cd202023-03-01 10:56:29 +08009062 }else if (width == 320){
9063 switch (channel) {
9064 case 1 ... 29:
9065 centerchan = 31;
9066 break;
9067 case 33 ... 93:
9068 centerchan = 63;
9069 break;
9070 case 97 ... 157:
9071 centerchan = 127;
9072 break;
9073 case 161 ... 221:
9074 centerchan = 191;
9075 break;
9076 default:
9077 return -EINVAL;
9078 }
developerb7593de2022-10-18 09:51:57 +08009079 }
9080 return centerchan;
9081}
developer06a01d92022-09-07 16:32:39 +08009082static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9083{
9084 BOOL onlyG, onlyN, onlyA;
9085 CHAR tmp[64];
9086 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9087 if (ret == RETURN_OK) {
9088 sncopy(hw_mode, hw_mode_size, tmp);
9089 }
9090 return ret;
9091}
9092
9093INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9094{
9095 // Sample commands:
9096 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9097 // hostapd_cli -i wifi0 chan_switch 30 2437
9098 char cmd[MAX_CMD_SIZE] = {0};
9099 char buf[MAX_BUF_SIZE] = {0};
9100 int freq = 0, ret = 0;
9101 char center_freq1_str[32] = ""; // center_freq1=%d
9102 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9103 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9104 char hw_mode[16] = ""; // n|ac
9105 char bw_mode[16] = ""; // ht|ht vht
9106 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08009107 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009108 int sec_chan_offset;
9109 int width;
developer4fb0b922022-09-30 14:29:09 +08009110 char config_file[64] = {0};
9111 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08009112 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08009113 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08009114 wifi_band band = band_invalid;
9115 int center_chan = 0;
9116 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08009117
developer4fb0b922022-09-30 14:29:09 +08009118 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08009119
developerac6f1142022-12-20 19:26:35 +08009120 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009121 return RETURN_ERR;
9122
developer06a01d92022-09-07 16:32:39 +08009123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9124
developerb7593de2022-10-18 09:51:57 +08009125 band = wifi_index_to_band(radioIndex);
9126
developer5884e982022-10-06 10:52:50 +08009127 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009128
9129 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009130 if (channel){
developerb7593de2022-10-18 09:51:57 +08009131 if (band == band_6){
9132 freq = util_6G_chan_to_freq(channel);
9133 }else{
9134 freq = util_chan_to_freq(channel);
9135 }
developer7c4cd202023-03-01 10:56:29 +08009136 if (width == 320) {
9137 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9138 setEHT320 = TRUE;
9139 }
developer5884e982022-10-06 10:52:50 +08009140 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009141
developer5884e982022-10-06 10:52:50 +08009142 // Provide bandwith if specified
9143 if (channel_width_MHz > 20) {
9144 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9145 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9146 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009147
developer5884e982022-10-06 10:52:50 +08009148 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9149 }else if (channel_width_MHz == 20){
9150 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9151 }
developer06a01d92022-09-07 16:32:39 +08009152
developerb7593de2022-10-18 09:51:57 +08009153
developer5884e982022-10-06 10:52:50 +08009154 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009155 if (band == band_6){
9156 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9157 if(center_chan){
9158 center_freq1 = util_6G_chan_to_freq(center_chan);
9159 }
9160 }else{
9161 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9162 if(center_chan){
9163 center_freq1 = util_chan_to_freq(center_chan);
9164 }
developer5884e982022-10-06 10:52:50 +08009165 }
developerb7593de2022-10-18 09:51:57 +08009166
9167 if (center_freq1)
9168 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9169
9170 }
9171
9172 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9173 if (band == band_6){
9174 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9175 }else{
9176 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009177 }
developerb7593de2022-10-18 09:51:57 +08009178 if (sec_chan_offset != -EINVAL)
9179 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009180
developer5884e982022-10-06 10:52:50 +08009181 // Only the first AP, other are hanging on the same radio
9182 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009183 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9184 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009185 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9186 wifi_dbg_printf("execute: '%s'\n", cmd);
9187 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009188 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009189
developer5884e982022-10-06 10:52:50 +08009190 ret = wifi_setRadioChannel(radioIndex, channel);
9191 if (ret != RETURN_OK) {
9192 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9193 return RETURN_ERR;
9194 }
9195
9196 if (sec_chan_offset == 1) ext_str = "Above";
9197 else if (sec_chan_offset == -1) ext_str = "Below";
9198
9199 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009200
developer5884e982022-10-06 10:52:50 +08009201 } else {
9202 if (channel_width_MHz > 20)
9203 ext_str = "Above";
9204 }
developer4fb0b922022-09-30 14:29:09 +08009205
developer06a01d92022-09-07 16:32:39 +08009206 char mhz_str[16];
9207 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009208 if (setEHT320 == TRUE)
9209 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9210 else
9211 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009212
developer57fa24a2023-03-15 17:25:07 +08009213 writeBandWidth(radioIndex, mhz_str);
9214 if (band == band_2_4 || band == band_5) {
9215 if (width == 20)
9216 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9217 else
9218 wifi_setRadioExtChannel(radioIndex, ext_str);
9219 }
developer06a01d92022-09-07 16:32:39 +08009220 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9221
9222 return RETURN_OK;
9223}
9224
9225INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9226{
developer615510b2022-09-27 10:14:35 +08009227 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009228 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009229 char cmd[256]={0};
9230 char buf[128]={0};
9231 char file_name[32] = {0};
9232 char filter_SSID[32] = {0};
9233 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009234 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009235 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009236 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009237 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009238 size_t len=0;
9239 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009240 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009241 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009242 bool filter_enable = false;
9243 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009244 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009245
developer615510b2022-09-27 10:14:35 +08009246 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009247
developer615510b2022-09-27 10:14:35 +08009248 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9249 f = fopen(file_name, "r");
9250 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009251 fgets(buf, sizeof(file_name), f);
9252 if ((strncmp(buf, "0", 1)) != 0) {
9253 fgets(filter_SSID, sizeof(file_name), f);
9254 if (strlen(filter_SSID) != 0)
9255 filter_enable = true;
9256 }
developer615510b2022-09-27 10:14:35 +08009257 fclose(f);
9258 }
9259
developerac6f1142022-12-20 19:26:35 +08009260 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009261 return RETURN_ERR;
9262
developer033b37b2022-10-18 11:27:46 +08009263 phyId = radio_index_to_phy(radio_index);
9264
9265 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009266 _syscmd(cmd, buf, sizeof(buf));
9267 channels_num = strtol(buf, NULL, 10);
9268
developerd946fd62022-12-08 18:03:28 +08009269 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9270 // 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 +08009271 fprintf(stderr, "cmd: %s\n", cmd);
9272 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009273 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9274 return RETURN_ERR;
9275 }
developer5550e242022-09-30 09:59:32 +08009276
9277 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9278 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9279
developer615510b2022-09-27 10:14:35 +08009280 ret = fgets(line, sizeof(line), f);
9281 while (ret != NULL) {
9282 if(strstr(line, "BSS") != NULL) { // new neighbor info
9283 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9284 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9285 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9286
9287 if (!filter_BSS) {
9288 index++;
9289 wifi_neighbor_ap2_t *tmp;
9290 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9291 if (tmp == NULL) { // no more memory to use
9292 index--;
9293 wifi_dbg_printf("%s: realloc failed\n", __func__);
9294 break;
9295 }
9296 scan_array = tmp;
9297 }
9298 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009299
developer615510b2022-09-27 10:14:35 +08009300 filter_BSS = false;
9301 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9302 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9303 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9304 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9305 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009306 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009307 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009308
developer615510b2022-09-27 10:14:35 +08009309 if (freq >= 2412 && freq <= 2484) {
9310 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9311 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9312 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9313 }
9314 else if (freq >= 5160 && freq <= 5805) {
9315 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9316 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9317 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9318 }
developer06a01d92022-09-07 16:32:39 +08009319
developer615510b2022-09-27 10:14:35 +08009320 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009321 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009322 for (int i = 0; i < channels_num; i++) {
9323 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9324 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9325 break;
9326 }
9327 }
developer06a01d92022-09-07 16:32:39 +08009328 }
developer615510b2022-09-27 10:14:35 +08009329 } else if (strstr(line, "beacon interval") != NULL) {
9330 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9331 } else if (strstr(line, "signal") != NULL) {
9332 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9333 } else if (strstr(line,"SSID") != NULL) {
9334 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9335 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9336 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009337 }
developer615510b2022-09-27 10:14:35 +08009338 } else if (strstr(line, "Supported rates") != NULL) {
9339 char SRate[80] = {0}, *tmp = NULL;
9340 memset(buf, 0, sizeof(buf));
9341 strcpy(SRate, line);
9342 tmp = strtok(SRate, ":");
9343 tmp = strtok(NULL, ":");
9344 strcpy(buf, tmp);
9345 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009346
developer615510b2022-09-27 10:14:35 +08009347 tmp = strtok(buf, " \n");
9348 while (tmp != NULL) {
9349 strcat(SRate, tmp);
9350 if (SRate[strlen(SRate) - 1] == '*') {
9351 SRate[strlen(SRate) - 1] = '\0';
9352 }
9353 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009354
developer615510b2022-09-27 10:14:35 +08009355 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009356 }
developer615510b2022-09-27 10:14:35 +08009357 SRate[strlen(SRate) - 1] = '\0';
9358 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9359 } else if (strstr(line, "DTIM") != NULL) {
9360 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9361 } else if (strstr(line, "VHT capabilities") != NULL) {
9362 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9363 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9364 } else if (strstr(line, "HT capabilities") != NULL) {
9365 strcat(scan_array[index].ap_SupportedStandards, ",n");
9366 strcpy(scan_array[index].ap_OperatingStandards, "n");
9367 } else if (strstr(line, "VHT operation") != NULL) {
9368 ret = fgets(line, sizeof(line), f);
9369 sscanf(line," * channel width: %d", &vht_channel_width);
9370 if(vht_channel_width == 1) {
9371 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9372 } else {
9373 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9374 }
9375 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9376 continue;
9377 } else if (strstr(line, "HT operation") != NULL) {
9378 ret = fgets(line, sizeof(line), f);
9379 sscanf(line," * secondary channel offset: %s", &buf);
9380 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009381 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009382 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 +08009383 }
developer615510b2022-09-27 10:14:35 +08009384 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009385 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009386 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9387 } else {
9388 //20Mhz
9389 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 +08009390 }
developer615510b2022-09-27 10:14:35 +08009391 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009392 continue;
developer615510b2022-09-27 10:14:35 +08009393 } else if (strstr(line, "HE capabilities") != NULL) {
9394 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9395 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9396 ret = fgets(line, sizeof(line), f);
9397 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9398 if (strstr(line, "HE40/2.4GHz") != NULL)
9399 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9400 else
9401 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9402 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9403 if (strstr(line, "HE80/5GHz") != NULL) {
9404 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9405 ret = fgets(line, sizeof(line), f);
9406 } else
9407 continue;
9408 if (strstr(line, "HE160/5GHz") != NULL)
9409 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009410 }
developer615510b2022-09-27 10:14:35 +08009411 continue;
9412 } else if (strstr(line, "WPA") != NULL) {
9413 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9414 } else if (strstr(line, "RSN") != NULL) {
9415 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9416 } else if (strstr(line, "Group cipher") != NULL) {
9417 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9418 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9419 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009420 }
developer06a01d92022-09-07 16:32:39 +08009421 }
developer615510b2022-09-27 10:14:35 +08009422 ret = fgets(line, sizeof(line), f);
9423 }
9424
9425 if (!filter_BSS) {
9426 *output_array_size = index + 1;
9427 } else {
9428 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9429 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009430 }
developer06a01d92022-09-07 16:32:39 +08009431 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009432 pclose(f);
developer5550e242022-09-30 09:59:32 +08009433 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009435 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009436}
developer615510b2022-09-27 10:14:35 +08009437
developer06a01d92022-09-07 16:32:39 +08009438INT wifi_getApAssociatedDeviceStats(
9439 INT apIndex,
9440 mac_address_t *clientMacAddress,
9441 wifi_associated_dev_stats_t *associated_dev_stats,
9442 u64 *handle)
9443{
9444 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9445 char interface_name[50] = {0};
9446 char cmd[1024] = {0};
9447 char mac_str[18] = {0};
9448 char *key = NULL;
9449 char *val = NULL;
9450 FILE *f = NULL;
9451 char *line = NULL;
9452 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009453
9454 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9455 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9456 return RETURN_ERR;
9457 }
9458
9459 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9460 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9461 if((f = popen(cmd, "r")) == NULL) {
9462 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9463 return RETURN_ERR;
9464 }
9465
developer30423732022-12-01 16:17:49 +08009466 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009467 key = strtok(line,":");
9468 val = strtok(NULL,":");
9469
9470 if(!strncmp(key,"rx bytes",8))
9471 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9472 if(!strncmp(key,"tx bytes",8))
9473 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9474 if(!strncmp(key,"rx packets",10))
9475 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9476 if(!strncmp(key,"tx packets",10))
9477 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9478 if(!strncmp(key,"tx retries",10))
9479 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9480 if(!strncmp(key,"tx failed",9))
9481 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9482 if(!strncmp(key,"rx drop misc",13))
9483 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9484 if(!strncmp(key,"rx bitrate",10)) {
9485 val = strtok(val, " ");
9486 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9487 }
9488 if(!strncmp(key,"tx bitrate",10)) {
9489 val = strtok(val, " ");
9490 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9491 }
9492 }
9493 free(line);
9494 pclose(f);
9495 return RETURN_OK;
9496}
9497
9498INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9499{
developerd946fd62022-12-08 18:03:28 +08009500 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009501 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9502
9503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9504 if (NULL == output_string)
9505 return RETURN_ERR;
9506
developerac6f1142022-12-20 19:26:35 +08009507 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009508 return RETURN_ERR;
9509 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 +08009510 _syscmd(cmd, buf, sizeof(buf));
9511
9512 //size of SSID name restricted to value less than 32 bytes
9513 snprintf(output_string, 32, "%s", buf);
9514 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9515
9516 return RETURN_OK;
9517}
9518
9519INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9520{
9521 //char cmd[MAX_CMD_SIZE] = {0};
9522 char config_file[MAX_BUF_SIZE] = {0};
9523 char buf[32] = {0};
9524
9525 if (!output_filterMode)
9526 return RETURN_ERR;
9527
9528 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9529 //_syscmd(cmd, buf, sizeof(buf));
9530 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08009531 if (!syn_flag)
9532 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9533 else
developer07ded1f2024-01-10 10:30:15 +08009534 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer10adcc12022-09-13 14:39:17 +08009535 if(strlen(buf) == 0) {
9536 *output_filterMode = 0;
9537 }
9538 else {
9539 int macaddr_acl_mode = strtol(buf, NULL, 10);
9540 if (macaddr_acl_mode == 1) {
9541 *output_filterMode = 1;
9542 } else if (macaddr_acl_mode == 0) {
9543 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9544 if (strlen(buf) == 0) {
9545 *output_filterMode = 0;
9546 } else {
9547 *output_filterMode = 2;
9548 }
9549 } else {
9550 return RETURN_ERR;
9551 }
9552 }
developer06a01d92022-09-07 16:32:39 +08009553
9554 return RETURN_OK;
9555}
9556
9557INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9558{
9559 FILE *fp = NULL;
9560 char str[MAX_BUF_SIZE] = {0};
9561 int wificlientindex = 0 ;
9562 int count = 0;
9563 int signalstrength = 0;
9564 int arr[MACADDRESS_SIZE] = {0};
9565 unsigned char mac[MACADDRESS_SIZE] = {0};
9566 UINT wifi_count = 0;
9567 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9568 char pipeCmd[MAX_CMD_SIZE] = {0};
9569
9570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9571 *output_array_size = 0;
9572 *associated_dev_array = NULL;
9573 char interface_name[50] = {0};
9574
9575 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9576 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9577 return RETURN_ERR;
9578 }
9579
9580 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9581 fp = popen(pipeCmd, "r");
9582 if (fp == NULL)
9583 {
9584 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9585 return RETURN_ERR;
9586 }
9587
9588 /* Read the output a line at a time - output it. */
9589 fgets(str, sizeof(str)-1, fp);
9590 wifi_count = (unsigned int) atoi ( str );
9591 *output_array_size = wifi_count;
9592 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9593 pclose(fp);
9594
9595 if(wifi_count == 0)
9596 {
9597 return RETURN_OK;
9598 }
9599 else
9600 {
9601 wifi_associated_dev2_t* temp = NULL;
9602 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9603 *associated_dev_array = temp;
9604 if(temp == NULL)
9605 {
9606 printf("Error Statement. Insufficient memory \n");
9607 return RETURN_ERR;
9608 }
9609
9610 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9611 system(pipeCmd);
9612
9613 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9614 if(fp == NULL)
9615 {
9616 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9617 return RETURN_ERR;
9618 }
9619 fclose(fp);
9620
developer30423732022-12-01 16:17:49 +08009621 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009622 fp = popen(pipeCmd, "r");
9623 if(fp)
9624 {
9625 for(count =0 ; count < wifi_count; count++)
9626 {
9627 fgets(str, MAX_BUF_SIZE, fp);
9628 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9629 {
9630 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9631 {
9632 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9633
9634 }
9635 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9636 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]);
9637 }
9638 temp[count].cli_AuthenticationState = 1; //TODO
9639 temp[count].cli_Active = 1; //TODO
9640 }
9641 pclose(fp);
9642 }
9643
9644 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009645 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 +08009646 fp = popen(pipeCmd, "r");
9647 if(fp)
9648 {
9649 pclose(fp);
9650 }
9651 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9652 if(fp)
9653 {
9654 for(count =0 ; count < wifi_count ;count++)
9655 {
9656 fgets(str, MAX_BUF_SIZE, fp);
9657 signalstrength = atoi(str);
9658 temp[count].cli_RSSI = signalstrength;
9659 }
9660 pclose(fp);
9661 }
9662
9663
9664 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009665 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 +08009666 fp = popen(pipeCmd, "r");
9667 if (fp)
9668 {
9669 pclose(fp);
9670 }
9671 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9672 if (fp)
9673 {
9674 for (count = 0; count < wifi_count; count++)
9675 {
9676 fgets(str, MAX_BUF_SIZE, fp);
9677 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9678 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9679 }
9680 pclose(fp);
9681 }
9682
9683 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009684 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 +08009685 fp = popen(pipeCmd, "r");
9686 if (fp)
9687 {
9688 pclose(fp);
9689 }
9690 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9691 if (fp)
9692 {
9693 for (count = 0; count < wifi_count; count++)
9694 {
9695 fgets(str, MAX_BUF_SIZE, fp);
9696 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9697 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9698 }
9699 pclose(fp);
9700 }
9701 }
9702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9703 return RETURN_OK;
9704
9705}
9706
9707INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9708{
9709#if 0
9710 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009711 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009712 _syscmd(cmd, buf, sizeof(buf));*/
9713
9714 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9715 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9716 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9717 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9718
9719 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.
9720 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].
9721 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].
9722 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].
9723 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9724 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9725
9726 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9727 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9728 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9729 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.
9730 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.
9731 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.
9732 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.
9733 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.
9734 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.
9735 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.
9736 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9737#endif
9738
9739 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009740 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009741 char pipeCmd[128] = {0};
9742 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009743 wifi_ssidTrafficStats2_t *out = output_struct;
9744
developerce736392022-09-13 15:24:34 +08009745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009746 if (!output_struct)
9747 return RETURN_ERR;
9748
developerce736392022-09-13 15:24:34 +08009749 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009750 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009751 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009752 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009753
developer06a01d92022-09-07 16:32:39 +08009754 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009755 if (fp == NULL) {
9756 fprintf(stderr, "%s: popen failed\n", __func__);
9757 return RETURN_ERR;
9758 }
9759 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009760 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009761
developerce736392022-09-13 15:24:34 +08009762 if (strlen(str) == 0) // interface not exist
9763 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009764
developerce736392022-09-13 15:24:34 +08009765 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9766 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009767
developerce736392022-09-13 15:24:34 +08009768 memset(str, 0, sizeof(str));
9769 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009770 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009771 if (fp == NULL) {
9772 fprintf(stderr, "%s: popen failed\n", __func__);
9773 return RETURN_ERR;
9774 }
9775 fgets(str, sizeof(str), fp);
9776
9777 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9778 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009779 pclose(fp);
developerce736392022-09-13 15:24:34 +08009780
9781 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9782 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9783
9784 // Not supported
9785 output_struct->ssid_RetransCount = 0;
9786 output_struct->ssid_FailedRetransCount = 0;
9787 output_struct->ssid_RetryCount = 0;
9788 output_struct->ssid_MultipleRetryCount = 0;
9789 output_struct->ssid_ACKFailureCount = 0;
9790 output_struct->ssid_AggregatedPacketCount = 0;
9791
developer06a01d92022-09-07 16:32:39 +08009792 return RETURN_OK;
9793}
9794
9795//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).
9796INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9797{
9798 char output_val[16]={'\0'};
9799 char config_file[MAX_BUF_SIZE] = {0};
9800
9801 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9802 if (!output)
9803 return RETURN_ERR;
9804 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08009805 if (!syn_flag)
9806 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9807 else
developer07ded1f2024-01-10 10:30:15 +08009808 snprintf(output_val, sizeof(output_val), "%s", vap_info[apIndex].ap_isolate);
developer06a01d92022-09-07 16:32:39 +08009809 if( strcmp(output_val,"1") == 0 )
9810 *output = TRUE;
9811 else
9812 *output = FALSE;
9813 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9814
9815 return RETURN_OK;
9816}
9817
9818INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9819{
9820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9821 char str[MAX_BUF_SIZE]={'\0'};
9822 char string[MAX_BUF_SIZE]={'\0'};
9823 char cmd[MAX_CMD_SIZE]={'\0'};
9824 char *ch;
9825 char config_file[MAX_BUF_SIZE] = {0};
9826 struct params params;
9827
9828 if(enable == TRUE)
9829 strcpy(string,"1");
9830 else
9831 strcpy(string,"0");
9832
9833 params.name = "ap_isolate";
9834 params.value = string;
9835
9836 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9837 wifi_hostapdWrite(config_file,&params,1);
developerefb790a2023-12-26 18:58:32 +08009838 snprintf(vap_info[apIndex].ap_isolate, sizeof(vap_info[apIndex].ap_isolate), "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08009839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9840
9841 return RETURN_OK;
9842}
9843
9844INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9845{
9846 if (NULL == output_dBm)
9847 return RETURN_ERR;
9848
9849 *output_dBm = 0;
9850 return RETURN_OK;
9851}
9852
9853INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9854{
9855 return RETURN_OK;
9856}
9857INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9858{
9859 return RETURN_OK;
9860}
9861INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9862{
9863 return RETURN_OK;
9864}
9865INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9866{
9867 return RETURN_OK;
9868}
9869INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9870{
9871 return RETURN_OK;
9872}
9873INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9874{
9875 char config_file[MAX_BUF_SIZE] = {0};
9876 struct params list;
9877
9878 list.name = "bss_transition";
9879 list.value = activate?"1":"0";
9880 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9881 wifi_hostapdWrite(config_file, &list, 1);
developerefb790a2023-12-26 18:58:32 +08009882 snprintf(vap_info[apIndex].bss_transition, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08009883
9884 return RETURN_OK;
9885}
9886wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9887
9888void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9889{
9890 return;
9891}
9892
9893INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9894{
9895 // TODO Implement me!
9896 return RETURN_OK;
9897}
9898
9899INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9900{
developera3c68b92022-09-13 15:27:29 +08009901 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009902 FILE *f = NULL;
9903
developer72ec5572023-01-05 16:27:13 +08009904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009905
developer72ec5572023-01-05 16:27:13 +08009906 if (essid == NULL)
9907 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009908
developer72ec5572023-01-05 16:27:13 +08009909 if (strlen(essid) == 0 || apIndex == -1) {
9910 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9911 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009912 }
9913
developer72ec5572023-01-05 16:27:13 +08009914 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9915 f = fopen(file_name, "w");
9916 if (f == NULL)
9917 return RETURN_ERR;
9918
9919 // For mode == 0 is to disable filter, just don't write ssid to the file.
9920 fprintf(f, "%d\n%s", mode, mode?essid:"");
9921 fclose(f);
9922 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009923 return RETURN_OK;
9924}
9925
9926INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9927{
9928 // TODO Implement me!
9929 //Apply wifi_pushRadioChannel() instantly
9930 return RETURN_ERR;
9931}
9932
9933INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9934{
9935 // TODO Implement me!
9936 return RETURN_OK;
9937}
9938
9939#ifdef HAL_NETLINK_IMPL
9940static int tidStats_callback(struct nl_msg *msg, void *arg) {
9941 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9942 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9943 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9944 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9945 int rem , tid_index = 0;
9946
9947 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9948 wifi_associated_dev_tid_entry_t *stats_entry;
9949
9950 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9951 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9952 };
9953 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9954 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9955 };
9956
9957 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9958 genlmsg_attrlen(gnlh, 0), NULL);
9959
9960
9961 if (!tb[NL80211_ATTR_STA_INFO]) {
9962 fprintf(stderr, "station stats missing!\n");
9963 return NL_SKIP;
9964 }
9965
9966 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9967 tb[NL80211_ATTR_STA_INFO],
9968 stats_policy)) {
9969 fprintf(stderr, "failed to parse nested attributes!\n");
9970 return NL_SKIP;
9971 }
9972
9973 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9974 {
9975 stats_entry = &out->tid_array[tid_index];
9976
9977 stats_entry->tid = tid_index;
9978 stats_entry->ac = _tid_ac_index_get[tid_index];
9979
9980 if(sinfo[NL80211_STA_INFO_TID_STATS])
9981 {
9982 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9983 printf("failed to parse nested stats attributes!");
9984 return NL_SKIP;
9985 }
9986 }
9987 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9988 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9989
9990 if(tid_index < (PS_MAX_TID - 1))
9991 tid_index++;
9992 }
9993 //ToDo: sum_time_ms, ewma_time_ms
9994 return NL_SKIP;
9995}
9996#endif
9997
9998INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9999{
10000#ifdef HAL_NETLINK_IMPL
10001 Netlink nl;
10002 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010003 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010004
developerac6f1142022-12-20 19:26:35 +080010005 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010006 return RETURN_ERR;
10007
10008 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010009
10010 nl.id = initSock80211(&nl);
10011
10012 if (nl.id < 0) {
10013 fprintf(stderr, "Error initializing netlink \n");
10014 return -1;
10015 }
10016
10017 struct nl_msg* msg = nlmsg_alloc();
10018
10019 if (!msg) {
10020 fprintf(stderr, "Failed to allocate netlink message.\n");
10021 nlfree(&nl);
10022 return -2;
10023 }
10024
10025 genlmsg_put(msg,
10026 NL_AUTO_PORT,
10027 NL_AUTO_SEQ,
10028 nl.id,
10029 0,
10030 0,
10031 NL80211_CMD_GET_STATION,
10032 0);
10033
10034 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10035 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10036 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
10037 nl_send_auto(nl.socket, msg);
10038 nl_recvmsgs(nl.socket, nl.cb);
10039 nlmsg_free(msg);
10040 nlfree(&nl);
10041 return RETURN_OK;
10042#else
10043//iw implementation
10044#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10045#define TOTAL_MAX_LINES 50
10046
10047 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +080010048 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +080010049 FILE *fp=NULL;
10050 char pipeCmd[1024]= {'\0'};
10051 int lines,tid_index=0;
10052 char mac_addr[20] = {'\0'};
10053
developerac6f1142022-12-20 19:26:35 +080010054 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010055 return RETURN_ERR;
10056
developer06a01d92022-09-07 16:32:39 +080010057 wifi_associated_dev_tid_entry_t *stats_entry;
10058
developer06a01d92022-09-07 16:32:39 +080010059 strcpy(mac_addr,clientMacAddress);
10060
10061 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10062 fp= popen(pipeCmd,"r");
10063 if(fp == NULL)
10064 {
10065 perror("popen for station dump failed\n");
10066 return RETURN_ERR;
10067 }
10068 pclose(fp);
10069
10070 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10071 fp=popen(pipeCmd,"r");
10072 if(fp == NULL)
10073 {
10074 perror("popen for grep station failed\n");
10075 return RETURN_ERR;
10076 }
10077 else if(fgets(buf,sizeof(buf),fp) != NULL)
10078 lines=atoi(buf);
10079 else
10080 {
10081 pclose(fp);
10082 fprintf(stderr,"No devices are connected \n");
10083 return RETURN_ERR;
10084 }
10085 pclose(fp);
10086
10087 if(lines == 1)
10088 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10089
10090 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10091 {
10092 stats_entry = &tid_stats->tid_array[tid_index];
10093 stats_entry->tid = tid_index;
10094
10095 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);
10096
10097 fp=popen(pipeCmd,"r");
10098 if(fp ==NULL)
10099 {
10100 perror("Failed to read from tid file \n");
10101 return RETURN_ERR;
10102 }
10103 else if(fgets(buf,sizeof(buf),fp) != NULL)
10104 stats_entry->num_msdus = atol(buf);
10105
10106 pclose(fp);
10107 stats_entry->ac = _tid_ac_index_get[tid_index];
10108// TODO:
10109// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10110// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10111 }
10112 return RETURN_OK;
10113#endif
10114}
10115
10116
10117INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10118{
developerd946fd62022-12-08 18:03:28 +080010119 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +080010120 char cmd[128]={0};
10121 char buf[128]={0};
10122 int freq = 0;
10123
10124 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10125
10126 // full mode is used to scan all channels.
10127 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10128 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10129 ieee80211_channel_to_frequency(chan_list[0], &freq);
10130
developerac6f1142022-12-20 19:26:35 +080010131 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010132 return RETURN_ERR;
10133
developer615510b2022-09-27 10:14:35 +080010134 if (freq)
developerd946fd62022-12-08 18:03:28 +080010135 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010136 else
developerd946fd62022-12-08 18:03:28 +080010137 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010138
10139 _syscmd(cmd, buf, sizeof(buf));
10140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10141
developer06a01d92022-09-07 16:32:39 +080010142 return RETURN_OK;
10143}
10144
10145
10146INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10147{
10148 // TODO Implement me!
10149 return RETURN_ERR;
10150}
10151
10152INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10153{
10154 // TODO Implement me!
10155 return RETURN_ERR;
10156}
10157
10158INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10159{
10160 // TODO Implement me!
10161 return RETURN_ERR;
10162}
10163
10164INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10165{
10166 // TODO Implement me!
10167 return RETURN_ERR;
10168}
10169
10170INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10171{
10172 // TODO Implement me!
10173 return RETURN_ERR;
10174}
10175
10176INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10177{
10178 // TODO Implement me!
10179 return RETURN_ERR;
10180}
10181
10182INT wifi_steering_eventUnregister(void)
10183{
10184 // TODO Implement me!
10185 return RETURN_ERR;
10186}
10187
10188INT wifi_delApAclDevices(INT apIndex)
10189{
10190#if 0
10191 char cmd[MAX_BUF_SIZE] = {0};
10192 char buf[MAX_BUF_SIZE] = {0};
10193
10194 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010195 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010196 if(_syscmd(cmd,buf,sizeof(buf)))
10197 return RETURN_ERR;
10198#endif
developer9988c232023-03-06 14:57:08 +080010199 char cmd[256]={0};
10200 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010201
developere6aafda2022-09-13 14:59:28 +080010202 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010203 sprintf(cmd, "rm %s%d %s%d 2>&1 && touch %s%d %s%d", ACL_PREFIX, apIndex, DENY_PREFIX, apIndex, ACL_PREFIX, apIndex, DENY_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +080010204 if(_syscmd(cmd, buf, sizeof(buf)))
10205 return RETURN_ERR;
10206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010207
10208 return RETURN_OK;
10209}
10210
10211#ifdef HAL_NETLINK_IMPL
10212static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10213 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10214 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10215 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10216 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10217 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10218 char mac_addr[20],dev[20];
10219
10220 nla_parse(tb,
10221 NL80211_ATTR_MAX,
10222 genlmsg_attrdata(gnlh, 0),
10223 genlmsg_attrlen(gnlh, 0),
10224 NULL);
10225
10226 if(!tb[NL80211_ATTR_STA_INFO]) {
10227 fprintf(stderr, "sta stats missing!\n");
10228 return NL_SKIP;
10229 }
10230
10231 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10232 fprintf(stderr, "failed to parse nested attributes!\n");
10233 return NL_SKIP;
10234 }
10235 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10236
10237 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10238
10239 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10240 fprintf(stderr, "failed to parse nested rate attributes!");
10241 return NL_SKIP;
10242 }
10243
10244 if(sinfo[NL80211_STA_INFO_TID_STATS])
10245 {
10246 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10247 printf("failed to parse nested stats attributes!");
10248 return NL_SKIP;
10249 }
10250 }
10251
10252 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10253 {
10254 printf("Type is VHT\n");
10255 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10256 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10257
10258 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10259 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10260 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10261 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10262 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10263 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10264 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10265 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10266 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10267 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10268 }
10269 else
10270 {
10271 printf(" OFDM or CCK \n");
10272 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10273 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10274 }
10275
10276 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10277 if(rinfo[NL80211_RATE_INFO_MCS])
10278 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10279 }
10280 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10281 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10282 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10283 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10284
10285 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10286 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10287
10288 if (sinfo[NL80211_STA_INFO_SIGNAL])
10289 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10290 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10291 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10292 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10293 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10294 //rssi_array need to be filled
10295 return NL_SKIP;
10296}
10297#endif
10298
10299INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10300{
10301#ifdef HAL_NETLINK_IMPL
10302 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010303 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010304 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010305 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010306
10307 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10308
10309 if (*output_array_size <= 0)
10310 return RETURN_OK;
10311
developer06a01d92022-09-07 16:32:39 +080010312 nl.id = initSock80211(&nl);
10313
10314 if (nl.id < 0) {
10315 fprintf(stderr, "Error initializing netlink \n");
10316 return 0;
10317 }
10318
10319 struct nl_msg* msg = nlmsg_alloc();
10320
10321 if (!msg) {
10322 fprintf(stderr, "Failed to allocate netlink message.\n");
10323 nlfree(&nl);
10324 return 0;
10325 }
10326
10327 genlmsg_put(msg,
10328 NL_AUTO_PORT,
10329 NL_AUTO_SEQ,
10330 nl.id,
10331 0,
10332 0,
10333 NL80211_CMD_GET_STATION,
10334 0);
10335
10336 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10337 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10338 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10339 nl_send_auto(nl.socket, msg);
10340 nl_recvmsgs(nl.socket, nl.cb);
10341 nlmsg_free(msg);
10342 nlfree(&nl);
10343 return RETURN_OK;
10344#else
10345 //TODO Implement me
10346 return RETURN_OK;
10347#endif
10348}
10349
10350#ifdef HAL_NETLINK_IMPL
10351static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10352 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10353 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10354 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10355 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10356 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10357 char mac_addr[20],dev[20];
10358
10359 nla_parse(tb,
10360 NL80211_ATTR_MAX,
10361 genlmsg_attrdata(gnlh, 0),
10362 genlmsg_attrlen(gnlh, 0),
10363 NULL);
10364
10365 if(!tb[NL80211_ATTR_STA_INFO]) {
10366 fprintf(stderr, "sta stats missing!\n");
10367 return NL_SKIP;
10368 }
10369
10370 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10371 fprintf(stderr, "failed to parse nested attributes!\n");
10372 return NL_SKIP;
10373 }
10374
10375 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10376
10377 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10378
10379 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10380 fprintf(stderr, "failed to parse nested rate attributes!");
10381 return NL_SKIP;
10382 }
10383
10384 if(sinfo[NL80211_STA_INFO_TID_STATS])
10385 {
10386 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10387 printf("failed to parse nested stats attributes!");
10388 return NL_SKIP;
10389 }
10390 }
10391 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10392 {
10393 printf("Type is VHT\n");
10394 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10395 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10396
10397 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10398 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10399 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10400 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10401 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10402 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10403 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10404 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10405 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10406 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10407 }
10408 else
10409 {
10410 printf(" OFDM or CCK \n");
10411 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10412 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10413 }
10414
10415 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10416 if(rinfo[NL80211_RATE_INFO_MCS])
10417 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10418 }
10419
10420 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10421 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10422 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10423 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10424
10425 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10426 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10427 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10428
10429 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10430 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10431
10432 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10433 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10434
10435 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10436 ((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]);
10437
10438 return NL_SKIP;
10439}
10440#endif
10441
10442INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10443{
10444#ifdef HAL_NETLINK_IMPL
10445 Netlink nl;
10446 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010447 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010448 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010449 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010450
10451 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10452
10453 if (*output_array_size <= 0)
10454 return RETURN_OK;
10455
developerd946fd62022-12-08 18:03:28 +080010456 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010457
10458 nl.id = initSock80211(&nl);
10459
10460 if(nl.id < 0) {
10461 fprintf(stderr, "Error initializing netlink \n");
10462 return 0;
10463 }
10464
10465 struct nl_msg* msg = nlmsg_alloc();
10466
10467 if(!msg) {
10468 fprintf(stderr, "Failed to allocate netlink message.\n");
10469 nlfree(&nl);
10470 return 0;
10471 }
10472
10473 genlmsg_put(msg,
10474 NL_AUTO_PORT,
10475 NL_AUTO_SEQ,
10476 nl.id,
10477 0,
10478 0,
10479 NL80211_CMD_GET_STATION,
10480 0);
10481
10482 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10483 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10484 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10485 nl_send_auto(nl.socket, msg);
10486 nl_recvmsgs(nl.socket, nl.cb);
10487 nlmsg_free(msg);
10488 nlfree(&nl);
10489 return RETURN_OK;
10490#else
10491 //TODO Implement me
10492 return RETURN_OK;
10493#endif
10494}
10495
10496INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10497{
10498 // TODO Implement me!
10499 char buf[MAX_BUF_SIZE] = {0};
10500 char config_file[MAX_BUF_SIZE] = {0};
10501
10502 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +080010503 if (!syn_flag)
10504 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10505 else
developer07ded1f2024-01-10 10:30:15 +080010506 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].bss_transition);
developer06a01d92022-09-07 16:32:39 +080010507 *activate = (strncmp("1",buf,1) == 0);
10508
10509 return RETURN_OK;
10510}
10511
10512INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10513{
10514 char config_file[MAX_BUF_SIZE] = {0};
10515 struct params list;
10516
10517 list.name = "rrm_neighbor_report";
10518 list.value = activate?"1":"0";
10519 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10520 wifi_hostapdWrite(config_file, &list, 1);
10521
10522 return RETURN_OK;
10523}
10524
10525INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10526{
10527 char buf[32] = {0};
10528 char config_file[MAX_BUF_SIZE] = {0};
10529
10530 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10531 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10532 *activate = (strncmp("1",buf,1) == 0);
10533
10534 return RETURN_OK;
10535}
10536#undef HAL_NETLINK_IMPL
10537#ifdef HAL_NETLINK_IMPL
10538static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10539 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10540 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10541 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10542 char dev[20];
10543 int freq =0 ;
10544 static int i=0;
10545
10546 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10547
10548 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10549 };
10550
10551 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10552
10553 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10554
10555 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10556 fprintf(stderr, "survey data missing!\n");
10557 return NL_SKIP;
10558 }
10559
10560 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10561 {
10562 fprintf(stderr, "failed to parse nested attributes!\n");
10563 return NL_SKIP;
10564 }
10565
10566
10567 if(out[0].array_size == 1 )
10568 {
10569 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10570 {
10571 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10572 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10573 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10574
10575 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10576 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10577 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10578 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10579 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10580 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10581 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10582 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10583 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10584 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10585 if (sinfo[NL80211_SURVEY_INFO_TIME])
10586 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10587 return NL_STOP;
10588 }
10589 }
10590 else
10591 {
10592 if ( i <= out[0].array_size )
10593 {
10594 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10595 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10596 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10597
10598 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10599 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10600 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10601 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10602 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10603 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10604 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10605 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10606 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10607 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10608 if (sinfo[NL80211_SURVEY_INFO_TIME])
10609 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10610 }
10611 }
10612
10613 i++;
10614 return NL_SKIP;
10615}
10616#endif
10617
10618static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10619{
10620 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10621 FILE *fp;
10622
10623 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10624 {
10625 printf("Creating Frequency-Channel Map\n");
10626 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10627 }
10628 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10629 if((fp = popen(command, "r")))
10630 {
10631 fgets(output, sizeof(output), fp);
10632 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010633 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010634 }
10635
10636 return 0;
10637}
10638
10639static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10640{
10641 int freqMHz = -1;
10642 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010643 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010644
10645 ieee80211_channel_to_frequency(channel, &freqMHz);
10646 if (freqMHz == -1) {
10647 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10648 return -1;
10649 }
10650
developer7930d352022-12-21 17:55:42 +080010651 wifi_GetInterfaceName(radioIndex, interface_name);
10652 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010653 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10654 radioIndex, freqMHz);
10655 return -1;
10656 }
10657
10658 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10659 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10660 return -1;
10661 }
10662
10663 return 0;
10664}
10665
10666static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10667{
10668 const char *ptr = buf;
10669 char *key = NULL;
10670 char *val = NULL;
10671 char line[256] = { '\0' };
10672
10673 while (ptr = get_line_from_str_buf(ptr, line)) {
10674 if (strstr(line, "Frequency")) continue;
10675
10676 key = strtok(line, ":");
10677 val = strtok(NULL, " ");
10678 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10679
10680 if (!strcmp(key, "noise")) {
10681 sscanf(val, "%d", &stats->ch_noise);
10682 if (stats->ch_noise == 0) {
10683 // Workaround for missing noise information.
10684 // Assume -95 for 2.4G and -103 for 5G
10685 if (radioIndex == 0) stats->ch_noise = -95;
10686 if (radioIndex == 1) stats->ch_noise = -103;
10687 }
10688 }
10689 else if (!strcmp(key, "channel active time")) {
10690 sscanf(val, "%llu", &stats->ch_utilization_total);
10691 }
10692 else if (!strcmp(key, "channel busy time")) {
10693 sscanf(val, "%llu", &stats->ch_utilization_busy);
10694 }
10695 else if (!strcmp(key, "channel receive time")) {
10696 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10697 }
10698 else if (!strcmp(key, "channel transmit time")) {
10699 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10700 }
10701 };
10702
10703 return 0;
10704}
10705
10706INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10707{
10708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10709#ifdef HAL_NETLINK_IMPL
10710 Netlink nl;
10711 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010712 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010713
10714 local[0].array_size = array_size;
10715
developerac6f1142022-12-20 19:26:35 +080010716 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010717 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010718
10719 nl.id = initSock80211(&nl);
10720
10721 if (nl.id < 0) {
10722 fprintf(stderr, "Error initializing netlink \n");
10723 return -1;
10724 }
10725
10726 struct nl_msg* msg = nlmsg_alloc();
10727
10728 if (!msg) {
10729 fprintf(stderr, "Failed to allocate netlink message.\n");
10730 nlfree(&nl);
10731 return -2;
10732 }
10733
10734 genlmsg_put(msg,
10735 NL_AUTO_PORT,
10736 NL_AUTO_SEQ,
10737 nl.id,
10738 0,
10739 NLM_F_DUMP,
10740 NL80211_CMD_GET_SURVEY,
10741 0);
10742
10743 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10744 nl_send_auto(nl.socket, msg);
10745 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10746 nl_recvmsgs(nl.socket, nl.cb);
10747 nlmsg_free(msg);
10748 nlfree(&nl);
10749 //Copying the Values
10750 for(int i=0;i<array_size;i++)
10751 {
10752 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10753 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10754 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10755 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10756 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10757 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10758 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10759 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10760 }
10761#else
10762 ULONG channel = 0;
10763 int i;
10764 int number_of_channels = array_size;
10765 char buf[512];
10766 INT ret;
10767 wifi_channelStats_t tmp_stats;
10768
10769 if (number_of_channels == 0) {
10770 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10771 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10772 return RETURN_ERR;
10773 }
10774 number_of_channels = 1;
10775 input_output_channelStats_array[0].ch_number = channel;
10776 }
10777
10778 for (i = 0; i < number_of_channels; i++) {
10779
10780 input_output_channelStats_array[i].ch_noise = 0;
10781 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10782 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10783 input_output_channelStats_array[i].ch_utilization_busy = 0;
10784 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10785 input_output_channelStats_array[i].ch_utilization_total = 0;
10786
10787 memset(buf, 0, sizeof(buf));
10788 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10789 return RETURN_ERR;
10790 }
10791 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10792 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10793 return RETURN_ERR;
10794 }
10795
10796 // XXX: fake missing 'self' counter which is not available in iw survey output
10797 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10798 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10799
10800 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10801 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10802 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10803 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10804 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10805
10806 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",
10807 __func__,
10808 input_output_channelStats_array[i].ch_number,
10809 input_output_channelStats_array[i].ch_noise,
10810 input_output_channelStats_array[i].ch_utilization_total,
10811 input_output_channelStats_array[i].ch_utilization_busy,
10812 input_output_channelStats_array[i].ch_utilization_busy_rx,
10813 input_output_channelStats_array[i].ch_utilization_busy_tx,
10814 input_output_channelStats_array[i].ch_utilization_busy_self,
10815 input_output_channelStats_array[i].ch_utilization_busy_ext);
10816 }
10817#endif
10818 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10819 return RETURN_OK;
10820}
10821#define HAL_NETLINK_IMPL
10822
10823/* Hostapd events */
10824
10825#ifndef container_of
10826#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10827#define container_of(ptr, type, member) \
10828 ((type *)((char *)ptr - offset_of(type, member)))
10829#endif /* container_of */
10830
10831struct ctrl {
10832 char sockpath[128];
10833 char sockdir[128];
10834 char bss[IFNAMSIZ];
10835 char reply[4096];
10836 int ssid_index;
10837 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10838 void (*overrun)(struct ctrl *ctrl);
10839 struct wpa_ctrl *wpa;
10840 unsigned int ovfl;
10841 size_t reply_len;
10842 int initialized;
10843 ev_timer retry;
10844 ev_timer watchdog;
10845 ev_stat stat;
10846 ev_io io;
10847};
10848static wifi_newApAssociatedDevice_callback clients_connect_cb;
10849static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10850static struct ctrl wpa_ctrl[MAX_APS];
10851static int initialized;
10852
10853static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10854{
10855 char cbuf[256] = {};
10856 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10857 struct cmsghdr *cmsg;
10858 unsigned int ovfl = ctrl->ovfl;
10859 unsigned int drop;
10860
10861 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10862 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10863 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10864 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10865
10866 drop = ovfl - ctrl->ovfl;
10867 ctrl->ovfl = ovfl;
10868
10869 return drop;
10870}
10871
10872static void ctrl_close(struct ctrl *ctrl)
10873{
10874 if (ctrl->io.cb)
10875 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10876 if (ctrl->retry.cb)
10877 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10878 if (!ctrl->wpa)
10879 return;
10880
10881 wpa_ctrl_detach(ctrl->wpa);
10882 wpa_ctrl_close(ctrl->wpa);
10883 ctrl->wpa = NULL;
10884 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10885}
10886
10887static void ctrl_process(struct ctrl *ctrl)
10888{
10889 const char *str;
10890 int drops;
10891 int level;
10892 int err;
10893
10894 /* Example events:
10895 *
10896 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10897 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10898 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10899 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10900 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10901 */
10902 if (!(str = index(ctrl->reply, '>')))
10903 return;
10904 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10905 return;
10906
10907 str++;
10908
10909 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10910 if (!(str = index(ctrl->reply, ' ')))
10911 return;
10912 wifi_associated_dev_t sta;
10913 memset(&sta, 0, sizeof(sta));
10914
10915 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10916 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10917 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10918
10919 sta.cli_Active=true;
10920
10921 (clients_connect_cb)(ctrl->ssid_index, &sta);
10922 goto handled;
10923 }
10924
10925 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10926 if (!(str = index(ctrl->reply, ' ')))
10927 return;
10928
10929 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10930 goto handled;
10931 }
10932
10933 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10934 printf("CTRL_WPA: handle TERMINATING event\n");
10935 goto retry;
10936 }
10937
10938 if (strncmp("AP-DISABLED", str, 11) == 0) {
10939 printf("CTRL_WPA: handle AP-DISABLED\n");
10940 goto retry;
10941 }
10942
10943 printf("Event not supported!!\n");
10944
10945handled:
10946
10947 if ((drops = ctrl_get_drops(ctrl))) {
10948 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10949 if (ctrl->overrun)
10950 ctrl->overrun(ctrl);
10951 }
10952
10953 return;
10954
10955retry:
10956 printf("WPA_CTRL: closing\n");
10957 ctrl_close(ctrl);
10958 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10959 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10960}
10961
10962static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10963{
10964 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10965 int err;
10966
10967 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10968 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10969 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10970 ctrl->reply[ctrl->reply_len] = 0;
10971 if (err < 0) {
10972 if (errno == EAGAIN || errno == EWOULDBLOCK)
10973 return;
10974 ctrl_close(ctrl);
10975 ev_timer_again(EV_A_ &ctrl->retry);
10976 return;
10977 }
10978
10979 ctrl_process(ctrl);
10980}
10981
10982static int ctrl_open(struct ctrl *ctrl)
10983{
10984 int fd;
10985
10986 if (ctrl->wpa)
10987 return 0;
10988
10989 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10990 if (!ctrl->wpa)
10991 goto err;
10992
10993 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10994 goto err_close;
10995
10996 fd = wpa_ctrl_get_fd(ctrl->wpa);
10997 if (fd < 0)
10998 goto err_detach;
10999
11000 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11001 goto err_detach;
11002
11003 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11004 ev_io_start(EV_DEFAULT_ &ctrl->io);
11005
11006 return 0;
11007
11008err_detach:
11009 wpa_ctrl_detach(ctrl->wpa);
11010err_close:
11011 wpa_ctrl_close(ctrl->wpa);
11012err:
11013 ctrl->wpa = NULL;
11014 return -1;
11015}
11016
11017static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11018{
11019 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11020
11021 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11022 ctrl_open(ctrl);
11023}
11024
11025static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11026{
11027 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11028
11029 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11030 if (ctrl_open(ctrl) == 0) {
11031 printf("WPA_CTRL: retry successful\n");
11032 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11033 }
11034}
11035
11036int ctrl_enable(struct ctrl *ctrl)
11037{
11038 if (ctrl->wpa)
11039 return 0;
11040
11041 if (!ctrl->stat.cb) {
11042 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11043 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11044 }
11045
11046 if (!ctrl->retry.cb) {
11047 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11048 }
11049
11050 return ctrl_open(ctrl);
11051}
11052
11053static void
11054ctrl_msg_cb(char *buf, size_t len)
11055{
11056 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11057
11058 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11059 ctrl_process(ctrl);
11060}
11061
11062static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11063{
11064 int err;
11065
11066 if (!ctrl->wpa)
11067 return -1;
11068 if (*reply_len < 2)
11069 return -1;
11070
11071 (*reply_len)--;
11072 ctrl->reply_len = sizeof(ctrl->reply);
11073 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11074 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11075 if (err < 0)
11076 return err;
11077
11078 if (ctrl->reply_len > *reply_len)
11079 ctrl->reply_len = *reply_len;
11080
11081 *reply_len = ctrl->reply_len;
11082 memcpy(reply, ctrl->reply, *reply_len);
11083 reply[*reply_len - 1] = 0;
11084 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11085 return 0;
11086}
11087
11088static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11089{
11090 const char *pong = "PONG";
11091 const char *ping = "PING";
11092 char reply[1024];
11093 size_t len = sizeof(reply);
11094 int err;
11095 ULONG s, snum;
11096 INT ret;
11097 BOOL status;
11098
11099 printf("WPA_CTRL: watchdog cb\n");
11100
11101 ret = wifi_getSSIDNumberOfEntries(&snum);
11102 if (ret != RETURN_OK) {
11103 printf("%s: failed to get SSID count", __func__);
11104 return;
11105 }
11106
11107 if (snum > MAX_APS) {
11108 printf("more ssid than supported! %lu\n", snum);
11109 return;
11110 }
11111
11112 for (s = 0; s < snum; s++) {
11113 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080011114 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080011115 continue;
11116 }
11117 if (status == false) continue;
11118
11119 memset(reply, 0, sizeof(reply));
11120 len = sizeof(reply);
11121 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11122 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11123 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11124 continue;
11125
11126 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11127 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080011128 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080011129 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11130 }
11131}
11132
11133static int init_wpa()
11134{
11135 int ret = 0, i = 0;
11136 ULONG s, snum;
11137
11138 ret = wifi_getSSIDNumberOfEntries(&snum);
11139 if (ret != RETURN_OK) {
11140 printf("%s: failed to get SSID count", __func__);
11141 return RETURN_ERR;
11142 }
11143
11144 if (snum > MAX_APS) {
11145 printf("more ssid than supported! %lu\n", snum);
11146 return RETURN_ERR;
11147 }
11148
11149 for (s = 0; s < snum; s++) {
11150 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11151 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11152 wpa_ctrl[s].ssid_index = s;
11153 ctrl_enable(&wpa_ctrl[s]);
11154 }
11155
11156 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11157 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11158
11159 initialized = 1;
11160 printf("WPA_CTRL: initialized\n");
11161
11162 return RETURN_OK;
11163}
11164
11165void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11166{
11167 clients_connect_cb = callback_proc;
11168 if (!initialized)
11169 init_wpa();
11170}
11171
11172void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11173{
11174 clients_disconnect_cb = callback_proc;
11175 if (!initialized)
11176 init_wpa();
11177}
11178
11179INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11180{
11181 // TODO Implement me!
11182 return RETURN_ERR;
11183}
11184
11185INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11186{
11187 // TODO Implement me!
11188 return RETURN_ERR;
11189}
11190
11191INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11192{
11193 int i;
developer4b102122023-02-15 10:53:03 +080011194 int phyId = -1;
11195 char cmd[256] = {0};
11196 char channel_numbers_buf[256] = {0};
11197 char dfs_state_buf[256] = {0};
11198 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011199 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011200 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011201
developer4b102122023-02-15 10:53:03 +080011202 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011203
developer4b102122023-02-15 10:53:03 +080011204 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11205 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011206
developer4b102122023-02-15 10:53:03 +080011207 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 +080011208
developer4b102122023-02-15 10:53:03 +080011209 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11210 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11211 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011212 }
11213
developer4b102122023-02-15 10:53:03 +080011214 ptr = channel_numbers_buf;
11215 i = 0;
11216 while (ptr = get_line_from_str_buf(ptr, line)) {
11217 if (i >= outputMapSize) {
11218 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11219 return RETURN_ERR;
11220 }
11221 sscanf(line, "%d", &outputMap[i].ch_number);
11222
11223 memset(cmd, 0, sizeof(cmd));
11224 // Below command should fetch string for DFS state (usable, available or unavailable)
11225 // Example line: "DFS state: usable (for 78930 sec)"
11226 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) {
11227 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011228 return RETURN_ERR;
11229 }
11230
developer4b102122023-02-15 10:53:03 +080011231 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11232 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011233 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11234 return RETURN_ERR;
11235 }
11236
developer4b102122023-02-15 10:53:03 +080011237 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011238
developer4b102122023-02-15 10:53:03 +080011239 if (!strcmp(dfs_state_buf, "usable")) {
11240 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11241 } else if (!strcmp(dfs_state_buf, "available")) {
11242 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11243 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11244 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11245 } else {
11246 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011247 }
developer4b102122023-02-15 10:53:03 +080011248 i++;
developer06a01d92022-09-07 16:32:39 +080011249 }
11250
developer4b102122023-02-15 10:53:03 +080011251 return RETURN_OK;
11252
developer06a01d92022-09-07 16:32:39 +080011253 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11254 return RETURN_ERR;
11255}
11256
11257INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11258{
11259 // TODO Implement me!
11260 return RETURN_ERR;
11261}
11262
11263INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11264{
11265 return RETURN_OK;
11266}
11267
11268INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11269{
11270 // TODO Implement me!
11271 return RETURN_ERR;
11272}
11273
11274INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11275{
11276 // TODO API refrence Implementaion is present on RPI hal
11277 return RETURN_ERR;
11278}
11279
developerfeab1d12023-09-27 11:29:38 +080011280
developer06a01d92022-09-07 16:32:39 +080011281INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11282{
developera5005b62022-09-13 15:43:35 +080011283 char cmd[128]={'\0'};
11284 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011285 int radioIndex = -1;
11286 int phyIndex = -1;
11287 bool enabled = false;
11288 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011289
11290 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011291
developera5005b62022-09-13 15:43:35 +080011292 if(txpwr_pcntg == NULL)
11293 return RETURN_ERR;
11294
developerfeab1d12023-09-27 11:29:38 +080011295 // The API name as getRadioXXX, I think the input index should be radioIndex,
11296 // but current we not change the name, but use it as radioIndex
11297 radioIndex = apIndex;
11298 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011299
developera5005b62022-09-13 15:43:35 +080011300 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011301 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11302 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011303 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011304 if (strcmp(buf, "enable") == 0)
11305 enabled = true;
developera5005b62022-09-13 15:43:35 +080011306
developerfeab1d12023-09-27 11:29:38 +080011307 if (!enabled) {
11308 *txpwr_pcntg = 100;
11309 return RETURN_OK;
11310 }
11311
developera5005b62022-09-13 15:43:35 +080011312 memset(cmd, 0, sizeof(cmd));
11313 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011314 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11315 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011316 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011317 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011318
developerfeab1d12023-09-27 11:29:38 +080011319 switch (cur_tx_dbm) {
11320 case 0:
11321 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011322 break;
developerfeab1d12023-09-27 11:29:38 +080011323 case 1:
11324 *txpwr_pcntg = 75; // range 61-90
11325 break;
11326 case 3:
11327 *txpwr_pcntg = 50; // range 31-60
11328 break;
11329 case 6:
11330 *txpwr_pcntg = 25; // range 16-30
11331 break;
11332 case 9:
11333 *txpwr_pcntg = 12; // range 10-15
11334 break;
11335 case 12:
11336 *txpwr_pcntg = 6; // range 1-9
11337 break;
11338 default:
11339 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011340 }
developerfeab1d12023-09-27 11:29:38 +080011341
developer06a01d92022-09-07 16:32:39 +080011342 return RETURN_OK;
11343}
11344
11345INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11346{
developer58599c22022-09-13 16:40:34 +080011347 // TODO precac feature.
11348 struct params params = {0};
11349 char config_file[128] = {0};
11350
11351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11352
11353 params.name = "enable_background_radar";
11354 params.value = enable?"1":"0";
11355 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11356 wifi_hostapdWrite(config_file, &params, 1);
11357 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11358
11359 /* TODO precac feature */
11360
11361 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11362 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011363}
11364
11365INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11366{
developer58599c22022-09-13 16:40:34 +080011367 char config_file[128] = {0};
11368 char buf[64] = {0};
11369
11370 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11371 if (NULL == enable || NULL == precac)
11372 return RETURN_ERR;
11373
11374 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11375 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011376 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011377 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011378 *precac = true;
11379 } else {
developer58599c22022-09-13 16:40:34 +080011380 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011381 *precac = false;
11382 }
developer58599c22022-09-13 16:40:34 +080011383
11384 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11385 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011386}
11387
11388INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11389{
developer58599c22022-09-13 16:40:34 +080011390 *supported = TRUE;
11391 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011392}
11393
developera7149722023-01-11 11:36:21 +080011394bool check_is_hemu_vendor_new_patch() {
11395 char cmd[128] = {0};
11396 char buf[128] = {0};
11397
11398 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11399 _syscmd(cmd, buf, sizeof(buf));
11400
11401 if (strlen(buf) > 0)
11402 return FALSE;
11403 else
11404 return TRUE;
11405}
11406
developer3e6b1692022-09-30 18:04:05 +080011407INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11408{
11409 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11410 struct params params = {0};
11411 char config_file[64] = {0};
11412 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011413 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011414 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011415 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11417
developera7149722023-01-11 11:36:21 +080011418 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011419
11420 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11421 set_mu_type &= ~0x05; // unset bit 0, 2
11422 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11423 set_mu_type |= 0x01;
11424 set_mu_type &= ~0x04;
11425 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11426 set_mu_type &= ~0x01;
11427 set_mu_type |= 0x04;
11428 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11429 set_mu_type |= 0x05; // set bit 0, 2
11430 }
11431
developera7149722023-01-11 11:36:21 +080011432 new_vendor_patch = check_is_hemu_vendor_new_patch();
11433 if (new_vendor_patch)
11434 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11435 else
11436 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11437
11438 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011439 sprintf(buf, "%u", set_mu_type);
11440 params.value = buf;
11441 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11442 wifi_hostapdWrite(config_file, &params, 1);
11443 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011444 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011445
11446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11447 return RETURN_OK;
11448}
11449
11450INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11451{
11452 struct params params={0};
11453 char config_file[64] = {0};
11454 char buf[64] = {0};
11455 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011456 bool new_vendor_patch = FALSE;
11457 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011458
11459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11460
11461 if (mu_type == NULL)
11462 return RETURN_ERR;
11463
developera7149722023-01-11 11:36:21 +080011464 new_vendor_patch = check_is_hemu_vendor_new_patch();
11465
11466 if (new_vendor_patch)
11467 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11468 else
11469 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11470
developer3e6b1692022-09-30 18:04:05 +080011471 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011472 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011473 get_mu_type = strtol(buf, NULL, 10);
11474
11475 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11476 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11477 else if (get_mu_type & 0x04)
11478 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11479 else if (get_mu_type & 0x01)
11480 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11481 else
11482 *mu_type = WIFI_DL_MU_TYPE_NONE;
11483
11484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11485 return RETURN_OK;
11486}
11487
11488INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11489{
11490 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11491 struct params params={0};
11492 char config_file[64] = {0};
11493 char buf[64] = {0};
11494 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011495 bool new_vendor_patch = FALSE;
11496 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11498
developera7149722023-01-11 11:36:21 +080011499 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011500
11501 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11502 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11503 set_mu_type &= ~0x0a;
11504 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11505 set_mu_type |= 0x02;
11506 set_mu_type &= ~0x08;
11507 }
11508
developera7149722023-01-11 11:36:21 +080011509 new_vendor_patch = check_is_hemu_vendor_new_patch();
11510
11511 if (new_vendor_patch)
11512 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11513 else
11514 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11515
11516 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011517 sprintf(buf, "%u", set_mu_type);
11518 params.value = buf;
11519 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11520 wifi_hostapdWrite(config_file, &params, 1);
11521 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011522 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011523
11524 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11525 return RETURN_OK;
11526}
11527
11528INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11529{
11530 struct params params={0};
11531 char config_file[64] = {0};
11532 char buf[64] = {0};
11533 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011534 bool new_vendor_patch = FALSE;
11535 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011536
11537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11538
developera7149722023-01-11 11:36:21 +080011539 new_vendor_patch = check_is_hemu_vendor_new_patch();
11540
11541 if (new_vendor_patch)
11542 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11543 else
11544 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11545
developer3e6b1692022-09-30 18:04:05 +080011546 if (mu_type == NULL)
11547 return RETURN_ERR;
11548
11549 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011550 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011551
11552 get_mu_type = strtol(buf, NULL, 10);
11553 if (get_mu_type & 0x02)
11554 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11555 else
11556 *mu_type = WIFI_DL_MU_TYPE_NONE;
11557
11558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11559 return RETURN_OK;
11560}
11561
11562
developer454b9462022-09-13 15:29:16 +080011563INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11564{
11565 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011566 char buf[256] = {0};
11567 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011568 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011569 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011570 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011571 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011572
11573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11574
developer254882b2022-09-30 17:12:31 +080011575 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011576 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11577 return RETURN_ERR;
11578 }
developer454b9462022-09-13 15:29:16 +080011579
developer254882b2022-09-30 17:12:31 +080011580 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011581 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011582
developer254882b2022-09-30 17:12:31 +080011583 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11584 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011585 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011586 _syscmd(cmd, buf, sizeof(buf));
11587 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11588 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11589 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011590 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 +080011591 _syscmd(cmd, buf, sizeof(buf));
11592 }
11593 if (band == band_5) {
11594 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11595 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011596 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 +080011597 _syscmd(cmd, buf, sizeof(buf));
11598 }
11599 }
11600 }
11601 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011602
developer254882b2022-09-30 17:12:31 +080011603 if (guard_interval == wifi_guard_interval_400)
11604 strcpy(GI, "0.4");
11605 else if (guard_interval == wifi_guard_interval_800)
11606 strcpy(GI, "0.8");
11607 else if (guard_interval == wifi_guard_interval_1600)
11608 strcpy(GI, "1.6");
11609 else if (guard_interval == wifi_guard_interval_3200)
11610 strcpy(GI, "3.2");
11611 else if (guard_interval == wifi_guard_interval_auto)
11612 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011613 // Record GI for get GI function
11614 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11615 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011616 if (f == NULL)
11617 return RETURN_ERR;
11618 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011619 fclose(f);
11620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11621 return RETURN_OK;
11622}
11623
11624INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11625{
11626 char buf[32] = {0};
11627 char cmd[64] = {0};
11628
11629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11630
11631 if (guard_interval == NULL)
11632 return RETURN_ERR;
11633
developer7c4cd202023-03-01 10:56:29 +080011634 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011635 _syscmd(cmd, buf, sizeof(buf));
11636
11637 if (strncmp(buf, "0.4", 3) == 0)
11638 *guard_interval = wifi_guard_interval_400;
11639 else if (strncmp(buf, "0.8", 3) == 0)
11640 *guard_interval = wifi_guard_interval_800;
11641 else if (strncmp(buf, "1.6", 3) == 0)
11642 *guard_interval = wifi_guard_interval_1600;
11643 else if (strncmp(buf, "3.2", 3) == 0)
11644 *guard_interval = wifi_guard_interval_3200;
11645 else
11646 *guard_interval = wifi_guard_interval_auto;
11647
11648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11649 return RETURN_OK;
11650}
11651
developer3cc61d12022-09-13 16:36:05 +080011652INT wifi_setBSSColor(INT radio_index, UCHAR color)
11653{
11654 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11655 struct params params = {0};
11656 char config_file[128] = {0};
11657 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011658 UCHAR *color_list;
11659 int color_num = 0;
11660 int maxNumberColors = 64;
11661 BOOL color_is_aval = FALSE;
11662
developerbf0b9dc2023-07-06 14:30:54 +080011663 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011664 return RETURN_ERR;
11665
developer517f3be2023-05-08 10:02:39 +080011666 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11667 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11668 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011669 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011670 }
developer2acb9632023-03-14 14:58:31 +080011671
11672 for (int i = 0; i < color_num; i++) {
11673 if (color_list[i] == color) {
11674 color_is_aval = TRUE;
11675 break;
11676 }
11677 }
11678 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011679 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011680 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11681 return RETURN_ERR;
11682 }
developer3cc61d12022-09-13 16:36:05 +080011683
11684 params.name = "he_bss_color";
11685 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11686 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011687 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011688 wifi_hostapdWrite(config_file, &params, 1);
11689 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011690 wifi_reloadAp(radio_index);
11691
developer517f3be2023-05-08 10:02:39 +080011692 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11694 return RETURN_OK;
11695}
11696
11697INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11698{
developer3cc61d12022-09-13 16:36:05 +080011699 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011700 char cmd[128] = {0};
11701 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011702
developer3cc61d12022-09-13 16:36:05 +080011703 if (NULL == color)
11704 return RETURN_ERR;
11705
developer2acb9632023-03-14 14:58:31 +080011706 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11707 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011708
developer2acb9632023-03-14 14:58:31 +080011709 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11710 _syscmd(cmd, buf, sizeof(buf));
11711 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011712
developer2acb9632023-03-14 14:58:31 +080011713 return RETURN_OK;
11714}
11715
11716INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11717{
11718 char buf[64] = {0};
11719 char cmd[128] = {0};
11720 char interface_name[16] = {0};
11721 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011722
developer2acb9632023-03-14 14:58:31 +080011723 if (NULL == colorList || NULL == numColorReturned)
11724 return RETURN_ERR;
11725
11726 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11727 return RETURN_ERR;
11728
11729 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11730 _syscmd(cmd, buf, sizeof(buf));
11731 color_bitmap = strtoull(buf, NULL, 16);
11732
11733 *numColorReturned = 0;
11734 for (int i = 0; i < maxNumberColors; i++) {
11735 if (color_bitmap & 1) {
11736 colorList[*numColorReturned] = i;
11737 (*numColorReturned) += 1;
11738 }
11739 color_bitmap >>= 1;
11740 }
developer3cc61d12022-09-13 16:36:05 +080011741 return RETURN_OK;
11742}
11743
developer06a01d92022-09-07 16:32:39 +080011744/* multi-psk support */
11745INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11746{
11747 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011748 char interface_name[16] = {0};
11749
developerac6f1142022-12-20 19:26:35 +080011750 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011751 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011752
developerd946fd62022-12-08 18:03:28 +080011753 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11754 interface_name,
developer06a01d92022-09-07 16:32:39 +080011755 mac[0],
11756 mac[1],
11757 mac[2],
11758 mac[3],
11759 mac[4],
11760 mac[5]
11761 );
11762 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11763 _syscmd(cmd, key->wifi_keyId, 64);
11764
11765
11766 return RETURN_OK;
11767}
11768
11769INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11770{
developerd946fd62022-12-08 18:03:28 +080011771 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011772 FILE *fd = NULL;
11773 char fname[100];
11774 char cmd[128] = {0};
11775 char out[64] = {0};
11776 wifi_key_multi_psk_t * key = NULL;
11777 if(keysNumber < 0)
11778 return RETURN_ERR;
11779
developer431128d2022-12-16 15:30:41 +080011780 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011781 fd = fopen(fname, "w");
11782 if (!fd) {
11783 return RETURN_ERR;
11784 }
11785 key= (wifi_key_multi_psk_t *) keys;
11786 for(int i=0; i<keysNumber; ++i, key++) {
11787 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11788 }
11789 fclose(fd);
11790
11791 //reload file
developerac6f1142022-12-20 19:26:35 +080011792 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011793 return RETURN_ERR;
11794 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011795 _syscmd(cmd, out, 64);
11796 return RETURN_OK;
11797}
11798
11799INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11800{
11801 FILE *fd = NULL;
11802 char fname[100];
11803 char * line = NULL;
11804 char * pos = NULL;
11805 size_t len = 0;
11806 ssize_t read = 0;
11807 INT ret = RETURN_OK;
11808 wifi_key_multi_psk_t *keys_it = NULL;
11809
11810 if (keysNumber < 1) {
11811 return RETURN_ERR;
11812 }
11813
developer431128d2022-12-16 15:30:41 +080011814 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011815 fd = fopen(fname, "r");
11816 if (!fd) {
11817 return RETURN_ERR;
11818 }
11819
11820 if (keys == NULL) {
11821 ret = RETURN_ERR;
11822 goto close;
11823 }
11824
11825 keys_it = keys;
11826 while ((read = getline(&line, &len, fd)) != -1) {
11827 //Strip trailing new line if present
11828 if (read > 0 && line[read-1] == '\n') {
11829 line[read-1] = '\0';
11830 }
11831
11832 if(strcmp(line,"keyid=")) {
11833 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11834 if (!(pos = index(line, ' '))) {
11835 ret = RETURN_ERR;
11836 goto close;
11837 }
11838 pos++;
11839 //Here should be 00:00:00:00:00:00
11840 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11841 printf("Not supported MAC: %s\n", pos);
11842 }
11843 if (!(pos = index(pos, ' '))) {
11844 ret = RETURN_ERR;
11845 goto close;
11846 }
11847 pos++;
11848
11849 //The rest is PSK
11850 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11851 keys_it++;
11852
11853 if(--keysNumber <= 0)
11854 break;
11855 }
11856 }
11857
11858close:
11859 free(line);
11860 fclose(fd);
11861 return ret;
11862}
11863/* end of multi-psk support */
11864
11865INT wifi_setNeighborReports(UINT apIndex,
11866 UINT numNeighborReports,
11867 wifi_NeighborReport_t *neighborReports)
11868{
11869 char cmd[256] = { 0 };
11870 char hex_bssid[13] = { 0 };
11871 char bssid[18] = { 0 };
11872 char nr[256] = { 0 };
11873 char ssid[256];
11874 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011875 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011876 INT ret;
11877
11878 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011879 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011880 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011881 return RETURN_ERR;
11882 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 +080011883 system(cmd);
11884
11885 for(unsigned int i = 0; i < numNeighborReports; i++)
11886 {
11887 memset(ssid, 0, sizeof(ssid));
11888 ret = wifi_getSSIDName(apIndex, ssid);
11889 if (ret != RETURN_OK)
11890 return RETURN_ERR;
11891
11892 memset(hex_ssid, 0, sizeof(hex_ssid));
11893 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11894 sprintf(hex_ssid + k,"%02x", ssid[j]);
11895
11896 snprintf(hex_bssid, sizeof(hex_bssid),
11897 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11898 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11899 snprintf(bssid, sizeof(bssid),
11900 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11901 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11902
11903 snprintf(nr, sizeof(nr),
11904 "%s" // bssid
11905 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11906 "%02hhx" // operclass
11907 "%02hhx" // channel
11908 "%02hhx", // phy_mode
11909 hex_bssid,
11910 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11911 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11912 neighborReports[i].opClass,
11913 neighborReports[i].channel,
11914 neighborReports[i].phyTable);
11915
11916 snprintf(cmd, sizeof(cmd),
11917 "hostapd_cli set_neighbor "
11918 "%s " // bssid
11919 "ssid=%s " // ssid
11920 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011921 "-i %s",
11922 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011923
11924 if (WEXITSTATUS(system(cmd)) != 0)
11925 {
11926 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11927 }
11928 }
11929
11930 return RETURN_OK;
11931}
11932
11933INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11934{
11935 return RETURN_OK;
11936}
11937
11938#ifdef _WIFI_HAL_TEST_
11939int main(int argc,char **argv)
11940{
11941 int index;
11942 INT ret=0;
11943 char buf[1024]="";
11944
11945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11946 if(argc<3)
11947 {
11948 if(argc==2)
11949 {
11950 if(!strcmp(argv[1], "init"))
11951 return wifi_init();
11952 if(!strcmp(argv[1], "reset"))
11953 return wifi_reset();
11954 if(!strcmp(argv[1], "wifi_getHalVersion"))
11955 {
11956 char buffer[64];
11957 if(wifi_getHalVersion(buffer)==RETURN_OK)
11958 printf("Version: %s\n", buffer);
11959 else
11960 printf("Error in wifi_getHalVersion\n");
11961 return RETURN_OK;
11962 }
11963 }
11964 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11965 exit(-1);
11966 }
11967
11968 index = atoi(argv[2]);
11969 if(strstr(argv[1], "wifi_getApName")!=NULL)
11970 {
11971 wifi_getApName(index,buf);
11972 printf("Ap name is %s \n",buf);
11973 return 0;
11974 }
11975 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11976 {
11977 BOOL b = FALSE;
11978 BOOL *output_bool = &b;
11979 wifi_getRadioAutoChannelEnable(index,output_bool);
11980 printf("Channel enabled = %d \n",b);
11981 return 0;
11982 }
11983 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11984 {
11985 wifi_getApWpaEncryptionMode(index,buf);
11986 printf("encryption enabled = %s\n",buf);
11987 return 0;
11988 }
11989 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11990 {
11991 BOOL b = FALSE;
11992 BOOL *output_bool = &b;
11993 wifi_getApSsidAdvertisementEnable(index,output_bool);
11994 printf("advertisment enabled = %d\n",b);
11995 return 0;
11996 }
11997 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11998 {
11999 if(argc <= 3 )
12000 {
12001 printf("Insufficient arguments \n");
12002 exit(-1);
12003 }
12004
12005 char sta[20] = {'\0'};
12006 ULLONG handle= 0;
12007 strcpy(sta,argv[3]);
12008 mac_address_t st;
12009 mac_addr_aton(st,sta);
12010
12011 wifi_associated_dev_tid_stats_t tid_stats;
12012 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12013 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12014 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);
12015 }
12016
12017 if(strstr(argv[1], "getApEnable")!=NULL) {
12018 BOOL enable;
12019 ret=wifi_getApEnable(index, &enable);
12020 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12021 }
12022 else if(strstr(argv[1], "setApEnable")!=NULL) {
12023 BOOL enable = atoi(argv[3]);
12024 ret=wifi_setApEnable(index, enable);
12025 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12026 }
12027 else if(strstr(argv[1], "getApStatus")!=NULL) {
12028 char status[64];
12029 ret=wifi_getApStatus(index, status);
12030 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12031 }
12032 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12033 {
12034 wifi_getSSIDNameStatus(index,buf);
12035 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12036 return 0;
12037 }
12038 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12039 wifi_ssidTrafficStats2_t stats={0};
12040 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12041 printf("%s %d: returns %d\n", argv[1], index, ret);
12042 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12043 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12044 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12045 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12046 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12047 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12048 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12049 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12050 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12051 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12052 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12053 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12054 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12055 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12056 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12057 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12058 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12059 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12060 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12061 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12062 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12063 }
12064 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12065 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12066 UINT array_size=0;
12067 UINT i=0;
12068 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12069 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12070 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
12071 printf(" neighbor %d:\n", i);
12072 printf(" ap_SSID =%s\n", pt->ap_SSID);
12073 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12074 printf(" ap_Mode =%s\n", pt->ap_Mode);
12075 printf(" ap_Channel =%d\n", pt->ap_Channel);
12076 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12077 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12078 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12079 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12080 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12081 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12082 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12083 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12084 printf(" ap_Noise =%d\n", pt->ap_Noise);
12085 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12086 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12087 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
12088 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
12089 }
12090 if(neighbor_ap_array)
12091 free(neighbor_ap_array); //make sure to free the list
12092 }
12093 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12094 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12095 UINT array_size=0;
12096 UINT i=0;
12097 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12098 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12099 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
12100 printf(" associated_dev %d:\n", i);
12101 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12102 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12103 printf(" cli_SNR =%d\n", pt->cli_SNR);
12104 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12105 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12106 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12107 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12108 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12109 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12110 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12111 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12112 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12113 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12114 }
12115 if(associated_dev_array)
12116 free(associated_dev_array); //make sure to free the list
12117 }
12118
12119 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12120 {
12121#define MAX_ARRAY_SIZE 64
12122 int i, array_size;
12123 char *p, *ch_str;
12124 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12125
12126 if(argc != 5)
12127 {
12128 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12129 exit(-1);
12130 }
12131 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12132
12133 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12134 {
12135 strtok_r(ch_str, ",", &p);
12136 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12137 }
12138 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12139 if(!array_size)
12140 array_size=1;//Need to print current channel statistics
12141 for(i=0; i<array_size; i++)
12142 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12143 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12144 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12145 input_output_channelStats_array[i].ch_number,\
12146 input_output_channelStats_array[i].ch_noise,\
12147 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12148 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12149 input_output_channelStats_array[i].ch_utilization_busy,\
12150 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12151 input_output_channelStats_array[i].ch_utilization_total);
12152 }
12153
12154 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12155 {
12156 if(argc <= 3 )
12157 {
12158 printf("Insufficient arguments \n");
12159 exit(-1);
12160 }
12161 char mac_addr[20] = {'\0'};
12162 wifi_device_t output_struct;
12163 int dev_index = atoi(argv[3]);
12164
12165 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12166 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12167 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);
12168 }
12169
12170 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12171 {
12172 if (argc <= 3)
12173 {
12174 printf("Insufficient arguments\n");
12175 exit(-1);
12176 }
12177 char args[256];
12178 wifi_NeighborReport_t *neighborReports;
12179
12180 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12181 if (!neighborReports)
12182 {
12183 printf("Failed to allocate memory");
12184 exit(-1);
12185 }
12186
12187 for (int i = 3; i < argc; ++i)
12188 {
12189 char *val;
12190 int j = 0;
12191 memset(args, 0, sizeof(args));
12192 strncpy(args, argv[i], sizeof(args));
12193 val = strtok(args, ";");
12194 while (val != NULL)
12195 {
12196 if (j == 0)
12197 {
12198 mac_addr_aton(neighborReports[i - 3].bssid, val);
12199 } else if (j == 1)
12200 {
12201 neighborReports[i - 3].info = strtol(val, NULL, 16);
12202 } else if (j == 2)
12203 {
12204 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12205 } else if (j == 3)
12206 {
12207 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12208 } else if (j == 4)
12209 {
12210 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12211 } else {
12212 printf("Insufficient arguments]n\n");
12213 exit(-1);
12214 }
12215 val = strtok(NULL, ";");
12216 j++;
12217 }
12218 }
12219
12220 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12221 if (ret != RETURN_OK)
12222 {
12223 printf("wifi_setNeighborReports ret = %d", ret);
12224 exit(-1);
12225 }
12226 }
12227 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12228 {
12229 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12230 printf("%s.\n", buf);
12231 else
12232 printf("Error returned\n");
12233 }
12234 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12235 {
12236 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12237 printf("%s.\n", buf);
12238 else
12239 printf("Error returned\n");
12240 }
12241 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12242 {
12243 if (argc <= 2)
12244 {
12245 printf("Insufficient arguments\n");
12246 exit(-1);
12247 }
12248 char buf[64]= {'\0'};
12249 wifi_getRadioOperatingChannelBandwidth(index,buf);
12250 printf("Current bandwidth is %s \n",buf);
12251 return 0;
12252 }
12253 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12254 {
12255 if (argc <= 5)
12256 {
12257 printf("Insufficient arguments\n");
12258 exit(-1);
12259 }
12260 UINT channel = atoi(argv[3]);
12261 UINT width = atoi(argv[4]);
12262 UINT beacon = atoi(argv[5]);
12263 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12264 printf("Result = %d", ret);
12265 }
12266
12267 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12268 return 0;
12269}
12270
12271#endif
12272
12273#ifdef WIFI_HAL_VERSION_3
12274
developer1e5aa162022-09-13 16:06:24 +080012275INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12276{
12277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12278 if (bitMap & WIFI_BITRATE_1MBPS)
12279 strcat(BasicRate, "1,");
12280 if (bitMap & WIFI_BITRATE_2MBPS)
12281 strcat(BasicRate, "2,");
12282 if (bitMap & WIFI_BITRATE_5_5MBPS)
12283 strcat(BasicRate, "5.5,");
12284 if (bitMap & WIFI_BITRATE_6MBPS)
12285 strcat(BasicRate, "6,");
12286 if (bitMap & WIFI_BITRATE_9MBPS)
12287 strcat(BasicRate, "9,");
12288 if (bitMap & WIFI_BITRATE_11MBPS)
12289 strcat(BasicRate, "11,");
12290 if (bitMap & WIFI_BITRATE_12MBPS)
12291 strcat(BasicRate, "12,");
12292 if (bitMap & WIFI_BITRATE_18MBPS)
12293 strcat(BasicRate, "18,");
12294 if (bitMap & WIFI_BITRATE_24MBPS)
12295 strcat(BasicRate, "24,");
12296 if (bitMap & WIFI_BITRATE_36MBPS)
12297 strcat(BasicRate, "36,");
12298 if (bitMap & WIFI_BITRATE_48MBPS)
12299 strcat(BasicRate, "48,");
12300 if (bitMap & WIFI_BITRATE_54MBPS)
12301 strcat(BasicRate, "54,");
12302 if (strlen(BasicRate) != 0) // remove last comma
12303 BasicRate[strlen(BasicRate) - 1] = '\0';
12304 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12305 return RETURN_OK;
12306}
12307
12308INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12309{
12310 UINT BitMap = 0;
12311 char *rate;
12312
12313 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12314 rate = strtok(BasicRatesList, ",");
12315 while(rate != NULL)
12316 {
12317 if (strcmp(rate, "1") == 0)
12318 BitMap |= WIFI_BITRATE_1MBPS;
12319 else if (strcmp(rate, "2") == 0)
12320 BitMap |= WIFI_BITRATE_2MBPS;
12321 else if (strcmp(rate, "5.5") == 0)
12322 BitMap |= WIFI_BITRATE_5_5MBPS;
12323 else if (strcmp(rate, "6") == 0)
12324 BitMap |= WIFI_BITRATE_6MBPS;
12325 else if (strcmp(rate, "9") == 0)
12326 BitMap |= WIFI_BITRATE_9MBPS;
12327 else if (strcmp(rate, "11") == 0)
12328 BitMap |= WIFI_BITRATE_11MBPS;
12329 else if (strcmp(rate, "12") == 0)
12330 BitMap |= WIFI_BITRATE_12MBPS;
12331 else if (strcmp(rate, "18") == 0)
12332 BitMap |= WIFI_BITRATE_18MBPS;
12333 else if (strcmp(rate, "24") == 0)
12334 BitMap |= WIFI_BITRATE_24MBPS;
12335 else if (strcmp(rate, "36") == 0)
12336 BitMap |= WIFI_BITRATE_36MBPS;
12337 else if (strcmp(rate, "48") == 0)
12338 BitMap |= WIFI_BITRATE_48MBPS;
12339 else if (strcmp(rate, "54") == 0)
12340 BitMap |= WIFI_BITRATE_54MBPS;
12341 rate = strtok(NULL, ",");
12342 }
12343 *basicRateBitMap = BitMap;
12344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12345 return RETURN_OK;
12346}
12347
developer7c4cd202023-03-01 10:56:29 +080012348INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12349{
12350 int center_channel = 0;
12351 char central_channel_str[16] = {0};
12352 char config_file[32] = {0};
12353 struct params param = {0};
12354
12355 center_channel = util_unii_6g_centerfreq("HT320", channel);
12356 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12357 if (channel >= 193)
12358 return RETURN_ERR;
12359 if (channel >= 33) {
12360 if (channel > center_channel)
12361 center_channel += 32;
12362 else
12363 center_channel -= 32;
12364 }
12365 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12366 if (channel <= 29)
12367 return RETURN_ERR;
12368 }
12369 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12370 param.name = "eht_oper_centr_freq_seg0_idx";
12371 param.value = central_channel_str;
12372 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12373 wifi_hostapdWrite(config_file, &param, 1);
12374
12375 return RETURN_OK;
12376}
12377
12378INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12379{
12380 int op_class = 0;
12381 char config_file[32] = {0};
12382 char op_class_str[8] = {0};
12383 struct params param = {0};
12384
12385 if (bandwidth == 20)
12386 op_class = 131;
12387 else if (bandwidth == 40)
12388 op_class = 132;
12389 else if (bandwidth == 80)
12390 op_class = 133;
12391 else if (bandwidth == 160)
12392 op_class = 134;
12393 else if (bandwidth == 320)
12394 op_class = 137;
12395 else
12396 return RETURN_ERR;
12397 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12398 param.name = "op_class";
12399 param.value = op_class_str;
12400 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12401 wifi_hostapdWrite(config_file, &param, 1);
12402 return RETURN_OK;
12403}
12404
12405INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12406{
12407 char config_file[32] = {0};
12408 char buf [16] = {0};
12409
12410 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12411 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12412 return RETURN_ERR; // 6g band should set op_class
12413 *class = (UINT)strtoul(buf, NULL, 10);
12414
12415 return RETURN_OK;
12416}
12417
developer1e5aa162022-09-13 16:06:24 +080012418// 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 +080012419INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12420{
developer1e5aa162022-09-13 16:06:24 +080012421 char buf[128] = {0};
12422 char cmd[128] = {0};
12423 char config_file[64] = {0};
12424 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012425 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012426 wifi_radio_operationParam_t current_param;
12427
12428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12429
12430 multiple_set = TRUE;
12431 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12432 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12433 return RETURN_ERR;
12434 }
12435 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12436 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12437 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12438 return RETURN_ERR;
12439 }
12440 }
developer5884e982022-10-06 10:52:50 +080012441
12442 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12443 bandwidth = 20;
12444 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12445 bandwidth = 40;
12446 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12447 bandwidth = 80;
12448 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12449 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012450 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12451 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012452 if (operationParam->autoChannelEnabled){
12453 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12454 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12455 return RETURN_ERR;
12456 }
12457 }else{
developer1e5aa162022-09-13 16:06:24 +080012458 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12459 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12460 return RETURN_ERR;
12461 }
12462 }
developer5884e982022-10-06 10:52:50 +080012463
developer7c4cd202023-03-01 10:56:29 +080012464 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12465 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12466 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12467 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12468 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12469 return RETURN_ERR;
12470 }
12471 }
12472
12473 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12474 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12475 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12476 return RETURN_ERR;
12477 }
12478 }
12479
developer1e5aa162022-09-13 16:06:24 +080012480 if (current_param.variant != operationParam->variant) {
12481 // Two different definition bit map, so need to check every bit.
12482 if (operationParam->variant & WIFI_80211_VARIANT_A)
12483 set_mode |= WIFI_MODE_A;
12484 if (operationParam->variant & WIFI_80211_VARIANT_B)
12485 set_mode |= WIFI_MODE_B;
12486 if (operationParam->variant & WIFI_80211_VARIANT_G)
12487 set_mode |= WIFI_MODE_G;
12488 if (operationParam->variant & WIFI_80211_VARIANT_N)
12489 set_mode |= WIFI_MODE_N;
12490 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12491 set_mode |= WIFI_MODE_AC;
12492 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12493 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012494 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12495 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012496 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12497 memset(buf, 0, sizeof(buf));
12498 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12499 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12500 return RETURN_ERR;
12501 }
12502 }
12503 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12504 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12505 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12506 return RETURN_ERR;
12507 }
12508 }
12509 if (current_param.beaconInterval != operationParam->beaconInterval) {
12510 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12511 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12512 return RETURN_ERR;
12513 }
12514 }
12515 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12516 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12517 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12518 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12519 return RETURN_ERR;
12520 }
12521 }
12522 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12523 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12524 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12525 return RETURN_ERR;
12526 }
12527 }
12528 if (current_param.guardInterval != operationParam->guardInterval) {
12529 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12530 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12531 return RETURN_ERR;
12532 }
12533 }
12534 if (current_param.transmitPower != operationParam->transmitPower) {
12535 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12536 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12537 return RETURN_ERR;
12538 }
12539 }
12540 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12541 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12542 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12543 return RETURN_ERR;
12544 }
12545 }
12546 if (current_param.obssCoex != operationParam->obssCoex) {
12547 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12548 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12549 return RETURN_ERR;
12550 }
12551 }
12552 if (current_param.stbcEnable != operationParam->stbcEnable) {
12553 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12554 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12555 return RETURN_ERR;
12556 }
12557 }
developer5735d092023-09-19 20:12:26 +080012558 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12559 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12560 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12561 return RETURN_ERR;
12562 }
12563 }
developer1e5aa162022-09-13 16:06:24 +080012564
12565 // if enable is true, then restart the radio
12566 wifi_setRadioEnable(index, FALSE);
12567 if (operationParam->enable == TRUE)
12568 wifi_setRadioEnable(index, TRUE);
12569 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12570
developer06a01d92022-09-07 16:32:39 +080012571 return RETURN_OK;
12572}
12573
12574INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12575{
developer1e5aa162022-09-13 16:06:24 +080012576 char band[64] = {0};
12577 char buf[256] = {0};
12578 char config_file[64] = {0};
12579 char cmd[128] = {0};
12580 int ret = RETURN_ERR;
12581 int mode = 0;
12582 ULONG channel = 0;
12583 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012584
12585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12586 printf("Entering %s index = %d\n", __func__, (int)index);
12587
developer1e5aa162022-09-13 16:06:24 +080012588 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12589 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12590 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012591 {
developer1e5aa162022-09-13 16:06:24 +080012592 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012593 return RETURN_ERR;
12594 }
12595 operationParam->enable = enabled;
12596
12597 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012598 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012599 {
developer1e5aa162022-09-13 16:06:24 +080012600 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012601 return RETURN_ERR;
12602 }
12603
12604 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012605 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012606 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012607 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012608 else if (!strcmp(band, "6GHz"))
12609 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012610 else
12611 {
developer1e5aa162022-09-13 16:06:24 +080012612 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012613 band);
12614 }
12615
developer1e5aa162022-09-13 16:06:24 +080012616 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12617 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12618 operationParam->channel = 0;
12619 operationParam->autoChannelEnabled = TRUE;
12620 } else {
12621 operationParam->channel = strtol(buf, NULL, 10);
12622 operationParam->autoChannelEnabled = FALSE;
12623 }
12624
developer06a01d92022-09-07 16:32:39 +080012625 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012626 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12627 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12628 return RETURN_ERR;
12629 }
developer06a01d92022-09-07 16:32:39 +080012630 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12631 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12632 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012633 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012634 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12635 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012636 else
12637 {
developer1e5aa162022-09-13 16:06:24 +080012638 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12639 return false;
developer06a01d92022-09-07 16:32:39 +080012640 }
12641
developer7c4cd202023-03-01 10:56:29 +080012642 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12643 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12644 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12645 return RETURN_ERR;
12646 }
12647 }
12648
developer1e5aa162022-09-13 16:06:24 +080012649 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12650 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12651 return RETURN_ERR;
12652 }
12653 // Two different definition bit map, so need to check every bit.
12654 if (mode & WIFI_MODE_A)
12655 operationParam->variant |= WIFI_80211_VARIANT_A;
12656 if (mode & WIFI_MODE_B)
12657 operationParam->variant |= WIFI_80211_VARIANT_B;
12658 if (mode & WIFI_MODE_G)
12659 operationParam->variant |= WIFI_80211_VARIANT_G;
12660 if (mode & WIFI_MODE_N)
12661 operationParam->variant |= WIFI_80211_VARIANT_N;
12662 if (mode & WIFI_MODE_AC)
12663 operationParam->variant |= WIFI_80211_VARIANT_AC;
12664 if (mode & WIFI_MODE_AX)
12665 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012666 if (mode & WIFI_MODE_BE)
12667 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012668 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12669 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12670 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012671 }
developer1e5aa162022-09-13 16:06:24 +080012672 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12673 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12674 return RETURN_ERR;
12675 }
12676 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12677 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12678 return RETURN_ERR;
12679 }
developer06a01d92022-09-07 16:32:39 +080012680
developer1e5aa162022-09-13 16:06:24 +080012681 memset(buf, 0, sizeof(buf));
12682 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12683 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12684 return RETURN_ERR;
12685 }
12686 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12687
12688 memset(buf, 0, sizeof(buf));
12689 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12690 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12691 return RETURN_ERR;
12692 }
12693 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12694
12695 memset(buf, 0, sizeof(buf));
12696 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12697 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12698
12699 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12700 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12701 return RETURN_ERR;
12702 }
12703 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12704 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12705 return RETURN_ERR;
12706 }
12707
12708 memset(buf, 0, sizeof(buf));
12709 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12710 if (strcmp(buf, "-1") == 0) {
12711 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12712 operationParam->ctsProtection = FALSE;
12713 } else {
12714 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12715 operationParam->ctsProtection = TRUE;
12716 }
12717
12718 memset(buf, 0, sizeof(buf));
12719 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12720 if (strcmp(buf, "0") == 0)
12721 operationParam->obssCoex = FALSE;
12722 else
12723 operationParam->obssCoex = TRUE;
12724
12725 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12726 _syscmd(cmd, buf, sizeof(buf));
12727 if (strlen(buf) != 0)
12728 operationParam->stbcEnable = TRUE;
12729 else
12730 operationParam->stbcEnable = FALSE;
12731
developer5735d092023-09-19 20:12:26 +080012732 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12733 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12734 return RETURN_ERR;
12735 }
developer1e5aa162022-09-13 16:06:24 +080012736
12737 // Below value is hardcoded
12738
12739 operationParam->numSecondaryChannels = 0;
12740 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12741 operationParam->channelSecondary[i] = 0;
12742 }
12743 operationParam->csa_beacon_count = 15;
12744 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012745
12746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12747 return RETURN_OK;
12748}
12749
12750static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12751{
developerc086fb72022-10-04 10:18:22 +080012752 int max_radio_num = 0;
12753
12754 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012755 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012756 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12757 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012758 }
12759
developerc086fb72022-10-04 10:18:22 +080012760 return (arrayIndex * max_radio_num) + radioIndex;
12761}
developer06a01d92022-09-07 16:32:39 +080012762
developerc086fb72022-10-04 10:18:22 +080012763wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12764 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12765 return WIFI_BITRATE_1MBPS;
12766 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12767 return WIFI_BITRATE_2MBPS;
12768 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12769 return WIFI_BITRATE_5_5MBPS;
12770 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12771 return WIFI_BITRATE_6MBPS;
12772 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12773 return WIFI_BITRATE_9MBPS;
12774 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12775 return WIFI_BITRATE_11MBPS;
12776 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12777 return WIFI_BITRATE_12MBPS;
12778 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12779 return WIFI_BITRATE_18MBPS;
12780 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12781 return WIFI_BITRATE_24MBPS;
12782 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12783 return WIFI_BITRATE_36MBPS;
12784 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12785 return WIFI_BITRATE_48MBPS;
12786 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12787 return WIFI_BITRATE_54MBPS;
12788 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012789}
12790
developer1d57d002022-10-12 18:03:15 +080012791INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12792{
12793 if (beacon == WIFI_BITRATE_1MBPS)
12794 strcpy(beacon_str, "1Mbps");
12795 else if (beacon == WIFI_BITRATE_2MBPS)
12796 strcpy(beacon_str, "2Mbps");
12797 else if (beacon == WIFI_BITRATE_5_5MBPS)
12798 strcpy(beacon_str, "5.5Mbps");
12799 else if (beacon == WIFI_BITRATE_6MBPS)
12800 strcpy(beacon_str, "6Mbps");
12801 else if (beacon == WIFI_BITRATE_9MBPS)
12802 strcpy(beacon_str, "9Mbps");
12803 else if (beacon == WIFI_BITRATE_11MBPS)
12804 strcpy(beacon_str, "11Mbps");
12805 else if (beacon == WIFI_BITRATE_12MBPS)
12806 strcpy(beacon_str, "12Mbps");
12807 else if (beacon == WIFI_BITRATE_18MBPS)
12808 strcpy(beacon_str, "18Mbps");
12809 else if (beacon == WIFI_BITRATE_24MBPS)
12810 strcpy(beacon_str, "24Mbps");
12811 else if (beacon == WIFI_BITRATE_36MBPS)
12812 strcpy(beacon_str, "36Mbps");
12813 else if (beacon == WIFI_BITRATE_48MBPS)
12814 strcpy(beacon_str, "48Mbps");
12815 else if (beacon == WIFI_BITRATE_54MBPS)
12816 strcpy(beacon_str, "54Mbps");
12817 return RETURN_OK;
12818}
12819
developer74ed4192023-09-21 17:15:17 +080012820void checkVapStatus(int apIndex, bool *enable)
12821{
12822 char if_name[16] = {0};
12823 char cmd[128] = {0};
12824 char buf[128] = {0};
12825
12826 *enable = FALSE;
12827 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12828 return;
12829
12830 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12831 _syscmd(cmd, buf, sizeof(buf));
12832 if (strlen(buf) > 0)
12833 *enable = TRUE;
12834 return;
12835}
12836
developerefb790a2023-12-26 18:58:32 +080012837INT wifi_getVapInfoMisc(int vap_index)
12838{
12839 char config_file[MAX_BUF_SIZE] = {0};
12840
12841 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX,vap_index);
12842 wifi_hostapdRead(config_file,"ssid",vap_info[vap_index].ssid, MAX_BUF_SIZE);
12843 wifi_hostapdRead(config_file,"wpa", vap_info[vap_index].wpa, MAX_BUF_SIZE);
12844 wifi_hostapdRead(config_file,"wpa_key_mgmt", vap_info[vap_index].wpa_key_mgmt, MAX_BUF_SIZE);
12845 wifi_hostapdRead(config_file,"wpa_passphrase", vap_info[vap_index].wpa_passphrase, MAX_BUF_SIZE);
12846 wifi_hostapdRead(config_file,"ap_isolate", vap_info[vap_index].ap_isolate, MAX_BUF_SIZE);
12847 wifi_hostapdRead(config_file,"macaddr_acl", vap_info[vap_index].macaddr_acl, MAX_BUF_SIZE);
12848 wifi_hostapdRead(config_file,"bss_transition", vap_info[vap_index].bss_transition, MAX_BUF_SIZE);
12849 wifi_hostapdRead(config_file,"ignore_broadcast_ssid", vap_info[vap_index].ignore_broadcast_ssid, MAX_BUF_SIZE);
12850 wifi_hostapdRead(config_file, "max_num_sta", vap_info[vap_index].max_sta, MAX_BUF_SIZE);
12851 return RETURN_OK;
12852}
12853
12854int wifi_Syncthread(void *arg)
12855{
12856 int radio_idx = 0, i = 0;
12857 int vap_index = 0;
developera2af46a2024-01-04 19:11:23 +080012858 int max_radio = 0;
developerefb790a2023-12-26 18:58:32 +080012859
developera2af46a2024-01-04 19:11:23 +080012860 wifi_getMaxRadioNumber(&max_radio);
developerefb790a2023-12-26 18:58:32 +080012861 while (1)
12862 {
12863 sleep(5);
developera2af46a2024-01-04 19:11:23 +080012864 for (radio_idx = 0; radio_idx < max_radio; radio_idx++)
developerefb790a2023-12-26 18:58:32 +080012865 {
12866 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
12867 {
12868 vap_index = array_index_to_vap_index(radio_idx, i);
12869 if (vap_index >= 0)
12870 wifi_getVapInfoMisc(vap_index);
12871 }
12872 }
12873 syn_flag = 1;
12874 }
12875 return 0;
12876}
12877
developer06a01d92022-09-07 16:32:39 +080012878INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12879{
developerc086fb72022-10-04 10:18:22 +080012880 INT mode = 0;
12881 INT ret = -1;
12882 INT output = 0;
12883 int i = 0;
12884 int vap_index = 0;
12885 BOOL enabled = FALSE;
12886 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012887 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012888
developer06a01d92022-09-07 16:32:39 +080012889
12890 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12891 printf("Entering %s index = %d\n", __func__, (int)index);
12892
developera77d84b2023-02-22 16:10:50 +080012893 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012894 {
developerc086fb72022-10-04 10:18:22 +080012895 map->vap_array[i].radio_index = index;
12896
developer06a01d92022-09-07 16:32:39 +080012897 vap_index = array_index_to_vap_index(index, i);
12898 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012899 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012900
developerc086fb72022-10-04 10:18:22 +080012901 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012902
12903 map->vap_array[i].vap_index = vap_index;
12904
12905 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012906 ret = wifi_getApName(vap_index, buf);
12907 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012908 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12909
developerc086fb72022-10-04 10:18:22 +080012910 return RETURN_ERR;
12911 }
12912 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12913
12914 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012915 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012916 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012917 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012918 return RETURN_ERR;
12919 }
12920 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 +080012921
developer74ed4192023-09-21 17:15:17 +080012922 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012923 map->vap_array[i].u.bss_info.enabled = enabled;
12924
developerc086fb72022-10-04 10:18:22 +080012925 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12926 if (ret != RETURN_OK) {
12927 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12928 return RETURN_ERR;
12929 }
developer06a01d92022-09-07 16:32:39 +080012930 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012931
12932 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12933 if (ret != RETURN_OK) {
12934 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12935 return RETURN_ERR;
12936 }
12937 map->vap_array[i].u.bss_info.isolation = enabled;
12938
12939 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12940 if (ret != RETURN_OK) {
12941 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12942 return RETURN_ERR;
12943 }
12944 map->vap_array[i].u.bss_info.bssMaxSta = output;
12945
12946 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12947 if (ret != RETURN_OK) {
12948 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12949 return RETURN_ERR;
12950 }
12951 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012952
developerc086fb72022-10-04 10:18:22 +080012953 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12954 if (ret != RETURN_OK) {
12955 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12956 return RETURN_ERR;
12957 }
12958 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012959
developerc086fb72022-10-04 10:18:22 +080012960 ret = wifi_getApSecurity(vap_index, &security);
12961 if (ret != RETURN_OK) {
12962 printf("%s: wifi_getApSecurity return error\n", __func__);
12963 return RETURN_ERR;
12964 }
12965 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012966
developerc086fb72022-10-04 10:18:22 +080012967 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12968 if (ret != RETURN_OK) {
12969 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12970 return RETURN_ERR;
12971 }
12972 if (mode == 0)
12973 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12974 else
12975 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12976 if (mode == 1)
12977 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12978 else if (mode == 2)
12979 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012980
developerc086fb72022-10-04 10:18:22 +080012981 ret = wifi_getApWmmEnable(vap_index, &enabled);
12982 if (ret != RETURN_OK) {
12983 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12984 return RETURN_ERR;
12985 }
12986 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012987
developerc086fb72022-10-04 10:18:22 +080012988 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12989 if (ret != RETURN_OK) {
12990 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012991 return RETURN_ERR;
12992 }
developerc086fb72022-10-04 10:18:22 +080012993 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012994
12995 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012996 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012997 if (ret != RETURN_OK) {
12998 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12999 return RETURN_ERR;
13000 }
13001 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080013002
developerc086fb72022-10-04 10:18:22 +080013003 memset(buf, 0, sizeof(buf));
13004 ret = wifi_getBaseBSSID(vap_index, buf);
13005 if (ret != RETURN_OK) {
13006 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13007 return RETURN_ERR;
13008 }
13009 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13010 &map->vap_array[i].u.bss_info.bssid[0],
13011 &map->vap_array[i].u.bss_info.bssid[1],
13012 &map->vap_array[i].u.bss_info.bssid[2],
13013 &map->vap_array[i].u.bss_info.bssid[3],
13014 &map->vap_array[i].u.bss_info.bssid[4],
13015 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080013016 // 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]);
13017
13018 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13019 if (ret != RETURN_OK) {
13020 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13021 return RETURN_ERR;
13022 }
13023 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080013024
13025 ret = wifi_getApWpsEnable(vap_index, &enabled);
13026 if (ret != RETURN_OK) {
13027 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
13028 return RETURN_ERR;
13029 }
13030
13031 map->vap_array[i].u.bss_info.wps.enable = enabled;
13032
developera77d84b2023-02-22 16:10:50 +080013033 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080013034 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080013035 }
developerefb790a2023-12-26 18:58:32 +080013036
13037 if (!tflag) {
13038 result = pthread_create(&pthread_id, NULL, wifi_Syncthread,NULL);
13039 if (result != 0)
13040 printf("%s %d fail create sync thread\n", __func__, __LINE__);
13041 else
13042 tflag = 1;
13043 }
13044
developer06a01d92022-09-07 16:32:39 +080013045 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13046 return RETURN_OK;
13047}
13048
developer431128d2022-12-16 15:30:41 +080013049
developerd946fd62022-12-08 18:03:28 +080013050static int prepareInterface(UINT apIndex, char *new_interface)
13051{
13052 char cur_interface[16] = {0};
13053 char config_file[128] = {0};
13054 char cmd[128] = {0};
13055 char buf[16] = {0};
13056 int max_radio_num = 0;
13057 int radioIndex = -1;
13058 int phyIndex = -1;
13059
13060 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13061 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13062
13063 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
13064 wifi_getMaxRadioNumber(&max_radio_num);
13065 radioIndex = apIndex % max_radio_num;
13066 phyIndex = radio_index_to_phy(radioIndex);
13067 // disable and del old interface, then add new interface
13068 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080013069 if (!(apIndex/max_radio_num)) {
13070 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
13071 _syscmd(cmd, buf, sizeof(buf));
13072 }
developerd946fd62022-12-08 18:03:28 +080013073 }
developer431128d2022-12-16 15:30:41 +080013074 // update the vap status file
13075 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13076 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080013077 return RETURN_OK;
13078}
13079
developer06a01d92022-09-07 16:32:39 +080013080INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13081{
developerd946fd62022-12-08 18:03:28 +080013082 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013083 unsigned int i;
13084 wifi_vap_info_t *vap_info = NULL;
13085 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080013086 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080013087 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080013088 char buf[256] = {0};
13089 char cmd[128] = {0};
13090 char config_file[64] = {0};
13091 char bssid[32] = {0};
13092 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080013093 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080013094
13095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13096 printf("Entering %s index = %d\n", __func__, (int)index);
13097 for (i = 0; i < map->num_vaps; i++)
13098 {
developer1d57d002022-10-12 18:03:15 +080013099 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080013100 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080013101
13102 // Check vap status file to enable multiple ap if the system boot.
13103 checkVapStatus(vap_info->vap_index, &enable);
13104 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080013105 continue;
developer06a01d92022-09-07 16:32:39 +080013106
developer1d57d002022-10-12 18:03:15 +080013107 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13108
developer431128d2022-12-16 15:30:41 +080013109 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13110 enable = FALSE;
13111
13112 // multi-ap first up need to copy current radio config
13113 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080013114 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13115 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080013116 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13117 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13118 } else {
13119 // Check whether the interface name is valid or this ap change it.
13120 int apIndex = -1;
13121 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13122 if (apIndex != -1 && apIndex != vap_info->vap_index)
13123 continue;
13124 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080013125 }
developer06a01d92022-09-07 16:32:39 +080013126
developer1d57d002022-10-12 18:03:15 +080013127 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080013128 params[0].name = "interface";
13129 params[0].value = vap_info->vap_name;
13130 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13131 params[1].name = "bssid";
13132 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080013133 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080013134 params[2].name = "wpa_psk_file";
13135 params[2].value = psk_file;
13136
13137 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13138 wifi_hostapdWrite(config_file, params, 3);
13139
13140 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13141 _syscmd(cmd, buf, sizeof(buf));
13142
13143 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13144 if (ret != RETURN_OK) {
13145 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13146 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013147 }
developer1d57d002022-10-12 18:03:15 +080013148
13149 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13150 if (ret != RETURN_OK) {
13151 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13152 return RETURN_ERR;
13153 }
13154
13155 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13156 if (ret != RETURN_OK) {
13157 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13158 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013159 }
13160
developer1d57d002022-10-12 18:03:15 +080013161 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13162 if (ret != RETURN_OK) {
13163 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13164 return RETURN_ERR;
13165 }
developer06a01d92022-09-07 16:32:39 +080013166
developer1d57d002022-10-12 18:03:15 +080013167 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13168 if (ret != RETURN_OK) {
13169 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13170 return RETURN_ERR;
13171 }
developer06a01d92022-09-07 16:32:39 +080013172
developer1d57d002022-10-12 18:03:15 +080013173 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13174 if (ret != RETURN_OK) {
13175 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13176 return RETURN_ERR;
13177 }
13178
developer804c64f2022-10-19 13:54:40 +080013179 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080013180 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080013181 }else {
13182 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080013183 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080013184 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13185 _syscmd(cmd, buf, sizeof(buf));
13186 }else{
developer1d57d002022-10-12 18:03:15 +080013187 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013188 }
developer1d57d002022-10-12 18:03:15 +080013189 }
13190
13191 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13192 if (ret != RETURN_OK) {
13193 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13194 return RETURN_ERR;
13195 }
13196
13197 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13198 if (ret != RETURN_OK) {
13199 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13200 return RETURN_ERR;
13201 }
13202
13203 memset(buf, 0, sizeof(buf));
13204 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13205 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13206 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13207 if (ret != RETURN_OK) {
13208 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13209 return RETURN_ERR;
13210 }
13211
developer1d57d002022-10-12 18:03:15 +080013212 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13213 if (ret != RETURN_OK) {
13214 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13215 return RETURN_ERR;
13216 }
13217
13218 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13219 if (ret != RETURN_OK) {
13220 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13221 return RETURN_ERR;
13222 }
developer06a01d92022-09-07 16:32:39 +080013223
developer894affa2023-05-10 18:13:19 +080013224 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13225 if (ret != RETURN_OK) {
13226 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13227 return RETURN_ERR;
13228 }
13229
developer2f995fb2023-02-24 10:40:44 +080013230 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013231 if (vap_info->u.bss_info.enabled == TRUE)
13232 wifi_setApEnable(vap_info->vap_index, TRUE);
13233
developer2f995fb2023-02-24 10:40:44 +080013234 multiple_set = FALSE;
13235
13236 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013237 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013238 // The set wps methods function should check whether wps is configured.
13239 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13240 if (ret != RETURN_OK) {
13241 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13242 return RETURN_ERR;
13243 }
13244 // wifi_setApWpsConfigMethodsEnabled only write to config.
13245 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13246 if (ret != RETURN_OK) {
13247 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13248 return RETURN_ERR;
13249 }
13250 }
developer2f995fb2023-02-24 10:40:44 +080013251
developer894affa2023-05-10 18:13:19 +080013252 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013253 }
developerfb09ba62023-06-09 17:03:21 +080013254
13255 // IGMP Snooping enable should be placed after all hostapd_reload.
13256 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13257 if (ret != RETURN_OK) {
13258 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13259 return RETURN_ERR;
13260 }
13261
developer06a01d92022-09-07 16:32:39 +080013262 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13263 return RETURN_OK;
13264}
13265
13266int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13267{
13268 char *token, *next;
13269 const char s[2] = ",";
13270 int count =0;
13271
13272 /* get the first token */
13273 token = strtok_r(pchannels, s, &next);
13274
13275 /* walk through other tokens */
13276 while( token != NULL && count < MAX_CHANNELS) {
13277 chlistptr->channels_list[count++] = atoi(token);
13278 token = strtok_r(NULL, s, &next);
13279 }
13280
13281 return count;
13282}
13283
13284static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13285{
13286 INT status;
13287 wifi_channels_list_t *chlistp;
13288 CHAR output_string[64];
13289 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013290 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013291 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013292
13293 if(rcap == NULL)
13294 {
13295 return RETURN_ERR;
13296 }
13297
13298 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013299 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013300
developer1e5aa162022-09-13 16:06:24 +080013301 if (band == band_2_4)
13302 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13303 else if (band == band_5)
13304 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13305 else if (band == band_6)
13306 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013307
13308 chlistp = &(rcap->channel_list[0]);
13309 memset(pchannels, 0, sizeof(pchannels));
13310
13311 /* possible number of radio channels */
13312 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13313 {
13314 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13315 }
13316 /* Number of channels and list*/
13317 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13318
13319 /* autoChannelSupported */
13320 /* always ON with wifi_getRadioAutoChannelSupported */
13321 rcap->autoChannelSupported = TRUE;
13322
13323 /* DCSSupported */
13324 /* always ON with wifi_getRadioDCSSupported */
13325 rcap->DCSSupported = TRUE;
13326
13327 /* zeroDFSSupported - TBD */
13328 rcap->zeroDFSSupported = FALSE;
13329
13330 /* Supported Country List*/
13331 memset(output_string, 0, sizeof(output_string));
13332 status = wifi_getRadioCountryCode(radioIndex, output_string);
13333 if( status != 0 ) {
13334 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13335 return RETURN_ERR;
13336 } else {
13337 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13338 }
13339 if(!strcmp(output_string,"US")){
13340 rcap->countrySupported[0] = wifi_countrycode_US;
13341 rcap->countrySupported[1] = wifi_countrycode_CA;
13342 } else if (!strcmp(output_string,"CA")) {
13343 rcap->countrySupported[0] = wifi_countrycode_CA;
13344 rcap->countrySupported[1] = wifi_countrycode_US;
13345 } else {
13346 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13347 }
13348
13349 rcap->numcountrySupported = 2;
13350
13351 /* csi */
13352 rcap->csi.maxDevices = 8;
13353 rcap->csi.soudingFrameSupported = TRUE;
13354
developer7930d352022-12-21 17:55:42 +080013355 wifi_GetInterfaceName(radioIndex, interface_name);
13356 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013357
13358 /* channelWidth - all supported bandwidths */
13359 int i=0;
13360 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013361
13362 /* mode - all supported variants */
13363 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13364 wifi_getRadioSupportedStandards(radioIndex, output_string);
13365
developer06a01d92022-09-07 16:32:39 +080013366 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13367 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13368 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013369 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013370
developer7c4cd202023-03-01 10:56:29 +080013371 if (strstr(output_string, "n") != NULL)
13372 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13373 if (strstr(output_string, "ax") != NULL)
13374 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13375 if (strstr(output_string, "be") != NULL)
13376 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13377 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013378 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13379 WIFI_CHANNELBANDWIDTH_40MHZ |
13380 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013381 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013382
developer7c4cd202023-03-01 10:56:29 +080013383 if (strstr(output_string, "n") != NULL)
13384 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13385 if (strstr(output_string, "ac") != NULL)
13386 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13387 if (strstr(output_string, "ax") != NULL)
13388 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13389 if (strstr(output_string, "be") != NULL)
13390 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13391 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13392 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13393 WIFI_CHANNELBANDWIDTH_40MHZ |
13394 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013395 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013396
13397 if (strstr(output_string, "be") != NULL) {
13398 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13399 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13400 }
developer06a01d92022-09-07 16:32:39 +080013401 }
developer7c4cd202023-03-01 10:56:29 +080013402
developer06a01d92022-09-07 16:32:39 +080013403 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13404 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13405
13406 /* supportedBitRate - all supported bitrates */
13407 rcap->supportedBitRate[i] = 0;
13408 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13409 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13410 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13411 }
developer1e5aa162022-09-13 16:06:24 +080013412 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013413 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13414 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13415 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13416 }
13417
13418
13419 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13420 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13421 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13422 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13423 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13424 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13425 rcap->cipherSupported = 0;
13426 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13427 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13428
13429 return RETURN_OK;
13430}
13431
13432INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13433{
developer30423732022-12-01 16:17:49 +080013434 INT status = 0, radioIndex = 0;
13435 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013436 int iter = 0;
developer30423732022-12-01 16:17:49 +080013437 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013438 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013439 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013440
13441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13442
13443 memset(cap, 0, sizeof(wifi_hal_capability_t));
13444
13445 /* version */
13446 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13447 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13448
13449 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013450 wifi_getMaxRadioNumber(&max_num_radios);
13451 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013452
13453 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13454 {
13455 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13456 if (status != 0) {
13457 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13458 return RETURN_ERR;
13459 }
13460
13461 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13462 {
developer804c64f2022-10-19 13:54:40 +080013463 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013464 {
13465 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13466 return RETURN_ERR;
13467 }
13468 iface_info = &cap->wifi_prop.interface_map[iter];
13469 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13470 iface_info->rdk_radio_index = radioIndex;
13471 memset(output, 0, sizeof(output));
13472 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13473 {
13474 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13475 }
13476 // TODO: bridge name
13477 // TODO: vlan id
13478 // TODO: primary
13479 iface_info->index = array_index_to_vap_index(radioIndex, j);
13480 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013481 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013482 {
13483 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13484 }
13485 iter++;
13486 }
13487 }
13488
13489 cap->BandSteeringSupported = FALSE;
13490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13491 return RETURN_OK;
13492}
13493
developer9df4e652022-10-11 11:27:38 +080013494INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13495{
13496 struct params h_config={0};
13497 char config_file[64] = {0};
13498
13499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13500
13501 h_config.name = "okc";
13502 h_config.value = okc_enable?"1":"0";
13503
13504 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13505 wifi_hostapdWrite(config_file, &h_config, 1);
13506 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13507
13508 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13509 return RETURN_OK;
13510}
13511
13512INT wifi_setSAEMFP(int ap_index, BOOL enable)
13513{
13514 struct params h_config={0};
13515 char config_file[64] = {0};
13516 char buf[128] = {0};
13517
13518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13519
13520 h_config.name = "sae_require_mfp";
13521 h_config.value = enable?"1":"0";
13522
13523 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13524 wifi_hostapdWrite(config_file, &h_config, 1);
13525 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13526
13527 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13528 return RETURN_OK;
13529}
13530
13531INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13532{
13533 struct params h_config={0};
13534 char config_file[64] = {0};
13535 char buf[128] = {0};
13536
13537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13538
13539 h_config.name = "sae_pwe";
13540 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13541 h_config.value = buf;
13542
13543 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13544 wifi_hostapdWrite(config_file, &h_config, 1);
13545 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13546
13547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13548 return RETURN_OK;
13549}
13550
13551INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13552{
13553 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13554 struct params h_config={0};
13555 char config_file[64] = {0};
13556
13557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13558
13559 h_config.name = "wpa_disable_eapol_key_retries";
13560 h_config.value = disable_EAPOL_retries?"1":"0";
13561
13562 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13563 wifi_hostapdWrite(config_file, &h_config, 1);
13564 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13565
13566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13567 return RETURN_OK;
13568}
13569
developer06a01d92022-09-07 16:32:39 +080013570INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13571{
developer587c1b62022-09-27 15:58:59 +080013572 char buf[128] = {0};
13573 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013574 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013575 char password[64] = {0};
13576 char mfp[32] = {0};
13577 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013578 BOOL okc_enable = FALSE;
13579 BOOL sae_MFP = FALSE;
13580 BOOL disable_EAPOL_retries = TRUE;
13581 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013582 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013583 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013584
13585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13586
13587 multiple_set = TRUE;
13588 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13589 if (security->mode == wifi_security_mode_none) {
13590 strcpy(wpa_mode, "None");
13591 } else if (security->mode == wifi_security_mode_wpa_personal)
13592 strcpy(wpa_mode, "WPA-Personal");
13593 else if (security->mode == wifi_security_mode_wpa2_personal)
13594 strcpy(wpa_mode, "WPA2-Personal");
13595 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13596 strcpy(wpa_mode, "WPA-WPA2-Personal");
13597 else if (security->mode == wifi_security_mode_wpa_enterprise)
13598 strcpy(wpa_mode, "WPA-Enterprise");
13599 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13600 strcpy(wpa_mode, "WPA2-Enterprise");
13601 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13602 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013603 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013604 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013605 okc_enable = TRUE;
13606 sae_MFP = TRUE;
13607 sae_pwe = 2;
13608 disable_EAPOL_retries = FALSE;
13609 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013610 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013611 okc_enable = TRUE;
13612 sae_MFP = TRUE;
13613 sae_pwe = 2;
13614 disable_EAPOL_retries = FALSE;
13615 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013616 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013617 sae_MFP = TRUE;
13618 sae_pwe = 2;
13619 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013620 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013621 strcpy(wpa_mode, "OWE");
13622 sae_MFP = TRUE;
13623 sae_pwe = 2;
13624 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013625 }
13626
13627 band = wifi_index_to_band(ap_index);
13628 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13629 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13630 return RETURN_ERR;
13631 }
developer587c1b62022-09-27 15:58:59 +080013632
13633 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013634 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013635 wifi_setSAEMFP(ap_index, sae_MFP);
13636 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013637 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013638
developerae432c62023-04-24 11:07:20 +080013639 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013640 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) {
13641 int key_len = strlen(security->u.key.key);
13642 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13643 if (key_len == 64) { // set wpa_psk
13644 strncpy(password, security->u.key.key, 64); // 64 characters
13645 password[64] = '\0';
13646 wifi_setApSecurityPreSharedKey(ap_index, password);
13647 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13648 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13649 strncpy(password, security->u.key.key, 63);
13650 password[63] = '\0';
13651 wifi_setApSecurityKeyPassphrase(ap_index, password);
13652 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13653 } else
13654 return RETURN_ERR;
13655 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013656 }
13657 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13658 params.name = "sae_password";
13659 params.value = security->u.key.key;
13660 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013661 } else { // remove sae_password
13662 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13663 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013664 }
13665 }
developer587c1b62022-09-27 15:58:59 +080013666
13667 if (security->mode != wifi_security_mode_none) {
13668 memset(&params, 0, sizeof(params));
13669 params.name = "wpa_pairwise";
13670 if (security->encr == wifi_encryption_tkip)
13671 params.value = "TKIP";
13672 else if (security->encr == wifi_encryption_aes)
13673 params.value = "CCMP";
13674 else if (security->encr == wifi_encryption_aes_tkip)
13675 params.value = "TKIP CCMP";
13676 wifi_hostapdWrite(config_file, &params, 1);
13677 }
13678
13679 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013680 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013681 else if (security->mfp == wifi_mfp_cfg_optional)
13682 strcpy(mfp, "Optional");
13683 else if (security->mfp == wifi_mfp_cfg_required)
13684 strcpy(mfp, "Required");
13685 wifi_setApSecurityMFPConfig(ap_index, mfp);
13686
13687 memset(&params, 0, sizeof(params));
13688 params.name = "transition_disable";
13689 if (security->wpa3_transition_disable == TRUE)
13690 params.value = "0x01";
13691 else
13692 params.value = "0x00";
13693 wifi_hostapdWrite(config_file, &params, 1);
13694
13695 memset(&params, 0, sizeof(params));
13696 params.name = "wpa_group_rekey";
13697 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13698 params.value = buf;
13699 wifi_hostapdWrite(config_file, &params, 1);
13700
13701 memset(&params, 0, sizeof(params));
13702 params.name = "wpa_strict_rekey";
13703 params.value = security->strict_rekey?"1":"0";
13704 wifi_hostapdWrite(config_file, &params, 1);
13705
13706 memset(&params, 0, sizeof(params));
13707 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013708 if (security->eapol_key_retries == 0)
13709 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013710 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13711 params.value = buf;
13712 wifi_hostapdWrite(config_file, &params, 1);
13713
13714 memset(&params, 0, sizeof(params));
13715 params.name = "disable_pmksa_caching";
13716 params.value = security->disable_pmksa_caching?"1":"0";
13717 wifi_hostapdWrite(config_file, &params, 1);
13718
developer23e71282023-01-18 10:25:19 +080013719 if (multiple_set == FALSE) {
13720 wifi_setApEnable(ap_index, FALSE);
13721 wifi_setApEnable(ap_index, TRUE);
13722 }
developer587c1b62022-09-27 15:58:59 +080013723
13724 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13725
developer06a01d92022-09-07 16:32:39 +080013726 return RETURN_OK;
13727}
13728
13729INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13730{
developer9df4e652022-10-11 11:27:38 +080013731 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013732 char config_file[128] = {0};
13733 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013734 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013735
13736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13737 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13738 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13739 security->mode = wifi_security_mode_none;
13740 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013741 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013742 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013743 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013744 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013745 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013746 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013747 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013748 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013749 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013750 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013751 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013752 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013753 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013754 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013755 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013756 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013757 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013758 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013759 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013760 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013761 }
13762
13763 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13764 if (security->mode == wifi_security_mode_none)
13765 security->encr = wifi_encryption_none;
13766 else {
13767 if (strcmp(buf, "TKIP") == 0)
13768 security->encr = wifi_encryption_tkip;
13769 else if (strcmp(buf, "CCMP") == 0)
13770 security->encr = wifi_encryption_aes;
13771 else
13772 security->encr = wifi_encryption_aes_tkip;
13773 }
13774
developer9df4e652022-10-11 11:27:38 +080013775 if (security->mode != wifi_encryption_none) {
13776 memset(buf, 0, sizeof(buf));
13777 // wpa3 can use one or both configs as password, so we check sae_password first.
13778 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013779 if (strlen(buf) != 0) {
13780 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13781 security->u.key.type = wifi_security_key_type_sae;
13782 set_sae = TRUE;
13783 strncpy(security->u.key.key, buf, sizeof(buf));
13784 }
13785 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13786 if (strlen(buf) != 0){
13787 if (set_sae == TRUE)
13788 security->u.key.type = wifi_security_key_type_psk_sae;
13789 else if (strlen(buf) == 64)
13790 security->u.key.type = wifi_security_key_type_psk;
13791 else
13792 security->u.key.type = wifi_security_key_type_pass;
13793 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013794 }
developer9df4e652022-10-11 11:27:38 +080013795 security->u.key.key[255] = '\0';
13796 }
13797
developer587c1b62022-09-27 15:58:59 +080013798 memset(buf, 0, sizeof(buf));
13799 wifi_getApSecurityMFPConfig(ap_index, buf);
13800 if (strcmp(buf, "Disabled") == 0)
13801 security->mfp = wifi_mfp_cfg_disabled;
13802 else if (strcmp(buf, "Optional") == 0)
13803 security->mfp = wifi_mfp_cfg_optional;
13804 else if (strcmp(buf, "Required") == 0)
13805 security->mfp = wifi_mfp_cfg_required;
13806
13807 memset(buf, 0, sizeof(buf));
13808 security->wpa3_transition_disable = FALSE;
13809 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13810 disable = strtol(buf, NULL, 16);
13811 if (disable != 0)
13812 security->wpa3_transition_disable = TRUE;
13813
13814 memset(buf, 0, sizeof(buf));
13815 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13816 if (strlen(buf) == 0)
13817 security->rekey_interval = 86400;
13818 else
13819 security->rekey_interval = strtol(buf, NULL, 10);
13820
13821 memset(buf, 0, sizeof(buf));
13822 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13823 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013824 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013825 else
13826 security->strict_rekey = strtol(buf, NULL, 10);
13827
13828 memset(buf, 0, sizeof(buf));
13829 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13830 if (strlen(buf) == 0)
13831 security->eapol_key_retries = 4;
13832 else
13833 security->eapol_key_retries = strtol(buf, NULL, 10);
13834
13835 memset(buf, 0, sizeof(buf));
13836 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13837 if (strlen(buf) == 0)
13838 security->disable_pmksa_caching = FALSE;
13839 else
13840 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13841
13842 /* TODO
13843 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13844 */
13845 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13846 security->eap_identity_req_timeout = 0;
13847 security->eap_identity_req_retries = 0;
13848 security->eap_req_timeout = 0;
13849 security->eap_req_retries = 0;
13850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013851 return RETURN_OK;
13852}
13853
13854#endif /* WIFI_HAL_VERSION_3 */
13855
13856#ifdef WIFI_HAL_VERSION_3_PHASE2
13857INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13858{
developerd946fd62022-12-08 18:03:28 +080013859 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013860 char cmd[128] = {0};
13861 char buf[128] = {0};
13862 char *mac_addr = NULL;
13863 BOOL status = FALSE;
13864 size_t len = 0;
13865
13866 if(ap_index > MAX_APS)
13867 return RETURN_ERR;
13868
13869 *output_numDevices = 0;
13870 wifi_getApEnable(ap_index, &status);
13871 if (status == FALSE)
13872 return RETURN_OK;
13873
developerac6f1142022-12-20 19:26:35 +080013874 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013875 return RETURN_ERR;
13876 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013877 _syscmd(cmd, buf, sizeof(buf));
13878
13879 mac_addr = strtok(buf, "\n");
13880 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13881 *output_numDevices = i + 1;
13882 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13883 addr_ptr = output_deviceMacAddressArray[i];
13884 mac_addr_aton(addr_ptr, mac_addr);
13885 mac_addr = strtok(NULL, "\n");
13886 }
13887
13888 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013889}
13890#else
13891INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13892{
developerd946fd62022-12-08 18:03:28 +080013893 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013894 char cmd[128];
13895 BOOL status = false;
13896
13897 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13898 return RETURN_ERR;
13899
13900 output_buf[0] = '\0';
13901
13902 wifi_getApEnable(ap_index,&status);
13903 if (!status)
13904 return RETURN_OK;
13905
developerac6f1142022-12-20 19:26:35 +080013906 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013907 return RETURN_ERR;
13908 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013909 _syscmd(cmd, output_buf, output_buf_size);
13910
13911 return RETURN_OK;
13912}
13913#endif
developer2f513ab2022-09-13 14:26:06 +080013914
13915INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13916{
13917 char output[16]={'\0'};
13918 char config_file[MAX_BUF_SIZE] = {0};
13919
13920 if (!enable)
13921 return RETURN_ERR;
13922
13923 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13924 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13925
13926 if (strlen(output) == 0)
13927 *enable = FALSE;
13928 else if (strncmp(output, "1", 1) == 0)
13929 *enable = TRUE;
13930 else
13931 *enable = FALSE;
13932
13933 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13934 return RETURN_OK;
13935}
developer2d9c30f2022-09-13 15:06:14 +080013936
13937INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13938{
developer804c64f2022-10-19 13:54:40 +080013939 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013940 return RETURN_ERR;
13941 *output_enable=TRUE;
13942 return RETURN_OK;
13943}
developerfd7d2892022-09-13 16:44:53 +080013944
13945INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13946{
13947 char cmd[128] = {0};
13948 char buf[128] = {0};
13949 char line[128] = {0};
13950 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013951 FILE *f = NULL;
13952 int index = 0;
13953 int exp = 0;
13954 int mantissa = 0;
13955 int duration = 0;
13956 int radio_index = 0;
13957 int max_radio_num = 0;
13958 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013959 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013960 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13961
13962 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013963
developerfd7d2892022-09-13 16:44:53 +080013964 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013965
13966 phyId = radio_index_to_phy(radio_index);
13967 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013968 _syscmd(cmd, buf, sizeof(buf));
13969 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13970 if (*numSessionReturned > maxNumberSessions)
13971 *numSessionReturned = maxNumberSessions;
13972 else if (*numSessionReturned < 1) {
13973 *numSessionReturned = 0;
13974 return RETURN_OK;
13975 }
13976
developer033b37b2022-10-18 11:27:46 +080013977 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 +080013978 if ((f = popen(cmd, "r")) == NULL) {
13979 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13980 return RETURN_ERR;
13981 }
13982
13983 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013984 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013985 char *tmp = NULL;
13986 strcpy(buf, line);
13987 tmp = strtok(buf, " ");
13988 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13989 tmp = strtok(NULL, " ");
13990 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13991 tmp = strtok(NULL, " ");
13992 if (strstr(tmp, "t")) {
13993 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13994 }
13995 if (strstr(tmp, "a")) {
13996 twtSessions[index].twtParameters.operation.announced = TRUE;
13997 }
13998 tmp = strtok(NULL, " ");
13999 exp = strtol(tmp, NULL, 10);
14000 tmp = strtok(NULL, " ");
14001 mantissa = strtol(tmp, NULL, 10);
14002 tmp = strtok(NULL, " ");
14003 duration = strtol(tmp, NULL, 10);
14004
14005 // only implicit supported
14006 twtSessions[index].twtParameters.operation.implicit = TRUE;
14007 // only individual agreement supported
14008 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14009
14010 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14011 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080014012 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080014013 // Overflow handling
14014 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14015 } else {
14016 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14017 }
14018 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14019 index++;
14020 }
14021
14022 pclose(f);
14023 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14024 return RETURN_OK;
14025}