blob: c59e3b8fead0825b632028e0df53f45db3db45bb [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
developer7930d352022-12-21 17:55:42 +080066#define MAX_BUF_SIZE 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
developer06a01d92022-09-07 16:32:39 +080069#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080070#define ACL_PREFIX "/nvram/hostapd-acl"
71#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080072//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
73#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080074#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080075#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080076#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080077#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080078#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080079#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080080#define PSK_FILE "/nvram/hostapd"
developerf49437e2022-09-29 19:58:21 +080081#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080082#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080083
developer81bf2ed2022-09-13 15:31:14 +080084#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080085
86/*
87 MAX_APS - Number of all AP available in system
88 2x Home AP
89 2x Backhaul AP
90 2x Guest AP
91 2x Secure Onboard AP
92 2x Service AP
93
94*/
developer06a01d92022-09-07 16:32:39 +080095
developer033b37b2022-10-18 11:27:46 +080096
developera77d84b2023-02-22 16:10:50 +080097#define MAX_APS ((MAX_NUM_RADIOS)*(MAX_NUM_VAP_PER_RADIO))
developer06a01d92022-09-07 16:32:39 +080098#ifndef AP_PREFIX
99#define AP_PREFIX "wifi"
100#endif
101
102#ifndef RADIO_PREFIX
103#define RADIO_PREFIX "wlan"
104#endif
105
developer89df4502023-02-16 20:45:02 +0800106#define MAX_ASSOCIATED_STA_NUM 2007 // hostapd default
developer06a01d92022-09-07 16:32:39 +0800107
108//Uncomment to enable debug logs
109//#define WIFI_DEBUG
110
111#ifdef WIFI_DEBUG
112#define wifi_dbg_printf printf
113#define WIFI_ENTRY_EXIT_DEBUG printf
114#else
115#define wifi_dbg_printf(format, args...) printf("")
116#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
117#endif
118
119#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
120#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
121#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
122#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
123#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
124#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
125#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
126#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
127#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
128#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
129
developer4fb0b922022-09-30 14:29:09 +0800130#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800131
132#define BW_FNAME "/nvram/bw_file.txt"
133
134#define PS_MAX_TID 16
135
136static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
137 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
138 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
139 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
141 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
142 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
143 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
144 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
153};
154
155typedef unsigned long long u64;
156
157/* Enum to define WiFi Bands */
158typedef enum
159{
160 band_invalid = -1,
161 band_2_4 = 0,
162 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800163 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800164} wifi_band;
165
developerdb744382022-09-13 15:34:54 +0800166typedef enum {
167 WIFI_MODE_A = 0x01,
168 WIFI_MODE_B = 0x02,
169 WIFI_MODE_G = 0x04,
170 WIFI_MODE_N = 0x08,
171 WIFI_MODE_AC = 0x10,
172 WIFI_MODE_AX = 0x20,
developer7c4cd202023-03-01 10:56:29 +0800173 WIFI_MODE_BE = 0x40,
developerdb744382022-09-13 15:34:54 +0800174} wifi_ieee80211_Mode;
175
developer06a01d92022-09-07 16:32:39 +0800176#ifdef WIFI_HAL_VERSION_3
177
178// Return number of elements in array
179#ifndef ARRAY_SIZE
180#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
181#endif /* ARRAY_SIZE */
182
183#ifndef ARRAY_AND_SIZE
184#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
185#endif /* ARRAY_AND_SIZE */
186
187#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
188
189typedef struct {
190 int32_t value;
191 int32_t param;
192 intptr_t key;
193 intptr_t data;
194} wifi_secur_list;
195
developerfa41b1f2023-01-06 10:25:51 +0800196static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
197static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800198static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800199wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
200wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
201char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800202static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800203
204static wifi_secur_list map_security[] =
205{
206 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
207 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
208 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800214 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800216 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800217 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800270 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 +0800271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800289 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 +0800290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
developerf5745ee2022-10-05 16:09:53 +0800295 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800296 if (freq == 2484)
297 return 14;
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
299 else if (freq == 5935)
300 return 2;
developer06a01d92022-09-07 16:32:39 +0800301 else if (freq < 2484)
302 return (freq - 2407) / 5;
303 else if (freq >= 4910 && freq <= 4980)
304 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800305 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800306 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800307 else if (freq <= 45000) /* DMG band lower limit */
308 /* see 802.11ax D6.1 27.3.23.2 */
309 return (freq - 5950) / 5;
310 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800311 return (freq - 56160) / 2160;
312 else
313 return 0;
314}
315
316static int initSock80211(Netlink* nl) {
317 nl->socket = nl_socket_alloc();
318 if (!nl->socket) {
319 fprintf(stderr, "Failing to allocate the sock\n");
320 return -ENOMEM;
321 }
322
323 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
324
325 if (genl_connect(nl->socket)) {
326 fprintf(stderr, "Failed to connect\n");
327 nl_close(nl->socket);
328 nl_socket_free(nl->socket);
329 return -ENOLINK;
330 }
331
332 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
333 if (nl->id< 0) {
334 fprintf(stderr, "interface not found.\n");
335 nl_close(nl->socket);
336 nl_socket_free(nl->socket);
337 return -ENOENT;
338 }
339
340 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
341 if ((!nl->cb)) {
342 fprintf(stderr, "Failed to allocate netlink callback.\n");
343 nl_close(nl->socket);
344 nl_socket_free(nl->socket);
345 return ENOMEM;
346 }
347
348 return nl->id;
349}
350
351static int nlfree(Netlink *nl)
352{
353 nl_cb_put(nl->cb);
354 nl_close(nl->socket);
355 nl_socket_free(nl->socket);
356 return 0;
357}
358
359static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
360 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
361 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
362 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
363};
364
365static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
366};
367
368static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
369};
370
371typedef struct _wifi_channelStats_loc {
372 INT array_size;
373 INT ch_number;
374 BOOL ch_in_pool;
375 INT ch_noise;
376 BOOL ch_radar_noise;
377 INT ch_max_80211_rssi;
378 INT ch_non_80211_noise;
379 INT ch_utilization;
380 ULLONG ch_utilization_total;
381 ULLONG ch_utilization_busy;
382 ULLONG ch_utilization_busy_tx;
383 ULLONG ch_utilization_busy_rx;
384 ULLONG ch_utilization_busy_self;
385 ULLONG ch_utilization_busy_ext;
386} wifi_channelStats_t_loc;
387
388typedef struct wifi_device_info {
389 INT wifi_devIndex;
390 UCHAR wifi_devMacAddress[6];
391 CHAR wifi_devIPAddress[64];
392 BOOL wifi_devAssociatedDeviceAuthentiationState;
393 INT wifi_devSignalStrength;
394 INT wifi_devTxRate;
395 INT wifi_devRxRate;
396} wifi_device_info_t;
397
398#endif
399
400//For 5g Alias Interfaces
401static BOOL priv_flag = TRUE;
402static BOOL pub_flag = TRUE;
403static BOOL Radio_flag = TRUE;
404//wifi_setApBeaconRate(1, beaconRate);
405
developer1e5aa162022-09-13 16:06:24 +0800406BOOL multiple_set = FALSE;
407
developer06a01d92022-09-07 16:32:39 +0800408struct params
409{
410 char * name;
411 char * value;
412};
413
414static int _syscmd(char *cmd, char *retBuf, int retBufSize)
415{
416 FILE *f;
417 char *ptr = retBuf;
418 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
419
420 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
421 if((f = popen(cmd, "r")) == NULL) {
422 fprintf(stderr,"\npopen %s error\n", cmd);
423 return RETURN_ERR;
424 }
425
426 while(!feof(f))
427 {
428 *ptr = 0;
429 if(bufSize>=128) {
430 bufbytes=128;
431 } else {
432 bufbytes=bufSize-1;
433 }
434
435 fgets(ptr,bufbytes,f);
436 readbytes=strlen(ptr);
437
438 if(!readbytes)
439 break;
440
441 bufSize-=readbytes;
442 ptr += readbytes;
443 }
444 cmd_ret = pclose(f);
445 retBuf[retBufSize-1]=0;
446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
447
448 return cmd_ret >> 8;
449}
450
developer033b37b2022-10-18 11:27:46 +0800451INT radio_index_to_phy(int radioIndex)
452{
453 char cmd[128] = {0};
454 char buf[64] = {0};
455 int phyIndex = 0;
456 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
457 _syscmd(cmd, buf, sizeof(buf));
458
459 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800460 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800461 return RETURN_ERR;
462 }
463 sscanf(buf, "phy%d", &phyIndex);
464
465 return phyIndex;
466}
developer026ac9e2022-11-07 13:46:24 +0800467
developer431128d2022-12-16 15:30:41 +0800468INT wifi_getMaxRadioNumber(INT *max_radio_num)
469{
470 char cmd[64] = {0};
471 char buf[4] = {0};
472
473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
474
475 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
476 _syscmd(cmd, buf, sizeof(buf));
477 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
478
479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
480
481 return RETURN_OK;
482}
483
developer59ff6de2023-02-08 17:58:14 +0800484static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
485{
486 char cmd[MAX_CMD_SIZE]={'\0'};
487 char buf[MAX_BUF_SIZE]={'\0'};
488 int ret = 0;
489
490 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
491 ret = _syscmd(cmd, buf, sizeof(buf));
492 if ((ret != 0) && (strlen(buf) == 0))
493 return -1;
494 snprintf(output, output_size, "%s", buf);
495
496 return 0;
497}
498
499static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
500{
501 char cmd[MAX_CMD_SIZE]={'\0'};
502 char buf[MAX_BUF_SIZE]={'\0'};
503
504 for(int i=0;i<item_count;i++)
505 {
506 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
507 if (strlen(buf) == 0) //Insert
508 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
509 else //Update
510 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
511
512 if(_syscmd(cmd, buf, sizeof(buf)))
513 return -1;
514 }
515
516 return 0;
517}
518
developer431128d2022-12-16 15:30:41 +0800519wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800520{
521 char cmd[128] = {0};
522 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800523 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800524 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800525 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800526 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800527 int radioIndex = 0;
528 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800529 wifi_band band = band_invalid;
530
531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800532
developer431128d2022-12-16 15:30:41 +0800533 wifi_getMaxRadioNumber(&max_radio_num);
534 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800535 phyIndex = radio_index_to_phy(radioIndex);
developer59ff6de2023-02-08 17:58:14 +0800536 snprintf(cmd, sizeof(cmd), "cat /sys/class/ieee80211/phy%d/device/device 2> /dev/null", phyIndex);
537 _syscmd(cmd, buf, sizeof(buf));
538 if (strncmp(buf, "0x7915", 6) == 0) { // harrier have two bands, consider as a special case.
539 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
540 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
541 if (strncmp(buf, "a", 1) == 0)
542 return band_5;
543 else
544 return band_2_4;
545 }
developer5884e982022-10-06 10:52:50 +0800546 while(i < 10){
developer59ff6de2023-02-08 17:58:14 +0800547 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800548 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800549 nl80211_band = strtol(buf, NULL, 10);
550 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800551 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800552 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800553 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800554 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800555 band = band_6;
556
557 if(band != band_invalid)
558 break;
559
560 i++;
561 sleep(1);
562 }
developerc707e972022-09-13 15:38:02 +0800563
564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
565 return band;
566}
567
developerd946fd62022-12-08 18:03:28 +0800568//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800569static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800570{
571 char config_file[128] = {0};
572
573 if (interface_name == NULL)
574 return RETURN_ERR;
575
576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
577
578 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
579 wifi_hostapdRead(config_file, "interface", interface_name, 16);
580 if (strlen(interface_name) == 0)
581 return RETURN_ERR;
582
583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
584 return RETURN_OK;
585}
586
developerac6f1142022-12-20 19:26:35 +0800587// wifi agent will call this function, do not change the parameter
588void GetInterfaceName(char *interface_name, char *conf_file)
589{
590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
591 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
593}
594
developer06a01d92022-09-07 16:32:39 +0800595static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
596{
developerd946fd62022-12-08 18:03:28 +0800597 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800598 if (multiple_set == TRUE)
599 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800600 char cmd[MAX_CMD_SIZE]="", output[32]="";
601 FILE *fp;
602 int i;
603 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800604 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800605 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800606 for(i=0; i<item_count; i++, list++)
607 {
developerd946fd62022-12-08 18:03:28 +0800608 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800609 if((fp = popen(cmd, "r"))==NULL)
610 {
611 perror("popen failed");
612 return -1;
613 }
614 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
615 {
616 pclose(fp);
617 perror("fgets failed");
618 return -1;
619 }
620 pclose(fp);
621 }
622 return 0;
623}
624
625static int wifi_reloadAp(int apIndex)
626{
developerd946fd62022-12-08 18:03:28 +0800627 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800628 if (multiple_set == TRUE)
629 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800630 char cmd[MAX_CMD_SIZE]="";
631 char buf[MAX_BUF_SIZE]="";
632
developerac6f1142022-12-20 19:26:35 +0800633 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800634 return RETURN_ERR;
635 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800636 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
637 return RETURN_ERR;
638
developerd946fd62022-12-08 18:03:28 +0800639 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800640 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
641 return RETURN_ERR;
642
developerd946fd62022-12-08 18:03:28 +0800643 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800644 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
645 return RETURN_ERR;
646
647 return RETURN_OK;
648}
649
developer06a01d92022-09-07 16:32:39 +0800650INT File_Reading(CHAR *file, char *Value)
651{
652 FILE *fp = NULL;
653 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
654 int count = 0;
655
656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
657 fp = popen(file,"r");
658 if(fp == NULL)
659 return RETURN_ERR;
660
661 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
662 {
663 for(count=0;buf[count]!='\n';count++)
664 copy_buf[count]=buf[count];
665 copy_buf[count]='\0';
666 }
667 strcpy(Value,copy_buf);
668 pclose(fp);
669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
670
671 return RETURN_OK;
672}
673
674void wifi_RestartHostapd_2G()
675{
676 int Public2GApIndex = 4;
677
678 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
679 wifi_setApEnable(Public2GApIndex, FALSE);
680 wifi_setApEnable(Public2GApIndex, TRUE);
681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
682}
683
684void wifi_RestartHostapd_5G()
685{
686 int Public5GApIndex = 5;
687
688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
689 wifi_setApEnable(Public5GApIndex, FALSE);
690 wifi_setApEnable(Public5GApIndex, TRUE);
691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
692}
693
694void wifi_RestartPrivateWifi_2G()
695{
696 int PrivateApIndex = 0;
697
698 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
699 wifi_setApEnable(PrivateApIndex, FALSE);
700 wifi_setApEnable(PrivateApIndex, TRUE);
701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
702}
703
704void wifi_RestartPrivateWifi_5G()
705{
706 int Private5GApIndex = 1;
707
708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
709 wifi_setApEnable(Private5GApIndex, FALSE);
710 wifi_setApEnable(Private5GApIndex, TRUE);
711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
712}
713
714static int writeBandWidth(int radioIndex,char *bw_value)
715{
716 char buf[MAX_BUF_SIZE];
717 char cmd[MAX_CMD_SIZE];
718
719 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
720 if(_syscmd(cmd, buf, sizeof(buf)))
721 {
722 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
723 _syscmd(cmd, buf, sizeof(buf));
724 return RETURN_OK;
725 }
726
727 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
728 _syscmd(cmd,buf,sizeof(buf));
729 return RETURN_OK;
730}
731
732static int readBandWidth(int radioIndex,char *bw_value)
733{
developer30423732022-12-01 16:17:49 +0800734 char buf[MAX_BUF_SIZE] = {0};
735 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800736 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
737 _syscmd(cmd,buf,sizeof(buf));
738 if(NULL!=strstr(buf,"20MHz"))
developer06a01d92022-09-07 16:32:39 +0800739 strcpy(bw_value,"20MHz");
developer06a01d92022-09-07 16:32:39 +0800740 else if(NULL!=strstr(buf,"40MHz"))
developer06a01d92022-09-07 16:32:39 +0800741 strcpy(bw_value,"40MHz");
developer06a01d92022-09-07 16:32:39 +0800742 else if(NULL!=strstr(buf,"80MHz"))
developer06a01d92022-09-07 16:32:39 +0800743 strcpy(bw_value,"80MHz");
developer57fa24a2023-03-15 17:25:07 +0800744 else if(NULL!=strstr(buf,"160MHz"))
745 strcpy(bw_value,"160MHz");
746 else if(NULL!=strstr(buf,"320MHz"))
747 strcpy(bw_value,"320MHz");
developer06a01d92022-09-07 16:32:39 +0800748 else
developer06a01d92022-09-07 16:32:39 +0800749 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800750 return RETURN_OK;
751}
752
developer264159b2022-11-02 09:41:35 +0800753// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800754INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
755{
developer5f222492022-09-13 15:21:52 +0800756 struct params params={'\0'};
757 char config_file[MAX_BUF_SIZE] = {0};
758 char buf[MAX_BUF_SIZE] = {'\0'};
759
760 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800761 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800762 if (strlen (beaconRate) >= 5) {
763 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
764 buf[strlen(beaconRate) - 4] = '\0';
765 } else if (strlen(beaconRate) > 0)
766 strcpy(buf, beaconRate);
767 else
768 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800769
770 params.name = "beacon_rate";
771 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
772 if (strncmp(buf, "5.5", 3) == 0) {
773 snprintf(buf, sizeof(buf), "55");
774 params.value = buf;
775 } else {
776 strcat(buf, "0");
777 params.value = buf;
778 }
779
780 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
781 wifi_hostapdWrite(config_file, &params, 1);
782 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
784
785 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800786}
787
788INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
789{
developer1d57d002022-10-12 18:03:15 +0800790 char config_file[128] = {'\0'};
791 char temp_output[128] = {'\0'};
792 char buf[128] = {'\0'};
793 char cmd[128] = {'\0'};
794 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800795 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800796
797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
798 if (NULL == beaconRate)
799 return RETURN_ERR;
800
801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
802 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800803 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800804 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
805 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800806 if (strncmp(buf, "55", 2) == 0)
807 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
808 else {
809 rate = strtol(buf, NULL, 10)/10;
810 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
811 }
developer5f222492022-09-13 15:21:52 +0800812 } else {
developer1d57d002022-10-12 18:03:15 +0800813 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800814 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 +0800815 _syscmd(cmd, buf, sizeof(buf));
816 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800817 }
818 strncpy(beaconRate, temp_output, sizeof(temp_output));
819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
820
821 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800822}
823
824INT wifi_setLED(INT radioIndex, BOOL enable)
825{
826 return 0;
827}
828INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
829{
830 return RETURN_OK;
831}
832/**********************************************************************************
833 *
834 * Wifi Subsystem level function prototypes
835 *
836**********************************************************************************/
837//---------------------------------------------------------------------------------------------------
838//Wifi system api
839//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
840INT wifi_getHalVersion(CHAR *output_string) //RDKB
841{
842 if(!output_string)
843 return RETURN_ERR;
844 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
845
846 return RETURN_OK;
847}
848
849
850/* wifi_factoryReset() function */
851/**
852* @description Clears internal variables to implement a factory reset of the Wi-Fi
853* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
854*
855* @param None
856*
857* @return The status of the operation.
858* @retval RETURN_OK if successful.
859* @retval RETURN_ERR if any error is detected
860*
861* @execution Synchronous
862* @sideeffect None
863*
864* @note This function must not suspend and must not invoke any blocking system
865* calls. It should probably just send a message to a driver event handler task.
866*
867*/
868INT wifi_factoryReset()
869{
870 char cmd[128];
871
872 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800873 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
874 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800875 system(cmd);
876 system("systemctl restart hostapd.service");
877
878 return RETURN_OK;
879}
880
881/* wifi_factoryResetRadios() function */
882/**
883* @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.
884*
885* @param None
886* @return The status of the operation
887* @retval RETURN_OK if successful
888* @retval RETURN_ERR if any error is detected
889*
890* @execution Synchronous
891*
892* @sideeffect None
893*
894* @note This function must not suspend and must not invoke any blocking system
895* calls. It should probably just send a message to a driver event handler task.
896*
897*/
898INT wifi_factoryResetRadios()
899{
developer72ec5572023-01-05 16:27:13 +0800900 int max_radio_num = 0;
901 wifi_getMaxRadioNumber(&max_radio_num);
902 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
903 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800904
developer72ec5572023-01-05 16:27:13 +0800905 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800906}
907
908
909/* wifi_factoryResetRadio() function */
910/**
911* @description Restore selected radio parameters without touching access point parameters
912*
913* @param radioIndex - Index of Wi-Fi Radio channel
914*
915* @return The status of the operation.
916* @retval RETURN_OK if successful.
917* @retval RETURN_ERR if any error is detected
918*
919* @execution Synchronous.
920* @sideeffect None.
921*
922* @note This function must not suspend and must not invoke any blocking system
923* calls. It should probably just send a message to a driver event handler task.
924*
925*/
926INT wifi_factoryResetRadio(int radioIndex) //RDKB
927{
developer72ec5572023-01-05 16:27:13 +0800928 char cmd[128] = {0};
929 char buf[128] = {0};
930 int max_radio_num = 0;
931
932 wifi_getMaxRadioNumber(&max_radio_num);
933 if (radioIndex < 0 || radioIndex > max_radio_num)
934 return RETURN_ERR;
935
936 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
937 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800938
developer06a01d92022-09-07 16:32:39 +0800939 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800940 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
941 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800942
developer72ec5572023-01-05 16:27:13 +0800943 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
944 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800945 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
946 return RETURN_OK;
947}
948
949/* wifi_initRadio() function */
950/**
951* Description: This function call initializes the specified radio.
952* Implementation specifics may dictate the functionality since
953* different hardware implementations may have different initilization requirements.
954* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
955*
956* @return The status of the operation.
957* @retval RETURN_OK if successful.
958* @retval RETURN_ERR if any error is detected
959*
960* @execution Synchronous.
961* @sideeffect None.
962*
963* @note This function must not suspend and must not invoke any blocking system
964* calls. It should probably just send a message to a driver event handler task.
965*
966*/
967INT wifi_initRadio(INT radioIndex)
968{
969 //TODO: Initializes the wifi subsystem (for specified radio)
970 return RETURN_OK;
971}
972void macfilter_init()
973{
974 char count[4]={'\0'};
975 char buf[253]={'\0'};
976 char tmp[19]={'\0'};
977 int dev_count,block,mac_entry=0;
978 char res[4]={'\0'};
979 char acl_file_path[64] = {'\0'};
980 FILE *fp = NULL;
981 int index=0;
982 char iface[10]={'\0'};
983 char config_file[MAX_BUF_SIZE] = {0};
984
985
986 sprintf(acl_file_path,"/tmp/mac_filter.sh");
987
988 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800989 if (fp == NULL) {
990 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
991 return RETURN_ERR;
992 }
developer06a01d92022-09-07 16:32:39 +0800993 sprintf(buf,"#!/bin/sh \n");
994 fprintf(fp,"%s\n",buf);
995
996 system("chmod 0777 /tmp/mac_filter.sh");
997
998 for(index=0;index<=1;index++)
999 {
1000 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1001 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1002 sprintf(buf,"syscfg get %dcountfilter",index);
1003 _syscmd(buf,count,sizeof(count));
1004 mac_entry=atoi(count);
1005
1006 sprintf(buf,"syscfg get %dblockall",index);
1007 _syscmd(buf,res,sizeof(res));
1008 block = atoi(res);
1009
1010 //Allow only those macs mentioned in ACL
1011 if(block==1)
1012 {
1013 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1014 fprintf(fp,"%s\n",buf);
1015 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1016 {
1017 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1018 _syscmd(buf,tmp,sizeof(tmp));
1019 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1020 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1021 fprintf(fp,"%s\n",buf);
1022 }
1023 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1024 fprintf(fp,"%s\n",buf);
1025 }
1026
1027 //Block all the macs mentioned in ACL
1028 else if(block==2)
1029 {
1030 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1031 fprintf(fp,"%s\n",buf);
1032
1033 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1034 {
1035 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1036 _syscmd(buf,tmp,sizeof(tmp));
1037 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1038 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1039 fprintf(fp,"%s\n",buf);
1040 }
1041 }
1042 }
1043 fclose(fp);
1044}
1045
1046// Initializes the wifi subsystem (all radios)
1047INT wifi_init() //RDKB
1048{
1049 char interface[MAX_BUF_SIZE]={'\0'};
1050 char bridge_name[MAX_BUF_SIZE]={'\0'};
1051 INT len=0;
1052
1053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1054 //Not intitializing macfilter for Turris-Omnia Platform for now
1055 //macfilter_init();
1056
1057 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001058 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001059 sleep(2);//sleep to wait for hostapd to start
1060
1061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1062
1063 return RETURN_OK;
1064}
1065
1066/* wifi_reset() function */
1067/**
1068* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1069* Implementation specifics may dictate what is actualy reset since
1070* different hardware implementations may have different requirements.
1071* Parameters : None
1072*
1073* @return The status of the operation.
1074* @retval RETURN_OK if successful.
1075* @retval RETURN_ERR if any error is detected
1076*
1077* @execution Synchronous.
1078* @sideeffect None.
1079*
1080* @note This function must not suspend and must not invoke any blocking system
1081* calls. It should probably just send a message to a driver event handler task.
1082*
1083*/
1084INT wifi_reset()
1085{
1086 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001087 system("systemctl stop hostapd.service");
1088 sleep(2);
1089 system("systemctl start hostapd.service");
1090 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001091 return RETURN_OK;
1092}
1093
1094/* wifi_down() function */
1095/**
1096* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1097* Implementation specifics may dictate some functionality since
1098* different hardware implementations may have different requirements.
1099*
1100* @param None
1101*
1102* @return The status of the operation
1103* @retval RETURN_OK if successful
1104* @retval RETURN_ERR if any error is detected
1105*
1106* @execution Synchronous
1107* @sideeffect None
1108*
1109* @note This function must not suspend and must not invoke any blocking system
1110* calls. It should probably just send a message to a driver event handler task.
1111*
1112*/
1113INT wifi_down()
1114{
1115 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001116 int max_num_radios = 0;
1117 wifi_getMaxRadioNumber(&max_num_radios);
1118 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1119 wifi_setRadioEnable(radioIndex, FALSE);
1120
developer06a01d92022-09-07 16:32:39 +08001121 return RETURN_OK;
1122}
1123
1124
1125/* wifi_createInitialConfigFiles() function */
1126/**
1127* @description This function creates wifi configuration files. The format
1128* and content of these files are implementation dependent. This function call is
1129* used to trigger this task if necessary. Some implementations may not need this
1130* function. If an implementation does not need to create config files the function call can
1131* do nothing and return RETURN_OK.
1132*
1133* @param None
1134*
1135* @return The status of the operation
1136* @retval RETURN_OK if successful
1137* @retval RETURN_ERR if any error is detected
1138*
1139* @execution Synchronous
1140* @sideeffect None
1141*
1142* @note This function must not suspend and must not invoke any blocking system
1143* calls. It should probably just send a message to a driver event handler task.
1144*
1145*/
1146INT wifi_createInitialConfigFiles()
1147{
1148 //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)
1149 return RETURN_OK;
1150}
1151
1152// outputs the country code to a max 64 character string
1153INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1154{
developerd946fd62022-12-08 18:03:28 +08001155 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001156 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001157 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001158 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001159
developerac6f1142022-12-20 19:26:35 +08001160 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001161 return RETURN_ERR;
1162 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001163 _syscmd(cmd, buf, sizeof(buf));
1164 if(strlen(buf) > 0)
1165 snprintf(output_string, 64, "%s", buf);
1166 else
1167 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001168
1169 return RETURN_OK;
1170}
1171
1172INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1173{
1174 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001175 char str[MAX_BUF_SIZE]={'\0'};
1176 char cmd[MAX_CMD_SIZE]={'\0'};
1177 struct params params;
1178 char config_file[MAX_BUF_SIZE] = {0};
1179
1180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1181 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1182 return RETURN_ERR;
1183
developerb86c6f32022-10-07 14:34:58 +08001184 if (strlen(CountryCode) == 0)
1185 strcpy(CountryCode, "US");
1186
developer7543b3b2022-09-13 13:47:17 +08001187 params.name = "country_code";
1188 params.value = CountryCode;
1189 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1190 int ret = wifi_hostapdWrite(config_file, &params, 1);
1191 if (ret) {
1192 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1193 ,__func__, ret);
1194 }
1195
1196 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1197 if (ret) {
1198 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1199 ,__func__, ret);
1200 }
developer7543b3b2022-09-13 13:47:17 +08001201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1202
developer06a01d92022-09-07 16:32:39 +08001203 return RETURN_OK;
1204}
1205
developera748dcf2022-09-13 15:56:48 +08001206INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1207{
developerd946fd62022-12-08 18:03:28 +08001208 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001209 char channel_util_file[64] = {0};
1210 char cmd[128] = {0};
1211 char buf[128] = {0};
1212 char line[128] = {0};
1213 char *param = NULL, *value = NULL;
1214 int read = 0;
1215 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1216 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1217 size_t len = 0;
1218 FILE *f = NULL;
1219
1220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1221
developerac6f1142022-12-20 19:26:35 +08001222 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001223 return RETURN_ERR;
1224 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001225 _syscmd(cmd, buf, sizeof(buf));
1226 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1227
1228 memset(cmd, 0, sizeof(cmd));
1229 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001230 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001231 if ((f = popen(cmd, "r")) == NULL) {
1232 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1233 return RETURN_ERR;
1234 }
1235
1236 read = getline(&line, &len, f);
1237 while (read != -1) {
1238 param = strtok(line, ":\t");
1239 value = strtok(NULL, " ");
1240 if(strstr(param, "frequency") != NULL) {
1241 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1242 }
1243 if(strstr(param, "noise") != NULL) {
1244 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1245 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1246 }
1247 if(strstr(param, "channel active time") != NULL) {
1248 ActiveTime = strtol(value, NULL, 10);
1249 }
1250 if(strstr(param, "channel busy time") != NULL) {
1251 BusyTime = strtol(value, NULL, 10);
1252 }
1253 if(strstr(param, "channel transmit time") != NULL) {
1254 TransmitTime = strtol(value, NULL, 10);
1255 }
1256 read = getline(&line, &len, f);
1257 }
1258 pclose(f);
1259
1260 // The file should store the last active, busy and transmit time
1261 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1262 f = fopen(channel_util_file, "r");
1263 if (f != NULL) {
1264 read = getline(&line, &len, f);
1265 preActiveTime = strtol(line, NULL, 10);
1266 read = getline(&line, &len, f);
1267 preBusyTime = strtol(line, NULL, 10);
1268 read = getline(&line, &len, f);
1269 preTransmitTime = strtol(line, NULL, 10);
1270 fclose(f);
1271 }
1272
1273 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1274 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1275
1276 f = fopen(channel_util_file, "w");
1277 if (f != NULL) {
1278 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1279 fclose(f);
1280 }
1281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1282 return RETURN_OK;
1283}
1284
developer06a01d92022-09-07 16:32:39 +08001285/**********************************************************************************
1286 *
1287 * Wifi radio level function prototypes
1288 *
1289**********************************************************************************/
1290
1291//Get the total number of radios in this wifi subsystem
1292INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1293{
1294 if (NULL == output)
1295 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001296 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001297
1298 return RETURN_OK;
1299}
1300
1301//Get the total number of SSID entries in this wifi subsystem
1302INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1303{
1304 if (NULL == output)
1305 return RETURN_ERR;
1306 *output = MAX_APS;
1307
1308 return RETURN_OK;
1309}
1310
1311//Get the Radio enable config parameter
1312INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1313{
developerd946fd62022-12-08 18:03:28 +08001314 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001315 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001316 int apIndex;
1317 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001318
1319 if (NULL == output_bool)
1320 return RETURN_ERR;
1321
1322 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001323
1324 wifi_getMaxRadioNumber(&max_radio_num);
1325
1326 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001327 return RETURN_ERR;
1328
developera77d84b2023-02-22 16:10:50 +08001329 /* loop all interface in radio, if any is enable, reture true, else return false */
1330 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1331 {
developer643b28f2023-04-04 10:26:01 +08001332 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developera77d84b2023-02-22 16:10:50 +08001333 continue;
1334 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1335 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001336
developera77d84b2023-02-22 16:10:50 +08001337 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1338 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1339 /* return true if any interface is eanble */
1340 *output_bool = TRUE;
1341 break;
1342 }
1343 }
developer06a01d92022-09-07 16:32:39 +08001344 return RETURN_OK;
1345}
1346
1347INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1348{
developerd946fd62022-12-08 18:03:28 +08001349 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001350 char cmd[MAX_CMD_SIZE] = {0};
1351 char buf[MAX_CMD_SIZE] = {0};
1352 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001353 int max_radio_num = 0;
1354 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001355
1356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001357
1358 phyId = radio_index_to_phy(radioIndex);
1359
1360 wifi_getMaxRadioNumber(&max_radio_num);
1361
developer06a01d92022-09-07 16:32:39 +08001362 if(enable==FALSE)
1363 {
developera77d84b2023-02-22 16:10:50 +08001364 /* disable from max apindex to min, to avoid fail in mbss case */
1365 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001366 {
developer1e125222022-12-29 09:35:25 +08001367 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001368 continue;
developer1e125222022-12-29 09:35:25 +08001369
developer06a01d92022-09-07 16:32:39 +08001370 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001371 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001372 _syscmd(cmd, buf, sizeof(buf));
1373 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001374 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001375
developer2f18b9f2023-03-17 19:32:57 +08001376 if (!(apIndex/max_radio_num)) {
1377 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1378 _syscmd(cmd, buf, sizeof(buf));
1379 }
developer06a01d92022-09-07 16:32:39 +08001380 }
developer06a01d92022-09-07 16:32:39 +08001381 }
1382 else
1383 {
developer033b37b2022-10-18 11:27:46 +08001384 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001385 {
developer1e125222022-12-29 09:35:25 +08001386 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001387 continue;
developer1e125222022-12-29 09:35:25 +08001388
developer643b28f2023-04-04 10:26:01 +08001389 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001390 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001391 if(*buf == '1') {
developer2f18b9f2023-03-17 19:32:57 +08001392 if (!(apIndex/max_radio_num)) {
1393 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1394 ret = _syscmd(cmd, buf, sizeof(buf));
1395 if ( ret == RETURN_ERR) {
1396 fprintf(stderr, "VAP interface creation failed\n");
1397 continue;
1398 }
developera77d84b2023-02-22 16:10:50 +08001399 }
developer06a01d92022-09-07 16:32:39 +08001400 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001401 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001402 _syscmd(cmd, buf, sizeof(buf));
1403 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001404 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001405 }
1406 }
1407 }
1408
1409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1410 return RETURN_OK;
1411}
1412
1413//Get the Radio enable status
1414INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1415{
1416 if (NULL == output_bool)
1417 return RETURN_ERR;
1418
1419 return wifi_getRadioEnable(radioIndex, output_bool);
1420}
1421
1422//Get the Radio Interface name from platform, eg "wlan0"
1423INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1424{
developer804c64f2022-10-19 13:54:40 +08001425 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001426 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001427 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001428}
1429
1430//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1431//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1432INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1433{
developerbcc556a2022-09-22 20:02:45 +08001434 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1435 // For max bit rate, we should always choose the best MCS
1436 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001437 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001438 char *tmp = NULL;
1439 UINT mode_map = 0;
1440 UINT num_subcarrier = 0;
1441 UINT code_bits = 0;
1442 float code_rate = 0; // use max code rate
1443 int NSS = 0;
1444 UINT Symbol_duration = 0;
1445 UINT GI_duration = 0;
1446 wifi_band band = band_invalid;
1447 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1448 BOOL enable = FALSE;
1449 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001450
1451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1452 if (NULL == output_string)
1453 return RETURN_ERR;
1454
developerbcc556a2022-09-22 20:02:45 +08001455 wifi_getRadioEnable(radioIndex, &enable);
1456 if (enable == FALSE) {
1457 snprintf(output_string, 64, "0 Mb/s");
1458 return RETURN_OK;
1459 }
1460
1461 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1462 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1463 return RETURN_ERR;
1464 }
1465
1466 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1467 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1468 return RETURN_ERR;
1469 }
1470
1471 if (gi == wifi_guard_interval_3200)
1472 GI_duration = 32;
1473 else if (gi == wifi_guard_interval_1600)
1474 GI_duration = 16;
1475 else if (gi == wifi_guard_interval_800)
1476 GI_duration = 8;
1477 else // auto, 400
1478 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001479
developerbcc556a2022-09-22 20:02:45 +08001480 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1481 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1482 return RETURN_ERR;
1483 }
1484
1485 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1486 strcpy(channel_bandwidth_str, "160");
1487
1488 if (mode_map & WIFI_MODE_AX) {
1489 if (strstr(channel_bandwidth_str, "160") != NULL)
1490 num_subcarrier = 1960;
1491 else if (strstr(channel_bandwidth_str, "80") != NULL)
1492 num_subcarrier = 980;
1493 else if (strstr(channel_bandwidth_str, "40") != NULL)
1494 num_subcarrier = 468;
1495 else if (strstr(channel_bandwidth_str, "20") != NULL)
1496 num_subcarrier = 234;
1497 code_bits = 10;
1498 code_rate = (float)5/6;
1499 Symbol_duration = 128;
1500 } else if (mode_map & WIFI_MODE_AC) {
1501 if (strstr(channel_bandwidth_str, "160") != NULL)
1502 num_subcarrier = 468;
1503 else if (strstr(channel_bandwidth_str, "80") != NULL)
1504 num_subcarrier = 234;
1505 else if (strstr(channel_bandwidth_str, "40") != NULL)
1506 num_subcarrier = 108;
1507 else if (strstr(channel_bandwidth_str, "20") != NULL)
1508 num_subcarrier = 52;
1509 code_bits = 8;
1510 code_rate = (float)5/6;
1511 Symbol_duration = 32;
1512 } else if (mode_map & WIFI_MODE_N) {
1513 if (strstr(channel_bandwidth_str, "160") != NULL)
1514 num_subcarrier = 468;
1515 else if (strstr(channel_bandwidth_str, "80") != NULL)
1516 num_subcarrier = 234;
1517 else if (strstr(channel_bandwidth_str, "40") != NULL)
1518 num_subcarrier = 108;
1519 else if (strstr(channel_bandwidth_str, "20") != NULL)
1520 num_subcarrier = 52;
1521 code_bits = 6;
1522 code_rate = (float)3/4;
1523 Symbol_duration = 32;
1524 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1525 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1526 snprintf(output_string, 64, "65 Mb/s");
1527 return RETURN_OK;
1528 } else {
1529 snprintf(output_string, 64, "0 Mb/s");
1530 return RETURN_OK;
1531 }
developer06a01d92022-09-07 16:32:39 +08001532
developerbcc556a2022-09-22 20:02:45 +08001533 // Spatial streams
1534 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1535 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1536 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001537 }
developerbcc556a2022-09-22 20:02:45 +08001538
1539 // multiple 10 is to align duration unit (0.1 us)
1540 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1541 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1542
developer06a01d92022-09-07 16:32:39 +08001543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1544
1545 return RETURN_OK;
1546}
1547#if 0
1548INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1549{
1550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1551 char cmd[64];
1552 char buf[1024];
1553 int apIndex;
1554
1555 if (NULL == output_string)
1556 return RETURN_ERR;
1557
1558 apIndex=(radioIndex==0)?0:1;
1559
developerd946fd62022-12-08 18:03:28 +08001560 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001561 _syscmd(cmd,buf, sizeof(buf));
1562
1563 snprintf(output_string, 64, "%s", buf);
1564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1565 return RETURN_OK;
1566}
1567#endif
1568
1569
1570//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1571//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1572INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1573{
developer963da0c2022-09-13 15:58:27 +08001574 wifi_band band = band_invalid;
1575
developer06a01d92022-09-07 16:32:39 +08001576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1577 if (NULL == output_string)
1578 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001579
1580 band = wifi_index_to_band(radioIndex);
1581
1582 memset(output_string, 0, 10);
1583 if (band == band_2_4)
1584 strcpy(output_string, "2.4GHz");
1585 else if (band == band_5)
1586 strcpy(output_string, "5GHz");
1587 else if (band == band_6)
1588 strcpy(output_string, "6GHz");
1589 else
1590 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1592
1593 return RETURN_OK;
1594#if 0
1595 char buf[MAX_BUF_SIZE]={'\0'};
1596 char str[MAX_BUF_SIZE]={'\0'};
1597 char cmd[MAX_CMD_SIZE]={'\0'};
1598 char *ch=NULL;
1599 char *ch2=NULL;
1600
1601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1602 if (NULL == output_string)
1603 return RETURN_ERR;
1604
1605
1606 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1607
1608 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1609 {
1610 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1611 return RETURN_ERR;
1612 }
1613 ch=strchr(buf,'\n');
1614 *ch='\0';
1615 ch=strchr(buf,'=');
1616 if(ch==NULL)
1617 return RETURN_ERR;
1618
1619
1620 ch++;
1621
1622 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1623 strcpy(buf,"0");
1624 if(strlen(ch) == 1)
1625 ch=strcat(buf,ch);
1626
1627
1628 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1629
1630 if(_syscmd(cmd,str,64) == RETURN_ERR)
1631 {
1632 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1633 return RETURN_ERR;
1634 }
1635
1636
1637 ch2=strchr(str,'\n');
1638 //replace \n with \0
1639 *ch2='\0';
1640 ch2=strchr(str,'=');
1641 if(ch2==NULL)
1642 {
1643 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1644 return RETURN_ERR;
1645 }
1646 else
1647 wifi_dbg_printf("%s",ch2+1);
1648
1649
1650 ch2++;
1651
1652
1653 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1654
1655 memset(buf,'\0',sizeof(buf));
1656 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1657 {
1658 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1659 return RETURN_ERR;
1660 }
1661 if (strstr(buf,"2.4") != NULL )
1662 strcpy(output_string,"2.4GHz");
1663 else if(strstr(buf,"5.") != NULL )
1664 strcpy(output_string,"5GHz");
1665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1666
1667 return RETURN_OK;
1668#endif
1669}
1670
1671//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1672//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1673INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1674{
developerb7593de2022-10-18 09:51:57 +08001675 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1677 if (NULL == output_string)
1678 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001679 band = wifi_index_to_band(radioIndex);
1680
1681 if (band == band_2_4)
1682 snprintf(output_string, 64, "2.4GHz");
1683 else if (band == band_5)
1684 snprintf(output_string, 64, "5GHz");
1685 else if (band == band_6)
1686 snprintf(output_string, 64, "6GHz");
1687
developer06a01d92022-09-07 16:32:39 +08001688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1689
1690 return RETURN_OK;
1691#if 0
1692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1693 char buf[MAX_BUF_SIZE]={'\0'};
1694 char str[MAX_BUF_SIZE]={'\0'};
1695 char cmd[MAX_CMD_SIZE]={'\0'};
1696 char *ch=NULL;
1697 char *ch2=NULL;
1698 char ch1[5]="0";
1699
1700 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1701
1702 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1703 {
1704 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1705 return RETURN_ERR;
1706 }
1707
1708 ch=strchr(buf,'\n');
1709 *ch='\0';
1710 ch=strchr(buf,'=');
1711 if(ch==NULL)
1712 return RETURN_ERR;
1713 ch++;
1714
1715 if(strlen(ch)==1)
1716 {
1717 strcat(ch1,ch);
1718
1719 }
1720 else
1721 {
1722 strcpy(ch1,ch);
1723 }
1724
1725
1726
1727 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1728 if(_syscmd(cmd,str,64) == RETURN_ERR)
1729 {
1730 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1731 return RETURN_ERR;
1732 }
1733
1734
1735 ch2=strchr(str,'\n');
1736 //replace \n with \0
1737 *ch2='\0';
1738 ch2=strchr(str,'=');
1739 if(ch2==NULL)
1740 {
1741 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1742 return RETURN_ERR;
1743 }
1744 else
1745 wifi_dbg_printf("%s",ch2+1);
1746 ch2++;
1747
1748
1749 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1750 memset(buf,'\0',sizeof(buf));
1751 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1752 {
1753 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1754 return RETURN_ERR;
1755 }
1756
1757
1758 if(strstr(buf,"2.4")!=NULL)
1759 {
1760 strcpy(output_string,"2.4GHz");
1761 }
1762 if(strstr(buf,"5.")!=NULL)
1763 {
1764 strcpy(output_string,"5GHz");
1765 }
1766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1767 return RETURN_OK;
1768#endif
1769}
1770
1771//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1772//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1773INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1774{
developer963da0c2022-09-13 15:58:27 +08001775 char cmd[128]={0};
1776 char buf[128]={0};
1777 char temp_output[128] = {0};
1778 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001779 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001780
1781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001782 if (NULL == output_string)
1783 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001784
1785 band = wifi_index_to_band(radioIndex);
1786 if (band == band_2_4) {
1787 strcat(temp_output, "b,g,");
1788 } else if (band == band_5) {
1789 strcat(temp_output, "a,");
1790 }
developer033b37b2022-10-18 11:27:46 +08001791 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001792 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001793 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001794 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001795 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001796 strcat(temp_output, "n,");
1797 }
developer06a01d92022-09-07 16:32:39 +08001798
developer963da0c2022-09-13 15:58:27 +08001799 // vht capabilities
1800 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001801 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001802 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001803 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001804 strcat(temp_output, "ac,");
1805 }
1806 }
1807
1808 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001809 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001810 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001811 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001812 strcat(temp_output, "ax,");
1813 }
1814
developer7c4cd202023-03-01 10:56:29 +08001815 // eht capabilities
1816 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);
1817 _syscmd(cmd, buf, sizeof(buf));
1818 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1819 strcat(temp_output, "be,");
1820 }
1821
developer963da0c2022-09-13 15:58:27 +08001822 // Remove the last comma
1823 if (strlen(temp_output) != 0)
1824 temp_output[strlen(temp_output)-1] = '\0';
1825 strncpy(output_string, temp_output, strlen(temp_output));
1826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001827 return RETURN_OK;
1828}
1829
1830//Get the radio operating mode, and pure mode flag. eg: "ac"
1831//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.
1832INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1833{
1834 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1835 if (NULL == output_string)
1836 return RETURN_ERR;
1837
1838 if (radioIndex == 0) {
1839 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1840 *gOnly = FALSE;
1841 *nOnly = TRUE;
1842 *acOnly = FALSE;
1843 } else {
1844 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1845 *gOnly = FALSE;
1846 *nOnly = FALSE;
1847 *acOnly = FALSE;
1848 }
1849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1850
1851 return RETURN_OK;
1852#if 0
1853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1854 char buf[64] = {0};
1855 char config_file[MAX_BUF_SIZE] = {0};
1856
1857 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1858 return RETURN_ERR;
1859
1860 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1861 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1862
1863 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1864 if (strlen(buf) == 0)
1865 {
1866 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1867 return RETURN_ERR;
1868 }
1869 if(strcmp(buf,"g")==0)
1870 {
1871 wifi_dbg_printf("\nG\n");
1872 *gOnly=TRUE;
1873 *nOnly=FALSE;
1874 *acOnly=FALSE;
1875 }
1876 else if(strcmp(buf,"n")==0)
1877 {
1878 wifi_dbg_printf("\nN\n");
1879 *gOnly=FALSE;
1880 *nOnly=TRUE;
1881 *acOnly=FALSE;
1882 }
1883 else if(strcmp(buf,"ac")==0)
1884 {
1885 wifi_dbg_printf("\nac\n");
1886 *gOnly=FALSE;
1887 *nOnly=FALSE;
1888 *acOnly=TRUE;
1889 }
1890 /* hostapd-5G.conf has "a" as hw_mode */
1891 else if(strcmp(buf,"a")==0)
1892 {
1893 wifi_dbg_printf("\na\n");
1894 *gOnly=FALSE;
1895 *nOnly=FALSE;
1896 *acOnly=FALSE;
1897 }
1898 else
1899 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1900
1901 //for a,n mode
1902 if(radioIndex == 1)
1903 {
1904 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1905 if(strcmp(buf,"1")==0)
1906 {
1907 strncpy(output_string, "n", 1);
1908 *nOnly=FALSE;
1909 }
1910 }
1911
1912 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1914 return RETURN_OK;
1915#endif
1916}
1917
developerdb744382022-09-13 15:34:54 +08001918INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1919{
1920 char cmd[128] = {0};
1921 char buf[64] = {0};
1922 char config_file[64] = {0};
1923 wifi_band band;
1924
1925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1926 if(NULL == output_string || NULL == pureMode)
1927 return RETURN_ERR;
1928
1929 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001930 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001931 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 +08001932 _syscmd(cmd, buf, sizeof(buf));
1933
1934 band = wifi_index_to_band(radioIndex);
1935 // puremode is a bit map
1936 *pureMode = 0;
1937 if (band == band_2_4) {
1938 strcat(output_string, "b,g");
1939 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1940 if (strstr(buf, "n") != NULL) {
1941 strcat(output_string, ",n");
1942 *pureMode |= WIFI_MODE_N;
1943 }
1944 if (strstr(buf, "ax") != NULL) {
1945 strcat(output_string, ",ax");
1946 *pureMode |= WIFI_MODE_AX;
1947 }
developer7c4cd202023-03-01 10:56:29 +08001948 if (strstr(buf, "be") != NULL) {
1949 strcat(output_string, ",be");
1950 *pureMode |= WIFI_MODE_BE;
1951 }
developerdb744382022-09-13 15:34:54 +08001952 } else if (band == band_5) {
1953 strcat(output_string, "a");
1954 *pureMode |= WIFI_MODE_A;
1955 if (strstr(buf, "n") != NULL) {
1956 strcat(output_string, ",n");
1957 *pureMode |= WIFI_MODE_N;
1958 }
1959 if (strstr(buf, "ac") != NULL) {
1960 strcat(output_string, ",ac");
1961 *pureMode |= WIFI_MODE_AC;
1962 }
1963 if (strstr(buf, "ax") != NULL) {
1964 strcat(output_string, ",ax");
1965 *pureMode |= WIFI_MODE_AX;
1966 }
developer7c4cd202023-03-01 10:56:29 +08001967 if (strstr(buf, "be") != NULL) {
1968 strcat(output_string, ",be");
1969 *pureMode |= WIFI_MODE_BE;
1970 }
developerdb744382022-09-13 15:34:54 +08001971 } else if (band == band_6) {
1972 if (strstr(buf, "ax") != NULL) {
1973 strcat(output_string, "ax");
1974 *pureMode |= WIFI_MODE_AX;
1975 }
developer7c4cd202023-03-01 10:56:29 +08001976 if (strstr(buf, "be") != NULL) {
1977 strcat(output_string, ",be");
1978 *pureMode |= WIFI_MODE_BE;
1979 }
developerdb744382022-09-13 15:34:54 +08001980 }
1981
1982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1983 return RETURN_OK;
1984}
1985
1986// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001987INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1988{
1989 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1990 if (strcmp (channelMode,"11A") == 0)
1991 {
1992 writeBandWidth(radioIndex,"20MHz");
1993 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1994 printf("\nChannel Mode is 802.11a (5GHz)\n");
1995 }
1996 else if (strcmp (channelMode,"11NAHT20") == 0)
1997 {
1998 writeBandWidth(radioIndex,"20MHz");
1999 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2000 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2001 }
2002 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2003 {
2004 writeBandWidth(radioIndex,"40MHz");
2005 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2006 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2007 }
2008 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2009 {
2010 writeBandWidth(radioIndex,"40MHz");
2011 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2012 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2013 }
2014 else if (strcmp (channelMode,"11ACVHT20") == 0)
2015 {
2016 writeBandWidth(radioIndex,"20MHz");
2017 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2018 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2019 }
2020 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2021 {
2022 writeBandWidth(radioIndex,"40MHz");
2023 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2024 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2025 }
2026 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2027 {
2028 writeBandWidth(radioIndex,"40MHz");
2029 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2030 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2031 }
2032 else if (strcmp (channelMode,"11ACVHT80") == 0)
2033 {
2034 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2035 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2036 }
2037 else if (strcmp (channelMode,"11ACVHT160") == 0)
2038 {
2039 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2040 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2041 }
2042 else if (strcmp (channelMode,"11B") == 0)
2043 {
2044 writeBandWidth(radioIndex,"20MHz");
2045 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2046 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2047 }
2048 else if (strcmp (channelMode,"11G") == 0)
2049 {
2050 writeBandWidth(radioIndex,"20MHz");
2051 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2052 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2053 }
2054 else if (strcmp (channelMode,"11NGHT20") == 0)
2055 {
2056 writeBandWidth(radioIndex,"20MHz");
2057 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2058 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2059 }
2060 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2061 {
2062 writeBandWidth(radioIndex,"40MHz");
2063 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2064 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2065 }
2066 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2067 {
2068 writeBandWidth(radioIndex,"40MHz");
2069 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2070 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2071 }
2072 else
2073 {
2074 return RETURN_ERR;
2075 }
2076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2077
2078 return RETURN_OK;
2079}
2080
developerdb744382022-09-13 15:34:54 +08002081// Set the radio operating mode, and pure mode flag.
2082INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2083{
developer7c4cd202023-03-01 10:56:29 +08002084 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002085 struct params list[num_hostapd_support_mode];
2086 char config_file[64] = {0};
2087 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002088 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002089 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002090 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002091
2092 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2093 // Set radio mode
2094 list[0].name = "ieee80211n";
2095 list[1].name = "ieee80211ac";
2096 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002097 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002098 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2099
2100 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002101 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002102 list[0].value = "1";
2103 else
2104 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002105 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002106 list[1].value = "1";
2107 else
2108 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002109 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002110 list[2].value = "1";
2111 else
2112 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002113 if (pureMode & WIFI_MODE_BE)
2114 list[3].value = "1";
2115 else
2116 list[3].value = "0";
2117
2118 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2119 if (strstr(supported_mode, "be") != NULL)
2120 eht_support = TRUE;
2121
2122 if (eht_support)
2123 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2124 else
2125 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002126
2127 if (channelMode == NULL || strlen(channelMode) == 0)
2128 return RETURN_OK;
2129 // Set bandwidth
2130 if (strstr(channelMode, "40") != NULL)
2131 strcpy(bandwidth, "40MHz");
2132 else if (strstr(channelMode, "80") != NULL)
2133 strcpy(bandwidth, "80MHz");
2134 else if (strstr(channelMode, "160") != NULL)
2135 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002136 else if (strstr(channelMode, "320") != NULL)
2137 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002138 else // 11A, 11B, 11G....
2139 strcpy(bandwidth, "20MHz");
2140
2141 writeBandWidth(radioIndex, bandwidth);
2142 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2143
2144 wifi_reloadAp(radioIndex);
2145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2146
2147 return RETURN_OK;
2148}
2149
developer1d12ebf2022-10-04 15:13:38 +08002150INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2151
2152 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002153 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002154 struct params params = {0};
2155 wifi_band band = band_invalid;
2156
2157 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2158
2159 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002160
2161 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002162 return RETURN_ERR;
2163 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2164 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002165 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2166 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002167
2168 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2169 params.name = "hw_mode";
2170 params.value = hw_mode;
2171 wifi_hostapdWrite(config_file, &params, 1);
2172 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2173
developeref938762022-10-19 17:21:01 +08002174 if (band == band_2_4) {
2175 if (strncmp(hw_mode, "b", 1) == 0) {
2176 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2177 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2178 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2179 snprintf(buf, sizeof(buf), "%s", "1,2");
2180 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2181 } else {
2182 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2183
2184 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2185 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2186 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2187 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2188 }
2189 }
2190
developer1d12ebf2022-10-04 15:13:38 +08002191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2192 return RETURN_OK;
2193}
2194
developere8988ba2022-10-18 17:42:30 +08002195INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2196{
2197 char config_file[64] = {0};
2198 struct params params = {0};
2199 wifi_band band = band_invalid;
2200
2201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2202
2203 band = wifi_index_to_band(radioIndex);
2204
2205 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2206 params.name = "noscan";
2207 params.value = noscan;
2208 wifi_hostapdWrite(config_file, &params, 1);
2209 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2210
2211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2212 return RETURN_OK;
2213}
2214
developer06a01d92022-09-07 16:32:39 +08002215//Get the list of supported channel. eg: "1-11"
2216//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.
2217INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2218{
developer6318ed52022-09-13 15:17:58 +08002219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002220 if (NULL == output_string)
2221 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002222 char cmd[256] = {0};
2223 char buf[128] = {0};
2224 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002225 int phyId = 0;
2226
developer6318ed52022-09-13 15:17:58 +08002227 // Parse possible channel number and separate them with commas.
2228 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002229 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002230 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002231 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002232 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 +08002233 else
developer033b37b2022-10-18 11:27:46 +08002234 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 +08002235
2236 _syscmd(cmd,buf,sizeof(buf));
2237 strncpy(output_string, buf, sizeof(buf));
2238
2239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2240 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002241}
2242
2243//Get the list for used channel. eg: "1,6,9,11"
2244//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.
2245INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2246{
developerd946fd62022-12-08 18:03:28 +08002247 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002248 char cmd[128] = {0};
2249 char buf[128] = {0};
2250 char config_file[64] = {0};
2251 int channel = 0;
2252 int freq = 0;
2253 int bandwidth = 0;
2254 int center_freq = 0;
2255 int center_channel = 0;
2256 int channel_delta = 0;
2257 wifi_band band = band_invalid;
2258
2259 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2260
developer06a01d92022-09-07 16:32:39 +08002261 if (NULL == output_string)
2262 return RETURN_ERR;
2263
developerac6f1142022-12-20 19:26:35 +08002264 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002265 return RETURN_ERR;
2266 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002267 _syscmd(cmd, buf, sizeof(buf));
2268 if (strlen(buf) == 0) {
2269 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2270 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002271 }
developerf5745ee2022-10-05 16:09:53 +08002272 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2273
2274 if (bandwidth == 20) {
2275 snprintf(output_string, 256, "%d", channel);
2276 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002277 }
developerf5745ee2022-10-05 16:09:53 +08002278
2279 center_channel = ieee80211_frequency_to_channel(center_freq);
2280
2281 band = wifi_index_to_band(radioIndex);
2282 if (band == band_2_4 && bandwidth == 40) {
2283 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2284 memset(buf, 0, sizeof(buf));
2285 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2286
developerf22724d2022-12-22 17:24:14 +08002287 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002288 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002289 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002290 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2291 } else {
2292 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2293 return RETURN_ERR;
2294 }
2295 } else if (band == band_5 || band == band_6){
2296 // 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 +08002297 // 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 +08002298 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002299 memset(output_string, 0, 256);
2300 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2301 // If i is not the last channel, we add a comma.
2302 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2303 strncat(output_string, buf, strlen(buf));
2304 }
developerf5745ee2022-10-05 16:09:53 +08002305 } else
2306 return RETURN_ERR;
2307
2308 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002309 return RETURN_OK;
2310}
2311
2312//Get the running channel number
2313INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2314{
developer5b398df2022-11-17 20:39:48 +08002315 char channel_str[16] = {0};
2316 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002317
developer5b398df2022-11-17 20:39:48 +08002318 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002319 return RETURN_ERR;
2320
developer5b398df2022-11-17 20:39:48 +08002321 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2322 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002323
developer5b398df2022-11-17 20:39:48 +08002324 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002325
developer06a01d92022-09-07 16:32:39 +08002326 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002327}
2328
2329
2330INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2331{
2332 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002333 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002334
2335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2336 if (NULL == output_ulong)
2337 return RETURN_ERR;
2338
developer06a01d92022-09-07 16:32:39 +08002339 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002340 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2341 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002342 _syscmd(cmd,buf,sizeof(buf));
2343 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2344 if (*output_ulong == 0) {
2345 return RETURN_ERR;
2346 }
2347
2348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2349 return RETURN_OK;
2350}
2351
2352//Storing the previous channel value
2353INT wifi_storeprevchanval(INT radioIndex)
2354{
2355 char buf[256] = {0};
2356 char output[4]={'\0'};
2357 char config_file[MAX_BUF_SIZE] = {0};
2358 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2359 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2360 if(radioIndex == 0)
2361 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2362 else if(radioIndex == 1)
2363 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2364 system(buf);
2365 Radio_flag = FALSE;
2366 return RETURN_OK;
2367}
2368
2369//Set the running channel number
2370INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2371{
developer76989232022-10-04 14:13:19 +08002372 // We only write hostapd config here
2373 char str_channel[8]={0};
2374 char *list_channel;
2375 char config_file[128] = {0};
2376 char possible_channels[256] = {0};
2377 int max_radio_num = 0;
2378 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002379
developer76989232022-10-04 14:13:19 +08002380 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002381
developer76989232022-10-04 14:13:19 +08002382 // Check valid
2383 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002384
developer76989232022-10-04 14:13:19 +08002385 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2386 list_channel = strtok(possible_channels, ",");
2387 while(true)
developer06a01d92022-09-07 16:32:39 +08002388 {
developer76989232022-10-04 14:13:19 +08002389 if(list_channel == NULL) { // input not in the list
2390 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2391 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002392 }
developer76989232022-10-04 14:13:19 +08002393 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2394 break;
2395 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002396 }
2397
developer76989232022-10-04 14:13:19 +08002398 list.name = "channel";
2399 list.value = str_channel;
2400 wifi_getMaxRadioNumber(&max_radio_num);
2401 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002402 {
developer76989232022-10-04 14:13:19 +08002403 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2404 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002405 }
2406
developer76989232022-10-04 14:13:19 +08002407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002408 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002409}
developer06a01d92022-09-07 16:32:39 +08002410
2411INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2412{
developer7c4cd202023-03-01 10:56:29 +08002413 struct params list[3];
2414 char str_idx[16] = {0};
2415 char supported_mode[32] = {0};
2416 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002417 int max_num_radios = 0;
2418 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002419 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002420
2421 band = wifi_index_to_band(radioIndex);
2422 if (band == band_2_4)
2423 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002424
developer7c4cd202023-03-01 10:56:29 +08002425 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2426 if (strstr(supported_mode, "be") != NULL)
2427 eht_support = TRUE;
2428
developer30423732022-12-01 16:17:49 +08002429 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002430 list[0].name = "vht_oper_centr_freq_seg0_idx";
2431 list[0].value = str_idx;
2432 list[1].name = "he_oper_centr_freq_seg0_idx";
2433 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002434 list[2].name = "eht_oper_centr_freq_seg0_idx";
2435 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002436
developer76989232022-10-04 14:13:19 +08002437 wifi_getMaxRadioNumber(&max_num_radios);
2438 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002439 {
developer76989232022-10-04 14:13:19 +08002440 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002441 if (eht_support)
2442 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002443 else
2444 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002445 }
2446
2447 return RETURN_OK;
2448}
2449
2450//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2451//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2452INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2453{
2454 //Set to wifi config only. Wait for wifi reset to apply.
2455 char buf[256] = {0};
2456 char str_channel[256] = {0};
2457 int count = 0;
2458 ULONG Value = 0;
2459 FILE *fp = NULL;
2460 if(enable == TRUE)
2461 {
developer06a01d92022-09-07 16:32:39 +08002462 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002463 }
developer5884e982022-10-06 10:52:50 +08002464 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002465}
2466
developer0b246d12022-09-30 15:24:20 +08002467INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2468{
2469 if (output_bool == NULL)
2470 return RETURN_ERR;
2471
2472 *output_bool = TRUE;
2473
2474 return RETURN_OK;
2475}
2476
developer06a01d92022-09-07 16:32:39 +08002477INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2478{
2479 if (NULL == output_bool)
2480 return RETURN_ERR;
2481 *output_bool=FALSE;
2482 return RETURN_OK;
2483}
2484
2485INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2486{
2487 if (NULL == output_bool)
2488 return RETURN_ERR;
2489 *output_bool=FALSE;
2490 return RETURN_OK;
2491}
2492
2493INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2494{
2495 //Set to wifi config only. Wait for wifi reset to apply.
2496 return RETURN_OK;
2497}
2498
2499INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2500{
2501 return RETURN_OK;
2502}
2503
2504INT wifi_factoryResetAP(int apIndex)
2505{
developer838cca92022-10-03 13:19:57 +08002506 char ap_config_file[64] = {0};
2507 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002508 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002509 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002510
developer06a01d92022-09-07 16:32:39 +08002511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002512
2513 wifi_setApEnable(apIndex, FALSE);
2514 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2515 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002516 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002517 wifi_getMaxRadioNumber(&max_radio_num);
2518 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2519 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002520
developer06a01d92022-09-07 16:32:39 +08002521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002522
developer06a01d92022-09-07 16:32:39 +08002523 return RETURN_OK;
2524}
2525
2526//To set Band Steering AP group
2527//To-do
2528INT wifi_setBandSteeringApGroup(char *ApGroup)
2529{
2530 return RETURN_OK;
2531}
2532
developer1e5aa162022-09-13 16:06:24 +08002533INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2534{
2535 char config_file[128] = {'\0'};
2536 char buf[128] = {'\0'};
2537
2538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2539 if (dtimInterval == NULL)
2540 return RETURN_ERR;
2541
2542 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2543 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2544
2545 if (strlen(buf) == 0) {
2546 *dtimInterval = 2;
2547 } else {
2548 *dtimInterval = strtoul(buf, NULL, 10);
2549 }
2550
2551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2552 return RETURN_OK;
2553}
2554
developer06a01d92022-09-07 16:32:39 +08002555INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2556{
developer5f222492022-09-13 15:21:52 +08002557 struct params params={0};
2558 char config_file[MAX_BUF_SIZE] = {'\0'};
2559 char buf[MAX_BUF_SIZE] = {'\0'};
2560
2561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2562 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002563 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002564 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002565 }
2566
2567 params.name = "dtim_period";
2568 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2569 params.value = buf;
2570
2571 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2572 wifi_hostapdWrite(config_file, &params, 1);
2573 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2574
2575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2576 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002577}
2578
2579//Check if the driver support the Dfs
2580INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2581{
developer78a15382022-11-02 10:57:40 +08002582 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002583 if (NULL == output_bool)
2584 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002585 *output_bool=FALSE;
2586
2587 band = wifi_index_to_band(radioIndex);
2588 if (band == band_5)
2589 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002590 return RETURN_OK;
2591}
2592
2593//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.
2594//The value of this parameter is a comma seperated list of channel number
2595INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2596{
2597 if (NULL == output_pool)
2598 return RETURN_ERR;
2599 if (radioIndex==1)
2600 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2601 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2602
2603 return RETURN_OK;
2604}
2605
2606INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2607{
2608 //Set to wifi config. And apply instantly.
2609 return RETURN_OK;
2610}
2611
2612INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2613{
2614 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2615 return RETURN_ERR;
2616 *output_interval_seconds=1800;
2617 *output_dwell_milliseconds=40;
2618
2619 return RETURN_OK;
2620}
2621
2622INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2623{
2624 //Set to wifi config. And apply instantly.
2625 return RETURN_OK;
2626}
2627
developerbfc18512022-10-05 17:54:28 +08002628INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2629{
2630 if (output_bool == NULL)
2631 return RETURN_ERR;
2632 *output_bool = true;
2633 return RETURN_OK;
2634}
2635
2636INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2637{
2638 return RETURN_OK;
2639}
2640
developer06a01d92022-09-07 16:32:39 +08002641//Get the Dfs enable status
2642INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2643{
developer9964b5b2022-09-13 15:59:34 +08002644 char buf[16] = {0};
2645 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002646
2647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2648
developer30423732022-12-01 16:17:49 +08002649 if (output_bool == NULL)
2650 return RETURN_ERR;
2651
developer9964b5b2022-09-13 15:59:34 +08002652 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002653 f = fopen(DFS_ENABLE_FILE, "r");
2654 if (f != NULL) {
2655 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002656 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002657 *output_bool = FALSE;
2658 fclose(f);
2659 }
2660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002661 return RETURN_OK;
2662}
2663
2664//Set the Dfs enable status
2665INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2666{
developer9964b5b2022-09-13 15:59:34 +08002667 char config_file[128] = {0};
2668 FILE *f = NULL;
2669 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002670
2671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2672
developer9964b5b2022-09-13 15:59:34 +08002673 f = fopen(DFS_ENABLE_FILE, "w");
2674 if (f == NULL)
2675 return RETURN_ERR;
2676 fprintf(f, "%d", enable);
2677 fclose(f);
2678
2679 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002680 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002681 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2682 wifi_hostapdWrite(config_file, &params, 1);
2683 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2684
2685 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2686
developer9964b5b2022-09-13 15:59:34 +08002687 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002688 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002689}
2690
2691//Check if the driver support the AutoChannelRefreshPeriod
2692INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2693{
2694 if (NULL == output_bool)
2695 return RETURN_ERR;
2696 *output_bool=FALSE; //not support
2697
2698 return RETURN_OK;
2699}
2700
2701//Get the ACS refresh period in seconds
2702INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2703{
2704 if (NULL == output_ulong)
2705 return RETURN_ERR;
2706 *output_ulong=300;
2707
2708 return RETURN_OK;
2709}
2710
2711//Set the ACS refresh period in seconds
2712INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2713{
2714 return RETURN_ERR;
2715}
2716
developer7c4cd202023-03-01 10:56:29 +08002717INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2718{
2719 int center_channel = 0;
2720 char config_file[32] = {0};
2721 char buf[32] = {0};
2722
2723 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2724 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2725
2726 center_channel = strtoul(buf, NULL, 10);
2727 center_channel += 1; // Add 1 to become muiltiple of 16
2728 if (center_channel % 64 == 32)
2729 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2730 else if (center_channel % 64 == 0)
2731 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2732 else
2733 return RETURN_ERR;
2734 return RETURN_OK;
2735}
2736
developer06a01d92022-09-07 16:32:39 +08002737//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2738//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.
2739INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2740{
developer72ec5572023-01-05 16:27:13 +08002741 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002742 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002743 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002744 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002745 wifi_band band;
developer70490032022-09-13 15:45:20 +08002746
2747 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2748
developer06a01d92022-09-07 16:32:39 +08002749 if (NULL == output_string)
2750 return RETURN_ERR;
2751
developer70490032022-09-13 15:45:20 +08002752 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2753 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002754
developer70490032022-09-13 15:45:20 +08002755 if (radio_enable != TRUE)
2756 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002757
developerfa41b1f2023-01-06 10:25:51 +08002758 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002759 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002760 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002761 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2762 snprintf(output_string, 64, "20MHz");
2763 else
2764 snprintf(output_string, 64, "40MHz");
2765
2766 } else {
2767 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2768 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2769 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2770 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2771 if (strncmp(buf, "0", 1) == 0)
2772 snprintf(output_string, 64, "20MHz");
2773 else
2774 snprintf(output_string, 64, "40MHz");
2775
2776 } else if (strncmp(buf, "1", 1) == 0)
2777 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002778 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002779 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002780 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2781 if (strncmp(buf, "9", 1) == 0) {
2782 int BandwidthSet = 0;
2783 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2784 return RETURN_ERR;
2785 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2786 snprintf(output_string, 64, "320-1MHz");
2787 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2788 snprintf(output_string, 64, "320-2MHz");
2789 }
2790 }
developer06a01d92022-09-07 16:32:39 +08002791 }
developer72ec5572023-01-05 16:27:13 +08002792
developer06a01d92022-09-07 16:32:39 +08002793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002794
2795 return RETURN_OK;
2796}
2797
2798//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002799INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002800{
developerf7a466e2022-09-29 11:55:56 +08002801 char config_file[128];
2802 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002803 char supported_mode[32] = {0};
2804 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002805 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002806 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002807
developer06a01d92022-09-07 16:32:39 +08002808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002809
developerf7a466e2022-09-29 11:55:56 +08002810 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002811 return RETURN_ERR;
2812
developer7c4cd202023-03-01 10:56:29 +08002813 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002814 strcpy(set_value, "2");
2815 else if(strstr(bandwidth,"80") != NULL)
2816 strcpy(set_value, "1");
2817 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2818 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002819 else if (strstr(bandwidth, "Auto") != NULL)
2820 return RETURN_OK;
2821 else {
developerf7a466e2022-09-29 11:55:56 +08002822 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002823 return RETURN_ERR;
2824 }
2825
developer7c4cd202023-03-01 10:56:29 +08002826 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2827 if (strstr(supported_mode, "be") != NULL)
2828 eht_support = TRUE;
2829
developerf7a466e2022-09-29 11:55:56 +08002830 params[0].name = "vht_oper_chwidth";
2831 params[0].value = set_value;
2832 params[1].name = "he_oper_chwidth";
2833 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002834 params[2].name = "eht_oper_chwidth";
2835 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2836 params[2].value = "9";
2837 else
2838 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002839
developerf7a466e2022-09-29 11:55:56 +08002840 wifi_getMaxRadioNumber(&max_radio_num);
2841 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002842 {
developer7c4cd202023-03-01 10:56:29 +08002843 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2844 if (eht_support == TRUE)
2845 wifi_hostapdWrite(config_file, params, 3);
2846 else
2847 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002848 }
2849
2850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2851 return RETURN_OK;
2852}
2853
2854//Getting current radio extension channel
2855INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2856{
2857 CHAR buf[150] = {0};
2858 CHAR cmd[150] = {0};
2859 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2860 _syscmd(cmd, buf, sizeof(buf));
2861 if(NULL != strstr(buf,"HT40+"))
2862 strcpy(Value,"AboveControlChannel");
2863 else if(NULL != strstr(buf,"HT40-"))
2864 strcpy(Value,"BelowControlChannel");
2865 return RETURN_OK;
2866}
2867
2868//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2869//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.
2870INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2871{
developerfa41b1f2023-01-06 10:25:51 +08002872 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002873 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002874
2875 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002876 return RETURN_ERR;
2877
developerfa41b1f2023-01-06 10:25:51 +08002878 band = wifi_index_to_band(radioIndex);
2879 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002880 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002881
2882 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2883
2884 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002885 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002886
2887 return RETURN_OK;
2888}
2889
developer57fa24a2023-03-15 17:25:07 +08002890// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2891INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2892{
2893 struct params params={0};
2894 char config_file[64] = {0};
2895 char ht_capab[128]={0};
2896 char buf[128] = {0};
2897 char cmd[128] = {0};
2898 int max_radio_num =0;
2899 bool stbcEnable = FALSE;
2900
2901 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2902 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2903 _syscmd(cmd, buf, sizeof(buf));
2904 if (strlen(buf) != 0)
2905 stbcEnable = TRUE;
2906
2907 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2908 params.value = ht_capab;
2909 params.name = "ht_capab";
2910
2911 wifi_getMaxRadioNumber(&max_radio_num);
2912 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2913 {
2914 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2915 wifi_hostapdWrite(config_file, &params, 1);
developer57fa24a2023-03-15 17:25:07 +08002916 }
developer8d7d0862023-05-18 16:50:23 +08002917 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer57fa24a2023-03-15 17:25:07 +08002918 return RETURN_OK;
2919}
2920
developer06a01d92022-09-07 16:32:39 +08002921//Set the extension channel.
2922INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002923{
developer06a01d92022-09-07 16:32:39 +08002924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002925 struct params params={0};
2926 char config_file[64] = {0};
2927 char ext_channel[128]={0};
2928 char buf[128] = {0};
2929 char cmd[128] = {0};
2930 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002931 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002932 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002933 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002934 wifi_band band;
2935
2936 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2937 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2938 _syscmd(cmd, buf, sizeof(buf));
2939 if (strlen(buf) != 0)
2940 stbcEnable = TRUE;
developer57fa24a2023-03-15 17:25:07 +08002941
2942 // readBandWidth get empty file will return error, that means we don't set new bandwidth
2943 if (readBandWidth(radioIndex, buf) != RETURN_OK) {
2944 // Get current bandwidth
2945 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2946 return RETURN_ERR;
2947 }
developerfa41b1f2023-01-06 10:25:51 +08002948 bandwidth = strtol(buf, NULL, 10);
2949 // TDK expected to get error with 20MHz
developer57fa24a2023-03-15 17:25:07 +08002950 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developerfa41b1f2023-01-06 10:25:51 +08002951 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2952 return RETURN_ERR;
2953
2954 band = wifi_index_to_band(radioIndex);
2955 if (band == band_invalid)
2956 return RETURN_ERR;
2957
2958 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2959 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002960
developer72ec5572023-01-05 16:27:13 +08002961 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2962 ret = util_get_sec_chan_offset(channel, buf);
2963 if (ret == -EINVAL)
2964 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002965
2966 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002967 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2968 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002969 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002970 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08002971 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
2972 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002973 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002974 } else {
developer57fa24a2023-03-15 17:25:07 +08002975 fprintf(stderr, "%s: unknow extchannel %s\n", __func__, string);
2976 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002977 }
developer06a01d92022-09-07 16:32:39 +08002978
2979 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002980
2981 wifi_getMaxRadioNumber(&max_radio_num);
2982 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002983 {
developer033b37b2022-10-18 11:27:46 +08002984 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002985 wifi_hostapdWrite(config_file, &params, 1);
2986 }
developer8d7d0862023-05-18 16:50:23 +08002987 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer06a01d92022-09-07 16:32:39 +08002988
2989 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2991 return RETURN_OK;
2992}
2993
2994//Get the guard interval value. eg "400nsec" or "800nsec"
2995//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.
2996INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2997{
developer454b9462022-09-13 15:29:16 +08002998 wifi_guard_interval_t GI;
2999
3000 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3001
3002 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08003003 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08003004
3005 if (GI == wifi_guard_interval_400)
3006 strcpy(output_string, "400nsec");
3007 else if (GI == wifi_guard_interval_800)
3008 strcpy(output_string, "800nsec");
3009 else if (GI == wifi_guard_interval_1600)
3010 strcpy(output_string, "1600nsec");
3011 else if (GI == wifi_guard_interval_3200)
3012 strcpy(output_string, "3200nsec");
3013 else
developer78a15382022-11-02 10:57:40 +08003014 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08003015
developer454b9462022-09-13 15:29:16 +08003016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003017 return RETURN_OK;
3018}
3019
3020//Set the guard interval value.
3021INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3022{
developer454b9462022-09-13 15:29:16 +08003023 wifi_guard_interval_t GI;
3024 int ret = 0;
3025
3026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3027
3028 if (strcmp(string, "400nsec") == 0)
3029 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08003030 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08003031 GI = wifi_guard_interval_800;
3032 else if (strcmp(string , "1600nsec") == 0)
3033 GI = wifi_guard_interval_1600;
3034 else if (strcmp(string , "3200nsec") == 0)
3035 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08003036 else
3037 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003038
3039 ret = wifi_setGuardInterval(radioIndex, GI);
3040
3041 if (ret == RETURN_ERR) {
3042 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3043 return RETURN_ERR;
3044 }
3045
3046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3047 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003048}
3049
3050//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3051INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3052{
developerf49437e2022-09-29 19:58:21 +08003053 char buf[32]={0};
3054 char mcs_file[64] = {0};
3055 char cmd[64] = {0};
3056 int mode_bitmap = 0;
3057
3058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3059 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003060 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003061 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3062
3063 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3064 _syscmd(cmd, buf, sizeof(buf));
3065 if (strlen(buf) > 0)
3066 *output_int = strtol(buf, NULL, 10);
3067 else {
3068 // output the max MCS for the current radio mode
3069 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3070 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3071 return RETURN_ERR;
3072 }
3073 if (mode_bitmap & WIFI_MODE_AX) {
3074 *output_int = 11;
3075 } else if (mode_bitmap & WIFI_MODE_AC) {
3076 *output_int = 9;
3077 } else if (mode_bitmap & WIFI_MODE_N) {
3078 *output_int = 7;
3079 }
3080 }
3081 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003082
3083 return RETURN_OK;
3084}
3085
3086//Set the Modulation Coding Scheme index
3087INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3088{
developerf49437e2022-09-29 19:58:21 +08003089 // 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).
3090 char config_file[64] = {0};
3091 char set_value[16] = {0};
3092 char mcs_file[32] = {0};
3093 wifi_band band = band_invalid;
3094 struct params set_config = {0};
3095 FILE *f = NULL;
3096
3097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3098
3099 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3100
developer78a15382022-11-02 10:57:40 +08003101 // -1 means auto
3102 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003103 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3104 return RETURN_ERR;
3105 }
3106
developer78a15382022-11-02 10:57:40 +08003107 if (MCS > 9 || MCS == -1)
3108 strcpy(set_value, "2");
3109 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003110 strcpy(set_value, "1");
3111 else
developer78a15382022-11-02 10:57:40 +08003112 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003113
3114 set_config.name = "he_basic_mcs_nss_set";
3115 set_config.value = set_value;
3116
3117 wifi_hostapdWrite(config_file, &set_config, 1);
3118 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3119
3120 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3121 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3122 f = fopen(mcs_file, "w");
3123 if (f == NULL) {
3124 fprintf(stderr, "%s: fopen failed\n", __func__);
3125 return RETURN_ERR;
3126 }
3127 fprintf(f, "%d", MCS);
3128 fclose(f);
3129
3130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3131 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003132}
3133
3134//Get supported Transmit Power list, eg : "0,25,50,75,100"
3135//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.
3136INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3137{
3138 if (NULL == output_list)
3139 return RETURN_ERR;
3140 snprintf(output_list, 64,"0,25,50,75,100");
3141 return RETURN_OK;
3142}
3143
developera5005b62022-09-13 15:43:35 +08003144//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08003145//The transmite power level is in units of full power for this radio.
3146INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3147{
developerd946fd62022-12-08 18:03:28 +08003148 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003149 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003150 char buf[16]={0};
3151 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003152
developera5005b62022-09-13 15:43:35 +08003153 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003154 return RETURN_ERR;
3155
developerac6f1142022-12-20 19:26:35 +08003156 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003157 return RETURN_ERR;
3158 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003159 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003160
developera5005b62022-09-13 15:43:35 +08003161 *output_ulong = strtol(buf, NULL, 10);
3162
3163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003164 return RETURN_OK;
3165}
3166
3167//Set Transmit Power
3168//The transmite power level is in units of full power for this radio.
3169INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3170{
developerd946fd62022-12-08 18:03:28 +08003171 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003172 char *support;
developer06a01d92022-09-07 16:32:39 +08003173 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003174 char buf[128]={0};
3175 char txpower_str[64] = {0};
3176 int txpower = 0;
3177 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08003178 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003179
3180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003181
developerac6f1142022-12-20 19:26:35 +08003182 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003183 return RETURN_ERR;
3184 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003185 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003186 maximum_tx = strtol(buf, NULL, 10);
3187
3188 // Get the Tx power supported list and check that is the input in the list
3189 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3190 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3191 support = strtok(buf, ",");
3192 while(true)
3193 {
3194 if(support == NULL) { // input not in the list
3195 wifi_dbg_printf("Input value is invalid.\n");
3196 return RETURN_ERR;
3197 }
3198 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3199 break;
3200 }
3201 support = strtok(NULL, ",");
3202 }
3203 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003204 phyId = radio_index_to_phy(radioIndex);
3205 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003206 _syscmd(cmd, buf, sizeof(buf));
3207 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003208
3209 return RETURN_OK;
3210}
3211
3212//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3213INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3214{
3215 if (NULL == Supported)
3216 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003217 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003218
3219 return RETURN_OK;
3220}
3221
3222//Get 80211h feature enable
3223INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3224{
developer3885fec2022-09-13 15:13:47 +08003225 char buf[64]={'\0'};
3226 char config_file[64] = {'\0'};
3227
3228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3229 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003230 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003231
3232 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3233 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003234
developer3885fec2022-09-13 15:13:47 +08003235 if (strncmp(buf, "1", 1) == 0)
3236 *enable = TRUE;
3237 else
3238 *enable = FALSE;
3239
3240 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003241 return RETURN_OK;
3242}
3243
3244//Set 80211h feature enable
3245INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3246{
developer3885fec2022-09-13 15:13:47 +08003247 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3248 struct params params={'\0'};
3249 char config_file[MAX_BUF_SIZE] = {0};
3250
3251 params.name = "ieee80211h";
3252
3253 if (enable) {
3254 params.value = "1";
3255 } else {
3256 params.value = "0";
3257 }
3258
3259 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3260 wifi_hostapdWrite(config_file, &params, 1);
3261
3262 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3263 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3264 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003265}
3266
3267//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.
3268INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3269{
3270 if (NULL == output)
3271 return RETURN_ERR;
3272 *output=100;
3273
3274 return RETURN_OK;
3275}
3276
3277//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.
3278INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3279{
3280 if (NULL == output)
3281 return RETURN_ERR;
3282 *output = -99;
3283
3284 return RETURN_OK;
3285}
3286
3287INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3288{
3289 return RETURN_ERR;
3290}
3291
3292
3293//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3294INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3295{
developerd946fd62022-12-08 18:03:28 +08003296 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003297 char cmd[MAX_BUF_SIZE]={'\0'};
3298 char buf[MAX_CMD_SIZE]={'\0'};
3299
3300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3301 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003302 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003303
developerac6f1142022-12-20 19:26:35 +08003304 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003305 return RETURN_ERR;
3306 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 +08003307 _syscmd(cmd, buf, sizeof(buf));
3308 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003309
developer5f222492022-09-13 15:21:52 +08003310 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003311 return RETURN_OK;
3312}
3313
3314INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3315{
developer5f222492022-09-13 15:21:52 +08003316 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3317 struct params params={'\0'};
3318 char buf[MAX_BUF_SIZE] = {'\0'};
3319 char config_file[MAX_BUF_SIZE] = {'\0'};
3320
developer5b398df2022-11-17 20:39:48 +08003321 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3322 return RETURN_ERR;
3323
developer5f222492022-09-13 15:21:52 +08003324 params.name = "beacon_int";
3325 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3326 params.value = buf;
3327
3328 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3329 wifi_hostapdWrite(config_file, &params, 1);
3330
3331 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3333 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003334}
3335
3336//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.
3337INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3338{
developer06a01d92022-09-07 16:32:39 +08003339 //TODO: need to revisit below implementation
3340 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003341 char temp_output[128] = {0};
3342 char temp_TransmitRates[64] = {0};
3343 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003344
3345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3346 if (NULL == output)
3347 return RETURN_ERR;
3348 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003349 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3350
3351 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3352 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3353 } else {
3354 temp = strtok(temp_TransmitRates," ");
3355 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003356 {
developere9d0abd2022-09-13 15:40:57 +08003357 // Convert 100 kbps to Mbps
3358 temp[strlen(temp)-1]=0;
3359 if((temp[0]=='5') && (temp[1]=='\0'))
3360 {
3361 temp="5.5";
3362 }
3363 strcat(temp_output,temp);
3364 temp = strtok(NULL," ");
3365 if(temp!=NULL)
3366 {
3367 strcat(temp_output,",");
3368 }
developer06a01d92022-09-07 16:32:39 +08003369 }
developere9d0abd2022-09-13 15:40:57 +08003370 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003371 }
developer06a01d92022-09-07 16:32:39 +08003372 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003373 return RETURN_OK;
3374}
3375
3376INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3377{
3378 char *temp;
3379 char temp1[128];
3380 char temp_output[128];
3381 char temp_TransmitRates[128];
3382 char set[128];
3383 char sub_set[128];
3384 int set_count=0,subset_count=0;
3385 int set_index=0,subset_index=0;
3386 char *token;
3387 int flag=0, i=0;
3388 struct params params={'\0'};
3389 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003390 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003391
3392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3393 if(NULL == TransmitRates)
3394 return RETURN_ERR;
3395 strcpy(sub_set,TransmitRates);
3396
3397 //Allow only supported Data transmit rate to be set
3398 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3399 token = strtok(sub_set,",");
3400 while( token != NULL ) /* split the basic rate to be set, by comma */
3401 {
3402 sub_set[subset_count]=atoi(token);
3403 subset_count++;
3404 token=strtok(NULL,",");
3405 }
3406 token=strtok(set,",");
3407 while(token!=NULL) /* split the supported rate by comma */
3408 {
3409 set[set_count]=atoi(token);
3410 set_count++;
3411 token=strtok(NULL,",");
3412 }
3413 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3414 {
3415 for(set_index=0;set_index < set_count;set_index++)
3416 {
3417 flag=0;
3418 if(sub_set[subset_index]==set[set_index])
3419 break;
3420 else
3421 flag=1; /* No match found */
3422 }
3423 if(flag==1)
3424 return RETURN_ERR; //If value not found return Error
3425 }
3426 strcpy(temp_TransmitRates,TransmitRates);
3427
3428 for(i=0;i<strlen(temp_TransmitRates);i++)
3429 {
3430 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003431 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003432 {
3433 continue;
3434 }
3435 else
3436 {
3437 return RETURN_ERR;
3438 }
3439 }
3440 strcpy(temp_output,"");
3441 temp = strtok(temp_TransmitRates,",");
3442 while(temp!=NULL)
3443 {
3444 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003445 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003446 {
developeref938762022-10-19 17:21:01 +08003447 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003448 {
3449 return RETURN_ERR;
3450 }
3451 }
3452
3453 if(strcmp(temp,"5.5")==0)
3454 {
3455 strcpy(temp1,"55");
3456 }
3457 else
3458 {
3459 strcat(temp1,"0");
3460 }
3461 strcat(temp_output,temp1);
3462 temp = strtok(NULL,",");
3463 if(temp!=NULL)
3464 {
3465 strcat(temp_output," ");
3466 }
3467 }
3468 strcpy(TransmitRates,temp_output);
3469
3470 params.name= "basic_rates";
3471 params.value =TransmitRates;
3472
3473 wifi_dbg_printf("\n%s:",__func__);
3474 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3475 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3476 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3477 wifi_hostapdWrite(config_file,&params,1);
3478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3479 return RETURN_OK;
3480}
3481
3482//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003483INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003484{
3485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3486 FILE *fp = NULL;
3487 char path[256] = {0}, output_string[256] = {0};
3488 int count = 0;
3489 char *interface = NULL;
3490
3491 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3492 if (fp == NULL)
3493 {
3494 printf("Failed to run command in Function %s\n", __FUNCTION__);
3495 return RETURN_ERR;
3496 }
3497 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3498 {
3499 interface = strchr(path, '=');
3500
3501 if (interface != NULL)
3502 {
3503 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003504 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003505 interface_name[count] = output_string[count];
3506
3507 interface_name[count] = '\0';
3508 }
3509 }
3510 pclose(fp);
3511 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3512 return RETURN_OK;
3513}
3514
3515INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3516{
3517 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3518 output_struct->radio_BytesSent = 0;
3519 output_struct->radio_BytesReceived = 0;
3520 output_struct->radio_PacketsSent = 0;
3521 output_struct->radio_PacketsReceived = 0;
3522 output_struct->radio_ErrorsSent = 0;
3523 output_struct->radio_ErrorsReceived = 0;
3524 output_struct->radio_DiscardPacketsSent = 0;
3525 output_struct->radio_DiscardPacketsReceived = 0;
3526 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3527 return RETURN_OK;
3528}
3529
3530
3531INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3532{
3533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3534 CHAR buf[MAX_CMD_SIZE] = {0};
3535 CHAR Value[MAX_BUF_SIZE] = {0};
3536 FILE *fp = NULL;
3537
3538 if (ifname == NULL || strlen(ifname) <= 1)
3539 return RETURN_OK;
3540
3541 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3542 system(buf);
3543
3544 fp = fopen("/tmp/Radio_Stats.txt", "r");
3545 if(fp == NULL)
3546 {
3547 printf("/tmp/Radio_Stats.txt not exists \n");
3548 return RETURN_ERR;
3549 }
3550 fclose(fp);
3551
3552 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3553 File_Reading(buf, Value);
3554 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3555
3556 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3557 File_Reading(buf, Value);
3558 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3559
3560 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3561 File_Reading(buf, Value);
3562 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3563
3564 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3565 File_Reading(buf, Value);
3566 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3567
3568 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3569 File_Reading(buf, Value);
3570 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3571
3572 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3573 File_Reading(buf, Value);
3574 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3575
3576 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3577 File_Reading(buf, Value);
3578 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3579
3580 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3581 File_Reading(buf, Value);
3582 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3583
3584 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3585 return RETURN_OK;
3586}
3587
3588INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3589{
3590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3591 CHAR buf[MAX_CMD_SIZE] = {0};
3592 FILE *fp = NULL;
3593 INT count = 0;
3594
3595 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3596 {
3597 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3598 File_Reading(buf, status);
3599 }
3600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3601 return RETURN_OK;
3602}
3603
3604//Get detail radio traffic static info
3605INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3606{
3607
3608#if 0
3609 //ifconfig radio_x
3610 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3611 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3612 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3613 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3614
3615 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3616 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3617 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.
3618 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.
3619
3620 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3621 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].
3622 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3623 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.
3624 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
3625 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
3626 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
3627 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
3628 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
3629
3630 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
3631 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
3632 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
3633 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.
3634
3635 return RETURN_OK;
3636#endif
3637
developera91d99f2022-09-29 15:59:10 +08003638 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003639 BOOL iface_status = FALSE;
3640 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003641
3642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3643 if (NULL == output_struct)
3644 return RETURN_ERR;
3645
developerac6f1142022-12-20 19:26:35 +08003646 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08003647 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003648
developera91d99f2022-09-29 15:59:10 +08003649 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003650
developera91d99f2022-09-29 15:59:10 +08003651 if (iface_status == TRUE)
3652 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3653 else
3654 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003655
developera91d99f2022-09-29 15:59:10 +08003656 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3657 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3658 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3659 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3660 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3661 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3662 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3663 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003664
3665 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3666 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].
3667 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3668 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.
3669 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
3670 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
3671 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
3672 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
3673 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
3674
3675 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
3676 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
3677 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
3678 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.
3679
3680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3681
3682 return RETURN_OK;
3683}
3684
3685//Set radio traffic static Measureing rules
3686INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3687{
3688 //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
3689 // Else, save the MeasuringRate and MeasuringInterval for future usage
3690
3691 return RETURN_OK;
3692}
3693
3694//To start or stop RadioTrafficStats
3695INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3696{
3697 //zqiu: If the RadioTrafficStats process running
3698 // if(enable)
3699 // return RETURN_OK.
3700 // else
3701 // Stop RadioTrafficStats process
3702 // Else
3703 // if(enable)
3704 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3705 // else
3706 // return RETURN_OK.
3707
3708 return RETURN_OK;
3709}
3710
3711//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
3712INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3713{
3714 //zqiu: Please ignor signalIndex.
3715 if (NULL == SignalLevel)
3716 return RETURN_ERR;
3717 *SignalLevel=(radioIndex==0)?-19:-19;
3718
3719 return RETURN_OK;
3720}
3721
3722//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3723INT wifi_applyRadioSettings(INT radioIndex)
3724{
3725 return RETURN_OK;
3726}
3727
3728//Get the radio index assocated with this SSID entry
3729INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3730{
developer5b398df2022-11-17 20:39:48 +08003731 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003732 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003733 int max_radio_num = 0;
3734 wifi_getMaxRadioNumber(&max_radio_num);
3735 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003736 return RETURN_OK;
3737}
3738
3739//Device.WiFi.SSID.{i}.Enable
3740//Get SSID enable configuration parameters (not the SSID enable status)
3741INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3742{
3743 if (NULL == output_bool)
3744 return RETURN_ERR;
3745
developer06a01d92022-09-07 16:32:39 +08003746 return wifi_getApEnable(ssidIndex, output_bool);
3747}
3748
3749//Device.WiFi.SSID.{i}.Enable
3750//Set SSID enable configuration parameters
3751INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3752{
developer06a01d92022-09-07 16:32:39 +08003753 return wifi_setApEnable(ssidIndex, enable);
3754}
3755
3756//Device.WiFi.SSID.{i}.Status
3757//Get the SSID enable status
3758INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3759{
3760 char cmd[MAX_CMD_SIZE]={0};
3761 char buf[MAX_BUF_SIZE]={0};
3762 BOOL output_bool;
3763
3764 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3765 if (NULL == output_string)
3766 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003767
developer06a01d92022-09-07 16:32:39 +08003768 wifi_getApEnable(ssidIndex,&output_bool);
3769 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3770
3771 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3772 return RETURN_OK;
3773}
3774
3775// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3776INT wifi_getSSIDName(INT apIndex, CHAR *output)
3777{
3778 char config_file[MAX_BUF_SIZE] = {0};
3779
3780 if (NULL == output)
3781 return RETURN_ERR;
3782
3783 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3784 wifi_hostapdRead(config_file,"ssid",output,32);
3785
3786 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3787 return RETURN_OK;
3788}
3789
3790// Set a max 32 byte string and sets an internal variable to the SSID name
3791INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3792{
3793 char str[MAX_BUF_SIZE]={'\0'};
3794 char cmd[MAX_CMD_SIZE]={'\0'};
3795 struct params params;
3796 char config_file[MAX_BUF_SIZE] = {0};
3797
3798 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003799 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003800 return RETURN_ERR;
3801
3802 params.name = "ssid";
3803 params.value = ssid_string;
3804 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3805 wifi_hostapdWrite(config_file, &params, 1);
3806 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3807 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3808
3809 return RETURN_OK;
3810}
3811
3812//Get the BSSID
3813INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3814{
3815 char cmd[MAX_CMD_SIZE]="";
3816
3817 if (NULL == output_string)
3818 return RETURN_ERR;
3819
3820 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3821 {
developer1d57d002022-10-12 18:03:15 +08003822 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 +08003823 _syscmd(cmd, output_string, 64);
3824 return RETURN_OK;
3825 }
3826 strncpy(output_string, "\0", 1);
3827
3828 return RETURN_ERR;
3829}
3830
3831//Get the MAC address associated with this Wifi SSID
3832INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3833{
3834 wifi_getBaseBSSID(ssidIndex,output_string);
3835 return RETURN_OK;
3836}
3837
3838//Get the basic SSID traffic static info
3839//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3840//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3841INT wifi_applySSIDSettings(INT ssidIndex)
3842{
developerd946fd62022-12-08 18:03:28 +08003843 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003844 BOOL status = false;
3845 char cmd[MAX_CMD_SIZE] = {0};
3846 char buf[MAX_CMD_SIZE] = {0};
3847 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003848 int max_radio_num = 0;
3849 int radioIndex = 0;
3850
3851 wifi_getMaxRadioNumber(&max_radio_num);
3852
3853 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003854
3855 wifi_getApEnable(ssidIndex,&status);
3856 // Do not apply when ssid index is disabled
3857 if (status == false)
3858 return RETURN_OK;
3859
3860 /* Doing full remove and add for ssid Index
3861 * Not all hostapd options are supported with reload
3862 * for example macaddr_acl
3863 */
3864 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3865 return RETURN_ERR;
3866
3867 ret = wifi_setApEnable(ssidIndex,true);
3868
3869 /* Workaround for hostapd issue with multiple bss definitions
3870 * when first created interface will be removed
3871 * then all vaps other vaps on same phy are removed
3872 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003873 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003874 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003875 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003876 continue;
developer643b28f2023-04-04 10:26:01 +08003877 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003878 _syscmd(cmd, buf, sizeof(buf));
3879 if(*buf == '1')
3880 wifi_setApEnable(apIndex, true);
3881 }
3882
3883 return ret;
3884}
3885
developera3c68b92022-09-13 15:27:29 +08003886struct channels_noise {
3887 int channel;
3888 int noise;
3889};
3890
3891// Return noise array for each channel
3892int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3893{
developerd946fd62022-12-08 18:03:28 +08003894 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003895 FILE *f = NULL;
3896 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003897 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003898 size_t len = 0;
3899 ssize_t read = 0;
3900 int tmp = 0, arr_index = -1;
3901
developerac6f1142022-12-20 19:26:35 +08003902 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003903 return RETURN_ERR;
3904 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003905
3906 if ((f = popen(cmd, "r")) == NULL) {
3907 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3908 return RETURN_ERR;
3909 }
developer5550e242022-09-30 09:59:32 +08003910
3911 while(fgets(line, sizeof(line), f) != NULL) {
3912 if(arr_index < channels_num){
3913 sscanf(line, "%d", &tmp);
3914 if (tmp > 0) { // channel frequency, the first line must be frequency
3915 arr_index++;
3916 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3917 } else { // noise
3918 channels_noise_arr[arr_index].noise = tmp;
3919 }
3920 }else{
3921 break;
developera3c68b92022-09-13 15:27:29 +08003922 }
3923 }
developera3c68b92022-09-13 15:27:29 +08003924 pclose(f);
3925 return RETURN_OK;
3926}
3927
developer06a01d92022-09-07 16:32:39 +08003928//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3929//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3930INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3931{
developera3c68b92022-09-13 15:27:29 +08003932 int index = -1;
3933 wifi_neighbor_ap2_t *scan_array = NULL;
3934 char cmd[256]={0};
3935 char buf[128]={0};
3936 char file_name[32] = {0};
3937 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003938 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003939 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003940 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003941 int freq=0;
3942 FILE *f = NULL;
3943 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003944 int channels_num = 0;
3945 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003946 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003947 bool filter_enable = false;
3948 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003949 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003950
developer615510b2022-09-27 10:14:35 +08003951 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003952
developerac6f1142022-12-20 19:26:35 +08003953 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003954 return RETURN_ERR;
3955
developera3c68b92022-09-13 15:27:29 +08003956 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3957 f = fopen(file_name, "r");
3958 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08003959 fgets(buf, sizeof(file_name), f);
3960 if ((strncmp(buf, "0", 1)) != 0) {
3961 fgets(filter_SSID, sizeof(file_name), f);
3962 if (strlen(filter_SSID) != 0)
3963 filter_enable = true;
3964 }
developera3c68b92022-09-13 15:27:29 +08003965 fclose(f);
3966 }
3967
developer033b37b2022-10-18 11:27:46 +08003968 phyId = radio_index_to_phy(radioIndex);
3969 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003970 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003971 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003972
developer5550e242022-09-30 09:59:32 +08003973
developer06a01d92022-09-07 16:32:39 +08003974
developerd946fd62022-12-08 18:03:28 +08003975 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3976 // 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 +08003977 fprintf(stderr, "cmd: %s\n", cmd);
3978 if ((f = popen(cmd, "r")) == NULL) {
3979 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3980 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003981 }
developer5550e242022-09-30 09:59:32 +08003982
3983 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3984 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3985
developer615510b2022-09-27 10:14:35 +08003986 ret = fgets(line, sizeof(line), f);
3987 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003988 if(strstr(line, "BSS") != NULL) { // new neighbor info
3989 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3990 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3991 // 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 +08003992
developera3c68b92022-09-13 15:27:29 +08003993 if (!filter_BSS) {
3994 index++;
3995 wifi_neighbor_ap2_t *tmp;
3996 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3997 if (tmp == NULL) { // no more memory to use
3998 index--;
3999 wifi_dbg_printf("%s: realloc failed\n", __func__);
4000 break;
4001 }
4002 scan_array = tmp;
4003 }
4004 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4005
4006 filter_BSS = false;
4007 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4008 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4009 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4010 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4011 } else if (strstr(line, "freq") != NULL) {
4012 sscanf(line," freq: %d", &freq);
4013 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4014
4015 if (freq >= 2412 && freq <= 2484) {
4016 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4017 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4018 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4019 }
4020 else if (freq >= 5160 && freq <= 5805) {
4021 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4022 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4023 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4024 }
4025
4026 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004027 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004028 for (int i = 0; i < channels_num; i++) {
4029 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4030 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4031 break;
4032 }
4033 }
4034 }
4035 } else if (strstr(line, "beacon interval") != NULL) {
4036 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4037 } else if (strstr(line, "signal") != NULL) {
4038 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4039 } else if (strstr(line,"SSID") != NULL) {
4040 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4041 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4042 filter_BSS = true;
4043 }
4044 } else if (strstr(line, "Supported rates") != NULL) {
4045 char SRate[80] = {0}, *tmp = NULL;
4046 memset(buf, 0, sizeof(buf));
4047 strcpy(SRate, line);
4048 tmp = strtok(SRate, ":");
4049 tmp = strtok(NULL, ":");
4050 strcpy(buf, tmp);
4051 memset(SRate, 0, sizeof(SRate));
4052
4053 tmp = strtok(buf, " \n");
4054 while (tmp != NULL) {
4055 strcat(SRate, tmp);
4056 if (SRate[strlen(SRate) - 1] == '*') {
4057 SRate[strlen(SRate) - 1] = '\0';
4058 }
4059 strcat(SRate, ",");
4060
4061 tmp = strtok(NULL, " \n");
4062 }
4063 SRate[strlen(SRate) - 1] = '\0';
4064 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4065 } else if (strstr(line, "DTIM") != NULL) {
4066 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4067 } else if (strstr(line, "VHT capabilities") != NULL) {
4068 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4069 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4070 } else if (strstr(line, "HT capabilities") != NULL) {
4071 strcat(scan_array[index].ap_SupportedStandards, ",n");
4072 strcpy(scan_array[index].ap_OperatingStandards, "n");
4073 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004074 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004075 sscanf(line," * channel width: %d", &vht_channel_width);
4076 if(vht_channel_width == 1) {
4077 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4078 } else {
4079 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4080 }
4081 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4082 continue;
4083 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004084 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004085 sscanf(line," * secondary channel offset: %s", &buf);
4086 if (!strcmp(buf, "above")) {
4087 //40Mhz +
4088 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4089 }
4090 else if (!strcmp(buf, "below")) {
4091 //40Mhz -
4092 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4093 } else {
4094 //20Mhz
4095 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4096 }
4097 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4098 continue;
4099 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004100 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4101 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4102 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004103 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4104 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004105 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004106 else
developer615510b2022-09-27 10:14:35 +08004107 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004108 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004109 if (strstr(line, "HE80/5GHz") != NULL) {
4110 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4111 ret = fgets(line, sizeof(line), f);
4112 } else
4113 continue;
developera3c68b92022-09-13 15:27:29 +08004114 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004115 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004116 }
developer615510b2022-09-27 10:14:35 +08004117 continue;
developera3c68b92022-09-13 15:27:29 +08004118 } else if (strstr(line, "WPA") != NULL) {
4119 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4120 } else if (strstr(line, "RSN") != NULL) {
4121 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4122 } else if (strstr(line, "Group cipher") != NULL) {
4123 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4124 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4125 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4126 }
4127 }
developer615510b2022-09-27 10:14:35 +08004128 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004129 }
4130
4131 if (!filter_BSS) {
4132 *output_array_size = index + 1;
4133 } else {
4134 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4135 *output_array_size = index;
4136 }
4137 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004138 pclose(f);
developer5550e242022-09-30 09:59:32 +08004139 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004141 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004142}
4143
4144//>> Deprecated: used for old RDKB code.
4145INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4146{
4147 INT status = RETURN_ERR;
4148
4149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4150 output_struct->wifi_PLCPErrorCount = 0;
4151 output_struct->wifi_FCSErrorCount = 0;
4152 output_struct->wifi_InvalidMACCount = 0;
4153 output_struct->wifi_PacketsOtherReceived = 0;
4154 output_struct->wifi_Noise = 0;
4155 status = RETURN_OK;
4156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4157 return status;
4158}
4159
4160INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4161{
developerd946fd62022-12-08 18:03:28 +08004162 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004163 char cmd[128] = {0};
4164 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004165 char *pos = NULL;
4166
4167 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4168 if (NULL == output_struct)
4169 return RETURN_ERR;
4170
developerac6f1142022-12-20 19:26:35 +08004171 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004172 return RETURN_ERR;
4173
developer06a01d92022-09-07 16:32:39 +08004174 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4175
developerd946fd62022-12-08 18:03:28 +08004176 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004177 _syscmd(cmd, buf, sizeof(buf));
4178
4179 pos = buf;
4180 if ((pos = strstr(pos, "RX packets:")) == NULL)
4181 return RETURN_ERR;
4182 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4183
4184 if ((pos = strstr(pos, "TX packets:")) == NULL)
4185 return RETURN_ERR;
4186 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4187
4188 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4189 return RETURN_ERR;
4190 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4191
4192 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4193 return RETURN_ERR;
4194 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4195
developerd946fd62022-12-08 18:03:28 +08004196 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004197 _syscmd(cmd, buf, sizeof(buf));
4198 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4199
4200#if 0
4201 //TODO: need to revisit below implementation
4202 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4203 char interface_name[MAX_BUF_SIZE] = {0};
4204 char interface_status[MAX_BUF_SIZE] = {0};
4205 char Value[MAX_BUF_SIZE] = {0};
4206 char buf[MAX_CMD_SIZE] = {0};
4207 char cmd[MAX_CMD_SIZE] = {0};
4208 FILE *fp = NULL;
4209
4210 if (NULL == output_struct) {
4211 return RETURN_ERR;
4212 }
4213
4214 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4215
4216 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4217 {
4218 if(apIndex == 0) //private_wifi for 2.4G
4219 {
developerac6f1142022-12-20 19:26:35 +08004220 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004221 }
4222 else if(apIndex == 1) //private_wifi for 5G
4223 {
developerac6f1142022-12-20 19:26:35 +08004224 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004225 }
4226 else if(apIndex == 4) //public_wifi for 2.4G
4227 {
4228 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4229 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4230 {
4231 return RETURN_ERR;
4232 }
4233 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004234 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004235 else//tenda
developerac6f1142022-12-20 19:26:35 +08004236 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004237 }
4238 else if(apIndex == 5) //public_wifi for 5G
4239 {
developerac6f1142022-12-20 19:26:35 +08004240 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004241 }
4242
4243 GetIfacestatus(interface_name, interface_status);
4244
4245 if(0 != strcmp(interface_status, "1"))
4246 return RETURN_ERR;
4247
4248 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4249 system(cmd);
4250
4251 fp = fopen("/tmp/SSID_Stats.txt", "r");
4252 if(fp == NULL)
4253 {
4254 printf("/tmp/SSID_Stats.txt not exists \n");
4255 return RETURN_ERR;
4256 }
4257 fclose(fp);
4258
4259 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4260 File_Reading(buf, Value);
4261 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4262
4263 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4264 File_Reading(buf, Value);
4265 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4266
4267 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4268 File_Reading(buf, Value);
4269 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4270
4271 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4272 File_Reading(buf, Value);
4273 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4274
4275 /* There is no specific parameter from caller to associate the value wifi_Associations */
4276 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4277 //_syscmd(cmd, buf, sizeof(buf));
4278 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4279 }
4280#endif
4281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4282 return RETURN_OK;
4283}
4284
4285INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4286{
4287 char interface_name[MAX_BUF_SIZE] = {0};
4288 char interface_status[MAX_BUF_SIZE] = {0};
4289 char Value[MAX_BUF_SIZE] = {0};
4290 char buf[MAX_CMD_SIZE] = {0};
4291 char cmd[MAX_CMD_SIZE] = {0};
4292 FILE *fp = NULL;
4293
4294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4295 if (NULL == output_struct)
4296 return RETURN_ERR;
4297
4298 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4299
developerac6f1142022-12-20 19:26:35 +08004300 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004301 return RETURN_ERR;
4302 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004303
developerd946fd62022-12-08 18:03:28 +08004304 if(0 != strcmp(interface_status, "1"))
4305 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004306
developerd946fd62022-12-08 18:03:28 +08004307 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4308 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004309
developerd946fd62022-12-08 18:03:28 +08004310 fp = fopen("/tmp/SSID_Stats.txt", "r");
4311 if(fp == NULL)
4312 {
4313 printf("/tmp/SSID_Stats.txt not exists \n");
4314 return RETURN_ERR;
4315 }
4316 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004317
developerd946fd62022-12-08 18:03:28 +08004318 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4319 File_Reading(buf, Value);
4320 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004321
developerd946fd62022-12-08 18:03:28 +08004322 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4323 File_Reading(buf, Value);
4324 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004325
developerd946fd62022-12-08 18:03:28 +08004326 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4327 File_Reading(buf, Value);
4328 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004329
developerd946fd62022-12-08 18:03:28 +08004330 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4331 File_Reading(buf, Value);
4332 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004333
4334 output_struct->wifi_UnicastPacketsSent = 0;
4335 output_struct->wifi_UnicastPacketsReceived = 0;
4336 output_struct->wifi_MulticastPacketsSent = 0;
4337 output_struct->wifi_MulticastPacketsReceived = 0;
4338 output_struct->wifi_BroadcastPacketsSent = 0;
4339 output_struct->wifi_BroadcastPacketsRecevied = 0;
4340 output_struct->wifi_UnknownPacketsReceived = 0;
4341
4342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4343 return RETURN_OK;
4344}
4345
4346INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4347{
4348 INT status = RETURN_ERR;
4349
4350 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4351 //Below values should get updated from hal
4352 output_struct->wifi_RetransCount=0;
4353 output_struct->wifi_FailedRetransCount=0;
4354 output_struct->wifi_RetryCount=0;
4355 output_struct->wifi_MultipleRetryCount=0;
4356 output_struct->wifi_ACKFailureCount=0;
4357 output_struct->wifi_AggregatedPacketCount=0;
4358
4359 status = RETURN_OK;
4360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4361
4362 return status;
4363}
4364
4365INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4366{
4367 INT status = RETURN_ERR;
4368 UINT index;
4369 wifi_neighbor_ap_t *pt=NULL;
4370
4371 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4372 *output_array_size=2;
4373 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4374 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4375 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4376 strcpy(pt->ap_Radio,"");
4377 strcpy(pt->ap_SSID,"");
4378 strcpy(pt->ap_BSSID,"");
4379 strcpy(pt->ap_Mode,"");
4380 pt->ap_Channel=1;
4381 pt->ap_SignalStrength=0;
4382 strcpy(pt->ap_SecurityModeEnabled,"");
4383 strcpy(pt->ap_EncryptionMode,"");
4384 strcpy(pt->ap_OperatingFrequencyBand,"");
4385 strcpy(pt->ap_SupportedStandards,"");
4386 strcpy(pt->ap_OperatingStandards,"");
4387 strcpy(pt->ap_OperatingChannelBandwidth,"");
4388 pt->ap_BeaconPeriod=1;
4389 pt->ap_Noise=0;
4390 strcpy(pt->ap_BasicDataTransferRates,"");
4391 strcpy(pt->ap_SupportedDataTransferRates,"");
4392 pt->ap_DTIMPeriod=1;
4393 pt->ap_ChannelUtilization = 1;
4394 }
4395
4396 status = RETURN_OK;
4397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4398
4399 return status;
4400}
4401
4402//----------------- AP HAL -------------------------------
4403
4404//>> Deprecated: used for old RDKB code.
4405INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4406{
4407 if (NULL == output_ulong || NULL == output_struct)
4408 return RETURN_ERR;
4409 *output_ulong = 0;
4410 *output_struct = NULL;
4411 return RETURN_OK;
4412}
4413
4414#ifdef HAL_NETLINK_IMPL
4415static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4416 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4417 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4418 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4419 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4420 char mac_addr[20];
4421 static int count=0;
4422 int rate=0;
4423
4424 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4425
4426 nla_parse(tb,
4427 NL80211_ATTR_MAX,
4428 genlmsg_attrdata(gnlh, 0),
4429 genlmsg_attrlen(gnlh, 0),
4430 NULL);
4431
4432 if(!tb[NL80211_ATTR_STA_INFO]) {
4433 fprintf(stderr, "sta stats missing!\n");
4434 return NL_SKIP;
4435 }
4436
4437
4438 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4439 fprintf(stderr, "failed to parse nested attributes!\n");
4440 return NL_SKIP;
4441 }
4442
4443 //devIndex starts from 1
4444 if( ++count == out->wifi_devIndex )
4445 {
4446 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4447 //Getting the mac addrress
4448 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4449
4450 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4451 fprintf(stderr, "failed to parse nested rate attributes!");
4452 return NL_SKIP;
4453 }
4454
4455 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4456 if(rinfo[NL80211_RATE_INFO_BITRATE])
4457 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4458 out->wifi_devTxRate = rate/10;
4459 }
4460
4461 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4462 fprintf(stderr, "failed to parse nested rate attributes!");
4463 return NL_SKIP;
4464 }
4465
4466 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4467 if(rinfo[NL80211_RATE_INFO_BITRATE])
4468 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4469 out->wifi_devRxRate = rate/10;
4470 }
4471 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4472 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4473
4474 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4475 count = 0; //starts the count for next cycle
4476 return NL_STOP;
4477 }
4478
4479 return NL_SKIP;
4480
4481}
4482#endif
4483
4484INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4485{
4486#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004487 Netlink nl = {0};
4488 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004489 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004490
developer30423732022-12-01 16:17:49 +08004491 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004492 info.wifi_devIndex = devIndex;
4493
developerac6f1142022-12-20 19:26:35 +08004494 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004495 return RETURN_ERR;
4496
4497 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004498
4499 nl.id = initSock80211(&nl);
4500
4501 if (nl.id < 0) {
4502 fprintf(stderr, "Error initializing netlink \n");
4503 return -1;
4504 }
4505
4506 struct nl_msg* msg = nlmsg_alloc();
4507
4508 if (!msg) {
4509 fprintf(stderr, "Failed to allocate netlink message.\n");
4510 nlfree(&nl);
4511 return -2;
4512 }
4513
4514 genlmsg_put(msg,
4515 NL_AUTO_PORT,
4516 NL_AUTO_SEQ,
4517 nl.id,
4518 0,
4519 NLM_F_DUMP,
4520 NL80211_CMD_GET_STATION,
4521 0);
4522
4523 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4524 nl_send_auto(nl.socket, msg);
4525 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4526 nl_recvmsgs(nl.socket, nl.cb);
4527 nlmsg_free(msg);
4528 nlfree(&nl);
4529
4530 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4531 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4532 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4533 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4534 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4535 return RETURN_OK;
4536#else
4537 //iw utility to retrieve station information
4538#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4539#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4540#define MACFILE "/tmp/wifi_AssoMac.txt"
4541#define TXRATEFILE "/tmp/wifi_txrate.txt"
4542#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4543 FILE *file = NULL;
4544 char if_name[10] = {'\0'};
4545 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004546 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004547 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004548 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004549
developerac6f1142022-12-20 19:26:35 +08004550 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004551 return RETURN_ERR;
4552
4553 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004554
4555 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4556 file = popen(pipeCmd, "r");
4557
4558 if(file == NULL)
4559 return RETURN_ERR; //popen failed
4560
4561 fgets(line, sizeof line, file);
4562 device = atoi(line);
4563 pclose(file);
4564
4565 if(device == 0)
4566 return RETURN_ERR; //No devices are connected
4567
4568 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4569 system(pipeCmd);
4570
4571 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4572
4573 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4574
4575 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4576
4577 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4578
4579 //devIndex starts from 1, ++count
4580 if((file = fopen(SIGNALFILE, "r")) != NULL )
4581 {
4582 for(count =0;fgets(line, sizeof line, file) != NULL;)
4583 {
4584 if (++count == devIndex)
4585 {
4586 output_struct->wifi_devSignalStrength = atoi(line);
4587 break;
4588 }
4589 }
4590 fclose(file);
4591 }
4592 else
4593 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4594
4595 if((file = fopen(MACFILE, "r")) != NULL )
4596 {
4597 for(count =0;fgets(line, sizeof line, file) != NULL;)
4598 {
4599 if (++count == devIndex)
4600 {
4601 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]);
4602 break;
4603 }
4604 }
4605 fclose(file);
4606 }
4607 else
4608 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4609
4610 if((file = fopen(TXRATEFILE, "r")) != NULL )
4611 {
4612 for(count =0;fgets(line, sizeof line, file) != NULL;)
4613 {
4614 if (++count == devIndex)
4615 {
4616 output_struct->wifi_devTxRate = atoi(line);
4617 break;
4618 }
4619 }
4620 fclose(file);
4621 }
4622 else
4623 fprintf(stderr,"fopen wifi_txrate.txt failed");
4624
4625 if((file = fopen(RXRATEFILE, "r")) != NULL)
4626 {
4627 for(count =0;fgets(line, sizeof line, file) != NULL;)
4628 {
4629 if (++count == devIndex)
4630 {
4631 output_struct->wifi_devRxRate = atoi(line);
4632 break;
4633 }
4634 }
4635 fclose(file);
4636 }
4637 else
4638 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4639
4640 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4641
4642 return RETURN_OK;
4643#endif
4644}
4645
4646INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4647{
4648 if (NULL == device)
4649 return RETURN_ERR;
4650 return RETURN_OK;
4651}
4652//<<
4653
4654
4655//--------------wifi_ap_hal-----------------------------
4656//enables CTS protection for the radio used by this AP
4657INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4658{
4659 //save config and Apply instantly
4660 return RETURN_ERR;
4661}
4662
4663// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4664INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4665{
developer463d39a2022-09-13 15:32:51 +08004666 char config_file[64] = {'\0'};
4667 char buf[64] = {'\0'};
4668 struct params list;
4669
4670 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4671 list.name = "ht_coex";
4672 snprintf(buf, sizeof(buf), "%d", enable);
4673 list.value = buf;
4674
4675 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4676 wifi_hostapdWrite(config_file, &list, 1);
4677 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4678
4679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4680
4681 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004682}
4683
4684//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4685INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4686{
developerea4bcce2022-09-13 15:26:13 +08004687 char config_file[MAX_BUF_SIZE] = {'\0'};
4688 char buf[MAX_BUF_SIZE] = {'\0'};
4689 struct params list;
4690
4691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4692 if (threshold < 256 || threshold > 2346 )
4693 return RETURN_ERR;
4694 list.name = "fragm_threshold";
4695 snprintf(buf, sizeof(buf), "%d", threshold);
4696 list.value = buf;
4697
4698 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4699 wifi_hostapdWrite(config_file, &list, 1);
4700 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004701
developerea4bcce2022-09-13 15:26:13 +08004702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004703
4704 return RETURN_OK;
4705}
4706
4707// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4708INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4709{
developer51a927d2022-09-13 15:42:22 +08004710 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004711 char cmd[512] = {'\0'};
4712 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004713 char stbc_config[16] = {'\0'};
4714 wifi_band band;
4715 int iterator = 0;
4716 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004717 int ant_count = 0;
4718 int ant_bitmap = 0;
4719 struct params list;
developer51a927d2022-09-13 15:42:22 +08004720
4721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4722
4723 band = wifi_index_to_band(radioIndex);
4724 if (band == band_invalid)
4725 return RETURN_ERR;
4726
4727 if (band == band_2_4)
4728 iterator = 1;
4729 else if (band == band_5)
4730 iterator = 2;
4731 else
4732 return RETURN_OK;
4733
developer110b8a32022-12-26 15:56:44 +08004734 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4735 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4736 ant_count += ant_bitmap & 1;
4737
4738 if (ant_count == 1 && STBC_Enable == TRUE) {
4739 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4740 return RETURN_OK;
4741 }
4742
developer51a927d2022-09-13 15:42:22 +08004743 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4744
4745 // set ht and vht config
4746 for (int i = 0; i < iterator; i++) {
4747 memset(stbc_config, 0, sizeof(stbc_config));
4748 memset(cmd, 0, sizeof(cmd));
4749 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004750 list.name = (i == 0)?"ht_capab":"vht_capab";
4751 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004752 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4753 _syscmd(cmd, buf, sizeof(buf));
4754 if (strlen(buf) != 0)
4755 current_stbc = TRUE;
4756 if (current_stbc == STBC_Enable)
4757 continue;
4758
4759 if (STBC_Enable == TRUE) {
4760 // Append the STBC flags in capab config
4761 memset(cmd, 0, sizeof(cmd));
4762 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004763 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004764 else
developer6372c2b2022-10-27 17:39:51 +08004765 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 +08004766 _syscmd(cmd, buf, sizeof(buf));
4767 } else if (STBC_Enable == FALSE) {
4768 // Remove the STBC flags and remain other flags in capab
4769 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004770 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004771 _syscmd(cmd, buf, sizeof(buf));
4772 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004773 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004774 _syscmd(cmd, buf, sizeof(buf));
4775 }
developer110b8a32022-12-26 15:56:44 +08004776 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4777 list.value = buf;
4778 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004779 }
4780
4781 wifi_reloadAp(radioIndex);
4782
4783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4784 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004785}
4786
4787// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4788INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4789{
developerfe7aefc2022-12-23 17:13:37 +08004790 char cmd[128] = {0};
4791 char buf[128] = {0};
4792 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004793
4794 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4795
4796 if(output_bool == NULL)
4797 return RETURN_ERR;
4798
developerfe7aefc2022-12-23 17:13:37 +08004799 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4800 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004801
developerfe7aefc2022-12-23 17:13:37 +08004802 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4803 _syscmd(cmd, buf, sizeof(buf));
4804
4805 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004806 *output_bool = TRUE;
4807 else
4808 *output_bool = FALSE;
4809
4810 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4811 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004812}
4813
4814// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4815INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4816{
developerfe7aefc2022-12-23 17:13:37 +08004817 char config_file[128] = {0};
4818 struct params list = {0};
4819 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004820
4821 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4822
developerfe7aefc2022-12-23 17:13:37 +08004823 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004824 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004825
developerfe7aefc2022-12-23 17:13:37 +08004826 if (amsduEnable == enable)
4827 return RETURN_OK;
4828
4829 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4830 list.name = "amsdu";
4831 list.value = amsduEnable? "1":"0";
4832 wifi_hostapdWrite(config_file, &list, 1);
4833 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4834 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004835
4836 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4837 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004838}
4839
4840//P2 // outputs the number of Tx streams
4841INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4842{
developer2de97692022-09-26 14:00:03 +08004843 char buf[8] = {0};
4844 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004845 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004846
4847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4848
developer033b37b2022-10-18 11:27:46 +08004849 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004850 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004851 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004852
developer110b8a32022-12-26 15:56:44 +08004853 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004854
4855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4856
4857 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004858}
4859
developer110b8a32022-12-26 15:56:44 +08004860INT fitChainMask(INT radioIndex, int antcount)
4861{
4862 char buf[128] = {0};
4863 char cmd[128] = {0};
4864 char config_file[64] = {0};
4865 wifi_band band;
4866 struct params list[2] = {0};
4867
4868 band = wifi_index_to_band(radioIndex);
4869 if (band == band_invalid)
4870 return RETURN_ERR;
4871
4872 list[0].name = "he_mu_beamformer";
4873 list[1].name = "he_su_beamformer";
4874
4875 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4876 if (antcount == 1) {
4877 // remove config about multiple antennas
4878 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4879 _syscmd(cmd, buf, sizeof(buf));
4880
4881 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4882 _syscmd(cmd, buf, sizeof(buf));
4883
4884 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4885 _syscmd(cmd, buf, sizeof(buf));
4886
4887 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4888 _syscmd(cmd, buf, sizeof(buf));
4889
4890 list[0].value = "0";
4891 list[1].value = "0";
4892 } else {
4893 // 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.
4894 if (band == band_2_4 || band == band_5) {
4895 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4896 _syscmd(cmd, buf, sizeof(buf));
4897 if (strlen(buf) > 0) {
4898 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4899 _syscmd(cmd, buf, sizeof(buf));
4900 }
4901 }
4902 if (band == band_5) {
4903 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4904 _syscmd(cmd, buf, sizeof(buf));
4905 if (strlen(buf) > 0) {
4906 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4907 _syscmd(cmd, buf, sizeof(buf));
4908 }
4909 }
4910
4911 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4912 _syscmd(cmd, buf, sizeof(buf));
4913 if (strlen(buf) == 0) {
4914 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4915 _syscmd(cmd, buf, sizeof(buf));
4916 }
4917
4918 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4919 _syscmd(cmd, buf, sizeof(buf));
4920 if (strlen(buf) == 0) {
4921 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4922 _syscmd(cmd, buf, sizeof(buf));
4923 }
4924
4925 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4926 _syscmd(cmd, buf, sizeof(buf));
4927 if (strlen(buf) == 0) {
4928 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4929 } else {
4930 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4931 }
4932 _syscmd(cmd, buf, sizeof(buf));
4933
4934 list[0].value = "1";
4935 list[1].value = "1";
4936 }
4937 wifi_hostapdWrite(config_file, list, 2);
4938}
4939
developer06a01d92022-09-07 16:32:39 +08004940//P2 // sets the number of Tx streams to an enviornment variable
4941INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4942{
developer2de97692022-09-26 14:00:03 +08004943 char cmd[128] = {0};
4944 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004945 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08004946 int cur_mask = 0;
4947 int antcount = 0;
4948 wifi_band band;
developer2de97692022-09-26 14:00:03 +08004949
4950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4951
developer110b8a32022-12-26 15:56:44 +08004952 if (numStreams <= 0) {
4953 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08004954 return RETURN_ERR;
4955 }
developer110b8a32022-12-26 15:56:44 +08004956
4957 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4958 if (cur_mask == numStreams)
4959 return RETURN_OK;
4960
developer2de97692022-09-26 14:00:03 +08004961 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004962
4963 phyId = radio_index_to_phy(radioIndex);
4964 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004965 _syscmd(cmd, buf, sizeof(buf));
4966
4967 if (strlen(buf) > 0) {
4968 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4969 return RETURN_ERR;
4970 }
developer2de97692022-09-26 14:00:03 +08004971
developer110b8a32022-12-26 15:56:44 +08004972 // if chain mask changed, we need to make the hostapd config valid.
4973 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
4974 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08004975 }
developer110b8a32022-12-26 15:56:44 +08004976 fitChainMask(radioIndex, antcount);
4977
4978 wifi_setRadioEnable(radioIndex, TRUE);
4979
developer2de97692022-09-26 14:00:03 +08004980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4981 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004982}
4983
4984//P2 // outputs the number of Rx streams
4985INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4986{
developer110b8a32022-12-26 15:56:44 +08004987 char buf[8] = {0};
4988 char cmd[128] = {0};
4989 int phyId = 0;
4990
developer2de97692022-09-26 14:00:03 +08004991 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004992
4993 phyId = radio_index_to_phy(radioIndex);
4994 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
4995 _syscmd(cmd, buf, sizeof(buf));
4996
4997 *output_int = (INT)strtol(buf, NULL, 16);
4998
developer2de97692022-09-26 14:00:03 +08004999 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005000
developer06a01d92022-09-07 16:32:39 +08005001 return RETURN_OK;
5002}
5003
5004//P2 // sets the number of Rx streams to an enviornment variable
5005INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5006{
developer2de97692022-09-26 14:00:03 +08005007 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5008 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5009 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5010 return RETURN_ERR;
5011 }
5012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005013 return RETURN_ERR;
5014}
5015
5016//Get radio RDG enable setting
5017INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5018{
5019 if (NULL == output_bool)
5020 return RETURN_ERR;
5021 *output_bool = TRUE;
5022 return RETURN_OK;
5023}
5024
5025//Get radio RDG enable setting
5026INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5027{
5028 if (NULL == output_bool)
5029 return RETURN_ERR;
5030 *output_bool = TRUE;
5031 return RETURN_OK;
5032}
5033
5034//Set radio RDG enable setting
5035INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5036{
5037 return RETURN_ERR;
5038}
5039
5040//Get radio ADDBA enable setting
5041INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5042{
5043 if (NULL == output_bool)
5044 return RETURN_ERR;
5045 *output_bool = TRUE;
5046 return RETURN_OK;
5047}
5048
5049//Set radio ADDBA enable setting
5050INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5051{
5052 return RETURN_ERR;
5053}
5054
5055//Get radio auto block ack enable setting
5056INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5057{
5058 if (NULL == output_bool)
5059 return RETURN_ERR;
5060 *output_bool = TRUE;
5061 return RETURN_OK;
5062}
5063
5064//Set radio auto block ack enable setting
5065INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5066{
5067 return RETURN_ERR;
5068}
5069
5070//Get radio 11n pure mode enable support
5071INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5072{
5073 if (NULL == output_bool)
5074 return RETURN_ERR;
5075 *output_bool = TRUE;
5076 return RETURN_OK;
5077}
5078
5079//Get radio 11n pure mode enable setting
5080INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5081{
5082 if (NULL == output_bool)
5083 return RETURN_ERR;
5084 *output_bool = TRUE;
5085 return RETURN_OK;
5086}
5087
5088//Set radio 11n pure mode enable setting
5089INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5090{
5091 return RETURN_ERR;
5092}
5093
5094//Get radio IGMP snooping enable setting
5095INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5096{
developerd946fd62022-12-08 18:03:28 +08005097 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005098 char cmd[128]={0};
5099 char buf[4]={0};
5100 bool bridge = FALSE, mac80211 = FALSE;
5101 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5102
5103 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005104 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005105
5106 *output_bool = FALSE;
5107
5108 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5109 _syscmd(cmd, buf, sizeof(buf));
5110 if (strncmp(buf, "1", 1) == 0)
5111 bridge = TRUE;
5112
developerac6f1142022-12-20 19:26:35 +08005113 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005114 return RETURN_ERR;
5115 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 +08005116 _syscmd(cmd, buf, sizeof(buf));
5117 if (strncmp(buf, "1", 1) == 0)
5118 mac80211 = TRUE;
5119
5120 if (bridge && mac80211)
5121 *output_bool = TRUE;
5122
5123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005124 return RETURN_OK;
5125}
5126
5127//Set radio IGMP snooping enable setting
5128INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5129{
developerd946fd62022-12-08 18:03:28 +08005130 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005131 char cmd[128]={0};
5132 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005133 int max_num_radios = 0;
5134 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5136
5137 // bridge
developerfb09ba62023-06-09 17:03:21 +08005138 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005139 _syscmd(cmd, buf, sizeof(buf));
5140
developer804c64f2022-10-19 13:54:40 +08005141 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005142 // mac80211
developer894affa2023-05-10 18:13:19 +08005143 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5144 apIndex = radioIndex + i*max_num_radios;
5145 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5146 continue;
developerfb09ba62023-06-09 17:03:21 +08005147 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 +08005148 _syscmd(cmd, buf, sizeof(buf));
5149 }
5150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5151 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005152}
5153
5154//Get the Reset count of radio
5155INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5156{
5157 if (NULL == output_int)
5158 return RETURN_ERR;
5159 *output_int = (radioIndex==0)? 1: 3;
5160
5161 return RETURN_OK;
5162}
5163
5164
5165//---------------------------------------------------------------------------------------------------
5166//
5167// Additional Wifi AP level APIs used for Access Point devices
5168//
5169//---------------------------------------------------------------------------------------------------
5170
5171// creates a new ap and pushes these parameters to the hardware
5172INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5173{
developer7930d352022-12-21 17:55:42 +08005174 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005175 return RETURN_OK;
5176}
5177
5178// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5179INT wifi_deleteAp(INT apIndex)
5180{
developerd946fd62022-12-08 18:03:28 +08005181 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005182 char buf[128] = {0};
5183 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005184
developerac6f1142022-12-20 19:26:35 +08005185 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005186 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005187
developer89df4502023-02-16 20:45:02 +08005188 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5189 return RETURN_ERR;
5190
developer7930d352022-12-21 17:55:42 +08005191 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005192 _syscmd(cmd, buf, sizeof(buf));
5193
5194 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005195 return RETURN_OK;
5196}
5197
5198// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5199INT wifi_getApName(INT apIndex, CHAR *output_string)
5200{
developerd946fd62022-12-08 18:03:28 +08005201 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005202 if(NULL == output_string)
5203 return RETURN_ERR;
5204
developerac6f1142022-12-20 19:26:35 +08005205 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005206 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005207 else
5208 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005209 return RETURN_OK;
5210}
5211
5212// Outputs the index number in that corresponds to the SSID string
5213INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5214{
developerd946fd62022-12-08 18:03:28 +08005215 char cmd [128] = {0};
5216 char buf[32] = {0};
5217 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005218 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005219
developerd946fd62022-12-08 18:03:28 +08005220 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5221 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005222
developerac6f1142022-12-20 19:26:35 +08005223 if (strlen(buf) != 0) {
5224 apIndex_str = strtok(buf, "\n");
5225 *output_int = strtoul(apIndex_str, NULL, 10);
5226 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005227 }
developer67b8ee92022-12-20 10:48:43 +08005228
5229 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5230 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5231 if (apIndex_str) {
5232 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5233 return RETURN_OK;
5234 }
developerd946fd62022-12-08 18:03:28 +08005235 *output_int = -1;
5236 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005237}
5238
5239INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5240{
5241 return wifi_getIndexFromName(inputSsidString, output_int);
5242}
5243
5244// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5245INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5246{
5247 char buf[MAX_BUF_SIZE] = {0};
5248 char cmd[MAX_CMD_SIZE] = {0};
5249 char config_file[MAX_BUF_SIZE] = {0};
5250
5251 if(NULL == output_string)
5252 return RETURN_ERR;
5253
5254 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5255 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5256 if((strcmp(buf,"3")==0))
5257 snprintf(output_string, 32, "WPAand11i");
5258 else if((strcmp(buf,"2")==0))
5259 snprintf(output_string, 32, "11i");
5260 else if((strcmp(buf,"1")==0))
5261 snprintf(output_string, 32, "WPA");
5262 else
5263 snprintf(output_string, 32, "None");
5264
5265 return RETURN_OK;
5266}
5267
5268// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5269INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5270{
5271 char config_file[MAX_BUF_SIZE] = {0};
5272 struct params list;
5273
5274 if (NULL == beaconTypeString)
5275 return RETURN_ERR;
5276 list.name = "wpa";
5277 list.value = "0";
5278
5279 if((strcmp(beaconTypeString,"WPAand11i")==0))
5280 list.value="3";
5281 else if((strcmp(beaconTypeString,"11i")==0))
5282 list.value="2";
5283 else if((strcmp(beaconTypeString,"WPA")==0))
5284 list.value="1";
5285
5286 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5287 wifi_hostapdWrite(config_file, &list, 1);
5288 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5289 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5290 return RETURN_OK;
5291}
5292
5293// sets the beacon interval on the hardware for this AP
5294INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5295{
developer5f222492022-09-13 15:21:52 +08005296 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5297 struct params params={'\0'};
5298 char buf[MAX_BUF_SIZE] = {'\0'};
5299 char config_file[MAX_BUF_SIZE] = {'\0'};
5300
5301 params.name = "beacon_int";
5302 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5303 params.value = buf;
5304
5305 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5306 wifi_hostapdWrite(config_file, &params, 1);
5307
5308 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5309 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5310 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005311}
5312
5313INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5314{
developer5b398df2022-11-17 20:39:48 +08005315 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5316 return RETURN_ERR;
5317 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005318}
5319
5320// Get the packet size threshold supported.
5321INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5322{
5323 //save config and apply instantly
5324 if (NULL == output_bool)
5325 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005326 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005327 return RETURN_OK;
5328}
5329
5330// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5331INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5332{
developer514406b2022-12-05 17:20:21 +08005333 char buf[16] = {0};
5334 char config_file[128] = {0};
5335 struct params param = {0};
5336
5337 if (threshold > 65535) {
5338 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5339 return RETURN_ERR;
5340 }
developer06a01d92022-09-07 16:32:39 +08005341
developer23e71282023-01-18 10:25:19 +08005342 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005343 snprintf(buf, sizeof(buf), "%u", threshold);
5344 param.name = "rts_threshold";
5345 param.value = buf;
5346 wifi_hostapdWrite(config_file, &param, 1);
5347 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5348 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005349
5350 return RETURN_OK;
5351}
5352
5353// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5354INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5355{
5356 if (NULL == output_string)
5357 return RETURN_ERR;
5358 snprintf(output_string, 32, "TKIPandAESEncryption");
5359 return RETURN_OK;
5360
5361}
5362
5363// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5364INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5365{
5366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005367 char *param_name = NULL;
5368 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005369
5370 if(NULL == output_string)
5371 return RETURN_ERR;
5372
5373 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5374 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5375
5376 if(strcmp(buf,"0")==0)
5377 {
5378 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5379 snprintf(output_string, 32, "None");
5380 return RETURN_OK;
5381 }
5382 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5383 param_name = "rsn_pairwise";
5384 else if((strcmp(buf,"1")==0))
5385 param_name = "wpa_pairwise";
5386 else
5387 return RETURN_ERR;
5388 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005389 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005390 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5391 param_name = "wpa_pairwise";
5392 memset(output_string, '\0', 32);
5393 wifi_hostapdRead(config_file, param_name, output_string, 32);
5394 }
developer06a01d92022-09-07 16:32:39 +08005395 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5396
developer72ec5572023-01-05 16:27:13 +08005397 if(strcmp(output_string,"TKIP CCMP") == 0)
5398 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5399 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005400 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5401 else if(strcmp(output_string,"CCMP") == 0)
5402 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005403
5404 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5405 return RETURN_OK;
5406}
5407
5408// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5409INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5410{
5411 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5412 struct params params={'\0'};
5413 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005414 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005415
5416 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005417 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005418
5419 if(strcmp(encMode, "TKIPEncryption") == 0)
5420 params.value = "TKIP";
5421 else if(strcmp(encMode,"AESEncryption") == 0)
5422 params.value = "CCMP";
5423 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5424 params.value = "TKIP CCMP";
5425
5426 if((strcmp(output_string,"WPAand11i")==0))
5427 {
5428 params.name = "wpa_pairwise";
5429 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5430 wifi_hostapdWrite(config_file, &params, 1);
5431 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5432
developer30423732022-12-01 16:17:49 +08005433 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005434 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5435 wifi_hostapdWrite(config_file, &params, 1);
5436 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5437
5438 return RETURN_OK;
5439 }
5440 else if((strcmp(output_string,"11i")==0))
5441 {
5442 params.name = "rsn_pairwise";
5443 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5444 wifi_hostapdWrite(config_file, &params, 1);
5445 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5446 return RETURN_OK;
5447 }
5448 else if((strcmp(output_string,"WPA")==0))
5449 {
5450 params.name = "wpa_pairwise";
5451 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5452 wifi_hostapdWrite(config_file, &params, 1);
5453 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5454 return RETURN_OK;
5455 }
5456
5457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5458 return RETURN_OK;
5459}
5460
5461// deletes internal security varable settings for this ap
5462INT wifi_removeApSecVaribles(INT apIndex)
5463{
5464 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005465 //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 +08005466 //_syscmd(cmd, buf, sizeof(buf));
5467
developerd946fd62022-12-08 18:03:28 +08005468 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005469 //_syscmd(cmd, buf, sizeof(buf));
5470 return RETURN_ERR;
5471}
5472
5473// changes the hardware settings to disable encryption on this ap
5474INT wifi_disableApEncryption(INT apIndex)
5475{
5476 //Apply instantly
5477 return RETURN_ERR;
5478}
5479
5480// set the authorization mode on this ap
5481// mode mapping as: 1: open, 2: shared, 4:auto
5482INT wifi_setApAuthMode(INT apIndex, INT mode)
5483{
developeraf95c502022-09-13 16:18:22 +08005484 struct params params={0};
5485 char config_file[64] = {0};
5486 int ret;
5487
5488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5489
5490 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5491 params.name = "auth_algs";
5492
developer72ec5572023-01-05 16:27:13 +08005493 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005494 params.value = "3";
5495 else if (mode & 2)
5496 params.value = "2";
5497 else if (mode & 1)
5498 params.value = "1";
5499 else
5500 params.value = "0";
5501
5502 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5503 wifi_hostapdWrite(config_file, &params, 1);
5504 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005505 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5507
5508 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005509}
5510
5511// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5512INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5513{
5514 //save to wifi config, and wait for wifi restart to apply
5515 struct params params={'\0'};
5516 char config_file[MAX_BUF_SIZE] = {0};
5517 int ret;
5518
5519 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5520 if(authMode == NULL)
5521 return RETURN_ERR;
5522
5523 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5524 params.name = "wpa_key_mgmt";
5525
5526 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5527 params.value = "WPA-PSK";
5528 else if(strcmp(authMode,"EAPAuthentication") == 0)
5529 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005530 else if (strcmp(authMode, "SAEAuthentication") == 0)
5531 params.value = "SAE";
5532 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5533 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005534 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5535 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005536 else if (strcmp(authMode, "Enhanced_Open") == 0)
5537 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005538 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5539 return RETURN_OK; //This is taken careof in beaconType
5540
5541 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5542 ret=wifi_hostapdWrite(config_file,&params,1);
5543 if(!ret)
5544 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5545 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5546
5547 return ret;
5548}
5549
5550// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5551INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5552{
5553 //save to wifi config, and wait for wifi restart to apply
5554 char BeaconType[50] = {0};
5555 char config_file[MAX_BUF_SIZE] = {0};
5556
5557 *authMode = 0;
5558 wifi_getApBeaconType(apIndex,BeaconType);
5559 printf("%s____%s \n",__FUNCTION__,BeaconType);
5560
5561 if(strcmp(BeaconType,"None") == 0)
5562 strcpy(authMode,"None");
5563 else
5564 {
5565 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5566 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5567 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5568 if(strcmp(authMode,"WPA-PSK") == 0)
5569 strcpy(authMode,"SharedAuthentication");
5570 else if(strcmp(authMode,"WPA-EAP") == 0)
5571 strcpy(authMode,"EAPAuthentication");
5572 }
5573
5574 return RETURN_OK;
5575}
5576
5577// Outputs the number of stations associated per AP
5578INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5579{
developerd946fd62022-12-08 18:03:28 +08005580 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005581 char cmd[128]={0};
5582 char buf[128]={0};
5583 BOOL status = false;
5584
5585 if(apIndex > MAX_APS)
5586 return RETURN_ERR;
5587
5588 wifi_getApEnable(apIndex,&status);
5589 if (!status)
5590 return RETURN_OK;
5591
developerd946fd62022-12-08 18:03:28 +08005592 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005593 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005594 return RETURN_ERR;
5595 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005596 _syscmd(cmd, buf, sizeof(buf));
5597 sscanf(buf,"%lu", output_ulong);
5598
5599 return RETURN_OK;
5600}
5601
5602// manually removes any active wi-fi association with the device specified on this ap
5603INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5604{
developerd946fd62022-12-08 18:03:28 +08005605 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005606 char buf[126]={'\0'};
5607
developerac6f1142022-12-20 19:26:35 +08005608 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005609 return RETURN_ERR;
5610 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005611 system(buf);
5612
5613 return RETURN_OK;
5614}
5615
5616// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5617INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5618{
5619 if(NULL == output_int)
5620 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005621 int max_radio_num = 0;
5622 wifi_getMaxRadioNumber(&max_radio_num);
5623 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005624 return RETURN_OK;
5625}
5626
5627// sets the radio index for the specific ap
5628INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5629{
5630 //set to config only and wait for wifi reset to apply settings
5631 return RETURN_ERR;
5632}
5633
5634// Get the ACL MAC list per AP
5635INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5636{
developerd946fd62022-12-08 18:03:28 +08005637 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005638 char cmd[MAX_CMD_SIZE]={'\0'};
5639 int ret = 0;
5640
developerac6f1142022-12-20 19:26:35 +08005641 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005642 return RETURN_ERR;
5643 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005644 ret = _syscmd(cmd,macArray,buf_size);
5645 if (ret != 0)
5646 return RETURN_ERR;
5647
5648 return RETURN_OK;
5649}
5650
developere6aafda2022-09-13 14:59:28 +08005651INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5652{
developerd946fd62022-12-08 18:03:28 +08005653 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005654 char cmd[MAX_CMD_SIZE]={'\0'};
5655 int ret = 0;
5656
developerac6f1142022-12-20 19:26:35 +08005657 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005658 return RETURN_ERR;
5659 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005660 ret = _syscmd(cmd,macArray,buf_size);
5661 if (ret != 0)
5662 return RETURN_ERR;
5663
5664 return RETURN_OK;
5665}
5666
developer06a01d92022-09-07 16:32:39 +08005667// Get the list of stations associated per AP
5668INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5669{
developerd946fd62022-12-08 18:03:28 +08005670 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005671 char cmd[128];
5672
5673 if(apIndex > 3) //Currently supporting apIndex upto 3
5674 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005675 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005676 return RETURN_ERR;
5677 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5678 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005679 _syscmd(cmd, macArray, buf_size);
5680
5681 return RETURN_OK;
5682}
5683
developer2f995fb2023-02-24 10:40:44 +08005684INT getAddressControlMode(INT apIndex, INT *mode)
5685{
5686 char buf [16] = {0};
5687 char config_file[64] = {0};
5688
5689 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5690 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5691
5692 *mode = -1;
5693 // 0 use deny file, 1 use accept file
5694 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5695 *mode = (INT)strtol(buf, NULL, 10);
5696
5697 return RETURN_OK;
5698}
5699
developer06a01d92022-09-07 16:32:39 +08005700// adds the mac address to the filter list
5701//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5702INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5703{
5704 char cmd[MAX_CMD_SIZE]={'\0'};
5705 char buf[MAX_BUF_SIZE]={'\0'};
5706
developer2f995fb2023-02-24 10:40:44 +08005707 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005708 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005709
developer06a01d92022-09-07 16:32:39 +08005710 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5711 if(_syscmd(cmd,buf,sizeof(buf)))
5712 return RETURN_ERR;
5713
5714 return RETURN_OK;
5715}
5716
developer2f995fb2023-02-24 10:40:44 +08005717INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5718{
5719 char cmd[MAX_CMD_SIZE]={'\0'};
5720 char buf[MAX_BUF_SIZE]={'\0'};
5721
5722 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5723 return RETURN_ERR;
5724
5725 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5726 if(_syscmd(cmd,buf,sizeof(buf)))
5727 return RETURN_ERR;
5728
5729 return RETURN_OK;
5730}
5731
developer06a01d92022-09-07 16:32:39 +08005732// deletes the mac address from the filter list
5733//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5734INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5735{
5736 char cmd[MAX_CMD_SIZE]={'\0'};
5737 char buf[MAX_BUF_SIZE]={'\0'};
5738
5739#if 0
developerd946fd62022-12-08 18:03:28 +08005740 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005741 if(_syscmd(cmd,buf,sizeof(buf)))
5742 return RETURN_ERR;
5743
5744#endif
developer2f995fb2023-02-24 10:40:44 +08005745 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005746 if(_syscmd(cmd,buf,sizeof(buf)))
5747 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005748 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5749 if(_syscmd(cmd,buf,sizeof(buf)))
5750 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005751
5752 return RETURN_OK;
5753}
5754
5755// outputs the number of devices in the filter list
5756INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5757{
developere6aafda2022-09-13 14:59:28 +08005758 char cmd[MAX_BUF_SIZE]={0};
5759 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005760 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005761
5762 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5763 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005764 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005765
developer2f995fb2023-02-24 10:40:44 +08005766 getAddressControlMode(apIndex, &mode);
5767 if (mode == -1)
5768 return RETURN_OK;
5769
5770 if (mode == 0)
5771 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5772 else if (mode == 1)
5773 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005774 _syscmd(cmd, buf, sizeof(buf));
5775
developer2f995fb2023-02-24 10:40:44 +08005776 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005777
5778 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5779 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005780}
5781
5782INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5783{
5784 char cmd[128]={'\0'};
5785 char buf[128]={'\0'};
5786
5787 if(strcmp(action,"DENY")==0)
5788 {
5789 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5790 system(buf);
5791 return RETURN_OK;
5792 }
5793
5794 if(strcmp(action,"ALLOW")==0)
5795 {
5796 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5797 system(buf);
5798 return RETURN_OK;
5799 }
5800
5801 return RETURN_ERR;
5802
5803}
5804
5805// enable kick for devices on acl black list
5806INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5807{
5808 char aclArray[512] = {0}, *acl = NULL;
5809 char assocArray[512] = {0}, *asso = NULL;
5810
developere6aafda2022-09-13 14:59:28 +08005811 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005812 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5813
5814 // if there are no devices connected there is nothing to do
5815 if (strlen(assocArray) < 17)
5816 return RETURN_OK;
5817
5818 if (enable == TRUE)
5819 {
5820 //kick off the MAC which is in ACL array (deny list)
5821 acl = strtok(aclArray, "\r\n");
5822 while (acl != NULL) {
5823 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5824 wifi_kickApAssociatedDevice(apIndex, acl);
5825
5826 acl = strtok(NULL, "\r\n");
5827 }
developere6aafda2022-09-13 14:59:28 +08005828 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005829 }
5830 else
5831 {
developere6aafda2022-09-13 14:59:28 +08005832 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005833 }
5834
5835#if 0
5836 //TODO: need to revisit below implementation
5837 char aclArray[512]={0}, *acl=NULL;
5838 char assocArray[512]={0}, *asso=NULL;
5839 char buf[256]={'\0'};
5840 char action[10]={'\0'};
5841 FILE *fr=NULL;
5842 char interface[10]={'\0'};
5843 char config_file[MAX_BUF_SIZE] = {0};
5844
5845 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5846 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5847 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5848 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5849
5850 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5851 system(buf);
5852 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5853 system(buf);
5854 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5855 system(buf);
5856 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5857 system(buf);
5858 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5859 system(buf);
5860
5861 if ( enable == TRUE )
5862 {
5863 int device_count=0;
5864 strcpy(action,"DENY");
5865 //kick off the MAC which is in ACL array (deny list)
5866 acl = strtok (aclArray,",");
5867 while (acl != NULL) {
5868 if(strlen(acl)>=17)
5869 {
5870 apply_rules(apIndex, acl,action,interface);
5871 device_count++;
5872 //Register mac to be blocked ,in syscfg.db persistent storage
5873 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5874 system(buf);
5875 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5876 system(buf);
5877 system("syscfg commit");
5878
5879 wifi_kickApAssociatedDevice(apIndex, acl);
5880 }
5881 acl = strtok (NULL, ",");
5882 }
5883 }
5884 else
5885 {
5886 int device_count=0;
5887 char cmdmac[20]={'\0'};
5888 strcpy(action,"ALLOW");
5889 //kick off the MAC which is not in ACL array (allow list)
5890 acl = strtok (aclArray,",");
5891 while (acl != NULL) {
5892 if(strlen(acl)>=17)
5893 {
5894 apply_rules(apIndex, acl,action,interface);
5895 device_count++;
5896 //Register mac to be Allowed ,in syscfg.db persistent storage
5897 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5898 system(buf);
5899 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5900 system(buf);
5901 sprintf(cmdmac,"%s",acl);
5902 }
5903 acl = strtok (NULL, ",");
5904 }
5905 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5906 system(buf);
5907
5908 //Disconnect the mac which is not in ACL
5909 asso = strtok (assocArray,",");
5910 while (asso != NULL) {
5911 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5912 wifi_kickApAssociatedDevice(apIndex, asso);
5913 asso = strtok (NULL, ",");
5914 }
5915 }
5916#endif
5917 return RETURN_OK;
5918}
5919
5920INT wifi_setPreferPrivateConnection(BOOL enable)
5921{
developer06a01d92022-09-07 16:32:39 +08005922 return RETURN_OK;
5923}
5924
5925// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5926INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5927{
developerd946fd62022-12-08 18:03:28 +08005928 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005929 int items = 1;
5930 struct params list[2];
5931 char buf[MAX_BUF_SIZE] = {0};
5932 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005933 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005934
5935 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005936
developer10adcc12022-09-13 14:39:17 +08005937 if (filterMode == 0) {
5938 sprintf(buf, "%d", 0);
5939 list[0].value = buf;
5940
developer2f995fb2023-02-24 10:40:44 +08005941 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08005942 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005943 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005944 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
5945 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005946 memset(cmd,0,sizeof(cmd));
5947 // Delete deny_mac_file in hostapd configuration
5948 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08005949 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005950 }
5951 else if (filterMode == 1) {
5952 sprintf(buf, "%d", filterMode);
5953 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005954 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5955 list[1].name = "accept_mac_file";
5956 list[1].value = acl_file;
5957 items = 2;
developer10adcc12022-09-13 14:39:17 +08005958 } else if (filterMode == 2) {
5959 //TODO: deny_mac_file
5960 sprintf(buf, "%d", 0);
5961 list[0].value = buf;
5962 list[1].name = "deny_mac_file";
5963 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5964 list[1].value = deny_file;
5965 items = 2;
5966 } else {
5967 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005968 }
developer10adcc12022-09-13 14:39:17 +08005969
developer06a01d92022-09-07 16:32:39 +08005970 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5971 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08005972 if (multiple_set == FALSE) {
5973 wifi_setApEnable(apIndex, FALSE);
5974 wifi_setApEnable(apIndex, TRUE);
5975 }
developer06a01d92022-09-07 16:32:39 +08005976
5977 return RETURN_OK;
5978
5979#if 0
5980 if(apIndex==0 || apIndex==1)
5981 {
5982 //set the filtermode
5983 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5984 system(buf);
5985 system("syscfg commit");
5986
5987 if(filterMode==0)
5988 {
5989 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5990 system(buf);
5991 return RETURN_OK;
5992 }
5993 }
5994 return RETURN_OK;
5995#endif
5996}
5997
5998// 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.
5999INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6000{
6001 return RETURN_ERR;
6002}
6003
6004// gets the vlan ID for this ap from an internal enviornment variable
6005INT wifi_getApVlanID(INT apIndex, INT *output_int)
6006{
developer30423732022-12-01 16:17:49 +08006007 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006008 {
6009 *output_int=100;
6010 return RETURN_OK;
6011 }
6012
6013 return RETURN_ERR;
6014}
6015
6016// sets the vlan ID for this ap to an internal enviornment variable
6017INT wifi_setApVlanID(INT apIndex, INT vlanId)
6018{
6019 //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)
6020 return RETURN_ERR;
6021}
6022
6023// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6024INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6025{
6026 snprintf(bridgeName, 32, "brlan0");
6027 snprintf(IP, 32, "10.0.0.1");
6028 snprintf(subnet, 32, "255.255.255.0");
6029
6030 return RETURN_OK;
6031}
6032
6033//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6034INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6035{
6036 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6037 return RETURN_ERR;
6038}
6039
6040// reset the vlan configuration for this ap
6041INT wifi_resetApVlanCfg(INT apIndex)
6042{
developerf5fef612022-09-20 19:38:26 +08006043 char original_config_file[64] = {0};
6044 char current_config_file[64] = {0};
6045 char buf[64] = {0};
6046 char cmd[64] = {0};
6047 char vlan_file[64] = {0};
6048 char vlan_tagged_interface[16] = {0};
6049 char vlan_bridge[16] = {0};
6050 char vlan_naming[16] = {0};
6051 struct params list[4] = {0};
6052 wifi_band band;
6053
6054 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6055
6056 band = wifi_index_to_band(apIndex);
6057 if (band == band_2_4)
6058 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006059 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006060 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006061 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006062 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6063
6064 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6065
6066 if (strlen(vlan_file) == 0)
6067 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006068
developerf5fef612022-09-20 19:38:26 +08006069 // The file should exist or this vap would not work.
6070 if (access(vlan_file, F_OK) != 0) {
6071 sprintf(cmd, "touch %s", vlan_file);
6072 _syscmd(cmd, buf, sizeof(buf));
6073 }
6074 list[0].name = "vlan_file";
6075 list[0].value = vlan_file;
6076
6077 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6078 list[1].name = "vlan_tagged_interface";
6079 list[1].value = vlan_tagged_interface;
6080
6081 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6082 list[2].name = "vlan_bridge";
6083 list[2].value = vlan_bridge;
6084
6085 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6086 list[3].name = "vlan_naming";
6087 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006088
developerf5fef612022-09-20 19:38:26 +08006089 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6090 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006091 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006092 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006093
developerf5fef612022-09-20 19:38:26 +08006094 // restart this ap
6095 wifi_setApEnable(apIndex, FALSE);
6096 wifi_setApEnable(apIndex, TRUE);
6097
6098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6099
6100 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006101}
6102
6103// 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.
6104INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6105{
6106 return RETURN_ERR;
6107}
6108
6109// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6110INT wifi_startHostApd()
6111{
6112 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6113 system("systemctl start hostapd.service");
6114 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6115 return RETURN_OK;
6116 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6117}
6118
6119// stops hostapd
6120INT wifi_stopHostApd()
6121{
6122 char cmd[128] = {0};
6123 char buf[128] = {0};
6124
6125 sprintf(cmd,"systemctl stop hostapd");
6126 _syscmd(cmd, buf, sizeof(buf));
6127
6128 return RETURN_OK;
6129}
6130
6131// restart hostapd dummy function
6132INT wifi_restartHostApd()
6133{
6134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6135 system("systemctl restart hostapd-global");
6136 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6137
6138 return RETURN_OK;
6139}
6140
6141static int align_hostapd_config(int index)
6142{
6143 ULONG lval;
6144 wifi_getRadioChannel(index%2, &lval);
6145 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006146 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006147}
6148
6149// sets the AP enable status variable for the specified ap.
6150INT wifi_setApEnable(INT apIndex, BOOL enable)
6151{
developerd946fd62022-12-08 18:03:28 +08006152 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006153 char config_file[MAX_BUF_SIZE] = {0};
6154 char cmd[MAX_CMD_SIZE] = {0};
6155 char buf[MAX_BUF_SIZE] = {0};
6156 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006157 int max_radio_num = 0;
6158 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006159
6160 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006161
6162 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006163 if (enable == status)
6164 return RETURN_OK;
6165
developerac6f1142022-12-20 19:26:35 +08006166 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006167 return RETURN_ERR;
6168
developer06a01d92022-09-07 16:32:39 +08006169 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006170 int radioIndex = apIndex % max_radio_num;
6171 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006172 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6173 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006174 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006175 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006176 if (!(apIndex/max_radio_num)) {
6177 sprintf(cmd, "iw %s del", interface_name);
6178 _syscmd(cmd, buf, sizeof(buf));
6179 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6180 _syscmd(cmd, buf, sizeof(buf));
6181 }
developer033b37b2022-10-18 11:27:46 +08006182 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006183 _syscmd(cmd, buf, sizeof(buf));
6184 }
6185 else {
developerd946fd62022-12-08 18:03:28 +08006186 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006187 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006188 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006189 _syscmd(cmd, buf, sizeof(buf));
6190 }
developera77d84b2023-02-22 16:10:50 +08006191
developer431128d2022-12-16 15:30:41 +08006192 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006193 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006194 _syscmd(cmd, buf, sizeof(buf));
6195 //Wait for wifi up/down to apply
6196 return RETURN_OK;
6197}
6198
6199// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6200INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6201{
developerd946fd62022-12-08 18:03:28 +08006202 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006203 char cmd[MAX_CMD_SIZE] = {'\0'};
6204 char buf[MAX_BUF_SIZE] = {'\0'};
6205
6206 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6207 return RETURN_ERR;
6208
6209 *output_bool = 0;
6210
6211 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6212 {
developerac6f1142022-12-20 19:26:35 +08006213 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006214 *output_bool = FALSE;
6215 return RETURN_OK;
6216 }
6217 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006218 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6219 }
6220
6221 return RETURN_OK;
6222}
6223
6224// Outputs the AP "Enabled" "Disabled" status from driver
6225INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6226{
6227 char cmd[128] = {0};
6228 char buf[128] = {0};
6229 BOOL output_bool;
6230
6231 if ( NULL == output_string)
6232 return RETURN_ERR;
6233 wifi_getApEnable(apIndex,&output_bool);
6234
6235 if(output_bool == 1)
6236 snprintf(output_string, 32, "Up");
6237 else
6238 snprintf(output_string, 32, "Disable");
6239
6240 return RETURN_OK;
6241}
6242
6243//Indicates whether or not beacons include the SSID name.
6244// outputs a 1 if SSID on the AP is enabled, else outputs 0
6245INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6246{
6247 //get the running status
6248 char config_file[MAX_BUF_SIZE] = {0};
6249 char buf[16] = {0};
6250
6251 if (!output)
6252 return RETURN_ERR;
6253
6254 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6255 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006256 // default is enable
6257 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6258 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006259
6260 return RETURN_OK;
6261}
6262
6263// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6264INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6265{
6266 //store the config, apply instantly
6267 char config_file[MAX_BUF_SIZE] = {0};
6268 struct params list;
6269
6270 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6271 list.name = "ignore_broadcast_ssid";
6272 list.value = enable?"0":"1";
6273
6274 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6275 wifi_hostapdWrite(config_file, &list, 1);
6276 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6277 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006278 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006279 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6280
6281 return RETURN_OK;
6282}
6283
6284//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6285INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6286{
6287 //get the running status
6288 if(!output_uint)
6289 return RETURN_ERR;
6290 *output_uint=16;
6291 return RETURN_OK;
6292}
6293
6294INT wifi_setApRetryLimit(INT apIndex, UINT number)
6295{
6296 //apply instantly
6297 return RETURN_ERR;
6298}
6299
6300//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6301INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6302{
6303 if(!output)
6304 return RETURN_ERR;
6305 *output=TRUE;
6306 return RETURN_OK;
6307}
6308
6309//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6310INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6311{
6312 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006313 char cmd[128] = {0};
6314 char buf[128] = {0};
6315 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006316 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006317
developer0b246d12022-09-30 15:24:20 +08006318 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006319
developer0b246d12022-09-30 15:24:20 +08006320 wifi_getMaxRadioNumber(&max_radio_num);
6321 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006322 phyId = radio_index_to_phy(radioIndex);
6323 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006324 _syscmd(cmd,buf, sizeof(buf));
6325
6326 if (strlen(buf) > 0)
6327 *output = true;
6328
6329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006330
developer06a01d92022-09-07 16:32:39 +08006331 return RETURN_OK;
6332}
6333
6334//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6335INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6336{
6337 //get the running status from driver
6338 if(!output)
6339 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006340
6341 char config_file[MAX_BUF_SIZE] = {0};
6342 char buf[16] = {0};
6343
6344 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6345 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006346 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006347 *output = TRUE;
6348 else
6349 *output = FALSE;
6350
developer06a01d92022-09-07 16:32:39 +08006351 return RETURN_OK;
6352}
6353
6354// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6355INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6356{
6357 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006358 char config_file[MAX_BUF_SIZE] = {0};
6359 struct params list;
6360
6361 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6362 list.name = "wmm_enabled";
6363 list.value = enable?"1":"0";
6364
6365 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6366 wifi_hostapdWrite(config_file, &list, 1);
6367 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6368 wifi_reloadAp(apIndex);
6369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6370
6371 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006372}
6373
6374//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.
6375INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6376{
6377 //get the running status from driver
6378 if(!output)
6379 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006380
6381 char config_file[128] = {0};
6382 char buf[16] = {0};
6383
6384 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6385 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6386 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6387 *output = TRUE;
6388 else
6389 *output = FALSE;
6390
developer06a01d92022-09-07 16:32:39 +08006391 return RETURN_OK;
6392}
6393
6394// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6395INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6396{
6397 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006398 char config_file[MAX_BUF_SIZE] = {0};
6399 struct params list;
6400
6401 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6402 list.name = "uapsd_advertisement_enabled";
6403 list.value = enable?"1":"0";
6404
6405 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6406 wifi_hostapdWrite(config_file, &list, 1);
6407 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6408 wifi_reloadAp(apIndex);
6409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6410
6411 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006412}
6413
developer6daeb3f2022-09-30 13:36:39 +08006414// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006415INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6416{
developerd946fd62022-12-08 18:03:28 +08006417 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006418 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6419 char cmd[128] = {0};
6420 char buf[128] = {0};
6421 char ack_filepath[128] = {0};
6422 uint16_t bitmap = 0;
6423 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6424 FILE *f = NULL;
6425
6426 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6427
6428 // Get current setting
6429 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6430 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6431 _syscmd(cmd, buf, sizeof(buf));
6432 if (strlen(buf) > 0)
6433 bitmap = strtoul(buf, NULL, 10);
6434
6435 bitmap = strtoul(buf, NULL, 10);
6436
6437 if (ackPolicy == TRUE) { // True, unset this class
6438 bitmap &= ~class_map[class];
6439 } else { // False, set this class
6440 bitmap |= class_map[class];
6441 }
6442
6443 f = fopen(ack_filepath, "w");
6444 if (f == NULL) {
6445 fprintf(stderr, "%s: fopen failed\n", __func__);
6446 return RETURN_ERR;
6447 }
6448 fprintf(f, "%hu", bitmap);
6449 fclose(f);
6450
developerac6f1142022-12-20 19:26:35 +08006451 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006452 return RETURN_ERR;
6453 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006454 _syscmd(cmd, buf, sizeof(buf));
6455
6456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6457 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006458}
6459
6460//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.
6461INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6462{
6463 //get the running status from driver
6464 if(!output_uint)
6465 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006466
6467 char output[16]={'\0'};
6468 char config_file[MAX_BUF_SIZE] = {0};
6469
6470 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6471 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6472 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6473 else {
6474 int device_num = atoi(output);
6475 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6476 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6477 return RETURN_ERR;
6478 }
6479 else {
6480 *output_uint = device_num;
6481 }
6482 }
6483
developer06a01d92022-09-07 16:32:39 +08006484 return RETURN_OK;
6485}
6486
6487INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6488{
6489 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006490 char str[MAX_BUF_SIZE]={'\0'};
6491 char cmd[MAX_CMD_SIZE]={'\0'};
6492 struct params params;
6493 char config_file[MAX_BUF_SIZE] = {0};
6494
6495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006496 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006497 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006498 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006499 }
6500 sprintf(str, "%d", number);
6501 params.name = "max_num_sta";
6502 params.value = str;
6503
6504 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6505 int ret = wifi_hostapdWrite(config_file, &params, 1);
6506 if (ret) {
6507 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6508 ,__func__, ret);
6509 }
6510
6511 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6512 if (ret) {
6513 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6514 ,__func__, ret);
6515 }
6516 wifi_reloadAp(apIndex);
6517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6518
6519 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006520}
6521
6522//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.
6523INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6524{
6525 //get the current threshold
6526 if(!output_uint)
6527 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006528 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6529 if (*output_uint == 0)
6530 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006531 return RETURN_OK;
6532}
6533
6534INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6535{
6536 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006537 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6538 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006539 return RETURN_ERR;
6540}
6541
6542//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.
6543INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6544{
6545 if(!output_uint)
6546 return RETURN_ERR;
6547 *output_uint = 3;
6548 return RETURN_OK;
6549}
6550
6551//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6552INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6553{
6554 if(!output_uint)
6555 return RETURN_ERR;
6556 *output_uint = 3;
6557 return RETURN_OK;
6558}
6559
6560//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.
6561INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6562{
6563 if(!output_in_seconds)
6564 return RETURN_ERR;
6565 *output_in_seconds = 0;
6566 return RETURN_OK;
6567}
6568
6569//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
6570INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6571{
6572 if(!output || apIndex>=MAX_APS)
6573 return RETURN_ERR;
6574 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006575 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006576 return RETURN_OK;
6577}
6578
6579//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6580INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6581{
developer587c1b62022-09-27 15:58:59 +08006582 char config_file[128] = {0};
6583 char wpa[16] = {0};
6584 char key_mgmt[64] = {0};
6585 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006586 if (!output)
6587 return RETURN_ERR;
6588
6589 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006590 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006591
developer587c1b62022-09-27 15:58:59 +08006592 strcpy(output, "None");//Copying "None" to output string for default case
6593 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006594 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006595 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006596 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006597 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006598 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006599 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006600 snprintf(output, 32, "WPA-WPA2-Personal");
6601
developer72ec5572023-01-05 16:27:13 +08006602 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6603 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006604 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006605 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006606 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006607 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006608 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006609 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006610 snprintf(output, 32, "WPA-WPA2-Enterprise");
6611 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006612 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006613 snprintf(output, 32, "WPA3-Personal");
6614 else
developer4a359672022-10-13 15:30:46 +08006615 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006616 }
developer06a01d92022-09-07 16:32:39 +08006617
6618 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6619 return RETURN_OK;
6620#if 0
6621 //TODO: need to revisit below implementation
6622 char securityType[32], authMode[32];
6623 int enterpriseMode=0;
6624
6625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6626 if(!output)
6627 return RETURN_ERR;
6628
6629 wifi_getApBeaconType(apIndex, securityType);
6630 strcpy(output,"None");//By default, copying "None" to output string
6631 if (strncmp(securityType,"None", strlen("None")) == 0)
6632 return RETURN_OK;
6633
6634 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6635 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6636
6637 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6638 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6639 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6640 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6641 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6642 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6643 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6644
6645 return RETURN_OK;
6646#endif
6647}
6648
6649INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6650{
6651 char securityType[32];
6652 char authMode[32];
6653
6654 //store settings and wait for wifi up to apply
6655 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6656 if(!encMode)
6657 return RETURN_ERR;
6658
developer06a01d92022-09-07 16:32:39 +08006659 if (strcmp(encMode, "None")==0)
6660 {
6661 strcpy(securityType,"None");
6662 strcpy(authMode,"None");
6663 }
6664 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6665 {
6666 strcpy(securityType,"WPAand11i");
6667 strcpy(authMode,"PSKAuthentication");
6668 }
6669 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6670 {
6671 strcpy(securityType,"WPAand11i");
6672 strcpy(authMode,"EAPAuthentication");
6673 }
6674 else if (strcmp(encMode, "WPA-Personal")==0)
6675 {
6676 strcpy(securityType,"WPA");
6677 strcpy(authMode,"PSKAuthentication");
6678 }
6679 else if (strcmp(encMode, "WPA-Enterprise")==0)
6680 {
6681 strcpy(securityType,"WPA");
6682 strcpy(authMode,"EAPAuthentication");
6683 }
6684 else if (strcmp(encMode, "WPA2-Personal")==0)
6685 {
6686 strcpy(securityType,"11i");
6687 strcpy(authMode,"PSKAuthentication");
6688 }
6689 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6690 {
6691 strcpy(securityType,"11i");
6692 strcpy(authMode,"EAPAuthentication");
6693 }
developer587c1b62022-09-27 15:58:59 +08006694 else if (strcmp(encMode, "WPA3-Personal") == 0)
6695 {
6696 strcpy(securityType,"11i");
6697 strcpy(authMode,"SAEAuthentication");
6698 }
developer4a359672022-10-13 15:30:46 +08006699 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006700 {
6701 strcpy(securityType, "11i");
6702 strcpy(authMode, "PSK-SAEAuthentication");
6703 }
developer587c1b62022-09-27 15:58:59 +08006704 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6705 {
6706 strcpy(securityType,"11i");
6707 strcpy(authMode,"EAP_192-bit_Authentication");
6708 }
developer5c9fee82023-01-13 14:44:16 +08006709 else if (strcmp(encMode, "OWE") == 0)
6710 {
6711 strcpy(securityType,"11i");
6712 strcpy(authMode,"Enhanced_Open");
6713 }
developer06a01d92022-09-07 16:32:39 +08006714 else
6715 {
6716 strcpy(securityType,"None");
6717 strcpy(authMode,"None");
6718 }
6719 wifi_setApBeaconType(apIndex, securityType);
6720 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6721 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6722
6723 return RETURN_OK;
6724}
6725
6726
developer4b102122023-02-15 10:53:03 +08006727// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006728//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006729INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6730{
developer30423732022-12-01 16:17:49 +08006731 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006732 char config_file[MAX_BUF_SIZE] = {0};
6733
6734 if(output_string==NULL)
6735 return RETURN_ERR;
6736
6737 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6738 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6739
6740 if(strcmp(buf,"0")==0)
6741 {
6742 printf("wpa_mode is %s ......... \n",buf);
6743 return RETURN_ERR;
6744 }
6745
6746 wifi_dbg_printf("\nFunc=%s\n",__func__);
6747 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006748 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006749 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6750
6751 return RETURN_OK;
6752}
6753
developer4b102122023-02-15 10:53:03 +08006754// Set PreSharedKey associated with a Access Point.
6755// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006756INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6757{
6758 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6759 struct params params={'\0'};
6760 int ret;
6761 char config_file[MAX_BUF_SIZE] = {0};
6762
6763 if(NULL == preSharedKey)
6764 return RETURN_ERR;
6765
developer4b102122023-02-15 10:53:03 +08006766 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006767
developer4b102122023-02-15 10:53:03 +08006768 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006769 {
developer4b102122023-02-15 10:53:03 +08006770 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006771 return RETURN_ERR;
6772 }
6773 params.value = preSharedKey;
6774 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6775 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006776 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006777 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006778 wifi_reloadAp(apIndex);
6779 }
developer06a01d92022-09-07 16:32:39 +08006780 return ret;
6781 //TODO: call hostapd_cli for dynamic_config_control
6782}
6783
6784//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6785// outputs the passphrase, maximum 63 characters
6786INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6787{
6788 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6789
6790 wifi_dbg_printf("\nFunc=%s\n",__func__);
6791 if (NULL == output_string)
6792 return RETURN_ERR;
6793
6794 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6795 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6796 if(strcmp(buf,"0")==0)
6797 {
6798 printf("wpa_mode is %s ......... \n",buf);
6799 return RETURN_ERR;
6800 }
6801
6802 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6803 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6804
6805 return RETURN_OK;
6806}
6807
6808// sets the passphrase enviornment variable, max 63 characters
6809INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6810{
6811 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6812 struct params params={'\0'};
6813 char config_file[MAX_BUF_SIZE] = {0};
6814 int ret;
6815
6816 if(NULL == passPhrase)
6817 return RETURN_ERR;
6818
6819 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6820 {
6821 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6822 return RETURN_ERR;
6823 }
6824 params.name = "wpa_passphrase";
6825 params.value = passPhrase;
6826 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6827 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006828 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006829 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006830 wifi_reloadAp(apIndex);
6831 }
developer06a01d92022-09-07 16:32:39 +08006832
6833 return ret;
6834}
6835
6836//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.
6837INT wifi_setApSecurityReset(INT apIndex)
6838{
developer8d583982022-09-20 11:28:22 +08006839 char original_config_file[64] = {0};
6840 char current_config_file[64] = {0};
6841 char buf[64] = {0};
6842 char cmd[64] = {0};
6843 char wpa[4] = {0};
6844 char wpa_psk[64] = {0};
6845 char wpa_passphrase[64] = {0};
6846 char wpa_psk_file[128] = {0};
6847 char wpa_key_mgmt[64] = {0};
6848 char wpa_pairwise[32] = {0};
6849 wifi_band band;
6850 struct params list[6];
6851
6852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6853
6854 band = wifi_index_to_band(apIndex);
6855 if (band == band_2_4)
6856 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006857 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006858 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006859 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006860 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6861 else
6862 return RETURN_ERR;
6863
6864 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6865 list[0].name = "wpa";
6866 list[0].value = wpa;
6867
6868 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6869 list[1].name = "wpa_psk";
6870 list[1].value = wpa_psk;
6871
6872 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6873 list[2].name = "wpa_passphrase";
6874 list[2].value = wpa_passphrase;
6875
6876 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6877
6878 if (strlen(wpa_psk_file) == 0)
6879 strcpy(wpa_psk_file, PSK_FILE);
6880
6881 if (access(wpa_psk_file, F_OK) != 0) {
6882 sprintf(cmd, "touch %s", wpa_psk_file);
6883 _syscmd(cmd, buf, sizeof(buf));
6884 }
6885 list[3].name = "wpa_psk_file";
6886 list[3].value = wpa_psk_file;
6887
6888 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6889 list[4].name = "wpa_key_mgmt";
6890 list[4].value = wpa_key_mgmt;
6891
6892 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6893 list[5].name = "wpa_pairwise";
6894 list[5].value = wpa_pairwise;
6895
6896 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6897 wifi_hostapdWrite(current_config_file, list, 6);
6898
6899 wifi_setApEnable(apIndex, FALSE);
6900 wifi_setApEnable(apIndex, TRUE);
6901
6902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6903 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006904}
6905
6906//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).
6907INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6908{
developer8f2ddd52022-09-13 15:39:24 +08006909 char config_file[64] = {0};
6910 char buf[64] = {0};
6911 char cmd[256] = {0};
6912
6913 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6914
developer06a01d92022-09-07 16:32:39 +08006915 if(!IP_output || !Port_output || !RadiusSecret_output)
6916 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006917
developer8f2ddd52022-09-13 15:39:24 +08006918 // Read the first matched config
6919 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6920 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6921 _syscmd(cmd, buf, sizeof(buf));
6922 strncpy(IP_output, buf, 64);
6923
6924 memset(buf, 0, sizeof(buf));
6925 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6926 _syscmd(cmd, buf, sizeof(buf));
6927 *Port_output = atoi(buf);
6928
6929 memset(buf, 0, sizeof(buf));
6930 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6931 _syscmd(cmd, buf, sizeof(buf));
6932 strncpy(RadiusSecret_output, buf, 64);
6933
6934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006935 return RETURN_OK;
6936}
6937
6938INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6939{
developer8f2ddd52022-09-13 15:39:24 +08006940 char config_file[64] = {0};
6941 char port_str[8] = {0};
6942 char cmd[256] = {0};
6943 char buf[128] = {0};
6944
6945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08006946 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
6947 return RETURN_ERR;
6948
6949 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
6950 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006951
6952 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6953
6954 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6955 _syscmd(cmd, buf, sizeof(buf));
6956 memset(cmd, 0, sizeof(cmd));
6957
6958 snprintf(port_str, sizeof(port_str), "%d", port);
6959 if (strlen(buf) == 0)
6960 // Append
6961 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6962 "auth_server_addr=%s\\n"
6963 "auth_server_port=%s\\n"
6964 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6965 else {
6966 // Delete the three lines setting after the "# radius 1" comment
6967 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6968 _syscmd(cmd, buf, sizeof(buf));
6969 memset(cmd, 0, sizeof(cmd));
6970 // Use "# radius 1" comment to find the location to insert the radius setting
6971 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6972 "# radius 1\\n"
6973 "auth_server_addr=%s\\n"
6974 "auth_server_port=%s\\n"
6975 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6976 }
6977 if(_syscmd(cmd, buf, sizeof(buf))) {
6978 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6979 return RETURN_ERR;
6980 }
6981
6982 wifi_reloadAp(apIndex);
6983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6984 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006985}
6986
6987INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6988{
developer8f2ddd52022-09-13 15:39:24 +08006989 char config_file[64] = {0};
6990 char buf[64] = {0};
6991 char cmd[256] = {0};
6992
6993 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6994
developer06a01d92022-09-07 16:32:39 +08006995 if(!IP_output || !Port_output || !RadiusSecret_output)
6996 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006997
6998 // Read the second matched config
6999 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7000 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7001 _syscmd(cmd, buf, sizeof(buf));
7002 strncpy(IP_output, buf, 64);
7003
7004 memset(buf, 0, sizeof(buf));
7005 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7006 _syscmd(cmd, buf, sizeof(buf));
7007 *Port_output = atoi(buf);
7008
7009 memset(buf, 0, sizeof(buf));
7010 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7011 _syscmd(cmd, buf, sizeof(buf));
7012 strncpy(RadiusSecret_output, buf, 64);
7013
7014 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007015 return RETURN_OK;
7016}
7017
7018INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7019{
developer8f2ddd52022-09-13 15:39:24 +08007020 char config_file[64] = {0};
7021 char port_str[8] = {0};
7022 char cmd[256] = {0};
7023 char buf[128] = {0};
7024
7025 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007026 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7027 return RETURN_ERR;
7028
7029 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7030 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007031
7032 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7033
7034 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7035 _syscmd(cmd, buf, sizeof(buf));
7036 memset(cmd, 0, sizeof(cmd));
7037
7038 snprintf(port_str, sizeof(port_str), "%d", port);
7039 if (strlen(buf) == 0)
7040 // Append
7041 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7042 "auth_server_addr=%s\\n"
7043 "auth_server_port=%s\\n"
7044 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7045 else {
7046 // Delete the three lines setting after the "# radius 2" comment
7047 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7048 _syscmd(cmd, buf, sizeof(buf));
7049 memset(cmd, 0, sizeof(cmd));
7050 // Use "# radius 2" comment to find the location to insert the radius setting
7051 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7052 "# radius 2\\n"
7053 "auth_server_addr=%s\\n"
7054 "auth_server_port=%s\\n"
7055 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7056 }
7057 if(_syscmd(cmd, buf, sizeof(buf))) {
7058 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7059 return RETURN_ERR;
7060 }
7061
7062 wifi_reloadAp(apIndex);
7063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7064 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007065}
7066
7067//RadiusSettings
7068INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7069{
7070 if(!output)
7071 return RETURN_ERR;
7072
7073 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7074 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7075 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7076 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7077 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7078 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.
7079 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7080 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7081 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7082 //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.
7083
7084 return RETURN_OK;
7085}
7086
7087INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7088{
7089 //store the paramters, and apply instantly
7090 return RETURN_ERR;
7091}
7092
7093//Device.WiFi.AccessPoint.{i}.WPS.Enable
7094//Enables or disables WPS functionality for this access point.
7095// outputs the WPS enable state of this ap in output_bool
7096INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7097{
developerd946fd62022-12-08 18:03:28 +08007098 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007099 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007100
7101 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007102 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007103 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007104 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007105 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007106 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007107 _syscmd(cmd, buf, sizeof(buf));
7108 if(strstr(buf, "configured"))
7109 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007110
7111 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007112}
developer06a01d92022-09-07 16:32:39 +08007113
7114//Device.WiFi.AccessPoint.{i}.WPS.Enable
7115// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7116INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7117{
7118 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007119 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007120 struct params params;
7121
developer06a01d92022-09-07 16:32:39 +08007122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7123 //store the paramters, and wait for wifi up to apply
7124 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007125 if (enable == TRUE) {
7126 wifi_getApBeaconType(apIndex, buf);
7127 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7128 params.value = "1";
7129 else // If ap set encryption
7130 params.value = "2";
7131 } else {
7132 params.value = "0";
7133 }
developer06a01d92022-09-07 16:32:39 +08007134
7135 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7136 wifi_hostapdWrite(config_file, &params, 1);
7137 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7138 wifi_reloadAp(apIndex);
7139
7140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7141 return RETURN_OK;
7142}
7143
7144//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
7145INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7146{
7147 if(!output)
7148 return RETURN_ERR;
7149 snprintf(output, 128, "PushButton,PIN");
7150 return RETURN_OK;
7151}
7152
7153//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7154//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.
7155// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7156INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7157{
7158 if(!output)
7159 return RETURN_ERR;
7160 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7161
7162 return RETURN_OK;
7163}
7164
7165//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7166// 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
7167INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7168{
7169 //apply instantly. No setting need to be stored.
7170 char methods[MAX_BUF_SIZE], *token, *next_token;
7171 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7172 struct params params;
7173
developer5b398df2022-11-17 20:39:48 +08007174 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007175 return RETURN_ERR;
7176 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7177 //store the paramters, and wait for wifi up to apply
7178
7179 snprintf(methods, sizeof(methods), "%s", methodString);
7180 for(token=methods; *token; token=next_token)
7181 {
7182 strtok_r(token, ",", &next_token);
7183 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7184 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7185 else if(*token=='E')
7186 {
7187 if(!strcmp(methods, "Ethernet"))
7188 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7189 else if(!strcmp(methods, "ExternalNFCToken"))
7190 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7191 else
7192 printf("%s: Unknown WpsConfigMethod\n", __func__);
7193 }
7194 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7195 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7196 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7197 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7198 else if(*token=='P' )
7199 {
7200 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007201 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007202 else if(!strcmp(token, "PIN"))
7203 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7204 else
7205 printf("%s: Unknown WpsConfigMethod\n", __func__);
7206 }
7207 else
7208 printf("%s: Unknown WpsConfigMethod\n", __func__);
7209 }
7210 params.name = "config_methods";
7211 params.value = config_methods;
7212 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7213 wifi_hostapdWrite(config_file, &params, 1);
7214 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7215 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7216
7217 return RETURN_OK;
7218}
7219
7220// outputs the pin value, ulong_pin must be allocated by the caller
7221INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7222{
7223 char buf[MAX_BUF_SIZE] = {0};
7224 char cmd[MAX_CMD_SIZE] = {0};
7225
developer5b398df2022-11-17 20:39:48 +08007226 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007227 return RETURN_ERR;
7228 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7229 _syscmd(cmd, buf, sizeof(buf));
7230 if(strlen(buf) > 0)
7231 *output_ulong=strtoul(buf, NULL, 10);
7232
7233 return RETURN_OK;
7234}
7235
7236// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7237INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7238{
7239 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7240 char ap_pin[16] = {0};
7241 char buf[MAX_BUF_SIZE] = {0};
7242 char config_file[MAX_BUF_SIZE] = {0};
7243 ULONG prev_pin = 0;
7244 struct params params;
7245
developer06a01d92022-09-07 16:32:39 +08007246 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7247 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7248 params.name = "ap_pin";
7249 params.value = ap_pin;
7250 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7251 wifi_hostapdWrite(config_file, &params, 1);
7252 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7253 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7254
7255 return RETURN_OK;
7256}
7257
7258// Output string is either Not configured or Configured, max 32 characters
7259INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7260{
developerd946fd62022-12-08 18:03:28 +08007261 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007262 char cmd[MAX_CMD_SIZE];
7263 char buf[MAX_BUF_SIZE]={0};
7264
developer5b398df2022-11-17 20:39:48 +08007265 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007266 return RETURN_ERR;
7267 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7268 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007269 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007270 return RETURN_ERR;
7271 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007272 _syscmd(cmd, buf, sizeof(buf));
7273
developer348e3d92022-09-13 14:48:41 +08007274 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007275 snprintf(output_string, 32, "Configured");
7276 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7277
7278 return RETURN_OK;
7279}
7280
7281// sets the WPS pin for this AP
7282INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7283{
developerd946fd62022-12-08 18:03:28 +08007284 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007285 char cmd[MAX_CMD_SIZE];
7286 char buf[MAX_BUF_SIZE]={0};
7287 BOOL enable;
7288
developer06a01d92022-09-07 16:32:39 +08007289 wifi_getApEnable(apIndex, &enable);
7290 if (!enable)
7291 return RETURN_ERR;
7292 wifi_getApWpsEnable(apIndex, &enable);
7293 if (!enable)
7294 return RETURN_ERR;
7295
developerac6f1142022-12-20 19:26:35 +08007296 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007297 return RETURN_ERR;
7298 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007299 _syscmd(cmd, buf, sizeof(buf));
7300 if((strstr(buf, "OK"))!=NULL)
7301 return RETURN_OK;
7302
7303 return RETURN_ERR;
7304}
7305
7306// This function is called when the WPS push button has been pressed for this AP
7307INT wifi_setApWpsButtonPush(INT apIndex)
7308{
7309 char cmd[MAX_CMD_SIZE];
7310 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007311 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007312 BOOL enable=FALSE;
7313
developer06a01d92022-09-07 16:32:39 +08007314 wifi_getApEnable(apIndex, &enable);
7315 if (!enable)
7316 return RETURN_ERR;
7317
7318 wifi_getApWpsEnable(apIndex, &enable);
7319 if (!enable)
7320 return RETURN_ERR;
7321
developerac6f1142022-12-20 19:26:35 +08007322 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007323 return RETURN_ERR;
7324
developer900e2b72023-05-23 10:23:48 +08007325 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 +08007326 _syscmd(cmd, buf, sizeof(buf));
7327
7328 if((strstr(buf, "OK"))!=NULL)
7329 return RETURN_OK;
7330 return RETURN_ERR;
7331}
7332
7333// cancels WPS mode for this AP
7334INT wifi_cancelApWPS(INT apIndex)
7335{
developerd946fd62022-12-08 18:03:28 +08007336 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007337 char cmd[MAX_CMD_SIZE];
7338 char buf[MAX_BUF_SIZE]={0};
7339
developerac6f1142022-12-20 19:26:35 +08007340 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007341 return RETURN_ERR;
7342 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007343 _syscmd(cmd,buf, sizeof(buf));
7344
7345 if((strstr(buf, "OK"))!=NULL)
7346 return RETURN_OK;
7347 return RETURN_ERR;
7348}
7349
7350//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7351//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7352INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7353{
developerd946fd62022-12-08 18:03:28 +08007354 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007355 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007356 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007357 char cmd[256] = {0}, buf[2048] = {0};
7358 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007359 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007360 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007361 wifi_associated_dev_t *dev=NULL;
7362
7363 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7364 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007365 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007366 return RETURN_ERR;
7367 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007368 _syscmd(cmd,buf,sizeof(buf));
7369 *output_array_size = atoi(buf);
7370
7371 if (*output_array_size <= 0)
7372 return RETURN_OK;
7373
7374 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7375 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007376 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007377 _syscmd(cmd,buf,sizeof(buf));
7378 f = fopen("/tmp/connected_devices.txt", "r");
7379 if (f==NULL)
7380 {
7381 *output_array_size=0;
7382 return RETURN_ERR;
7383 }
developer30423732022-12-01 16:17:49 +08007384 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007385 {
7386 param = strtok(line,"=");
7387 value = strtok(NULL,"=");
7388
7389 if( strcmp("flags",param) == 0 )
7390 {
7391 value[strlen(value)-1]='\0';
7392 if(strstr (value,"AUTHORIZED") != NULL )
7393 {
7394 dev[auth_temp].cli_AuthenticationState = 1;
7395 dev[auth_temp].cli_Active = 1;
7396 auth_temp++;
7397 read_flag=1;
7398 }
7399 }
7400 if(read_flag==1)
7401 {
7402 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7403 {
7404 value[strlen(value)-1]='\0';
7405 sscanf(value, "%x:%x:%x:%x:%x:%x",
7406 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7407 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7408 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7409 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7410 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7411 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7412 mac_temp++;
7413 read_flag=0;
7414 }
7415 }
7416 }
7417 *output_array_size = auth_temp;
7418 auth_temp=0;
7419 mac_temp=0;
7420 free(line);
7421 fclose(f);
7422 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7423 return RETURN_OK;
7424}
7425
7426#define MACADDRESS_SIZE 6
7427
7428INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7429{
7430 FILE *fp = NULL;
7431 char str[MAX_BUF_SIZE] = {0};
7432 int wificlientindex = 0 ;
7433 int count = 0;
7434 int signalstrength = 0;
7435 int arr[MACADDRESS_SIZE] = {0};
7436 unsigned char mac[MACADDRESS_SIZE] = {0};
7437 UINT wifi_count = 0;
7438 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7439 char pipeCmd[MAX_CMD_SIZE] = {0};
7440
7441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7442 *output_array_size = 0;
7443 *associated_dev_array = NULL;
7444
7445 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7446 fp = popen(pipeCmd, "r");
7447 if (fp == NULL)
7448 {
7449 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7450 return RETURN_ERR;
7451 }
7452
7453 /* Read the output a line at a time - output it. */
7454 fgets(str, sizeof(str)-1, fp);
7455 wifi_count = (unsigned int) atoi ( str );
7456 *output_array_size = wifi_count;
7457 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7458 pclose(fp);
7459
7460 if(wifi_count == 0)
7461 {
7462 return RETURN_OK;
7463 }
7464 else
7465 {
7466 wifi_associated_dev3_t* temp = NULL;
7467 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7468 if(temp == NULL)
7469 {
7470 printf("Error Statement. Insufficient memory \n");
7471 return RETURN_ERR;
7472 }
7473
7474 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7475 system(pipeCmd);
7476 memset(pipeCmd,0,sizeof(pipeCmd));
7477 if(apIndex == 0)
7478 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7479 else if(apIndex == 1)
7480 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7481 system(pipeCmd);
7482
7483 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7484 if(fp == NULL)
7485 {
7486 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007487 free(temp);
developer06a01d92022-09-07 16:32:39 +08007488 return RETURN_ERR;
7489 }
7490 fclose(fp);
7491
developer30423732022-12-01 16:17:49 +08007492 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007493 fp = popen(pipeCmd, "r");
7494 if(fp)
7495 {
7496 for(count =0 ; count < wifi_count; count++)
7497 {
7498 fgets(str, MAX_BUF_SIZE, fp);
7499 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7500 {
7501 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7502 {
7503 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7504
7505 }
7506 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7507 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]);
7508 }
7509 temp[count].cli_AuthenticationState = 1; //TODO
7510 temp[count].cli_Active = 1; //TODO
7511 }
7512 pclose(fp);
7513 }
7514
developer30423732022-12-01 16:17:49 +08007515 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 +08007516 fp = popen(pipeCmd, "r");
7517 if(fp)
7518 {
7519 pclose(fp);
7520 }
7521 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7522 if(fp)
7523 {
7524 for(count =0 ; count < wifi_count ;count++)
7525 {
7526 fgets(str, MAX_BUF_SIZE, fp);
7527 signalstrength = atoi(str);
7528 temp[count].cli_SignalStrength = signalstrength;
7529 temp[count].cli_RSSI = signalstrength;
7530 temp[count].cli_SNR = signalstrength + 95;
7531 }
7532 pclose(fp);
7533 }
7534
7535
7536 if((apIndex == 0) || (apIndex == 4))
7537 {
7538 for(count =0 ; count < wifi_count ;count++)
7539 {
7540 strcpy(temp[count].cli_OperatingStandard,"g");
7541 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7542 }
7543
7544 //BytesSent
developer30423732022-12-01 16:17:49 +08007545 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 +08007546 fp = popen(pipeCmd, "r");
7547 if(fp)
7548 {
7549 pclose(fp);
7550 }
7551 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7552 if(fp)
7553 {
7554 for (count = 0; count < wifi_count; count++)
7555 {
7556 fgets(str, MAX_BUF_SIZE, fp);
7557 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7558 }
7559 pclose(fp);
7560 }
7561
7562 //BytesReceived
developer30423732022-12-01 16:17:49 +08007563 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 +08007564 fp = popen(pipeCmd, "r");
7565 if (fp)
7566 {
7567 pclose(fp);
7568 }
7569 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7570 if (fp)
7571 {
7572 for (count = 0; count < wifi_count; count++)
7573 {
7574 fgets(str, MAX_BUF_SIZE, fp);
7575 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7576 }
7577 pclose(fp);
7578 }
7579
7580 //PacketsSent
developer30423732022-12-01 16:17:49 +08007581 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 +08007582 fp = popen(pipeCmd, "r");
7583 if (fp)
7584 {
7585 pclose(fp);
7586 }
7587
7588 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7589 if (fp)
7590 {
7591 for (count = 0; count < wifi_count; count++)
7592 {
7593 fgets(str, MAX_BUF_SIZE, fp);
7594 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7595 }
7596 pclose(fp);
7597 }
7598
7599 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007600 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 +08007601 fp = popen(pipeCmd, "r");
7602 if (fp)
7603 {
7604 pclose(fp);
7605 }
7606 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7607 if (fp)
7608 {
7609 for (count = 0; count < wifi_count; count++)
7610 {
7611 fgets(str, MAX_BUF_SIZE, fp);
7612 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7613 }
7614 pclose(fp);
7615 }
7616
7617 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007618 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 +08007619 fp = popen(pipeCmd, "r");
7620 if (fp)
7621 {
7622 pclose(fp);
7623 }
7624 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7625 if (fp)
7626 {
7627 for (count = 0; count < wifi_count; count++)
7628 {
7629 fgets(str, MAX_BUF_SIZE, fp);
7630 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7631 }
7632 pclose(fp);
7633 }
7634
7635 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007636 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 +08007637 fp = popen(pipeCmd, "r");
7638 if (fp)
7639 {
7640 pclose(fp);
7641 }
7642 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7643 if (fp)
7644 {
7645 for (count = 0; count < wifi_count; count++)
7646 {
7647 fgets(str, MAX_BUF_SIZE, fp);
7648 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7649 }
7650 pclose(fp);
7651 }
7652
7653 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007654 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 +08007655 fp = popen(pipeCmd, "r");
7656 if (fp)
7657 {
7658 pclose(fp);
7659 }
7660 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7661 if (fp)
7662 {
7663 for (count = 0; count < wifi_count; count++)
7664 {
7665 fgets(str, MAX_BUF_SIZE, fp);
7666 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7667 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7668 }
7669 pclose(fp);
7670 }
7671
7672 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007673 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 +08007674 fp = popen(pipeCmd, "r");
7675 if (fp)
7676 {
7677 pclose(fp);
7678 }
7679 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7680 if (fp)
7681 {
7682 for (count = 0; count < wifi_count; count++)
7683 {
7684 fgets(str, MAX_BUF_SIZE, fp);
7685 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7686 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7687 }
7688 pclose(fp);
7689 }
7690
7691 }
7692 else if ((apIndex == 1) || (apIndex == 5))
7693 {
7694 for (count = 0; count < wifi_count; count++)
7695 {
7696 strcpy(temp[count].cli_OperatingStandard, "a");
7697 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7698 temp[count].cli_BytesSent = 0;
7699 temp[count].cli_BytesReceived = 0;
7700 temp[count].cli_LastDataUplinkRate = 0;
7701 temp[count].cli_LastDataDownlinkRate = 0;
7702 temp[count].cli_PacketsSent = 0;
7703 temp[count].cli_PacketsReceived = 0;
7704 temp[count].cli_ErrorsSent = 0;
7705 }
7706 }
7707
7708 for (count = 0; count < wifi_count; count++)
7709 {
7710 temp[count].cli_Retransmissions = 0;
7711 temp[count].cli_DataFramesSentAck = 0;
7712 temp[count].cli_DataFramesSentNoAck = 0;
7713 temp[count].cli_MinRSSI = 0;
7714 temp[count].cli_MaxRSSI = 0;
7715 strncpy(temp[count].cli_InterferenceSources, "", 64);
7716 memset(temp[count].cli_IPAddress, 0, 64);
7717 temp[count].cli_RetransCount = 0;
7718 temp[count].cli_FailedRetransCount = 0;
7719 temp[count].cli_RetryCount = 0;
7720 temp[count].cli_MultipleRetryCount = 0;
7721 }
7722 *associated_dev_array = temp;
7723 }
7724 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7725 return RETURN_OK;
7726}
7727
7728int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7729{
7730 FILE *fp = NULL;
7731 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7732 char cmd[MAX_CMD_SIZE];
7733 int count = 0;
7734
7735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7736 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7737 fp = popen(cmd,"r");
7738 if(fp == NULL)
7739 {
7740 printf("Failed to run command in Function %s\n",__FUNCTION__);
7741 return 0;
7742 }
7743 if(fgets(path, sizeof(path)-1, fp) != NULL)
7744 {
7745 for(count=0;path[count]!='\n';count++)
7746 status[count]=path[count];
7747 status[count]='\0';
7748 }
7749 strcpy(wifi_status,status);
7750 pclose(fp);
7751 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7752 return RETURN_OK;
7753}
7754
7755/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7756struct hostapd_sta_param {
7757 char key[50];
7758 char value[100];
7759}
7760
7761static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7762 int i = 0;
7763
7764 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7765 if (strncmp(params[i].key,key,50) == 0){
7766 return &params[i].value;
7767 }
7768 i++;
7769 }
7770 return NULL;
7771
7772} */
7773
7774static unsigned int count_occurences(const char *buf, const char *word)
7775{
7776 unsigned int n = 0;
7777 char *ptr = strstr(buf, word);
7778
7779 while (ptr++) {
7780 n++;
7781 ptr = strstr(ptr, word);
7782 }
7783
7784 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7785 return n;
7786}
7787
7788static const char *get_line_from_str_buf(const char *buf, char *line)
7789{
7790 int i;
7791 int n = strlen(buf);
7792
7793 for (i = 0; i < n; i++) {
7794 line[i] = buf[i];
7795 if (buf[i] == '\n') {
7796 line[i] = '\0';
7797 return &buf[i + 1];
7798 }
7799 }
7800
7801 return NULL;
7802}
7803
7804INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7805{
7806 unsigned int assoc_cnt = 0;
7807 char interface_name[50] = {0};
7808 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7809 char cmd[MAX_CMD_SIZE] = {'\0'};
7810 char line[256] = {'\0'};
7811 int i = 0;
7812 int ret = 0;
7813 const char *ptr = NULL;
7814 char *key = NULL;
7815 char *val = NULL;
7816 wifi_associated_dev3_t *temp = NULL;
7817 int rssi;
7818
7819 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7820
7821 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7822 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7823 return RETURN_ERR;
7824 }
7825
7826 // Example filtered output of 'iw dev' command:
7827 // Station 0a:69:72:10:d2:fa (on wifi0)
7828 // signal avg:-67 [-71, -71] dBm
7829 // Station 28:c2:1f:25:5f:99 (on wifi0)
7830 // signal avg:-67 [-71, -70] dBm
7831 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7832 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7833 return RETURN_ERR;
7834 }
7835
7836 ret = _syscmd(cmd, buf, sizeof(buf));
7837 if (ret == RETURN_ERR) {
7838 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7839 return RETURN_ERR;
7840 }
7841
7842 *output_array_size = count_occurences(buf, "Station");
7843 if (*output_array_size == 0) return RETURN_OK;
7844
7845 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7846 if (temp == NULL) {
7847 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7848 return RETURN_ERR;
7849 }
7850 *associated_dev_array = temp;
7851
7852 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7853 ptr = get_line_from_str_buf(buf, line);
7854 i = -1;
7855 while (ptr) {
7856 if (strstr(line, "Station")) {
7857 i++;
7858 key = strtok(line, " ");
7859 val = strtok(NULL, " ");
7860 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7861 &temp[i].cli_MACAddress[0],
7862 &temp[i].cli_MACAddress[1],
7863 &temp[i].cli_MACAddress[2],
7864 &temp[i].cli_MACAddress[3],
7865 &temp[i].cli_MACAddress[4],
7866 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7867 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7868 free(*associated_dev_array);
7869 return RETURN_ERR;
7870 }
7871 }
7872 else if (i < 0) {
7873 ptr = get_line_from_str_buf(ptr, line);
7874 continue; // We didn't detect 'station' entry yet
7875 }
7876 else if (strstr(line, "signal avg")) {
7877 key = strtok(line, ":");
7878 val = strtok(NULL, " ");
7879 if (sscanf(val, "%d", &rssi) <= 0 ) {
7880 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7881 free(*associated_dev_array);
7882 return RETURN_ERR;
7883 }
7884 temp[i].cli_RSSI = rssi;
7885 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7886 }
7887 // Here other fields can be parsed if added to filter of 'iw dev' command
7888
7889 ptr = get_line_from_str_buf(ptr, line);
7890 };
7891
7892 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7893
7894 return RETURN_OK;
7895}
7896
7897#if 0
7898//To-do
7899INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7900{
7901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7902
7903 //Using different approach to get required WiFi Parameters from system available commands
7904#if 0
7905 FILE *f;
7906 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7907 char cmd[256], buf[2048];
7908 char *param , *value, *line=NULL;
7909 size_t len = 0;
7910 ssize_t nread;
7911 wifi_associated_dev3_t *dev=NULL;
7912 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007913 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007914 _syscmd(cmd,buf,sizeof(buf));
7915 *output_array_size = atoi(buf);
7916
7917 if (*output_array_size <= 0)
7918 return RETURN_OK;
7919
7920 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7921 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007922 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007923 _syscmd(cmd,buf,sizeof(buf));
7924 f = fopen("/tmp/connected_devices.txt", "r");
7925 if (f==NULL)
7926 {
7927 *output_array_size=0;
7928 return RETURN_ERR;
7929 }
7930 while ((nread = getline(&line, &len, f)) != -1)
7931 {
7932 param = strtok(line,"=");
7933 value = strtok(NULL,"=");
7934
7935 if( strcmp("flags",param) == 0 )
7936 {
7937 value[strlen(value)-1]='\0';
7938 if(strstr (value,"AUTHORIZED") != NULL )
7939 {
7940 dev[auth_temp].cli_AuthenticationState = 1;
7941 dev[auth_temp].cli_Active = 1;
7942 auth_temp++;
7943 read_flag=1;
7944 }
7945 }
7946 if(read_flag==1)
7947 {
7948 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7949 {
7950 value[strlen(value)-1]='\0';
7951 sscanf(value, "%x:%x:%x:%x:%x:%x",
7952 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7953 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7954 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7955 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7956 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7957 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7958
7959 }
7960 else if( strcmp("rx_packets",param) == 0 )
7961 {
7962 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7963 }
7964
7965 else if( strcmp("tx_packets",param) == 0 )
7966 {
7967 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7968 }
7969
7970 else if( strcmp("rx_bytes",param) == 0 )
7971 {
7972 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7973 }
7974
7975 else if( strcmp("tx_bytes",param) == 0 )
7976 {
7977 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7978 mac_temp++;
7979 read_flag=0;
7980 }
7981 }
7982 }
7983
7984 *output_array_size = auth_temp;
7985 auth_temp=0;
7986 mac_temp=0;
7987 free(line);
7988 fclose(f);
7989#endif
7990 char interface_name[MAX_BUF_SIZE] = {0};
7991 char wifi_status[MAX_BUF_SIZE] = {0};
7992 char hostapdconf[MAX_BUF_SIZE] = {0};
7993
7994 wifi_associated_dev3_t *dev_array = NULL;
7995 ULONG wifi_count = 0;
7996
7997 *associated_dev_array = NULL;
7998 *output_array_size = 0;
7999
8000 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8001 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8002 {
8003 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8004
developerac6f1142022-12-20 19:26:35 +08008005 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008006
8007 if(strlen(interface_name) > 1)
8008 {
8009 wifihal_interfacestatus(wifi_status,interface_name);
8010 if(strcmp(wifi_status,"RUNNING") == 0)
8011 {
8012 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8013
8014 *associated_dev_array = dev_array;
8015 *output_array_size = wifi_count;
8016 }
8017 else
8018 {
8019 *associated_dev_array = NULL;
8020 }
8021 }
8022 }
8023
8024 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8025 return RETURN_OK;
8026}
8027#endif
8028
8029/* getIPAddress function */
8030/**
8031* @description Returning IpAddress of the Matched String
8032*
8033* @param
8034* @str Having MacAddress
8035* @ipaddr Having ipaddr
8036* @return The status of the operation
8037* @retval RETURN_OK if successful
8038* @retval RETURN_ERR if any error is detected
8039*
8040*/
8041
8042INT getIPAddress(char *str,char *ipaddr)
8043{
8044 FILE *fp = NULL;
8045 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8046 int LeaseTime = 0,ret = 0;
8047 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8048 {
8049 return RETURN_ERR;
8050 }
8051
8052 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8053 {
8054 /*
8055 Sample:sss
8056 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8057 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8058 */
8059 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008060 &(LeaseTime),
8061 phyAddr,
8062 ipAddr,
8063 hostName
8064 );
developer06a01d92022-09-07 16:32:39 +08008065 if(ret != 4)
8066 continue;
8067 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008068 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008069 }
developerd946fd62022-12-08 18:03:28 +08008070 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008071 return RETURN_OK;
8072}
8073
8074/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8075/**
8076* @description Returning Inactive wireless connected clients informations
8077*
8078* @param
8079* @filename Holding private_wifi 2g/5g content files
8080* @associated_dev_array Having inactiv wireless clients informations
8081* @output_array_size Returning Inactive wireless counts
8082* @return The status of the operation
8083* @retval RETURN_OK if successful
8084* @retval RETURN_ERR if any error is detected
8085*
8086*/
8087
8088INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8089{
8090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8091 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8092 FILE *fp = NULL;
8093 int arr[MACADDRESS_SIZE] = {0};
8094 unsigned char mac[MACADDRESS_SIZE] = {0};
8095 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8096 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8097 fp = popen(buf,"r");
8098 if(fp == NULL)
8099 return RETURN_ERR;
8100 else
8101 {
8102 fgets(path,sizeof(path),fp);
8103 maccount = atoi(path);
8104 }
8105 pclose(fp);
8106 *output_array_size = maccount;
8107 wifi_associated_dev3_t* temp = NULL;
8108 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8109 *associated_dev_array = temp;
8110 if(temp == NULL)
8111 {
8112 printf("Error Statement. Insufficient memory \n");
8113 return RETURN_ERR;
8114 }
8115 memset(buf,0,sizeof(buf));
8116 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8117 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008118 if (fp == NULL) {
8119 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8120 return RETURN_ERR;
8121 }
developer06a01d92022-09-07 16:32:39 +08008122 for(count = 0; count < maccount ; count++)
8123 {
8124 fgets(path,sizeof(path),fp);
8125 for(i = 0; path[i]!='\n';i++)
8126 str[i]=path[i];
8127 str[i]='\0';
8128 getIPAddress(str,ipaddr);
8129 memset(buf,0,sizeof(buf));
8130 if(strlen(ipaddr) > 0)
8131 {
8132 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8133 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8134 {
8135 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8136 {
8137 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8138 {
8139 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8140
8141 }
8142 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8143 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]);
8144 }
8145 temp[count].cli_AuthenticationState = 0; //TODO
8146 temp[count].cli_Active = 0; //TODO
8147 temp[count].cli_SignalStrength = 0;
8148 }
8149 else //Active wireless clients info
8150 {
8151 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8152 {
8153 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8154 {
8155 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8156
8157 }
8158 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8159 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]);
8160 }
8161 temp[count].cli_Active = 1;
8162 }
8163 }
8164 memset(ipaddr,0,sizeof(ipaddr));
8165 }
8166 pclose(fp);
8167 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8168 return RETURN_OK;
8169}
8170//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8171//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8172//To get Band Steering Capability
8173INT wifi_getBandSteeringCapability(BOOL *support)
8174{
8175 *support = FALSE;
8176 return RETURN_OK;
8177}
8178
8179
8180//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8181//To get Band Steering enable status
8182INT wifi_getBandSteeringEnable(BOOL *enable)
8183{
8184 *enable = FALSE;
8185 return RETURN_OK;
8186}
8187
8188//To turn on/off Band steering
8189INT wifi_setBandSteeringEnable(BOOL enable)
8190{
8191 return RETURN_OK;
8192}
8193
8194//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8195//To get Band Steering AP group
8196INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8197{
8198 if (NULL == output_ApGroup)
8199 return RETURN_ERR;
8200
8201 strcpy(output_ApGroup, "1,2");
8202 return RETURN_OK;
8203}
8204
8205//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8206//to set and read the band steering BandUtilizationThreshold parameters
8207INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8208{
8209 return RETURN_ERR;
8210}
8211
8212INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8213{
8214 return RETURN_ERR;
8215}
8216
8217//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8218//to set and read the band steering RSSIThreshold parameters
8219INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8220{
8221 return RETURN_ERR;
8222}
8223
8224INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8225{
8226 return RETURN_ERR;
8227}
8228
8229
8230//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8231//to set and read the band steering physical modulation rate threshold parameters
8232INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8233{
8234 //If chip is not support, return -1
8235 return RETURN_ERR;
8236}
8237
8238INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8239{
8240 //If chip is not support, return -1
8241 return RETURN_ERR;
8242}
8243
8244//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8245//to set and read the inactivity time (in seconds) for steering under overload condition
8246INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8247{
8248 return RETURN_ERR;
8249}
8250
8251INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8252{
8253 return RETURN_ERR;
8254}
8255
8256//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8257//to set and read the inactivity time (in seconds) for steering under Idle condition
8258INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8259{
8260 return RETURN_ERR;
8261}
8262
8263INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8264{
8265 return RETURN_ERR;
8266}
8267
8268//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8269//pClientMAC[64]
8270//pSourceSSIDIndex[64]
8271//pDestSSIDIndex[64]
8272//pSteeringReason[256]
8273INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8274{
8275 //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
8276 *pSteeringTime=time(NULL);
8277 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8278 return RETURN_OK;
8279}
8280
8281INT wifi_ifConfigDown(INT apIndex)
8282{
8283 INT status = RETURN_OK;
8284 char cmd[64];
8285
8286 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8287 printf("%s: %s\n", __func__, cmd);
8288 system(cmd);
8289
8290 return status;
8291}
8292
8293INT wifi_ifConfigUp(INT apIndex)
8294{
developerd946fd62022-12-08 18:03:28 +08008295 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008296 char cmd[128];
8297 char buf[1024];
8298
developerac6f1142022-12-20 19:26:35 +08008299 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008300 return RETURN_ERR;
8301 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008302 _syscmd(cmd, buf, sizeof(buf));
8303 return 0;
8304}
8305
8306//>> Deprecated. Replace with wifi_applyRadioSettings
8307INT wifi_pushBridgeInfo(INT apIndex)
8308{
developerd946fd62022-12-08 18:03:28 +08008309 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008310 char ip[32] = {0};
8311 char subnet[32] = {0};
8312 char bridge[32] = {0};
8313 int vlanId = 0;
8314 char cmd[128] = {0};
8315 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008316
8317 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8318 wifi_getApVlanID(apIndex,&vlanId);
8319
developerac6f1142022-12-20 19:26:35 +08008320 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008321 return RETURN_ERR;
8322 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008323 _syscmd(cmd,buf, sizeof(buf));
8324
8325 return 0;
8326}
8327
8328INT wifi_pushChannel(INT radioIndex, UINT channel)
8329{
developerd946fd62022-12-08 18:03:28 +08008330 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008331 char cmd[128];
8332 char buf[1024];
8333 int apIndex;
8334
8335 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008336 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008337 return RETURN_ERR;
8338 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008339 _syscmd(cmd,buf, sizeof(buf));
8340
8341 return 0;
8342}
8343
8344INT wifi_pushChannelMode(INT radioIndex)
8345{
8346 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8347 return RETURN_ERR;
8348}
8349
8350INT wifi_pushDefaultValues(INT radioIndex)
8351{
8352 //Apply Comcast specified default radio settings instantly
8353 //AMPDU=1
8354 //AMPDUFrames=32
8355 //AMPDULim=50000
8356 //txqueuelen=1000
8357
8358 return RETURN_ERR;
8359}
8360
8361INT wifi_pushTxChainMask(INT radioIndex)
8362{
8363 //Apply default TxChainMask instantly
8364 return RETURN_ERR;
8365}
8366
8367INT wifi_pushRxChainMask(INT radioIndex)
8368{
8369 //Apply default RxChainMask instantly
8370 return RETURN_ERR;
8371}
8372
8373INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8374{
8375 INT status;
8376
8377 status = wifi_setSSIDName(apIndex,ssid);
8378 wifi_setApEnable(apIndex,FALSE);
8379 wifi_setApEnable(apIndex,TRUE);
8380
8381 return status;
8382}
8383
8384INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8385{
8386 //Apply default Ssid Advertisement instantly
8387 return RETURN_ERR;
8388}
8389
8390INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8391{
8392 INT status = RETURN_ERR;
8393 *output = 0;
8394 return RETURN_ERR;
8395}
8396
8397INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8398{
8399 return RETURN_OK;
8400}
8401
8402INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8403{
8404 return RETURN_OK;
8405}
8406
8407//To-do
8408INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8409{
developereb199ae2022-09-13 14:04:27 +08008410 char output[16]={'\0'};
8411 char config_file[MAX_BUF_SIZE] = {0};
8412
8413 if (!output_string)
8414 return RETURN_ERR;
8415
8416 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8417 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8418
8419 if (strlen(output) == 0)
8420 snprintf(output_string, 64, "Disabled");
8421 else if (strncmp(output, "0", 1) == 0)
8422 snprintf(output_string, 64, "Disabled");
8423 else if (strncmp(output, "1", 1) == 0)
8424 snprintf(output_string, 64, "Optional");
8425 else if (strncmp(output, "2", 1) == 0)
8426 snprintf(output_string, 64, "Required");
8427 else {
8428 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8429 return RETURN_ERR;
8430 }
8431
8432 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008433 return RETURN_OK;
8434}
8435INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8436{
developereb199ae2022-09-13 14:04:27 +08008437 char str[MAX_BUF_SIZE]={'\0'};
8438 char cmd[MAX_CMD_SIZE]={'\0'};
8439 struct params params;
8440 char config_file[MAX_BUF_SIZE] = {0};
8441
8442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8443 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8444 return RETURN_ERR;
8445
8446 params.name = "ieee80211w";
8447 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8448 params.value = "0";
8449 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8450 params.value = "1";
8451 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8452 params.value = "2";
8453 else{
8454 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8455 return RETURN_ERR;
8456 }
8457 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8458 wifi_hostapdWrite(config_file, &params, 1);
8459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008460 return RETURN_OK;
8461}
8462INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8463{
8464 char output[16]={'\0'};
8465 char config_file[MAX_BUF_SIZE] = {0};
8466
8467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8468 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8469 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8470
8471 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8472 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8473
8474 return RETURN_OK;
8475}
8476
8477INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8478{
8479 return RETURN_OK;
8480}
8481
8482INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8483{
8484 return RETURN_OK;
8485}
8486
8487INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8488{
8489 return RETURN_OK;
8490}
8491
8492INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8493{
8494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8495 char config_file[MAX_BUF_SIZE] = {0};
8496
8497 if (NULL == output)
8498 return RETURN_ERR;
8499 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8500 wifi_hostapdRead(config_file,"hw_mode",output,64);
8501
8502 if(strcmp(output,"b")==0)
8503 sprintf(output, "%s", "1,2,5.5,11");
8504 else if (strcmp(output,"a")==0)
8505 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8506 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8507 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8508
8509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8510 return RETURN_OK;
8511}
8512
8513INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8514{
8515 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8516 char *temp;
8517 char temp_output[128];
8518 char temp_TransmitRates[128];
8519 char config_file[MAX_BUF_SIZE] = {0};
8520
8521 if (NULL == output)
8522 return RETURN_ERR;
8523
8524 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8525 wifi_hostapdRead(config_file,"supported_rates",output,64);
8526
developer5b398df2022-11-17 20:39:48 +08008527 if (strlen(output) == 0) {
8528 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8529 return RETURN_OK;
8530 }
developer06a01d92022-09-07 16:32:39 +08008531 strcpy(temp_TransmitRates,output);
8532 strcpy(temp_output,"");
8533 temp = strtok(temp_TransmitRates," ");
8534 while(temp!=NULL)
8535 {
8536 temp[strlen(temp)-1]=0;
8537 if((temp[0]=='5') && (temp[1]=='\0'))
8538 {
8539 temp="5.5";
8540 }
8541 strcat(temp_output,temp);
8542 temp = strtok(NULL," ");
8543 if(temp!=NULL)
8544 {
8545 strcat(temp_output,",");
8546 }
8547 }
8548 strcpy(output,temp_output);
8549 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8550
8551 return RETURN_OK;
8552}
8553
8554INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8555{
8556 return RETURN_OK;
8557}
8558
8559
8560INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8561{
8562 int i=0;
8563 char *temp;
developeref938762022-10-19 17:21:01 +08008564 char temp1[128] = {0};
8565 char temp_output[128] = {0};
8566 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008567 struct params params={'\0'};
8568 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008569 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008570
8571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8572 if(NULL == output)
8573 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008574 strcpy(temp_TransmitRates,output);
8575
8576 for(i=0;i<strlen(temp_TransmitRates);i++)
8577 {
developeref938762022-10-19 17:21:01 +08008578 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008579 {
8580 continue;
8581 }
8582 else
8583 {
8584 return RETURN_ERR;
8585 }
8586 }
8587 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008588 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008589 while(temp!=NULL)
8590 {
8591 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008592 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008593 {
developeref938762022-10-19 17:21:01 +08008594 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008595 {
8596 return RETURN_ERR;
8597 }
8598 }
8599
8600 if(strcmp(temp,"5.5")==0)
8601 {
8602 strcpy(temp1,"55");
8603 }
8604 else
8605 {
8606 strcat(temp1,"0");
8607 }
8608 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008609 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008610 if(temp!=NULL)
8611 {
8612 strcat(temp_output," ");
8613 }
8614 }
8615 strcpy(output,temp_output);
8616
developer06a01d92022-09-07 16:32:39 +08008617 params.name = "supported_rates";
8618 params.value = output;
8619
8620 wifi_dbg_printf("\n%s:",__func__);
8621 wifi_dbg_printf("params.value=%s\n",params.value);
8622 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8623 wifi_hostapdWrite(config_file,&params,1);
8624 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8625
8626 return RETURN_OK;
8627}
8628
8629
8630static char *sncopy(char *dst, int dst_sz, const char *src)
8631{
8632 if (src && dst && dst_sz > 0) {
8633 strncpy(dst, src, dst_sz);
8634 dst[dst_sz - 1] = '\0';
8635 }
8636 return dst;
8637}
8638
8639static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8640{
8641 if (0 == strcmp(ht_mode, "HT40") ||
8642 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008643 0 == strcmp(ht_mode, "HT160") ||
8644 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008645 switch (channel) {
8646 case 1 ... 7:
8647 case 36:
8648 case 44:
8649 case 52:
8650 case 60:
8651 case 100:
8652 case 108:
8653 case 116:
8654 case 124:
8655 case 132:
8656 case 140:
8657 case 149:
8658 case 157:
8659 return 1;
8660 case 8 ... 13:
8661 case 40:
8662 case 48:
8663 case 56:
8664 case 64:
8665 case 104:
8666 case 112:
8667 case 120:
8668 case 128:
8669 case 136:
8670 case 144:
8671 case 153:
8672 case 161:
8673 return -1;
8674 default:
8675 return -EINVAL;
8676 }
8677 }
8678
8679 return -EINVAL;
8680}
8681
developerb7593de2022-10-18 09:51:57 +08008682static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8683{
8684 int idx = channel%8;
8685 if (0 == strcmp(ht_mode, "HT40") ||
8686 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008687 0 == strcmp(ht_mode, "HT160") ||
8688 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008689 switch (idx) {
8690 case 1:
8691 return 1;
8692 case 5:
8693 return -1;
8694 default:
8695 return -EINVAL;
8696 }
8697 }
8698
8699 return -EINVAL;
8700}
developer06a01d92022-09-07 16:32:39 +08008701static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8702{
8703 if (NULL == hw_mode) return;
8704
8705 if (0 == strcmp(hw_mode, "ac"))
8706 sncopy(bw_mode, bw_mode_len, "ht vht");
8707
8708 if (0 == strcmp(hw_mode, "n"))
8709 sncopy(bw_mode, bw_mode_len, "ht");
8710
8711 return;
8712}
8713
8714static int util_chan_to_freq(int chan)
8715{
8716 if (chan == 14)
8717 return 2484;
8718 else if (chan < 14)
8719 return 2407 + chan * 5;
8720 else if (chan >= 182 && chan <= 196)
8721 return 4000 + chan * 5;
8722 else
8723 return 5000 + chan * 5;
8724 return 0;
8725}
8726
developerb7593de2022-10-18 09:51:57 +08008727static int util_6G_chan_to_freq(int chan)
8728{
8729 if (chan)
8730 return 5950 + chan * 5;
8731 else
8732 return 0;
8733
8734}
developer06a01d92022-09-07 16:32:39 +08008735const int *util_unii_5g_chan2list(int chan, int width)
8736{
8737 static const int lists[] = {
8738 // <width>, <chan1>, <chan2>..., 0,
8739 20, 36, 0,
8740 20, 40, 0,
8741 20, 44, 0,
8742 20, 48, 0,
8743 20, 52, 0,
8744 20, 56, 0,
8745 20, 60, 0,
8746 20, 64, 0,
8747 20, 100, 0,
8748 20, 104, 0,
8749 20, 108, 0,
8750 20, 112, 0,
8751 20, 116, 0,
8752 20, 120, 0,
8753 20, 124, 0,
8754 20, 128, 0,
8755 20, 132, 0,
8756 20, 136, 0,
8757 20, 140, 0,
8758 20, 144, 0,
8759 20, 149, 0,
8760 20, 153, 0,
8761 20, 157, 0,
8762 20, 161, 0,
8763 20, 165, 0,
8764 40, 36, 40, 0,
8765 40, 44, 48, 0,
8766 40, 52, 56, 0,
8767 40, 60, 64, 0,
8768 40, 100, 104, 0,
8769 40, 108, 112, 0,
8770 40, 116, 120, 0,
8771 40, 124, 128, 0,
8772 40, 132, 136, 0,
8773 40, 140, 144, 0,
8774 40, 149, 153, 0,
8775 40, 157, 161, 0,
8776 80, 36, 40, 44, 48, 0,
8777 80, 52, 56, 60, 64, 0,
8778 80, 100, 104, 108, 112, 0,
8779 80, 116, 120, 124, 128, 0,
8780 80, 132, 136, 140, 144, 0,
8781 80, 149, 153, 157, 161, 0,
8782 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8783 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8784 -1 // final delimiter
8785 };
8786 const int *start;
8787 const int *p;
8788
8789 for (p = lists; *p != -1; p++) {
8790 if (*p == width) {
8791 for (start = ++p; *p != 0; p++) {
8792 if (*p == chan)
8793 return start;
8794 }
8795 }
8796 // move to the end of channel list of given width
8797 while (*p != 0) {
8798 p++;
8799 }
8800 }
8801
8802 return NULL;
8803}
8804
8805static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8806{
8807 if (NULL == ht_mode)
8808 return 0;
8809
8810 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8811 const int *chans = util_unii_5g_chan2list(channel, width);
8812 int sum = 0;
8813 int cnt = 0;
8814
8815 if (NULL == chans)
8816 return 0;
8817
8818 while (*chans) {
8819 sum += *chans;
8820 cnt++;
8821 chans++;
8822 }
developer30423732022-12-01 16:17:49 +08008823 if (cnt == 0)
8824 return 0;
developer06a01d92022-09-07 16:32:39 +08008825 return sum / cnt;
8826}
8827
developerb7593de2022-10-18 09:51:57 +08008828static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8829{
8830 if (NULL == ht_mode)
8831 return 0;
8832
8833 int width = strtol((ht_mode + 2), NULL, 10);
8834
8835 int idx = 0 ;
8836 int centerchan = 0;
8837 int chan_ofs = 1;
8838
8839 if (width == 40){
8840 idx = ((channel/4) + chan_ofs)%2;
8841 switch (idx) {
8842 case 0:
8843 centerchan = (channel - 2);
8844 break;
8845 case 1:
8846 centerchan = (channel + 2);
8847 break;
8848 default:
8849 return -EINVAL;
8850 }
8851 }else if (width == 80){
8852 idx = ((channel/4) + chan_ofs)%4;
8853 switch (idx) {
8854 case 0:
8855 centerchan = (channel - 6);
8856 break;
8857 case 1:
8858 centerchan = (channel + 6);
8859 break;
8860 case 2:
8861 centerchan = (channel + 2);
8862 break;
8863 case 3:
8864 centerchan = (channel - 2);
8865 break;
8866 default:
8867 return -EINVAL;
8868 }
8869 }else if (width == 160){
8870 switch (channel) {
8871 case 1 ... 29:
8872 centerchan = 15;
8873 break;
8874 case 33 ... 61:
8875 centerchan = 47;
8876 break;
8877 case 65 ... 93:
8878 centerchan = 79;
8879 break;
8880 case 97 ... 125:
8881 centerchan = 111;
8882 break;
8883 case 129 ... 157:
8884 centerchan = 143;
8885 break;
8886 case 161 ... 189:
8887 centerchan = 175;
8888 break;
8889 case 193 ... 221:
8890 centerchan = 207;
8891 break;
8892 default:
8893 return -EINVAL;
8894 }
developer7c4cd202023-03-01 10:56:29 +08008895 }else if (width == 320){
8896 switch (channel) {
8897 case 1 ... 29:
8898 centerchan = 31;
8899 break;
8900 case 33 ... 93:
8901 centerchan = 63;
8902 break;
8903 case 97 ... 157:
8904 centerchan = 127;
8905 break;
8906 case 161 ... 221:
8907 centerchan = 191;
8908 break;
8909 default:
8910 return -EINVAL;
8911 }
developerb7593de2022-10-18 09:51:57 +08008912 }
8913 return centerchan;
8914}
developer06a01d92022-09-07 16:32:39 +08008915static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8916{
8917 BOOL onlyG, onlyN, onlyA;
8918 CHAR tmp[64];
8919 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8920 if (ret == RETURN_OK) {
8921 sncopy(hw_mode, hw_mode_size, tmp);
8922 }
8923 return ret;
8924}
8925
8926INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8927{
8928 // Sample commands:
8929 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8930 // hostapd_cli -i wifi0 chan_switch 30 2437
8931 char cmd[MAX_CMD_SIZE] = {0};
8932 char buf[MAX_BUF_SIZE] = {0};
8933 int freq = 0, ret = 0;
8934 char center_freq1_str[32] = ""; // center_freq1=%d
8935 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8936 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8937 char hw_mode[16] = ""; // n|ac
8938 char bw_mode[16] = ""; // ht|ht vht
8939 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008940 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008941 int sec_chan_offset;
8942 int width;
developer4fb0b922022-09-30 14:29:09 +08008943 char config_file[64] = {0};
8944 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08008945 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08008946 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008947 wifi_band band = band_invalid;
8948 int center_chan = 0;
8949 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008950
developer4fb0b922022-09-30 14:29:09 +08008951 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008952
developerac6f1142022-12-20 19:26:35 +08008953 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008954 return RETURN_ERR;
8955
developer06a01d92022-09-07 16:32:39 +08008956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8957
developerb7593de2022-10-18 09:51:57 +08008958 band = wifi_index_to_band(radioIndex);
8959
developer5884e982022-10-06 10:52:50 +08008960 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008961
8962 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008963 if (channel){
developerb7593de2022-10-18 09:51:57 +08008964 if (band == band_6){
8965 freq = util_6G_chan_to_freq(channel);
8966 }else{
8967 freq = util_chan_to_freq(channel);
8968 }
developer7c4cd202023-03-01 10:56:29 +08008969 if (width == 320) {
8970 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
8971 setEHT320 = TRUE;
8972 }
developer5884e982022-10-06 10:52:50 +08008973 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008974
developer5884e982022-10-06 10:52:50 +08008975 // Provide bandwith if specified
8976 if (channel_width_MHz > 20) {
8977 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8978 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8979 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008980
developer5884e982022-10-06 10:52:50 +08008981 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8982 }else if (channel_width_MHz == 20){
8983 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8984 }
developer06a01d92022-09-07 16:32:39 +08008985
developerb7593de2022-10-18 09:51:57 +08008986
developer5884e982022-10-06 10:52:50 +08008987 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008988 if (band == band_6){
8989 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8990 if(center_chan){
8991 center_freq1 = util_6G_chan_to_freq(center_chan);
8992 }
8993 }else{
8994 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8995 if(center_chan){
8996 center_freq1 = util_chan_to_freq(center_chan);
8997 }
developer5884e982022-10-06 10:52:50 +08008998 }
developerb7593de2022-10-18 09:51:57 +08008999
9000 if (center_freq1)
9001 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9002
9003 }
9004
9005 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9006 if (band == band_6){
9007 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9008 }else{
9009 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009010 }
developerb7593de2022-10-18 09:51:57 +08009011 if (sec_chan_offset != -EINVAL)
9012 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009013
developer5884e982022-10-06 10:52:50 +08009014 // Only the first AP, other are hanging on the same radio
9015 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009016 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9017 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009018 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9019 wifi_dbg_printf("execute: '%s'\n", cmd);
9020 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009021 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009022
developer5884e982022-10-06 10:52:50 +08009023 ret = wifi_setRadioChannel(radioIndex, channel);
9024 if (ret != RETURN_OK) {
9025 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9026 return RETURN_ERR;
9027 }
9028
9029 if (sec_chan_offset == 1) ext_str = "Above";
9030 else if (sec_chan_offset == -1) ext_str = "Below";
9031
9032 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009033
developer5884e982022-10-06 10:52:50 +08009034 } else {
9035 if (channel_width_MHz > 20)
9036 ext_str = "Above";
9037 }
developer4fb0b922022-09-30 14:29:09 +08009038
developer06a01d92022-09-07 16:32:39 +08009039 char mhz_str[16];
9040 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009041 if (setEHT320 == TRUE)
9042 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9043 else
9044 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009045
developer57fa24a2023-03-15 17:25:07 +08009046 writeBandWidth(radioIndex, mhz_str);
9047 if (band == band_2_4 || band == band_5) {
9048 if (width == 20)
9049 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9050 else
9051 wifi_setRadioExtChannel(radioIndex, ext_str);
9052 }
developer06a01d92022-09-07 16:32:39 +08009053 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9054
9055 return RETURN_OK;
9056}
9057
9058INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9059{
developer615510b2022-09-27 10:14:35 +08009060 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009061 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009062 char cmd[256]={0};
9063 char buf[128]={0};
9064 char file_name[32] = {0};
9065 char filter_SSID[32] = {0};
9066 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009067 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009068 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009069 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009070 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009071 size_t len=0;
9072 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009073 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009074 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009075 bool filter_enable = false;
9076 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009077 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009078
developer615510b2022-09-27 10:14:35 +08009079 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009080
developer615510b2022-09-27 10:14:35 +08009081 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9082 f = fopen(file_name, "r");
9083 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009084 fgets(buf, sizeof(file_name), f);
9085 if ((strncmp(buf, "0", 1)) != 0) {
9086 fgets(filter_SSID, sizeof(file_name), f);
9087 if (strlen(filter_SSID) != 0)
9088 filter_enable = true;
9089 }
developer615510b2022-09-27 10:14:35 +08009090 fclose(f);
9091 }
9092
developerac6f1142022-12-20 19:26:35 +08009093 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009094 return RETURN_ERR;
9095
developer033b37b2022-10-18 11:27:46 +08009096 phyId = radio_index_to_phy(radio_index);
9097
9098 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009099 _syscmd(cmd, buf, sizeof(buf));
9100 channels_num = strtol(buf, NULL, 10);
9101
developerd946fd62022-12-08 18:03:28 +08009102 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9103 // 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 +08009104 fprintf(stderr, "cmd: %s\n", cmd);
9105 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009106 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9107 return RETURN_ERR;
9108 }
developer5550e242022-09-30 09:59:32 +08009109
9110 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9111 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9112
developer615510b2022-09-27 10:14:35 +08009113 ret = fgets(line, sizeof(line), f);
9114 while (ret != NULL) {
9115 if(strstr(line, "BSS") != NULL) { // new neighbor info
9116 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9117 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9118 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9119
9120 if (!filter_BSS) {
9121 index++;
9122 wifi_neighbor_ap2_t *tmp;
9123 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9124 if (tmp == NULL) { // no more memory to use
9125 index--;
9126 wifi_dbg_printf("%s: realloc failed\n", __func__);
9127 break;
9128 }
9129 scan_array = tmp;
9130 }
9131 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009132
developer615510b2022-09-27 10:14:35 +08009133 filter_BSS = false;
9134 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9135 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9136 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9137 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9138 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009139 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009140 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009141
developer615510b2022-09-27 10:14:35 +08009142 if (freq >= 2412 && freq <= 2484) {
9143 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9144 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9145 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9146 }
9147 else if (freq >= 5160 && freq <= 5805) {
9148 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9149 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9150 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9151 }
developer06a01d92022-09-07 16:32:39 +08009152
developer615510b2022-09-27 10:14:35 +08009153 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009154 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009155 for (int i = 0; i < channels_num; i++) {
9156 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9157 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9158 break;
9159 }
9160 }
developer06a01d92022-09-07 16:32:39 +08009161 }
developer615510b2022-09-27 10:14:35 +08009162 } else if (strstr(line, "beacon interval") != NULL) {
9163 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9164 } else if (strstr(line, "signal") != NULL) {
9165 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9166 } else if (strstr(line,"SSID") != NULL) {
9167 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9168 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9169 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009170 }
developer615510b2022-09-27 10:14:35 +08009171 } else if (strstr(line, "Supported rates") != NULL) {
9172 char SRate[80] = {0}, *tmp = NULL;
9173 memset(buf, 0, sizeof(buf));
9174 strcpy(SRate, line);
9175 tmp = strtok(SRate, ":");
9176 tmp = strtok(NULL, ":");
9177 strcpy(buf, tmp);
9178 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009179
developer615510b2022-09-27 10:14:35 +08009180 tmp = strtok(buf, " \n");
9181 while (tmp != NULL) {
9182 strcat(SRate, tmp);
9183 if (SRate[strlen(SRate) - 1] == '*') {
9184 SRate[strlen(SRate) - 1] = '\0';
9185 }
9186 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009187
developer615510b2022-09-27 10:14:35 +08009188 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009189 }
developer615510b2022-09-27 10:14:35 +08009190 SRate[strlen(SRate) - 1] = '\0';
9191 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9192 } else if (strstr(line, "DTIM") != NULL) {
9193 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9194 } else if (strstr(line, "VHT capabilities") != NULL) {
9195 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9196 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9197 } else if (strstr(line, "HT capabilities") != NULL) {
9198 strcat(scan_array[index].ap_SupportedStandards, ",n");
9199 strcpy(scan_array[index].ap_OperatingStandards, "n");
9200 } else if (strstr(line, "VHT operation") != NULL) {
9201 ret = fgets(line, sizeof(line), f);
9202 sscanf(line," * channel width: %d", &vht_channel_width);
9203 if(vht_channel_width == 1) {
9204 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9205 } else {
9206 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9207 }
9208 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9209 continue;
9210 } else if (strstr(line, "HT operation") != NULL) {
9211 ret = fgets(line, sizeof(line), f);
9212 sscanf(line," * secondary channel offset: %s", &buf);
9213 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009214 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009215 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 +08009216 }
developer615510b2022-09-27 10:14:35 +08009217 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009218 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009219 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9220 } else {
9221 //20Mhz
9222 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 +08009223 }
developer615510b2022-09-27 10:14:35 +08009224 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009225 continue;
developer615510b2022-09-27 10:14:35 +08009226 } else if (strstr(line, "HE capabilities") != NULL) {
9227 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9228 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9229 ret = fgets(line, sizeof(line), f);
9230 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9231 if (strstr(line, "HE40/2.4GHz") != NULL)
9232 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9233 else
9234 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9235 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9236 if (strstr(line, "HE80/5GHz") != NULL) {
9237 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9238 ret = fgets(line, sizeof(line), f);
9239 } else
9240 continue;
9241 if (strstr(line, "HE160/5GHz") != NULL)
9242 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009243 }
developer615510b2022-09-27 10:14:35 +08009244 continue;
9245 } else if (strstr(line, "WPA") != NULL) {
9246 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9247 } else if (strstr(line, "RSN") != NULL) {
9248 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9249 } else if (strstr(line, "Group cipher") != NULL) {
9250 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9251 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9252 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009253 }
developer06a01d92022-09-07 16:32:39 +08009254 }
developer615510b2022-09-27 10:14:35 +08009255 ret = fgets(line, sizeof(line), f);
9256 }
9257
9258 if (!filter_BSS) {
9259 *output_array_size = index + 1;
9260 } else {
9261 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9262 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009263 }
developer06a01d92022-09-07 16:32:39 +08009264 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009265 pclose(f);
developer5550e242022-09-30 09:59:32 +08009266 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009267 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009268 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009269}
developer615510b2022-09-27 10:14:35 +08009270
developer06a01d92022-09-07 16:32:39 +08009271INT wifi_getApAssociatedDeviceStats(
9272 INT apIndex,
9273 mac_address_t *clientMacAddress,
9274 wifi_associated_dev_stats_t *associated_dev_stats,
9275 u64 *handle)
9276{
9277 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9278 char interface_name[50] = {0};
9279 char cmd[1024] = {0};
9280 char mac_str[18] = {0};
9281 char *key = NULL;
9282 char *val = NULL;
9283 FILE *f = NULL;
9284 char *line = NULL;
9285 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009286
9287 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9288 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9289 return RETURN_ERR;
9290 }
9291
9292 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9293 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9294 if((f = popen(cmd, "r")) == NULL) {
9295 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9296 return RETURN_ERR;
9297 }
9298
developer30423732022-12-01 16:17:49 +08009299 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009300 key = strtok(line,":");
9301 val = strtok(NULL,":");
9302
9303 if(!strncmp(key,"rx bytes",8))
9304 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9305 if(!strncmp(key,"tx bytes",8))
9306 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9307 if(!strncmp(key,"rx packets",10))
9308 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9309 if(!strncmp(key,"tx packets",10))
9310 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9311 if(!strncmp(key,"tx retries",10))
9312 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9313 if(!strncmp(key,"tx failed",9))
9314 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9315 if(!strncmp(key,"rx drop misc",13))
9316 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9317 if(!strncmp(key,"rx bitrate",10)) {
9318 val = strtok(val, " ");
9319 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9320 }
9321 if(!strncmp(key,"tx bitrate",10)) {
9322 val = strtok(val, " ");
9323 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9324 }
9325 }
9326 free(line);
9327 pclose(f);
9328 return RETURN_OK;
9329}
9330
9331INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9332{
developerd946fd62022-12-08 18:03:28 +08009333 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009334 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9335
9336 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9337 if (NULL == output_string)
9338 return RETURN_ERR;
9339
developerac6f1142022-12-20 19:26:35 +08009340 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009341 return RETURN_ERR;
9342 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 +08009343 _syscmd(cmd, buf, sizeof(buf));
9344
9345 //size of SSID name restricted to value less than 32 bytes
9346 snprintf(output_string, 32, "%s", buf);
9347 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9348
9349 return RETURN_OK;
9350}
9351
9352INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9353{
9354 //char cmd[MAX_CMD_SIZE] = {0};
9355 char config_file[MAX_BUF_SIZE] = {0};
9356 char buf[32] = {0};
9357
9358 if (!output_filterMode)
9359 return RETURN_ERR;
9360
9361 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9362 //_syscmd(cmd, buf, sizeof(buf));
9363 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9364 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009365 if(strlen(buf) == 0) {
9366 *output_filterMode = 0;
9367 }
9368 else {
9369 int macaddr_acl_mode = strtol(buf, NULL, 10);
9370 if (macaddr_acl_mode == 1) {
9371 *output_filterMode = 1;
9372 } else if (macaddr_acl_mode == 0) {
9373 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9374 if (strlen(buf) == 0) {
9375 *output_filterMode = 0;
9376 } else {
9377 *output_filterMode = 2;
9378 }
9379 } else {
9380 return RETURN_ERR;
9381 }
9382 }
developer06a01d92022-09-07 16:32:39 +08009383
9384 return RETURN_OK;
9385}
9386
9387INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9388{
9389 FILE *fp = NULL;
9390 char str[MAX_BUF_SIZE] = {0};
9391 int wificlientindex = 0 ;
9392 int count = 0;
9393 int signalstrength = 0;
9394 int arr[MACADDRESS_SIZE] = {0};
9395 unsigned char mac[MACADDRESS_SIZE] = {0};
9396 UINT wifi_count = 0;
9397 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9398 char pipeCmd[MAX_CMD_SIZE] = {0};
9399
9400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9401 *output_array_size = 0;
9402 *associated_dev_array = NULL;
9403 char interface_name[50] = {0};
9404
9405 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9406 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9407 return RETURN_ERR;
9408 }
9409
9410 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9411 fp = popen(pipeCmd, "r");
9412 if (fp == NULL)
9413 {
9414 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9415 return RETURN_ERR;
9416 }
9417
9418 /* Read the output a line at a time - output it. */
9419 fgets(str, sizeof(str)-1, fp);
9420 wifi_count = (unsigned int) atoi ( str );
9421 *output_array_size = wifi_count;
9422 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9423 pclose(fp);
9424
9425 if(wifi_count == 0)
9426 {
9427 return RETURN_OK;
9428 }
9429 else
9430 {
9431 wifi_associated_dev2_t* temp = NULL;
9432 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9433 *associated_dev_array = temp;
9434 if(temp == NULL)
9435 {
9436 printf("Error Statement. Insufficient memory \n");
9437 return RETURN_ERR;
9438 }
9439
9440 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9441 system(pipeCmd);
9442
9443 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9444 if(fp == NULL)
9445 {
9446 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9447 return RETURN_ERR;
9448 }
9449 fclose(fp);
9450
developer30423732022-12-01 16:17:49 +08009451 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009452 fp = popen(pipeCmd, "r");
9453 if(fp)
9454 {
9455 for(count =0 ; count < wifi_count; count++)
9456 {
9457 fgets(str, MAX_BUF_SIZE, fp);
9458 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9459 {
9460 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9461 {
9462 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9463
9464 }
9465 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9466 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]);
9467 }
9468 temp[count].cli_AuthenticationState = 1; //TODO
9469 temp[count].cli_Active = 1; //TODO
9470 }
9471 pclose(fp);
9472 }
9473
9474 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009475 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 +08009476 fp = popen(pipeCmd, "r");
9477 if(fp)
9478 {
9479 pclose(fp);
9480 }
9481 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9482 if(fp)
9483 {
9484 for(count =0 ; count < wifi_count ;count++)
9485 {
9486 fgets(str, MAX_BUF_SIZE, fp);
9487 signalstrength = atoi(str);
9488 temp[count].cli_RSSI = signalstrength;
9489 }
9490 pclose(fp);
9491 }
9492
9493
9494 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009495 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 +08009496 fp = popen(pipeCmd, "r");
9497 if (fp)
9498 {
9499 pclose(fp);
9500 }
9501 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9502 if (fp)
9503 {
9504 for (count = 0; count < wifi_count; count++)
9505 {
9506 fgets(str, MAX_BUF_SIZE, fp);
9507 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9508 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9509 }
9510 pclose(fp);
9511 }
9512
9513 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009514 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 +08009515 fp = popen(pipeCmd, "r");
9516 if (fp)
9517 {
9518 pclose(fp);
9519 }
9520 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9521 if (fp)
9522 {
9523 for (count = 0; count < wifi_count; count++)
9524 {
9525 fgets(str, MAX_BUF_SIZE, fp);
9526 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9527 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9528 }
9529 pclose(fp);
9530 }
9531 }
9532 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9533 return RETURN_OK;
9534
9535}
9536
9537INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9538{
9539#if 0
9540 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009541 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009542 _syscmd(cmd, buf, sizeof(buf));*/
9543
9544 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9545 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9546 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9547 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9548
9549 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.
9550 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].
9551 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].
9552 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].
9553 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9554 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9555
9556 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9557 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9558 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9559 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.
9560 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.
9561 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.
9562 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.
9563 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.
9564 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.
9565 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.
9566 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9567#endif
9568
9569 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009570 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009571 char pipeCmd[128] = {0};
9572 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009573 wifi_ssidTrafficStats2_t *out = output_struct;
9574
developerce736392022-09-13 15:24:34 +08009575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009576 if (!output_struct)
9577 return RETURN_ERR;
9578
developerce736392022-09-13 15:24:34 +08009579 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009580 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009581 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009582 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009583
developer06a01d92022-09-07 16:32:39 +08009584 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009585 if (fp == NULL) {
9586 fprintf(stderr, "%s: popen failed\n", __func__);
9587 return RETURN_ERR;
9588 }
9589 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009590 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009591
developerce736392022-09-13 15:24:34 +08009592 if (strlen(str) == 0) // interface not exist
9593 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009594
developerce736392022-09-13 15:24:34 +08009595 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9596 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009597
developerce736392022-09-13 15:24:34 +08009598 memset(str, 0, sizeof(str));
9599 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009600 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009601 if (fp == NULL) {
9602 fprintf(stderr, "%s: popen failed\n", __func__);
9603 return RETURN_ERR;
9604 }
9605 fgets(str, sizeof(str), fp);
9606
9607 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9608 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009609 pclose(fp);
developerce736392022-09-13 15:24:34 +08009610
9611 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9612 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9613
9614 // Not supported
9615 output_struct->ssid_RetransCount = 0;
9616 output_struct->ssid_FailedRetransCount = 0;
9617 output_struct->ssid_RetryCount = 0;
9618 output_struct->ssid_MultipleRetryCount = 0;
9619 output_struct->ssid_ACKFailureCount = 0;
9620 output_struct->ssid_AggregatedPacketCount = 0;
9621
developer06a01d92022-09-07 16:32:39 +08009622 return RETURN_OK;
9623}
9624
9625//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).
9626INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9627{
9628 char output_val[16]={'\0'};
9629 char config_file[MAX_BUF_SIZE] = {0};
9630
9631 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9632 if (!output)
9633 return RETURN_ERR;
9634 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9635 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9636
9637 if( strcmp(output_val,"1") == 0 )
9638 *output = TRUE;
9639 else
9640 *output = FALSE;
9641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9642
9643 return RETURN_OK;
9644}
9645
9646INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9647{
9648 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9649 char str[MAX_BUF_SIZE]={'\0'};
9650 char string[MAX_BUF_SIZE]={'\0'};
9651 char cmd[MAX_CMD_SIZE]={'\0'};
9652 char *ch;
9653 char config_file[MAX_BUF_SIZE] = {0};
9654 struct params params;
9655
9656 if(enable == TRUE)
9657 strcpy(string,"1");
9658 else
9659 strcpy(string,"0");
9660
9661 params.name = "ap_isolate";
9662 params.value = string;
9663
9664 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9665 wifi_hostapdWrite(config_file,&params,1);
9666 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9667
9668 return RETURN_OK;
9669}
9670
9671INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9672{
9673 if (NULL == output_dBm)
9674 return RETURN_ERR;
9675
9676 *output_dBm = 0;
9677 return RETURN_OK;
9678}
9679
9680INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9681{
9682 return RETURN_OK;
9683}
9684INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9685{
9686 return RETURN_OK;
9687}
9688INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9689{
9690 return RETURN_OK;
9691}
9692INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9693{
9694 return RETURN_OK;
9695}
9696INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9697{
9698 return RETURN_OK;
9699}
9700INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9701{
9702 char config_file[MAX_BUF_SIZE] = {0};
9703 struct params list;
9704
9705 list.name = "bss_transition";
9706 list.value = activate?"1":"0";
9707 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9708 wifi_hostapdWrite(config_file, &list, 1);
9709
9710 return RETURN_OK;
9711}
9712wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9713
9714void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9715{
9716 return;
9717}
9718
9719INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9720{
9721 // TODO Implement me!
9722 return RETURN_OK;
9723}
9724
9725INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9726{
developera3c68b92022-09-13 15:27:29 +08009727 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009728 FILE *f = NULL;
9729
developer72ec5572023-01-05 16:27:13 +08009730 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009731
developer72ec5572023-01-05 16:27:13 +08009732 if (essid == NULL)
9733 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009734
developer72ec5572023-01-05 16:27:13 +08009735 if (strlen(essid) == 0 || apIndex == -1) {
9736 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9737 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009738 }
9739
developer72ec5572023-01-05 16:27:13 +08009740 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9741 f = fopen(file_name, "w");
9742 if (f == NULL)
9743 return RETURN_ERR;
9744
9745 // For mode == 0 is to disable filter, just don't write ssid to the file.
9746 fprintf(f, "%d\n%s", mode, mode?essid:"");
9747 fclose(f);
9748 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009749 return RETURN_OK;
9750}
9751
9752INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9753{
9754 // TODO Implement me!
9755 //Apply wifi_pushRadioChannel() instantly
9756 return RETURN_ERR;
9757}
9758
9759INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9760{
9761 // TODO Implement me!
9762 return RETURN_OK;
9763}
9764
9765#ifdef HAL_NETLINK_IMPL
9766static int tidStats_callback(struct nl_msg *msg, void *arg) {
9767 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9768 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9769 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9770 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9771 int rem , tid_index = 0;
9772
9773 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9774 wifi_associated_dev_tid_entry_t *stats_entry;
9775
9776 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9777 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9778 };
9779 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9780 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9781 };
9782
9783 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9784 genlmsg_attrlen(gnlh, 0), NULL);
9785
9786
9787 if (!tb[NL80211_ATTR_STA_INFO]) {
9788 fprintf(stderr, "station stats missing!\n");
9789 return NL_SKIP;
9790 }
9791
9792 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9793 tb[NL80211_ATTR_STA_INFO],
9794 stats_policy)) {
9795 fprintf(stderr, "failed to parse nested attributes!\n");
9796 return NL_SKIP;
9797 }
9798
9799 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9800 {
9801 stats_entry = &out->tid_array[tid_index];
9802
9803 stats_entry->tid = tid_index;
9804 stats_entry->ac = _tid_ac_index_get[tid_index];
9805
9806 if(sinfo[NL80211_STA_INFO_TID_STATS])
9807 {
9808 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9809 printf("failed to parse nested stats attributes!");
9810 return NL_SKIP;
9811 }
9812 }
9813 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9814 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9815
9816 if(tid_index < (PS_MAX_TID - 1))
9817 tid_index++;
9818 }
9819 //ToDo: sum_time_ms, ewma_time_ms
9820 return NL_SKIP;
9821}
9822#endif
9823
9824INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9825{
9826#ifdef HAL_NETLINK_IMPL
9827 Netlink nl;
9828 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009829 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009830
developerac6f1142022-12-20 19:26:35 +08009831 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009832 return RETURN_ERR;
9833
9834 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009835
9836 nl.id = initSock80211(&nl);
9837
9838 if (nl.id < 0) {
9839 fprintf(stderr, "Error initializing netlink \n");
9840 return -1;
9841 }
9842
9843 struct nl_msg* msg = nlmsg_alloc();
9844
9845 if (!msg) {
9846 fprintf(stderr, "Failed to allocate netlink message.\n");
9847 nlfree(&nl);
9848 return -2;
9849 }
9850
9851 genlmsg_put(msg,
9852 NL_AUTO_PORT,
9853 NL_AUTO_SEQ,
9854 nl.id,
9855 0,
9856 0,
9857 NL80211_CMD_GET_STATION,
9858 0);
9859
9860 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9861 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9862 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9863 nl_send_auto(nl.socket, msg);
9864 nl_recvmsgs(nl.socket, nl.cb);
9865 nlmsg_free(msg);
9866 nlfree(&nl);
9867 return RETURN_OK;
9868#else
9869//iw implementation
9870#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9871#define TOTAL_MAX_LINES 50
9872
9873 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009874 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009875 FILE *fp=NULL;
9876 char pipeCmd[1024]= {'\0'};
9877 int lines,tid_index=0;
9878 char mac_addr[20] = {'\0'};
9879
developerac6f1142022-12-20 19:26:35 +08009880 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009881 return RETURN_ERR;
9882
developer06a01d92022-09-07 16:32:39 +08009883 wifi_associated_dev_tid_entry_t *stats_entry;
9884
developer06a01d92022-09-07 16:32:39 +08009885 strcpy(mac_addr,clientMacAddress);
9886
9887 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9888 fp= popen(pipeCmd,"r");
9889 if(fp == NULL)
9890 {
9891 perror("popen for station dump failed\n");
9892 return RETURN_ERR;
9893 }
9894 pclose(fp);
9895
9896 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9897 fp=popen(pipeCmd,"r");
9898 if(fp == NULL)
9899 {
9900 perror("popen for grep station failed\n");
9901 return RETURN_ERR;
9902 }
9903 else if(fgets(buf,sizeof(buf),fp) != NULL)
9904 lines=atoi(buf);
9905 else
9906 {
9907 pclose(fp);
9908 fprintf(stderr,"No devices are connected \n");
9909 return RETURN_ERR;
9910 }
9911 pclose(fp);
9912
9913 if(lines == 1)
9914 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9915
9916 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9917 {
9918 stats_entry = &tid_stats->tid_array[tid_index];
9919 stats_entry->tid = tid_index;
9920
9921 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);
9922
9923 fp=popen(pipeCmd,"r");
9924 if(fp ==NULL)
9925 {
9926 perror("Failed to read from tid file \n");
9927 return RETURN_ERR;
9928 }
9929 else if(fgets(buf,sizeof(buf),fp) != NULL)
9930 stats_entry->num_msdus = atol(buf);
9931
9932 pclose(fp);
9933 stats_entry->ac = _tid_ac_index_get[tid_index];
9934// TODO:
9935// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9936// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9937 }
9938 return RETURN_OK;
9939#endif
9940}
9941
9942
9943INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9944{
developerd946fd62022-12-08 18:03:28 +08009945 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009946 char cmd[128]={0};
9947 char buf[128]={0};
9948 int freq = 0;
9949
9950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9951
9952 // full mode is used to scan all channels.
9953 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9954 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9955 ieee80211_channel_to_frequency(chan_list[0], &freq);
9956
developerac6f1142022-12-20 19:26:35 +08009957 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009958 return RETURN_ERR;
9959
developer615510b2022-09-27 10:14:35 +08009960 if (freq)
developerd946fd62022-12-08 18:03:28 +08009961 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009962 else
developerd946fd62022-12-08 18:03:28 +08009963 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009964
9965 _syscmd(cmd, buf, sizeof(buf));
9966 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9967
developer06a01d92022-09-07 16:32:39 +08009968 return RETURN_OK;
9969}
9970
9971
9972INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9973{
9974 // TODO Implement me!
9975 return RETURN_ERR;
9976}
9977
9978INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9979{
9980 // TODO Implement me!
9981 return RETURN_ERR;
9982}
9983
9984INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9985{
9986 // TODO Implement me!
9987 return RETURN_ERR;
9988}
9989
9990INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9991{
9992 // TODO Implement me!
9993 return RETURN_ERR;
9994}
9995
9996INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9997{
9998 // TODO Implement me!
9999 return RETURN_ERR;
10000}
10001
10002INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10003{
10004 // TODO Implement me!
10005 return RETURN_ERR;
10006}
10007
10008INT wifi_steering_eventUnregister(void)
10009{
10010 // TODO Implement me!
10011 return RETURN_ERR;
10012}
10013
10014INT wifi_delApAclDevices(INT apIndex)
10015{
10016#if 0
10017 char cmd[MAX_BUF_SIZE] = {0};
10018 char buf[MAX_BUF_SIZE] = {0};
10019
10020 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010021 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010022 if(_syscmd(cmd,buf,sizeof(buf)))
10023 return RETURN_ERR;
10024#endif
developer9988c232023-03-06 14:57:08 +080010025 char cmd[256]={0};
10026 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010027
developere6aafda2022-09-13 14:59:28 +080010028 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010029 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 +080010030 if(_syscmd(cmd, buf, sizeof(buf)))
10031 return RETURN_ERR;
10032 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010033
10034 return RETURN_OK;
10035}
10036
10037#ifdef HAL_NETLINK_IMPL
10038static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10039 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10040 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10041 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10042 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10043 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10044 char mac_addr[20],dev[20];
10045
10046 nla_parse(tb,
10047 NL80211_ATTR_MAX,
10048 genlmsg_attrdata(gnlh, 0),
10049 genlmsg_attrlen(gnlh, 0),
10050 NULL);
10051
10052 if(!tb[NL80211_ATTR_STA_INFO]) {
10053 fprintf(stderr, "sta stats missing!\n");
10054 return NL_SKIP;
10055 }
10056
10057 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10058 fprintf(stderr, "failed to parse nested attributes!\n");
10059 return NL_SKIP;
10060 }
10061 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10062
10063 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10064
10065 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10066 fprintf(stderr, "failed to parse nested rate attributes!");
10067 return NL_SKIP;
10068 }
10069
10070 if(sinfo[NL80211_STA_INFO_TID_STATS])
10071 {
10072 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10073 printf("failed to parse nested stats attributes!");
10074 return NL_SKIP;
10075 }
10076 }
10077
10078 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10079 {
10080 printf("Type is VHT\n");
10081 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10082 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10083
10084 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10085 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10086 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10087 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10088 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10089 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10090 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10091 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10092 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10093 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10094 }
10095 else
10096 {
10097 printf(" OFDM or CCK \n");
10098 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10099 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10100 }
10101
10102 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10103 if(rinfo[NL80211_RATE_INFO_MCS])
10104 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10105 }
10106 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10107 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10108 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10109 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10110
10111 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10112 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10113
10114 if (sinfo[NL80211_STA_INFO_SIGNAL])
10115 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10116 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10117 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10118 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10119 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10120 //rssi_array need to be filled
10121 return NL_SKIP;
10122}
10123#endif
10124
10125INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10126{
10127#ifdef HAL_NETLINK_IMPL
10128 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010129 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010130 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010131 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010132
10133 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10134
10135 if (*output_array_size <= 0)
10136 return RETURN_OK;
10137
developer06a01d92022-09-07 16:32:39 +080010138 nl.id = initSock80211(&nl);
10139
10140 if (nl.id < 0) {
10141 fprintf(stderr, "Error initializing netlink \n");
10142 return 0;
10143 }
10144
10145 struct nl_msg* msg = nlmsg_alloc();
10146
10147 if (!msg) {
10148 fprintf(stderr, "Failed to allocate netlink message.\n");
10149 nlfree(&nl);
10150 return 0;
10151 }
10152
10153 genlmsg_put(msg,
10154 NL_AUTO_PORT,
10155 NL_AUTO_SEQ,
10156 nl.id,
10157 0,
10158 0,
10159 NL80211_CMD_GET_STATION,
10160 0);
10161
10162 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10163 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10164 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10165 nl_send_auto(nl.socket, msg);
10166 nl_recvmsgs(nl.socket, nl.cb);
10167 nlmsg_free(msg);
10168 nlfree(&nl);
10169 return RETURN_OK;
10170#else
10171 //TODO Implement me
10172 return RETURN_OK;
10173#endif
10174}
10175
10176#ifdef HAL_NETLINK_IMPL
10177static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10178 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10179 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10180 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10181 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10182 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10183 char mac_addr[20],dev[20];
10184
10185 nla_parse(tb,
10186 NL80211_ATTR_MAX,
10187 genlmsg_attrdata(gnlh, 0),
10188 genlmsg_attrlen(gnlh, 0),
10189 NULL);
10190
10191 if(!tb[NL80211_ATTR_STA_INFO]) {
10192 fprintf(stderr, "sta stats missing!\n");
10193 return NL_SKIP;
10194 }
10195
10196 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10197 fprintf(stderr, "failed to parse nested attributes!\n");
10198 return NL_SKIP;
10199 }
10200
10201 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10202
10203 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10204
10205 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10206 fprintf(stderr, "failed to parse nested rate attributes!");
10207 return NL_SKIP;
10208 }
10209
10210 if(sinfo[NL80211_STA_INFO_TID_STATS])
10211 {
10212 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10213 printf("failed to parse nested stats attributes!");
10214 return NL_SKIP;
10215 }
10216 }
10217 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10218 {
10219 printf("Type is VHT\n");
10220 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10221 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10222
10223 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10224 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10225 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10226 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10227 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10228 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10229 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10230 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10231 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10232 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10233 }
10234 else
10235 {
10236 printf(" OFDM or CCK \n");
10237 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10238 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10239 }
10240
10241 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10242 if(rinfo[NL80211_RATE_INFO_MCS])
10243 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10244 }
10245
10246 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10247 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10248 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10249 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10250
10251 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10252 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10253 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10254
10255 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10256 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10257
10258 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10259 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10260
10261 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10262 ((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]);
10263
10264 return NL_SKIP;
10265}
10266#endif
10267
10268INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10269{
10270#ifdef HAL_NETLINK_IMPL
10271 Netlink nl;
10272 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010273 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010274 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010275 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010276
10277 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10278
10279 if (*output_array_size <= 0)
10280 return RETURN_OK;
10281
developerd946fd62022-12-08 18:03:28 +080010282 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010283
10284 nl.id = initSock80211(&nl);
10285
10286 if(nl.id < 0) {
10287 fprintf(stderr, "Error initializing netlink \n");
10288 return 0;
10289 }
10290
10291 struct nl_msg* msg = nlmsg_alloc();
10292
10293 if(!msg) {
10294 fprintf(stderr, "Failed to allocate netlink message.\n");
10295 nlfree(&nl);
10296 return 0;
10297 }
10298
10299 genlmsg_put(msg,
10300 NL_AUTO_PORT,
10301 NL_AUTO_SEQ,
10302 nl.id,
10303 0,
10304 0,
10305 NL80211_CMD_GET_STATION,
10306 0);
10307
10308 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10309 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10310 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10311 nl_send_auto(nl.socket, msg);
10312 nl_recvmsgs(nl.socket, nl.cb);
10313 nlmsg_free(msg);
10314 nlfree(&nl);
10315 return RETURN_OK;
10316#else
10317 //TODO Implement me
10318 return RETURN_OK;
10319#endif
10320}
10321
10322INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10323{
10324 // TODO Implement me!
10325 char buf[MAX_BUF_SIZE] = {0};
10326 char config_file[MAX_BUF_SIZE] = {0};
10327
10328 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10329 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10330 *activate = (strncmp("1",buf,1) == 0);
10331
10332 return RETURN_OK;
10333}
10334
10335INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10336{
10337 char config_file[MAX_BUF_SIZE] = {0};
10338 struct params list;
10339
10340 list.name = "rrm_neighbor_report";
10341 list.value = activate?"1":"0";
10342 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10343 wifi_hostapdWrite(config_file, &list, 1);
10344
10345 return RETURN_OK;
10346}
10347
10348INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10349{
10350 char buf[32] = {0};
10351 char config_file[MAX_BUF_SIZE] = {0};
10352
10353 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10354 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10355 *activate = (strncmp("1",buf,1) == 0);
10356
10357 return RETURN_OK;
10358}
10359#undef HAL_NETLINK_IMPL
10360#ifdef HAL_NETLINK_IMPL
10361static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10362 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10363 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10364 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10365 char dev[20];
10366 int freq =0 ;
10367 static int i=0;
10368
10369 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10370
10371 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10372 };
10373
10374 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10375
10376 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10377
10378 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10379 fprintf(stderr, "survey data missing!\n");
10380 return NL_SKIP;
10381 }
10382
10383 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10384 {
10385 fprintf(stderr, "failed to parse nested attributes!\n");
10386 return NL_SKIP;
10387 }
10388
10389
10390 if(out[0].array_size == 1 )
10391 {
10392 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10393 {
10394 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10395 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10396 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10397
10398 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10399 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10400 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10401 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10402 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10403 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10404 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10405 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10406 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10407 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10408 if (sinfo[NL80211_SURVEY_INFO_TIME])
10409 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10410 return NL_STOP;
10411 }
10412 }
10413 else
10414 {
10415 if ( i <= out[0].array_size )
10416 {
10417 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10418 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10419 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10420
10421 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10422 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10423 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10424 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10425 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10426 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10427 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10428 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10429 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10430 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10431 if (sinfo[NL80211_SURVEY_INFO_TIME])
10432 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10433 }
10434 }
10435
10436 i++;
10437 return NL_SKIP;
10438}
10439#endif
10440
10441static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10442{
10443 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10444 FILE *fp;
10445
10446 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10447 {
10448 printf("Creating Frequency-Channel Map\n");
10449 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10450 }
10451 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10452 if((fp = popen(command, "r")))
10453 {
10454 fgets(output, sizeof(output), fp);
10455 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010456 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010457 }
10458
10459 return 0;
10460}
10461
10462static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10463{
10464 int freqMHz = -1;
10465 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010466 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010467
10468 ieee80211_channel_to_frequency(channel, &freqMHz);
10469 if (freqMHz == -1) {
10470 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10471 return -1;
10472 }
10473
developer7930d352022-12-21 17:55:42 +080010474 wifi_GetInterfaceName(radioIndex, interface_name);
10475 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010476 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10477 radioIndex, freqMHz);
10478 return -1;
10479 }
10480
10481 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10482 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10483 return -1;
10484 }
10485
10486 return 0;
10487}
10488
10489static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10490{
10491 const char *ptr = buf;
10492 char *key = NULL;
10493 char *val = NULL;
10494 char line[256] = { '\0' };
10495
10496 while (ptr = get_line_from_str_buf(ptr, line)) {
10497 if (strstr(line, "Frequency")) continue;
10498
10499 key = strtok(line, ":");
10500 val = strtok(NULL, " ");
10501 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10502
10503 if (!strcmp(key, "noise")) {
10504 sscanf(val, "%d", &stats->ch_noise);
10505 if (stats->ch_noise == 0) {
10506 // Workaround for missing noise information.
10507 // Assume -95 for 2.4G and -103 for 5G
10508 if (radioIndex == 0) stats->ch_noise = -95;
10509 if (radioIndex == 1) stats->ch_noise = -103;
10510 }
10511 }
10512 else if (!strcmp(key, "channel active time")) {
10513 sscanf(val, "%llu", &stats->ch_utilization_total);
10514 }
10515 else if (!strcmp(key, "channel busy time")) {
10516 sscanf(val, "%llu", &stats->ch_utilization_busy);
10517 }
10518 else if (!strcmp(key, "channel receive time")) {
10519 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10520 }
10521 else if (!strcmp(key, "channel transmit time")) {
10522 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10523 }
10524 };
10525
10526 return 0;
10527}
10528
10529INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10530{
10531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10532#ifdef HAL_NETLINK_IMPL
10533 Netlink nl;
10534 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010535 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010536
10537 local[0].array_size = array_size;
10538
developerac6f1142022-12-20 19:26:35 +080010539 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010540 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010541
10542 nl.id = initSock80211(&nl);
10543
10544 if (nl.id < 0) {
10545 fprintf(stderr, "Error initializing netlink \n");
10546 return -1;
10547 }
10548
10549 struct nl_msg* msg = nlmsg_alloc();
10550
10551 if (!msg) {
10552 fprintf(stderr, "Failed to allocate netlink message.\n");
10553 nlfree(&nl);
10554 return -2;
10555 }
10556
10557 genlmsg_put(msg,
10558 NL_AUTO_PORT,
10559 NL_AUTO_SEQ,
10560 nl.id,
10561 0,
10562 NLM_F_DUMP,
10563 NL80211_CMD_GET_SURVEY,
10564 0);
10565
10566 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10567 nl_send_auto(nl.socket, msg);
10568 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10569 nl_recvmsgs(nl.socket, nl.cb);
10570 nlmsg_free(msg);
10571 nlfree(&nl);
10572 //Copying the Values
10573 for(int i=0;i<array_size;i++)
10574 {
10575 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10576 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10577 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10578 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10579 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10580 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10581 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10582 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10583 }
10584#else
10585 ULONG channel = 0;
10586 int i;
10587 int number_of_channels = array_size;
10588 char buf[512];
10589 INT ret;
10590 wifi_channelStats_t tmp_stats;
10591
10592 if (number_of_channels == 0) {
10593 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10594 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10595 return RETURN_ERR;
10596 }
10597 number_of_channels = 1;
10598 input_output_channelStats_array[0].ch_number = channel;
10599 }
10600
10601 for (i = 0; i < number_of_channels; i++) {
10602
10603 input_output_channelStats_array[i].ch_noise = 0;
10604 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10605 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10606 input_output_channelStats_array[i].ch_utilization_busy = 0;
10607 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10608 input_output_channelStats_array[i].ch_utilization_total = 0;
10609
10610 memset(buf, 0, sizeof(buf));
10611 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10612 return RETURN_ERR;
10613 }
10614 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10615 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10616 return RETURN_ERR;
10617 }
10618
10619 // XXX: fake missing 'self' counter which is not available in iw survey output
10620 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10621 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10622
10623 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10624 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10625 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10626 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10627 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10628
10629 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",
10630 __func__,
10631 input_output_channelStats_array[i].ch_number,
10632 input_output_channelStats_array[i].ch_noise,
10633 input_output_channelStats_array[i].ch_utilization_total,
10634 input_output_channelStats_array[i].ch_utilization_busy,
10635 input_output_channelStats_array[i].ch_utilization_busy_rx,
10636 input_output_channelStats_array[i].ch_utilization_busy_tx,
10637 input_output_channelStats_array[i].ch_utilization_busy_self,
10638 input_output_channelStats_array[i].ch_utilization_busy_ext);
10639 }
10640#endif
10641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10642 return RETURN_OK;
10643}
10644#define HAL_NETLINK_IMPL
10645
10646/* Hostapd events */
10647
10648#ifndef container_of
10649#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10650#define container_of(ptr, type, member) \
10651 ((type *)((char *)ptr - offset_of(type, member)))
10652#endif /* container_of */
10653
10654struct ctrl {
10655 char sockpath[128];
10656 char sockdir[128];
10657 char bss[IFNAMSIZ];
10658 char reply[4096];
10659 int ssid_index;
10660 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10661 void (*overrun)(struct ctrl *ctrl);
10662 struct wpa_ctrl *wpa;
10663 unsigned int ovfl;
10664 size_t reply_len;
10665 int initialized;
10666 ev_timer retry;
10667 ev_timer watchdog;
10668 ev_stat stat;
10669 ev_io io;
10670};
10671static wifi_newApAssociatedDevice_callback clients_connect_cb;
10672static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10673static struct ctrl wpa_ctrl[MAX_APS];
10674static int initialized;
10675
10676static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10677{
10678 char cbuf[256] = {};
10679 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10680 struct cmsghdr *cmsg;
10681 unsigned int ovfl = ctrl->ovfl;
10682 unsigned int drop;
10683
10684 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10685 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10686 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10687 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10688
10689 drop = ovfl - ctrl->ovfl;
10690 ctrl->ovfl = ovfl;
10691
10692 return drop;
10693}
10694
10695static void ctrl_close(struct ctrl *ctrl)
10696{
10697 if (ctrl->io.cb)
10698 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10699 if (ctrl->retry.cb)
10700 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10701 if (!ctrl->wpa)
10702 return;
10703
10704 wpa_ctrl_detach(ctrl->wpa);
10705 wpa_ctrl_close(ctrl->wpa);
10706 ctrl->wpa = NULL;
10707 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10708}
10709
10710static void ctrl_process(struct ctrl *ctrl)
10711{
10712 const char *str;
10713 int drops;
10714 int level;
10715 int err;
10716
10717 /* Example events:
10718 *
10719 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10720 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10721 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10722 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10723 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10724 */
10725 if (!(str = index(ctrl->reply, '>')))
10726 return;
10727 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10728 return;
10729
10730 str++;
10731
10732 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10733 if (!(str = index(ctrl->reply, ' ')))
10734 return;
10735 wifi_associated_dev_t sta;
10736 memset(&sta, 0, sizeof(sta));
10737
10738 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10739 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10740 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10741
10742 sta.cli_Active=true;
10743
10744 (clients_connect_cb)(ctrl->ssid_index, &sta);
10745 goto handled;
10746 }
10747
10748 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10749 if (!(str = index(ctrl->reply, ' ')))
10750 return;
10751
10752 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10753 goto handled;
10754 }
10755
10756 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10757 printf("CTRL_WPA: handle TERMINATING event\n");
10758 goto retry;
10759 }
10760
10761 if (strncmp("AP-DISABLED", str, 11) == 0) {
10762 printf("CTRL_WPA: handle AP-DISABLED\n");
10763 goto retry;
10764 }
10765
10766 printf("Event not supported!!\n");
10767
10768handled:
10769
10770 if ((drops = ctrl_get_drops(ctrl))) {
10771 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10772 if (ctrl->overrun)
10773 ctrl->overrun(ctrl);
10774 }
10775
10776 return;
10777
10778retry:
10779 printf("WPA_CTRL: closing\n");
10780 ctrl_close(ctrl);
10781 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10782 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10783}
10784
10785static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10786{
10787 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10788 int err;
10789
10790 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10791 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10792 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10793 ctrl->reply[ctrl->reply_len] = 0;
10794 if (err < 0) {
10795 if (errno == EAGAIN || errno == EWOULDBLOCK)
10796 return;
10797 ctrl_close(ctrl);
10798 ev_timer_again(EV_A_ &ctrl->retry);
10799 return;
10800 }
10801
10802 ctrl_process(ctrl);
10803}
10804
10805static int ctrl_open(struct ctrl *ctrl)
10806{
10807 int fd;
10808
10809 if (ctrl->wpa)
10810 return 0;
10811
10812 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10813 if (!ctrl->wpa)
10814 goto err;
10815
10816 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10817 goto err_close;
10818
10819 fd = wpa_ctrl_get_fd(ctrl->wpa);
10820 if (fd < 0)
10821 goto err_detach;
10822
10823 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10824 goto err_detach;
10825
10826 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10827 ev_io_start(EV_DEFAULT_ &ctrl->io);
10828
10829 return 0;
10830
10831err_detach:
10832 wpa_ctrl_detach(ctrl->wpa);
10833err_close:
10834 wpa_ctrl_close(ctrl->wpa);
10835err:
10836 ctrl->wpa = NULL;
10837 return -1;
10838}
10839
10840static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10841{
10842 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10843
10844 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10845 ctrl_open(ctrl);
10846}
10847
10848static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10849{
10850 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10851
10852 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10853 if (ctrl_open(ctrl) == 0) {
10854 printf("WPA_CTRL: retry successful\n");
10855 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10856 }
10857}
10858
10859int ctrl_enable(struct ctrl *ctrl)
10860{
10861 if (ctrl->wpa)
10862 return 0;
10863
10864 if (!ctrl->stat.cb) {
10865 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10866 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10867 }
10868
10869 if (!ctrl->retry.cb) {
10870 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10871 }
10872
10873 return ctrl_open(ctrl);
10874}
10875
10876static void
10877ctrl_msg_cb(char *buf, size_t len)
10878{
10879 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10880
10881 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10882 ctrl_process(ctrl);
10883}
10884
10885static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10886{
10887 int err;
10888
10889 if (!ctrl->wpa)
10890 return -1;
10891 if (*reply_len < 2)
10892 return -1;
10893
10894 (*reply_len)--;
10895 ctrl->reply_len = sizeof(ctrl->reply);
10896 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10897 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10898 if (err < 0)
10899 return err;
10900
10901 if (ctrl->reply_len > *reply_len)
10902 ctrl->reply_len = *reply_len;
10903
10904 *reply_len = ctrl->reply_len;
10905 memcpy(reply, ctrl->reply, *reply_len);
10906 reply[*reply_len - 1] = 0;
10907 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10908 return 0;
10909}
10910
10911static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10912{
10913 const char *pong = "PONG";
10914 const char *ping = "PING";
10915 char reply[1024];
10916 size_t len = sizeof(reply);
10917 int err;
10918 ULONG s, snum;
10919 INT ret;
10920 BOOL status;
10921
10922 printf("WPA_CTRL: watchdog cb\n");
10923
10924 ret = wifi_getSSIDNumberOfEntries(&snum);
10925 if (ret != RETURN_OK) {
10926 printf("%s: failed to get SSID count", __func__);
10927 return;
10928 }
10929
10930 if (snum > MAX_APS) {
10931 printf("more ssid than supported! %lu\n", snum);
10932 return;
10933 }
10934
10935 for (s = 0; s < snum; s++) {
10936 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010937 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010938 continue;
10939 }
10940 if (status == false) continue;
10941
10942 memset(reply, 0, sizeof(reply));
10943 len = sizeof(reply);
10944 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10945 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10946 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10947 continue;
10948
10949 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10950 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010951 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010952 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10953 }
10954}
10955
10956static int init_wpa()
10957{
10958 int ret = 0, i = 0;
10959 ULONG s, snum;
10960
10961 ret = wifi_getSSIDNumberOfEntries(&snum);
10962 if (ret != RETURN_OK) {
10963 printf("%s: failed to get SSID count", __func__);
10964 return RETURN_ERR;
10965 }
10966
10967 if (snum > MAX_APS) {
10968 printf("more ssid than supported! %lu\n", snum);
10969 return RETURN_ERR;
10970 }
10971
10972 for (s = 0; s < snum; s++) {
10973 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10974 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10975 wpa_ctrl[s].ssid_index = s;
10976 ctrl_enable(&wpa_ctrl[s]);
10977 }
10978
10979 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10980 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10981
10982 initialized = 1;
10983 printf("WPA_CTRL: initialized\n");
10984
10985 return RETURN_OK;
10986}
10987
10988void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10989{
10990 clients_connect_cb = callback_proc;
10991 if (!initialized)
10992 init_wpa();
10993}
10994
10995void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10996{
10997 clients_disconnect_cb = callback_proc;
10998 if (!initialized)
10999 init_wpa();
11000}
11001
11002INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11003{
11004 // TODO Implement me!
11005 return RETURN_ERR;
11006}
11007
11008INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11009{
11010 // TODO Implement me!
11011 return RETURN_ERR;
11012}
11013
11014INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11015{
11016 int i;
developer4b102122023-02-15 10:53:03 +080011017 int phyId = -1;
11018 char cmd[256] = {0};
11019 char channel_numbers_buf[256] = {0};
11020 char dfs_state_buf[256] = {0};
11021 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011022 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011023 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011024
developer4b102122023-02-15 10:53:03 +080011025 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011026
developer4b102122023-02-15 10:53:03 +080011027 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11028 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011029
developer4b102122023-02-15 10:53:03 +080011030 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 +080011031
developer4b102122023-02-15 10:53:03 +080011032 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11033 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11034 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011035 }
11036
developer4b102122023-02-15 10:53:03 +080011037 ptr = channel_numbers_buf;
11038 i = 0;
11039 while (ptr = get_line_from_str_buf(ptr, line)) {
11040 if (i >= outputMapSize) {
11041 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11042 return RETURN_ERR;
11043 }
11044 sscanf(line, "%d", &outputMap[i].ch_number);
11045
11046 memset(cmd, 0, sizeof(cmd));
11047 // Below command should fetch string for DFS state (usable, available or unavailable)
11048 // Example line: "DFS state: usable (for 78930 sec)"
11049 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) {
11050 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011051 return RETURN_ERR;
11052 }
11053
developer4b102122023-02-15 10:53:03 +080011054 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11055 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011056 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11057 return RETURN_ERR;
11058 }
11059
developer4b102122023-02-15 10:53:03 +080011060 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011061
developer4b102122023-02-15 10:53:03 +080011062 if (!strcmp(dfs_state_buf, "usable")) {
11063 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11064 } else if (!strcmp(dfs_state_buf, "available")) {
11065 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11066 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11067 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11068 } else {
11069 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011070 }
developer4b102122023-02-15 10:53:03 +080011071 i++;
developer06a01d92022-09-07 16:32:39 +080011072 }
11073
developer4b102122023-02-15 10:53:03 +080011074 return RETURN_OK;
11075
developer06a01d92022-09-07 16:32:39 +080011076 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11077 return RETURN_ERR;
11078}
11079
11080INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11081{
11082 // TODO Implement me!
11083 return RETURN_ERR;
11084}
11085
11086INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11087{
11088 return RETURN_OK;
11089}
11090
11091INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11092{
11093 // TODO Implement me!
11094 return RETURN_ERR;
11095}
11096
11097INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11098{
11099 // TODO API refrence Implementaion is present on RPI hal
11100 return RETURN_ERR;
11101}
11102
11103INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11104{
developerd946fd62022-12-08 18:03:28 +080011105 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080011106 char cmd[128]={'\0'};
11107 char buf[128]={'\0'};
11108 char *support;
11109 int maximum_tx = 0, current_tx = 0;
11110
11111 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11112 if(txpwr_pcntg == NULL)
11113 return RETURN_ERR;
11114
developerac6f1142022-12-20 19:26:35 +080011115 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011116 return RETURN_ERR;
11117
developera5005b62022-09-13 15:43:35 +080011118 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080011119 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080011120 _syscmd(cmd, buf, sizeof(buf));
11121 maximum_tx = strtol(buf, NULL, 10);
11122
11123 // Get the current tx power
11124 memset(cmd, 0, sizeof(cmd));
11125 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080011126 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080011127 _syscmd(cmd, buf, sizeof(buf));
11128 current_tx = strtol(buf, NULL, 10);
11129
11130 // Get the power supported list and find the current power percentage in supported list
11131 memset(buf, 0, sizeof(buf));
11132 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11133 support = strtok(buf, ",");
11134 while(true)
11135 {
11136 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
developer033b37b2022-10-18 11:27:46 +080011137 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080011138 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080011139 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080011140 }
11141 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11142 if (tmp == current_tx) {
11143 *txpwr_pcntg = strtol(support, NULL, 10);
11144 break;
11145 }
11146 support = strtok(NULL, ",");
11147 }
11148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080011149 return RETURN_OK;
11150}
11151
11152INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11153{
developer58599c22022-09-13 16:40:34 +080011154 // TODO precac feature.
11155 struct params params = {0};
11156 char config_file[128] = {0};
11157
11158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11159
11160 params.name = "enable_background_radar";
11161 params.value = enable?"1":"0";
11162 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11163 wifi_hostapdWrite(config_file, &params, 1);
11164 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11165
11166 /* TODO precac feature */
11167
11168 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11169 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011170}
11171
11172INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11173{
developer58599c22022-09-13 16:40:34 +080011174 char config_file[128] = {0};
11175 char buf[64] = {0};
11176
11177 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11178 if (NULL == enable || NULL == precac)
11179 return RETURN_ERR;
11180
11181 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11182 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011183 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011184 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011185 *precac = true;
11186 } else {
developer58599c22022-09-13 16:40:34 +080011187 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011188 *precac = false;
11189 }
developer58599c22022-09-13 16:40:34 +080011190
11191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11192 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011193}
11194
11195INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11196{
developer58599c22022-09-13 16:40:34 +080011197 *supported = TRUE;
11198 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011199}
11200
developera7149722023-01-11 11:36:21 +080011201bool check_is_hemu_vendor_new_patch() {
11202 char cmd[128] = {0};
11203 char buf[128] = {0};
11204
11205 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11206 _syscmd(cmd, buf, sizeof(buf));
11207
11208 if (strlen(buf) > 0)
11209 return FALSE;
11210 else
11211 return TRUE;
11212}
11213
developer3e6b1692022-09-30 18:04:05 +080011214INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11215{
11216 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11217 struct params params = {0};
11218 char config_file[64] = {0};
11219 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011220 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011221 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011222 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11224
developera7149722023-01-11 11:36:21 +080011225 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011226
11227 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11228 set_mu_type &= ~0x05; // unset bit 0, 2
11229 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11230 set_mu_type |= 0x01;
11231 set_mu_type &= ~0x04;
11232 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11233 set_mu_type &= ~0x01;
11234 set_mu_type |= 0x04;
11235 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11236 set_mu_type |= 0x05; // set bit 0, 2
11237 }
11238
developera7149722023-01-11 11:36:21 +080011239 new_vendor_patch = check_is_hemu_vendor_new_patch();
11240 if (new_vendor_patch)
11241 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11242 else
11243 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11244
11245 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011246 sprintf(buf, "%u", set_mu_type);
11247 params.value = buf;
11248 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11249 wifi_hostapdWrite(config_file, &params, 1);
11250 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011251 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011252
11253 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11254 return RETURN_OK;
11255}
11256
11257INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11258{
11259 struct params params={0};
11260 char config_file[64] = {0};
11261 char buf[64] = {0};
11262 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011263 bool new_vendor_patch = FALSE;
11264 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011265
11266 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11267
11268 if (mu_type == NULL)
11269 return RETURN_ERR;
11270
developera7149722023-01-11 11:36:21 +080011271 new_vendor_patch = check_is_hemu_vendor_new_patch();
11272
11273 if (new_vendor_patch)
11274 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11275 else
11276 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11277
developer3e6b1692022-09-30 18:04:05 +080011278 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011279 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011280 get_mu_type = strtol(buf, NULL, 10);
11281
11282 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11283 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11284 else if (get_mu_type & 0x04)
11285 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11286 else if (get_mu_type & 0x01)
11287 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11288 else
11289 *mu_type = WIFI_DL_MU_TYPE_NONE;
11290
11291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11292 return RETURN_OK;
11293}
11294
11295INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11296{
11297 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11298 struct params params={0};
11299 char config_file[64] = {0};
11300 char buf[64] = {0};
11301 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011302 bool new_vendor_patch = FALSE;
11303 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11305
developera7149722023-01-11 11:36:21 +080011306 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011307
11308 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11309 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11310 set_mu_type &= ~0x0a;
11311 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11312 set_mu_type |= 0x02;
11313 set_mu_type &= ~0x08;
11314 }
11315
developera7149722023-01-11 11:36:21 +080011316 new_vendor_patch = check_is_hemu_vendor_new_patch();
11317
11318 if (new_vendor_patch)
11319 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11320 else
11321 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11322
11323 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011324 sprintf(buf, "%u", set_mu_type);
11325 params.value = buf;
11326 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11327 wifi_hostapdWrite(config_file, &params, 1);
11328 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011329 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011330
11331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11332 return RETURN_OK;
11333}
11334
11335INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11336{
11337 struct params params={0};
11338 char config_file[64] = {0};
11339 char buf[64] = {0};
11340 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011341 bool new_vendor_patch = FALSE;
11342 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011343
11344 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11345
developera7149722023-01-11 11:36:21 +080011346 new_vendor_patch = check_is_hemu_vendor_new_patch();
11347
11348 if (new_vendor_patch)
11349 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11350 else
11351 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11352
developer3e6b1692022-09-30 18:04:05 +080011353 if (mu_type == NULL)
11354 return RETURN_ERR;
11355
11356 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011357 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011358
11359 get_mu_type = strtol(buf, NULL, 10);
11360 if (get_mu_type & 0x02)
11361 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11362 else
11363 *mu_type = WIFI_DL_MU_TYPE_NONE;
11364
11365 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11366 return RETURN_OK;
11367}
11368
11369
developer454b9462022-09-13 15:29:16 +080011370INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11371{
11372 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011373 char buf[256] = {0};
11374 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011375 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011376 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011377 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011378 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011379
11380 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11381
developer254882b2022-09-30 17:12:31 +080011382 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011383 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11384 return RETURN_ERR;
11385 }
developer454b9462022-09-13 15:29:16 +080011386
developer254882b2022-09-30 17:12:31 +080011387 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011388 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011389
developer254882b2022-09-30 17:12:31 +080011390 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11391 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011392 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011393 _syscmd(cmd, buf, sizeof(buf));
11394 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11395 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11396 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011397 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 +080011398 _syscmd(cmd, buf, sizeof(buf));
11399 }
11400 if (band == band_5) {
11401 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11402 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011403 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 +080011404 _syscmd(cmd, buf, sizeof(buf));
11405 }
11406 }
11407 }
11408 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011409
developer254882b2022-09-30 17:12:31 +080011410 if (guard_interval == wifi_guard_interval_400)
11411 strcpy(GI, "0.4");
11412 else if (guard_interval == wifi_guard_interval_800)
11413 strcpy(GI, "0.8");
11414 else if (guard_interval == wifi_guard_interval_1600)
11415 strcpy(GI, "1.6");
11416 else if (guard_interval == wifi_guard_interval_3200)
11417 strcpy(GI, "3.2");
11418 else if (guard_interval == wifi_guard_interval_auto)
11419 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011420 // Record GI for get GI function
11421 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11422 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011423 if (f == NULL)
11424 return RETURN_ERR;
11425 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011426 fclose(f);
11427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11428 return RETURN_OK;
11429}
11430
11431INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11432{
11433 char buf[32] = {0};
11434 char cmd[64] = {0};
11435
11436 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11437
11438 if (guard_interval == NULL)
11439 return RETURN_ERR;
11440
developer7c4cd202023-03-01 10:56:29 +080011441 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011442 _syscmd(cmd, buf, sizeof(buf));
11443
11444 if (strncmp(buf, "0.4", 3) == 0)
11445 *guard_interval = wifi_guard_interval_400;
11446 else if (strncmp(buf, "0.8", 3) == 0)
11447 *guard_interval = wifi_guard_interval_800;
11448 else if (strncmp(buf, "1.6", 3) == 0)
11449 *guard_interval = wifi_guard_interval_1600;
11450 else if (strncmp(buf, "3.2", 3) == 0)
11451 *guard_interval = wifi_guard_interval_3200;
11452 else
11453 *guard_interval = wifi_guard_interval_auto;
11454
11455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11456 return RETURN_OK;
11457}
11458
developer3cc61d12022-09-13 16:36:05 +080011459INT wifi_setBSSColor(INT radio_index, UCHAR color)
11460{
11461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11462 struct params params = {0};
11463 char config_file[128] = {0};
11464 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011465 UCHAR *color_list;
11466 int color_num = 0;
11467 int maxNumberColors = 64;
11468 BOOL color_is_aval = FALSE;
11469
developerbf0b9dc2023-07-06 14:30:54 +080011470 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011471 return RETURN_ERR;
11472
developer517f3be2023-05-08 10:02:39 +080011473 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11474 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11475 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011476 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011477 }
developer2acb9632023-03-14 14:58:31 +080011478
11479 for (int i = 0; i < color_num; i++) {
11480 if (color_list[i] == color) {
11481 color_is_aval = TRUE;
11482 break;
11483 }
11484 }
11485 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011486 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011487 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11488 return RETURN_ERR;
11489 }
developer3cc61d12022-09-13 16:36:05 +080011490
11491 params.name = "he_bss_color";
11492 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11493 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011494 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011495 wifi_hostapdWrite(config_file, &params, 1);
11496 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011497 wifi_reloadAp(radio_index);
11498
developer517f3be2023-05-08 10:02:39 +080011499 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11501 return RETURN_OK;
11502}
11503
11504INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11505{
developer3cc61d12022-09-13 16:36:05 +080011506 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011507 char cmd[128] = {0};
11508 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011509
developer3cc61d12022-09-13 16:36:05 +080011510 if (NULL == color)
11511 return RETURN_ERR;
11512
developer2acb9632023-03-14 14:58:31 +080011513 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11514 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011515
developer2acb9632023-03-14 14:58:31 +080011516 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11517 _syscmd(cmd, buf, sizeof(buf));
11518 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011519
developer2acb9632023-03-14 14:58:31 +080011520 return RETURN_OK;
11521}
11522
11523INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11524{
11525 char buf[64] = {0};
11526 char cmd[128] = {0};
11527 char interface_name[16] = {0};
11528 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011529
developer2acb9632023-03-14 14:58:31 +080011530 if (NULL == colorList || NULL == numColorReturned)
11531 return RETURN_ERR;
11532
11533 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11534 return RETURN_ERR;
11535
11536 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11537 _syscmd(cmd, buf, sizeof(buf));
11538 color_bitmap = strtoull(buf, NULL, 16);
11539
11540 *numColorReturned = 0;
11541 for (int i = 0; i < maxNumberColors; i++) {
11542 if (color_bitmap & 1) {
11543 colorList[*numColorReturned] = i;
11544 (*numColorReturned) += 1;
11545 }
11546 color_bitmap >>= 1;
11547 }
developer3cc61d12022-09-13 16:36:05 +080011548 return RETURN_OK;
11549}
11550
developer06a01d92022-09-07 16:32:39 +080011551/* multi-psk support */
11552INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11553{
11554 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011555 char interface_name[16] = {0};
11556
developerac6f1142022-12-20 19:26:35 +080011557 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011558 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011559
developerd946fd62022-12-08 18:03:28 +080011560 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11561 interface_name,
developer06a01d92022-09-07 16:32:39 +080011562 mac[0],
11563 mac[1],
11564 mac[2],
11565 mac[3],
11566 mac[4],
11567 mac[5]
11568 );
11569 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11570 _syscmd(cmd, key->wifi_keyId, 64);
11571
11572
11573 return RETURN_OK;
11574}
11575
11576INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11577{
developerd946fd62022-12-08 18:03:28 +080011578 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011579 FILE *fd = NULL;
11580 char fname[100];
11581 char cmd[128] = {0};
11582 char out[64] = {0};
11583 wifi_key_multi_psk_t * key = NULL;
11584 if(keysNumber < 0)
11585 return RETURN_ERR;
11586
developer431128d2022-12-16 15:30:41 +080011587 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011588 fd = fopen(fname, "w");
11589 if (!fd) {
11590 return RETURN_ERR;
11591 }
11592 key= (wifi_key_multi_psk_t *) keys;
11593 for(int i=0; i<keysNumber; ++i, key++) {
11594 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11595 }
11596 fclose(fd);
11597
11598 //reload file
developerac6f1142022-12-20 19:26:35 +080011599 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011600 return RETURN_ERR;
11601 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011602 _syscmd(cmd, out, 64);
11603 return RETURN_OK;
11604}
11605
11606INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11607{
11608 FILE *fd = NULL;
11609 char fname[100];
11610 char * line = NULL;
11611 char * pos = NULL;
11612 size_t len = 0;
11613 ssize_t read = 0;
11614 INT ret = RETURN_OK;
11615 wifi_key_multi_psk_t *keys_it = NULL;
11616
11617 if (keysNumber < 1) {
11618 return RETURN_ERR;
11619 }
11620
developer431128d2022-12-16 15:30:41 +080011621 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011622 fd = fopen(fname, "r");
11623 if (!fd) {
11624 return RETURN_ERR;
11625 }
11626
11627 if (keys == NULL) {
11628 ret = RETURN_ERR;
11629 goto close;
11630 }
11631
11632 keys_it = keys;
11633 while ((read = getline(&line, &len, fd)) != -1) {
11634 //Strip trailing new line if present
11635 if (read > 0 && line[read-1] == '\n') {
11636 line[read-1] = '\0';
11637 }
11638
11639 if(strcmp(line,"keyid=")) {
11640 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11641 if (!(pos = index(line, ' '))) {
11642 ret = RETURN_ERR;
11643 goto close;
11644 }
11645 pos++;
11646 //Here should be 00:00:00:00:00:00
11647 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11648 printf("Not supported MAC: %s\n", pos);
11649 }
11650 if (!(pos = index(pos, ' '))) {
11651 ret = RETURN_ERR;
11652 goto close;
11653 }
11654 pos++;
11655
11656 //The rest is PSK
11657 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11658 keys_it++;
11659
11660 if(--keysNumber <= 0)
11661 break;
11662 }
11663 }
11664
11665close:
11666 free(line);
11667 fclose(fd);
11668 return ret;
11669}
11670/* end of multi-psk support */
11671
11672INT wifi_setNeighborReports(UINT apIndex,
11673 UINT numNeighborReports,
11674 wifi_NeighborReport_t *neighborReports)
11675{
11676 char cmd[256] = { 0 };
11677 char hex_bssid[13] = { 0 };
11678 char bssid[18] = { 0 };
11679 char nr[256] = { 0 };
11680 char ssid[256];
11681 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011682 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011683 INT ret;
11684
11685 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011686 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011687 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011688 return RETURN_ERR;
11689 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 +080011690 system(cmd);
11691
11692 for(unsigned int i = 0; i < numNeighborReports; i++)
11693 {
11694 memset(ssid, 0, sizeof(ssid));
11695 ret = wifi_getSSIDName(apIndex, ssid);
11696 if (ret != RETURN_OK)
11697 return RETURN_ERR;
11698
11699 memset(hex_ssid, 0, sizeof(hex_ssid));
11700 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11701 sprintf(hex_ssid + k,"%02x", ssid[j]);
11702
11703 snprintf(hex_bssid, sizeof(hex_bssid),
11704 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11705 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11706 snprintf(bssid, sizeof(bssid),
11707 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11708 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11709
11710 snprintf(nr, sizeof(nr),
11711 "%s" // bssid
11712 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11713 "%02hhx" // operclass
11714 "%02hhx" // channel
11715 "%02hhx", // phy_mode
11716 hex_bssid,
11717 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11718 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11719 neighborReports[i].opClass,
11720 neighborReports[i].channel,
11721 neighborReports[i].phyTable);
11722
11723 snprintf(cmd, sizeof(cmd),
11724 "hostapd_cli set_neighbor "
11725 "%s " // bssid
11726 "ssid=%s " // ssid
11727 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011728 "-i %s",
11729 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011730
11731 if (WEXITSTATUS(system(cmd)) != 0)
11732 {
11733 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11734 }
11735 }
11736
11737 return RETURN_OK;
11738}
11739
11740INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11741{
11742 return RETURN_OK;
11743}
11744
11745#ifdef _WIFI_HAL_TEST_
11746int main(int argc,char **argv)
11747{
11748 int index;
11749 INT ret=0;
11750 char buf[1024]="";
11751
11752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11753 if(argc<3)
11754 {
11755 if(argc==2)
11756 {
11757 if(!strcmp(argv[1], "init"))
11758 return wifi_init();
11759 if(!strcmp(argv[1], "reset"))
11760 return wifi_reset();
11761 if(!strcmp(argv[1], "wifi_getHalVersion"))
11762 {
11763 char buffer[64];
11764 if(wifi_getHalVersion(buffer)==RETURN_OK)
11765 printf("Version: %s\n", buffer);
11766 else
11767 printf("Error in wifi_getHalVersion\n");
11768 return RETURN_OK;
11769 }
11770 }
11771 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11772 exit(-1);
11773 }
11774
11775 index = atoi(argv[2]);
11776 if(strstr(argv[1], "wifi_getApName")!=NULL)
11777 {
11778 wifi_getApName(index,buf);
11779 printf("Ap name is %s \n",buf);
11780 return 0;
11781 }
11782 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11783 {
11784 BOOL b = FALSE;
11785 BOOL *output_bool = &b;
11786 wifi_getRadioAutoChannelEnable(index,output_bool);
11787 printf("Channel enabled = %d \n",b);
11788 return 0;
11789 }
11790 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11791 {
11792 wifi_getApWpaEncryptionMode(index,buf);
11793 printf("encryption enabled = %s\n",buf);
11794 return 0;
11795 }
11796 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11797 {
11798 BOOL b = FALSE;
11799 BOOL *output_bool = &b;
11800 wifi_getApSsidAdvertisementEnable(index,output_bool);
11801 printf("advertisment enabled = %d\n",b);
11802 return 0;
11803 }
11804 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11805 {
11806 if(argc <= 3 )
11807 {
11808 printf("Insufficient arguments \n");
11809 exit(-1);
11810 }
11811
11812 char sta[20] = {'\0'};
11813 ULLONG handle= 0;
11814 strcpy(sta,argv[3]);
11815 mac_address_t st;
11816 mac_addr_aton(st,sta);
11817
11818 wifi_associated_dev_tid_stats_t tid_stats;
11819 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11820 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11821 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);
11822 }
11823
11824 if(strstr(argv[1], "getApEnable")!=NULL) {
11825 BOOL enable;
11826 ret=wifi_getApEnable(index, &enable);
11827 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11828 }
11829 else if(strstr(argv[1], "setApEnable")!=NULL) {
11830 BOOL enable = atoi(argv[3]);
11831 ret=wifi_setApEnable(index, enable);
11832 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11833 }
11834 else if(strstr(argv[1], "getApStatus")!=NULL) {
11835 char status[64];
11836 ret=wifi_getApStatus(index, status);
11837 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11838 }
11839 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11840 {
11841 wifi_getSSIDNameStatus(index,buf);
11842 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11843 return 0;
11844 }
11845 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11846 wifi_ssidTrafficStats2_t stats={0};
11847 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11848 printf("%s %d: returns %d\n", argv[1], index, ret);
11849 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11850 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11851 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11852 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11853 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11854 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11855 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11856 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11857 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11858 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11859 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11860 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11861 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11862 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11863 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11864 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11865 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11866 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11867 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11868 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11869 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11870 }
11871 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11872 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11873 UINT array_size=0;
11874 UINT i=0;
11875 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11876 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11877 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11878 printf(" neighbor %d:\n", i);
11879 printf(" ap_SSID =%s\n", pt->ap_SSID);
11880 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11881 printf(" ap_Mode =%s\n", pt->ap_Mode);
11882 printf(" ap_Channel =%d\n", pt->ap_Channel);
11883 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11884 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11885 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11886 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11887 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11888 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11889 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11890 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11891 printf(" ap_Noise =%d\n", pt->ap_Noise);
11892 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11893 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11894 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11895 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11896 }
11897 if(neighbor_ap_array)
11898 free(neighbor_ap_array); //make sure to free the list
11899 }
11900 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11901 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11902 UINT array_size=0;
11903 UINT i=0;
11904 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11905 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11906 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11907 printf(" associated_dev %d:\n", i);
11908 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11909 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11910 printf(" cli_SNR =%d\n", pt->cli_SNR);
11911 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11912 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11913 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11914 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11915 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11916 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11917 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11918 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11919 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11920 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11921 }
11922 if(associated_dev_array)
11923 free(associated_dev_array); //make sure to free the list
11924 }
11925
11926 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11927 {
11928#define MAX_ARRAY_SIZE 64
11929 int i, array_size;
11930 char *p, *ch_str;
11931 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11932
11933 if(argc != 5)
11934 {
11935 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11936 exit(-1);
11937 }
11938 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11939
11940 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11941 {
11942 strtok_r(ch_str, ",", &p);
11943 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11944 }
11945 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11946 if(!array_size)
11947 array_size=1;//Need to print current channel statistics
11948 for(i=0; i<array_size; i++)
11949 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11950 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11951 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11952 input_output_channelStats_array[i].ch_number,\
11953 input_output_channelStats_array[i].ch_noise,\
11954 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11955 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11956 input_output_channelStats_array[i].ch_utilization_busy,\
11957 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11958 input_output_channelStats_array[i].ch_utilization_total);
11959 }
11960
11961 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11962 {
11963 if(argc <= 3 )
11964 {
11965 printf("Insufficient arguments \n");
11966 exit(-1);
11967 }
11968 char mac_addr[20] = {'\0'};
11969 wifi_device_t output_struct;
11970 int dev_index = atoi(argv[3]);
11971
11972 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11973 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11974 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);
11975 }
11976
11977 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11978 {
11979 if (argc <= 3)
11980 {
11981 printf("Insufficient arguments\n");
11982 exit(-1);
11983 }
11984 char args[256];
11985 wifi_NeighborReport_t *neighborReports;
11986
11987 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11988 if (!neighborReports)
11989 {
11990 printf("Failed to allocate memory");
11991 exit(-1);
11992 }
11993
11994 for (int i = 3; i < argc; ++i)
11995 {
11996 char *val;
11997 int j = 0;
11998 memset(args, 0, sizeof(args));
11999 strncpy(args, argv[i], sizeof(args));
12000 val = strtok(args, ";");
12001 while (val != NULL)
12002 {
12003 if (j == 0)
12004 {
12005 mac_addr_aton(neighborReports[i - 3].bssid, val);
12006 } else if (j == 1)
12007 {
12008 neighborReports[i - 3].info = strtol(val, NULL, 16);
12009 } else if (j == 2)
12010 {
12011 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12012 } else if (j == 3)
12013 {
12014 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12015 } else if (j == 4)
12016 {
12017 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12018 } else {
12019 printf("Insufficient arguments]n\n");
12020 exit(-1);
12021 }
12022 val = strtok(NULL, ";");
12023 j++;
12024 }
12025 }
12026
12027 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12028 if (ret != RETURN_OK)
12029 {
12030 printf("wifi_setNeighborReports ret = %d", ret);
12031 exit(-1);
12032 }
12033 }
12034 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12035 {
12036 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12037 printf("%s.\n", buf);
12038 else
12039 printf("Error returned\n");
12040 }
12041 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12042 {
12043 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12044 printf("%s.\n", buf);
12045 else
12046 printf("Error returned\n");
12047 }
12048 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12049 {
12050 if (argc <= 2)
12051 {
12052 printf("Insufficient arguments\n");
12053 exit(-1);
12054 }
12055 char buf[64]= {'\0'};
12056 wifi_getRadioOperatingChannelBandwidth(index,buf);
12057 printf("Current bandwidth is %s \n",buf);
12058 return 0;
12059 }
12060 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12061 {
12062 if (argc <= 5)
12063 {
12064 printf("Insufficient arguments\n");
12065 exit(-1);
12066 }
12067 UINT channel = atoi(argv[3]);
12068 UINT width = atoi(argv[4]);
12069 UINT beacon = atoi(argv[5]);
12070 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12071 printf("Result = %d", ret);
12072 }
12073
12074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12075 return 0;
12076}
12077
12078#endif
12079
12080#ifdef WIFI_HAL_VERSION_3
12081
developer1e5aa162022-09-13 16:06:24 +080012082INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12083{
12084 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12085 if (bitMap & WIFI_BITRATE_1MBPS)
12086 strcat(BasicRate, "1,");
12087 if (bitMap & WIFI_BITRATE_2MBPS)
12088 strcat(BasicRate, "2,");
12089 if (bitMap & WIFI_BITRATE_5_5MBPS)
12090 strcat(BasicRate, "5.5,");
12091 if (bitMap & WIFI_BITRATE_6MBPS)
12092 strcat(BasicRate, "6,");
12093 if (bitMap & WIFI_BITRATE_9MBPS)
12094 strcat(BasicRate, "9,");
12095 if (bitMap & WIFI_BITRATE_11MBPS)
12096 strcat(BasicRate, "11,");
12097 if (bitMap & WIFI_BITRATE_12MBPS)
12098 strcat(BasicRate, "12,");
12099 if (bitMap & WIFI_BITRATE_18MBPS)
12100 strcat(BasicRate, "18,");
12101 if (bitMap & WIFI_BITRATE_24MBPS)
12102 strcat(BasicRate, "24,");
12103 if (bitMap & WIFI_BITRATE_36MBPS)
12104 strcat(BasicRate, "36,");
12105 if (bitMap & WIFI_BITRATE_48MBPS)
12106 strcat(BasicRate, "48,");
12107 if (bitMap & WIFI_BITRATE_54MBPS)
12108 strcat(BasicRate, "54,");
12109 if (strlen(BasicRate) != 0) // remove last comma
12110 BasicRate[strlen(BasicRate) - 1] = '\0';
12111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12112 return RETURN_OK;
12113}
12114
12115INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12116{
12117 UINT BitMap = 0;
12118 char *rate;
12119
12120 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12121 rate = strtok(BasicRatesList, ",");
12122 while(rate != NULL)
12123 {
12124 if (strcmp(rate, "1") == 0)
12125 BitMap |= WIFI_BITRATE_1MBPS;
12126 else if (strcmp(rate, "2") == 0)
12127 BitMap |= WIFI_BITRATE_2MBPS;
12128 else if (strcmp(rate, "5.5") == 0)
12129 BitMap |= WIFI_BITRATE_5_5MBPS;
12130 else if (strcmp(rate, "6") == 0)
12131 BitMap |= WIFI_BITRATE_6MBPS;
12132 else if (strcmp(rate, "9") == 0)
12133 BitMap |= WIFI_BITRATE_9MBPS;
12134 else if (strcmp(rate, "11") == 0)
12135 BitMap |= WIFI_BITRATE_11MBPS;
12136 else if (strcmp(rate, "12") == 0)
12137 BitMap |= WIFI_BITRATE_12MBPS;
12138 else if (strcmp(rate, "18") == 0)
12139 BitMap |= WIFI_BITRATE_18MBPS;
12140 else if (strcmp(rate, "24") == 0)
12141 BitMap |= WIFI_BITRATE_24MBPS;
12142 else if (strcmp(rate, "36") == 0)
12143 BitMap |= WIFI_BITRATE_36MBPS;
12144 else if (strcmp(rate, "48") == 0)
12145 BitMap |= WIFI_BITRATE_48MBPS;
12146 else if (strcmp(rate, "54") == 0)
12147 BitMap |= WIFI_BITRATE_54MBPS;
12148 rate = strtok(NULL, ",");
12149 }
12150 *basicRateBitMap = BitMap;
12151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12152 return RETURN_OK;
12153}
12154
developer7c4cd202023-03-01 10:56:29 +080012155INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12156{
12157 int center_channel = 0;
12158 char central_channel_str[16] = {0};
12159 char config_file[32] = {0};
12160 struct params param = {0};
12161
12162 center_channel = util_unii_6g_centerfreq("HT320", channel);
12163 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12164 if (channel >= 193)
12165 return RETURN_ERR;
12166 if (channel >= 33) {
12167 if (channel > center_channel)
12168 center_channel += 32;
12169 else
12170 center_channel -= 32;
12171 }
12172 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12173 if (channel <= 29)
12174 return RETURN_ERR;
12175 }
12176 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12177 param.name = "eht_oper_centr_freq_seg0_idx";
12178 param.value = central_channel_str;
12179 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12180 wifi_hostapdWrite(config_file, &param, 1);
12181
12182 return RETURN_OK;
12183}
12184
12185INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12186{
12187 int op_class = 0;
12188 char config_file[32] = {0};
12189 char op_class_str[8] = {0};
12190 struct params param = {0};
12191
12192 if (bandwidth == 20)
12193 op_class = 131;
12194 else if (bandwidth == 40)
12195 op_class = 132;
12196 else if (bandwidth == 80)
12197 op_class = 133;
12198 else if (bandwidth == 160)
12199 op_class = 134;
12200 else if (bandwidth == 320)
12201 op_class = 137;
12202 else
12203 return RETURN_ERR;
12204 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12205 param.name = "op_class";
12206 param.value = op_class_str;
12207 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12208 wifi_hostapdWrite(config_file, &param, 1);
12209 return RETURN_OK;
12210}
12211
12212INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12213{
12214 char config_file[32] = {0};
12215 char buf [16] = {0};
12216
12217 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12218 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12219 return RETURN_ERR; // 6g band should set op_class
12220 *class = (UINT)strtoul(buf, NULL, 10);
12221
12222 return RETURN_OK;
12223}
12224
developer1e5aa162022-09-13 16:06:24 +080012225// 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 +080012226INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12227{
developer1e5aa162022-09-13 16:06:24 +080012228 char buf[128] = {0};
12229 char cmd[128] = {0};
12230 char config_file[64] = {0};
12231 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012232 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012233 wifi_radio_operationParam_t current_param;
12234
12235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12236
12237 multiple_set = TRUE;
12238 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12239 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12240 return RETURN_ERR;
12241 }
12242 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12243 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12244 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12245 return RETURN_ERR;
12246 }
12247 }
developer5884e982022-10-06 10:52:50 +080012248
12249 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12250 bandwidth = 20;
12251 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12252 bandwidth = 40;
12253 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12254 bandwidth = 80;
12255 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12256 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012257 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12258 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012259 if (operationParam->autoChannelEnabled){
12260 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12261 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12262 return RETURN_ERR;
12263 }
12264 }else{
developer1e5aa162022-09-13 16:06:24 +080012265 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12266 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12267 return RETURN_ERR;
12268 }
12269 }
developer5884e982022-10-06 10:52:50 +080012270
developer7c4cd202023-03-01 10:56:29 +080012271 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12272 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12273 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12274 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12275 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12276 return RETURN_ERR;
12277 }
12278 }
12279
12280 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12281 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12282 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12283 return RETURN_ERR;
12284 }
12285 }
12286
developer1e5aa162022-09-13 16:06:24 +080012287 if (current_param.variant != operationParam->variant) {
12288 // Two different definition bit map, so need to check every bit.
12289 if (operationParam->variant & WIFI_80211_VARIANT_A)
12290 set_mode |= WIFI_MODE_A;
12291 if (operationParam->variant & WIFI_80211_VARIANT_B)
12292 set_mode |= WIFI_MODE_B;
12293 if (operationParam->variant & WIFI_80211_VARIANT_G)
12294 set_mode |= WIFI_MODE_G;
12295 if (operationParam->variant & WIFI_80211_VARIANT_N)
12296 set_mode |= WIFI_MODE_N;
12297 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12298 set_mode |= WIFI_MODE_AC;
12299 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12300 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012301 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12302 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012303 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12304 memset(buf, 0, sizeof(buf));
12305 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12306 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12307 return RETURN_ERR;
12308 }
12309 }
12310 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12311 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12312 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12313 return RETURN_ERR;
12314 }
12315 }
12316 if (current_param.beaconInterval != operationParam->beaconInterval) {
12317 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12318 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12319 return RETURN_ERR;
12320 }
12321 }
12322 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12323 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12324 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12325 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12326 return RETURN_ERR;
12327 }
12328 }
12329 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12330 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12331 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12332 return RETURN_ERR;
12333 }
12334 }
12335 if (current_param.guardInterval != operationParam->guardInterval) {
12336 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12337 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12338 return RETURN_ERR;
12339 }
12340 }
12341 if (current_param.transmitPower != operationParam->transmitPower) {
12342 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12343 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12344 return RETURN_ERR;
12345 }
12346 }
12347 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12348 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12349 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12350 return RETURN_ERR;
12351 }
12352 }
12353 if (current_param.obssCoex != operationParam->obssCoex) {
12354 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12355 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12356 return RETURN_ERR;
12357 }
12358 }
12359 if (current_param.stbcEnable != operationParam->stbcEnable) {
12360 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12361 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12362 return RETURN_ERR;
12363 }
12364 }
developer5735d092023-09-19 20:12:26 +080012365 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12366 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12367 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12368 return RETURN_ERR;
12369 }
12370 }
developer1e5aa162022-09-13 16:06:24 +080012371
12372 // if enable is true, then restart the radio
12373 wifi_setRadioEnable(index, FALSE);
12374 if (operationParam->enable == TRUE)
12375 wifi_setRadioEnable(index, TRUE);
12376 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12377
developer06a01d92022-09-07 16:32:39 +080012378 return RETURN_OK;
12379}
12380
12381INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12382{
developer1e5aa162022-09-13 16:06:24 +080012383 char band[64] = {0};
12384 char buf[256] = {0};
12385 char config_file[64] = {0};
12386 char cmd[128] = {0};
12387 int ret = RETURN_ERR;
12388 int mode = 0;
12389 ULONG channel = 0;
12390 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012391
12392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12393 printf("Entering %s index = %d\n", __func__, (int)index);
12394
developer1e5aa162022-09-13 16:06:24 +080012395 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12396 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12397 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012398 {
developer1e5aa162022-09-13 16:06:24 +080012399 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012400 return RETURN_ERR;
12401 }
12402 operationParam->enable = enabled;
12403
12404 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012405 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012406 {
developer1e5aa162022-09-13 16:06:24 +080012407 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012408 return RETURN_ERR;
12409 }
12410
12411 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012412 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012413 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012414 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012415 else if (!strcmp(band, "6GHz"))
12416 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012417 else
12418 {
developer1e5aa162022-09-13 16:06:24 +080012419 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012420 band);
12421 }
12422
developer1e5aa162022-09-13 16:06:24 +080012423 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12424 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12425 operationParam->channel = 0;
12426 operationParam->autoChannelEnabled = TRUE;
12427 } else {
12428 operationParam->channel = strtol(buf, NULL, 10);
12429 operationParam->autoChannelEnabled = FALSE;
12430 }
12431
developer06a01d92022-09-07 16:32:39 +080012432 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012433 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12434 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12435 return RETURN_ERR;
12436 }
developer06a01d92022-09-07 16:32:39 +080012437 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12438 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12439 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012440 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012441 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12442 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012443 else
12444 {
developer1e5aa162022-09-13 16:06:24 +080012445 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12446 return false;
developer06a01d92022-09-07 16:32:39 +080012447 }
12448
developer7c4cd202023-03-01 10:56:29 +080012449 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12450 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12451 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12452 return RETURN_ERR;
12453 }
12454 }
12455
developer1e5aa162022-09-13 16:06:24 +080012456 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12457 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12458 return RETURN_ERR;
12459 }
12460 // Two different definition bit map, so need to check every bit.
12461 if (mode & WIFI_MODE_A)
12462 operationParam->variant |= WIFI_80211_VARIANT_A;
12463 if (mode & WIFI_MODE_B)
12464 operationParam->variant |= WIFI_80211_VARIANT_B;
12465 if (mode & WIFI_MODE_G)
12466 operationParam->variant |= WIFI_80211_VARIANT_G;
12467 if (mode & WIFI_MODE_N)
12468 operationParam->variant |= WIFI_80211_VARIANT_N;
12469 if (mode & WIFI_MODE_AC)
12470 operationParam->variant |= WIFI_80211_VARIANT_AC;
12471 if (mode & WIFI_MODE_AX)
12472 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012473 if (mode & WIFI_MODE_BE)
12474 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012475 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12476 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12477 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012478 }
developer1e5aa162022-09-13 16:06:24 +080012479 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12480 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12481 return RETURN_ERR;
12482 }
12483 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12484 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12485 return RETURN_ERR;
12486 }
developer06a01d92022-09-07 16:32:39 +080012487
developer1e5aa162022-09-13 16:06:24 +080012488 memset(buf, 0, sizeof(buf));
12489 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12490 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12491 return RETURN_ERR;
12492 }
12493 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12494
12495 memset(buf, 0, sizeof(buf));
12496 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12497 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12498 return RETURN_ERR;
12499 }
12500 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12501
12502 memset(buf, 0, sizeof(buf));
12503 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12504 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12505
12506 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12507 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12508 return RETURN_ERR;
12509 }
12510 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12511 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12512 return RETURN_ERR;
12513 }
12514
12515 memset(buf, 0, sizeof(buf));
12516 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12517 if (strcmp(buf, "-1") == 0) {
12518 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12519 operationParam->ctsProtection = FALSE;
12520 } else {
12521 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12522 operationParam->ctsProtection = TRUE;
12523 }
12524
12525 memset(buf, 0, sizeof(buf));
12526 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12527 if (strcmp(buf, "0") == 0)
12528 operationParam->obssCoex = FALSE;
12529 else
12530 operationParam->obssCoex = TRUE;
12531
12532 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12533 _syscmd(cmd, buf, sizeof(buf));
12534 if (strlen(buf) != 0)
12535 operationParam->stbcEnable = TRUE;
12536 else
12537 operationParam->stbcEnable = FALSE;
12538
developer5735d092023-09-19 20:12:26 +080012539 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12540 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12541 return RETURN_ERR;
12542 }
developer1e5aa162022-09-13 16:06:24 +080012543
12544 // Below value is hardcoded
12545
12546 operationParam->numSecondaryChannels = 0;
12547 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12548 operationParam->channelSecondary[i] = 0;
12549 }
12550 operationParam->csa_beacon_count = 15;
12551 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012552
12553 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12554 return RETURN_OK;
12555}
12556
12557static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12558{
developerc086fb72022-10-04 10:18:22 +080012559 int max_radio_num = 0;
12560
12561 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012562 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012563 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12564 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012565 }
12566
developerc086fb72022-10-04 10:18:22 +080012567 return (arrayIndex * max_radio_num) + radioIndex;
12568}
developer06a01d92022-09-07 16:32:39 +080012569
developerc086fb72022-10-04 10:18:22 +080012570wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12571 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12572 return WIFI_BITRATE_1MBPS;
12573 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12574 return WIFI_BITRATE_2MBPS;
12575 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12576 return WIFI_BITRATE_5_5MBPS;
12577 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12578 return WIFI_BITRATE_6MBPS;
12579 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12580 return WIFI_BITRATE_9MBPS;
12581 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12582 return WIFI_BITRATE_11MBPS;
12583 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12584 return WIFI_BITRATE_12MBPS;
12585 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12586 return WIFI_BITRATE_18MBPS;
12587 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12588 return WIFI_BITRATE_24MBPS;
12589 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12590 return WIFI_BITRATE_36MBPS;
12591 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12592 return WIFI_BITRATE_48MBPS;
12593 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12594 return WIFI_BITRATE_54MBPS;
12595 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012596}
12597
developer1d57d002022-10-12 18:03:15 +080012598INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12599{
12600 if (beacon == WIFI_BITRATE_1MBPS)
12601 strcpy(beacon_str, "1Mbps");
12602 else if (beacon == WIFI_BITRATE_2MBPS)
12603 strcpy(beacon_str, "2Mbps");
12604 else if (beacon == WIFI_BITRATE_5_5MBPS)
12605 strcpy(beacon_str, "5.5Mbps");
12606 else if (beacon == WIFI_BITRATE_6MBPS)
12607 strcpy(beacon_str, "6Mbps");
12608 else if (beacon == WIFI_BITRATE_9MBPS)
12609 strcpy(beacon_str, "9Mbps");
12610 else if (beacon == WIFI_BITRATE_11MBPS)
12611 strcpy(beacon_str, "11Mbps");
12612 else if (beacon == WIFI_BITRATE_12MBPS)
12613 strcpy(beacon_str, "12Mbps");
12614 else if (beacon == WIFI_BITRATE_18MBPS)
12615 strcpy(beacon_str, "18Mbps");
12616 else if (beacon == WIFI_BITRATE_24MBPS)
12617 strcpy(beacon_str, "24Mbps");
12618 else if (beacon == WIFI_BITRATE_36MBPS)
12619 strcpy(beacon_str, "36Mbps");
12620 else if (beacon == WIFI_BITRATE_48MBPS)
12621 strcpy(beacon_str, "48Mbps");
12622 else if (beacon == WIFI_BITRATE_54MBPS)
12623 strcpy(beacon_str, "54Mbps");
12624 return RETURN_OK;
12625}
12626
developer74ed4192023-09-21 17:15:17 +080012627void checkVapStatus(int apIndex, bool *enable)
12628{
12629 char if_name[16] = {0};
12630 char cmd[128] = {0};
12631 char buf[128] = {0};
12632
12633 *enable = FALSE;
12634 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12635 return;
12636
12637 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12638 _syscmd(cmd, buf, sizeof(buf));
12639 if (strlen(buf) > 0)
12640 *enable = TRUE;
12641 return;
12642}
12643
developer06a01d92022-09-07 16:32:39 +080012644INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12645{
developerc086fb72022-10-04 10:18:22 +080012646 INT mode = 0;
12647 INT ret = -1;
12648 INT output = 0;
12649 int i = 0;
12650 int vap_index = 0;
12651 BOOL enabled = FALSE;
12652 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012653 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012654
developer06a01d92022-09-07 16:32:39 +080012655
12656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12657 printf("Entering %s index = %d\n", __func__, (int)index);
12658
developera77d84b2023-02-22 16:10:50 +080012659 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012660 {
developerc086fb72022-10-04 10:18:22 +080012661 map->vap_array[i].radio_index = index;
12662
developer06a01d92022-09-07 16:32:39 +080012663 vap_index = array_index_to_vap_index(index, i);
12664 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012665 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012666
developerc086fb72022-10-04 10:18:22 +080012667 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012668
12669 map->vap_array[i].vap_index = vap_index;
12670
12671 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012672 ret = wifi_getApName(vap_index, buf);
12673 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012674 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12675
developerc086fb72022-10-04 10:18:22 +080012676 return RETURN_ERR;
12677 }
12678 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12679
12680 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012681 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012682 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012683 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012684 return RETURN_ERR;
12685 }
12686 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 +080012687
developer74ed4192023-09-21 17:15:17 +080012688 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012689 map->vap_array[i].u.bss_info.enabled = enabled;
12690
developerc086fb72022-10-04 10:18:22 +080012691 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12692 if (ret != RETURN_OK) {
12693 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12694 return RETURN_ERR;
12695 }
developer06a01d92022-09-07 16:32:39 +080012696 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012697
12698 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12699 if (ret != RETURN_OK) {
12700 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12701 return RETURN_ERR;
12702 }
12703 map->vap_array[i].u.bss_info.isolation = enabled;
12704
12705 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12706 if (ret != RETURN_OK) {
12707 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12708 return RETURN_ERR;
12709 }
12710 map->vap_array[i].u.bss_info.bssMaxSta = output;
12711
12712 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12713 if (ret != RETURN_OK) {
12714 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12715 return RETURN_ERR;
12716 }
12717 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012718
developerc086fb72022-10-04 10:18:22 +080012719 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12720 if (ret != RETURN_OK) {
12721 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12722 return RETURN_ERR;
12723 }
12724 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012725
developerc086fb72022-10-04 10:18:22 +080012726 ret = wifi_getApSecurity(vap_index, &security);
12727 if (ret != RETURN_OK) {
12728 printf("%s: wifi_getApSecurity return error\n", __func__);
12729 return RETURN_ERR;
12730 }
12731 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012732
developerc086fb72022-10-04 10:18:22 +080012733 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12734 if (ret != RETURN_OK) {
12735 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12736 return RETURN_ERR;
12737 }
12738 if (mode == 0)
12739 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12740 else
12741 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12742 if (mode == 1)
12743 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12744 else if (mode == 2)
12745 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012746
developerc086fb72022-10-04 10:18:22 +080012747 ret = wifi_getApWmmEnable(vap_index, &enabled);
12748 if (ret != RETURN_OK) {
12749 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12750 return RETURN_ERR;
12751 }
12752 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012753
developerc086fb72022-10-04 10:18:22 +080012754 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12755 if (ret != RETURN_OK) {
12756 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012757 return RETURN_ERR;
12758 }
developerc086fb72022-10-04 10:18:22 +080012759 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012760
12761 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012762 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012763 if (ret != RETURN_OK) {
12764 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12765 return RETURN_ERR;
12766 }
12767 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012768
developerc086fb72022-10-04 10:18:22 +080012769 memset(buf, 0, sizeof(buf));
12770 ret = wifi_getBaseBSSID(vap_index, buf);
12771 if (ret != RETURN_OK) {
12772 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12773 return RETURN_ERR;
12774 }
12775 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12776 &map->vap_array[i].u.bss_info.bssid[0],
12777 &map->vap_array[i].u.bss_info.bssid[1],
12778 &map->vap_array[i].u.bss_info.bssid[2],
12779 &map->vap_array[i].u.bss_info.bssid[3],
12780 &map->vap_array[i].u.bss_info.bssid[4],
12781 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012782 // 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]);
12783
12784 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12785 if (ret != RETURN_OK) {
12786 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12787 return RETURN_ERR;
12788 }
12789 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080012790
12791 ret = wifi_getApWpsEnable(vap_index, &enabled);
12792 if (ret != RETURN_OK) {
12793 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
12794 return RETURN_ERR;
12795 }
12796
12797 map->vap_array[i].u.bss_info.wps.enable = enabled;
12798
developera77d84b2023-02-22 16:10:50 +080012799 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012800 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012801 }
12802 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12803 return RETURN_OK;
12804}
12805
developer431128d2022-12-16 15:30:41 +080012806
developerd946fd62022-12-08 18:03:28 +080012807static int prepareInterface(UINT apIndex, char *new_interface)
12808{
12809 char cur_interface[16] = {0};
12810 char config_file[128] = {0};
12811 char cmd[128] = {0};
12812 char buf[16] = {0};
12813 int max_radio_num = 0;
12814 int radioIndex = -1;
12815 int phyIndex = -1;
12816
12817 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12818 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12819
12820 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12821 wifi_getMaxRadioNumber(&max_radio_num);
12822 radioIndex = apIndex % max_radio_num;
12823 phyIndex = radio_index_to_phy(radioIndex);
12824 // disable and del old interface, then add new interface
12825 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080012826 if (!(apIndex/max_radio_num)) {
12827 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12828 _syscmd(cmd, buf, sizeof(buf));
12829 }
developerd946fd62022-12-08 18:03:28 +080012830 }
developer431128d2022-12-16 15:30:41 +080012831 // update the vap status file
12832 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12833 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012834 return RETURN_OK;
12835}
12836
developer06a01d92022-09-07 16:32:39 +080012837INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12838{
developerd946fd62022-12-08 18:03:28 +080012839 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012840 unsigned int i;
12841 wifi_vap_info_t *vap_info = NULL;
12842 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012843 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012844 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012845 char buf[256] = {0};
12846 char cmd[128] = {0};
12847 char config_file[64] = {0};
12848 char bssid[32] = {0};
12849 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012850 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012851
12852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12853 printf("Entering %s index = %d\n", __func__, (int)index);
12854 for (i = 0; i < map->num_vaps; i++)
12855 {
developer1d57d002022-10-12 18:03:15 +080012856 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012857 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012858
12859 // Check vap status file to enable multiple ap if the system boot.
12860 checkVapStatus(vap_info->vap_index, &enable);
12861 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012862 continue;
developer06a01d92022-09-07 16:32:39 +080012863
developer1d57d002022-10-12 18:03:15 +080012864 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12865
developer431128d2022-12-16 15:30:41 +080012866 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12867 enable = FALSE;
12868
12869 // multi-ap first up need to copy current radio config
12870 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012871 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12872 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012873 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12874 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12875 } else {
12876 // Check whether the interface name is valid or this ap change it.
12877 int apIndex = -1;
12878 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12879 if (apIndex != -1 && apIndex != vap_info->vap_index)
12880 continue;
12881 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012882 }
developer06a01d92022-09-07 16:32:39 +080012883
developer1d57d002022-10-12 18:03:15 +080012884 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012885 params[0].name = "interface";
12886 params[0].value = vap_info->vap_name;
12887 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12888 params[1].name = "bssid";
12889 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012890 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012891 params[2].name = "wpa_psk_file";
12892 params[2].value = psk_file;
12893
12894 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12895 wifi_hostapdWrite(config_file, params, 3);
12896
12897 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12898 _syscmd(cmd, buf, sizeof(buf));
12899
12900 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12901 if (ret != RETURN_OK) {
12902 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12903 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012904 }
developer1d57d002022-10-12 18:03:15 +080012905
12906 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12907 if (ret != RETURN_OK) {
12908 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12909 return RETURN_ERR;
12910 }
12911
12912 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12913 if (ret != RETURN_OK) {
12914 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12915 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012916 }
12917
developer1d57d002022-10-12 18:03:15 +080012918 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12919 if (ret != RETURN_OK) {
12920 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12921 return RETURN_ERR;
12922 }
developer06a01d92022-09-07 16:32:39 +080012923
developer1d57d002022-10-12 18:03:15 +080012924 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12925 if (ret != RETURN_OK) {
12926 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12927 return RETURN_ERR;
12928 }
developer06a01d92022-09-07 16:32:39 +080012929
developer1d57d002022-10-12 18:03:15 +080012930 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12931 if (ret != RETURN_OK) {
12932 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12933 return RETURN_ERR;
12934 }
12935
developer804c64f2022-10-19 13:54:40 +080012936 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012937 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012938 }else {
12939 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012940 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012941 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12942 _syscmd(cmd, buf, sizeof(buf));
12943 }else{
developer1d57d002022-10-12 18:03:15 +080012944 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012945 }
developer1d57d002022-10-12 18:03:15 +080012946 }
12947
12948 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12949 if (ret != RETURN_OK) {
12950 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12951 return RETURN_ERR;
12952 }
12953
12954 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12955 if (ret != RETURN_OK) {
12956 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12957 return RETURN_ERR;
12958 }
12959
12960 memset(buf, 0, sizeof(buf));
12961 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12962 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12963 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12964 if (ret != RETURN_OK) {
12965 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12966 return RETURN_ERR;
12967 }
12968
developer1d57d002022-10-12 18:03:15 +080012969 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12970 if (ret != RETURN_OK) {
12971 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12972 return RETURN_ERR;
12973 }
12974
12975 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12976 if (ret != RETURN_OK) {
12977 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12978 return RETURN_ERR;
12979 }
developer06a01d92022-09-07 16:32:39 +080012980
developer894affa2023-05-10 18:13:19 +080012981 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
12982 if (ret != RETURN_OK) {
12983 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
12984 return RETURN_ERR;
12985 }
12986
developer2f995fb2023-02-24 10:40:44 +080012987 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080012988 if (vap_info->u.bss_info.enabled == TRUE)
12989 wifi_setApEnable(vap_info->vap_index, TRUE);
12990
developer2f995fb2023-02-24 10:40:44 +080012991 multiple_set = FALSE;
12992
12993 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080012994 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080012995 // The set wps methods function should check whether wps is configured.
12996 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
12997 if (ret != RETURN_OK) {
12998 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
12999 return RETURN_ERR;
13000 }
13001 // wifi_setApWpsConfigMethodsEnabled only write to config.
13002 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13003 if (ret != RETURN_OK) {
13004 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13005 return RETURN_ERR;
13006 }
13007 }
developer2f995fb2023-02-24 10:40:44 +080013008
developer894affa2023-05-10 18:13:19 +080013009 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013010 }
developerfb09ba62023-06-09 17:03:21 +080013011
13012 // IGMP Snooping enable should be placed after all hostapd_reload.
13013 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13014 if (ret != RETURN_OK) {
13015 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13016 return RETURN_ERR;
13017 }
13018
developer06a01d92022-09-07 16:32:39 +080013019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13020 return RETURN_OK;
13021}
13022
13023int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13024{
13025 char *token, *next;
13026 const char s[2] = ",";
13027 int count =0;
13028
13029 /* get the first token */
13030 token = strtok_r(pchannels, s, &next);
13031
13032 /* walk through other tokens */
13033 while( token != NULL && count < MAX_CHANNELS) {
13034 chlistptr->channels_list[count++] = atoi(token);
13035 token = strtok_r(NULL, s, &next);
13036 }
13037
13038 return count;
13039}
13040
13041static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13042{
13043 INT status;
13044 wifi_channels_list_t *chlistp;
13045 CHAR output_string[64];
13046 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013047 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013048 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013049
13050 if(rcap == NULL)
13051 {
13052 return RETURN_ERR;
13053 }
13054
13055 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013056 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013057
developer1e5aa162022-09-13 16:06:24 +080013058 if (band == band_2_4)
13059 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13060 else if (band == band_5)
13061 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13062 else if (band == band_6)
13063 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013064
13065 chlistp = &(rcap->channel_list[0]);
13066 memset(pchannels, 0, sizeof(pchannels));
13067
13068 /* possible number of radio channels */
13069 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13070 {
13071 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13072 }
13073 /* Number of channels and list*/
13074 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13075
13076 /* autoChannelSupported */
13077 /* always ON with wifi_getRadioAutoChannelSupported */
13078 rcap->autoChannelSupported = TRUE;
13079
13080 /* DCSSupported */
13081 /* always ON with wifi_getRadioDCSSupported */
13082 rcap->DCSSupported = TRUE;
13083
13084 /* zeroDFSSupported - TBD */
13085 rcap->zeroDFSSupported = FALSE;
13086
13087 /* Supported Country List*/
13088 memset(output_string, 0, sizeof(output_string));
13089 status = wifi_getRadioCountryCode(radioIndex, output_string);
13090 if( status != 0 ) {
13091 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13092 return RETURN_ERR;
13093 } else {
13094 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13095 }
13096 if(!strcmp(output_string,"US")){
13097 rcap->countrySupported[0] = wifi_countrycode_US;
13098 rcap->countrySupported[1] = wifi_countrycode_CA;
13099 } else if (!strcmp(output_string,"CA")) {
13100 rcap->countrySupported[0] = wifi_countrycode_CA;
13101 rcap->countrySupported[1] = wifi_countrycode_US;
13102 } else {
13103 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13104 }
13105
13106 rcap->numcountrySupported = 2;
13107
13108 /* csi */
13109 rcap->csi.maxDevices = 8;
13110 rcap->csi.soudingFrameSupported = TRUE;
13111
developer7930d352022-12-21 17:55:42 +080013112 wifi_GetInterfaceName(radioIndex, interface_name);
13113 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013114
13115 /* channelWidth - all supported bandwidths */
13116 int i=0;
13117 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013118
13119 /* mode - all supported variants */
13120 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13121 wifi_getRadioSupportedStandards(radioIndex, output_string);
13122
developer06a01d92022-09-07 16:32:39 +080013123 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13124 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13125 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013126 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013127
developer7c4cd202023-03-01 10:56:29 +080013128 if (strstr(output_string, "n") != NULL)
13129 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13130 if (strstr(output_string, "ax") != NULL)
13131 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13132 if (strstr(output_string, "be") != NULL)
13133 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13134 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013135 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13136 WIFI_CHANNELBANDWIDTH_40MHZ |
13137 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013138 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013139
developer7c4cd202023-03-01 10:56:29 +080013140 if (strstr(output_string, "n") != NULL)
13141 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13142 if (strstr(output_string, "ac") != NULL)
13143 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13144 if (strstr(output_string, "ax") != NULL)
13145 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13146 if (strstr(output_string, "be") != NULL)
13147 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13148 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13149 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13150 WIFI_CHANNELBANDWIDTH_40MHZ |
13151 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013152 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013153
13154 if (strstr(output_string, "be") != NULL) {
13155 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13156 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13157 }
developer06a01d92022-09-07 16:32:39 +080013158 }
developer7c4cd202023-03-01 10:56:29 +080013159
developer06a01d92022-09-07 16:32:39 +080013160 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13161 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13162
13163 /* supportedBitRate - all supported bitrates */
13164 rcap->supportedBitRate[i] = 0;
13165 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13166 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13167 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13168 }
developer1e5aa162022-09-13 16:06:24 +080013169 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013170 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13171 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13172 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13173 }
13174
13175
13176 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13177 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13178 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13179 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13180 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13181 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13182 rcap->cipherSupported = 0;
13183 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13184 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13185
13186 return RETURN_OK;
13187}
13188
13189INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13190{
developer30423732022-12-01 16:17:49 +080013191 INT status = 0, radioIndex = 0;
13192 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013193 int iter = 0;
developer30423732022-12-01 16:17:49 +080013194 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013195 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013196 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013197
13198 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13199
13200 memset(cap, 0, sizeof(wifi_hal_capability_t));
13201
13202 /* version */
13203 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13204 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13205
13206 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013207 wifi_getMaxRadioNumber(&max_num_radios);
13208 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013209
13210 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13211 {
13212 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13213 if (status != 0) {
13214 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13215 return RETURN_ERR;
13216 }
13217
13218 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13219 {
developer804c64f2022-10-19 13:54:40 +080013220 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013221 {
13222 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13223 return RETURN_ERR;
13224 }
13225 iface_info = &cap->wifi_prop.interface_map[iter];
13226 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13227 iface_info->rdk_radio_index = radioIndex;
13228 memset(output, 0, sizeof(output));
13229 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13230 {
13231 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13232 }
13233 // TODO: bridge name
13234 // TODO: vlan id
13235 // TODO: primary
13236 iface_info->index = array_index_to_vap_index(radioIndex, j);
13237 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013238 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013239 {
13240 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13241 }
13242 iter++;
13243 }
13244 }
13245
13246 cap->BandSteeringSupported = FALSE;
13247 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13248 return RETURN_OK;
13249}
13250
developer9df4e652022-10-11 11:27:38 +080013251INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13252{
13253 struct params h_config={0};
13254 char config_file[64] = {0};
13255
13256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13257
13258 h_config.name = "okc";
13259 h_config.value = okc_enable?"1":"0";
13260
13261 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13262 wifi_hostapdWrite(config_file, &h_config, 1);
13263 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13264
13265 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13266 return RETURN_OK;
13267}
13268
13269INT wifi_setSAEMFP(int ap_index, BOOL enable)
13270{
13271 struct params h_config={0};
13272 char config_file[64] = {0};
13273 char buf[128] = {0};
13274
13275 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13276
13277 h_config.name = "sae_require_mfp";
13278 h_config.value = enable?"1":"0";
13279
13280 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13281 wifi_hostapdWrite(config_file, &h_config, 1);
13282 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13283
13284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13285 return RETURN_OK;
13286}
13287
13288INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13289{
13290 struct params h_config={0};
13291 char config_file[64] = {0};
13292 char buf[128] = {0};
13293
13294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13295
13296 h_config.name = "sae_pwe";
13297 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13298 h_config.value = buf;
13299
13300 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13301 wifi_hostapdWrite(config_file, &h_config, 1);
13302 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13303
13304 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13305 return RETURN_OK;
13306}
13307
13308INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13309{
13310 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13311 struct params h_config={0};
13312 char config_file[64] = {0};
13313
13314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13315
13316 h_config.name = "wpa_disable_eapol_key_retries";
13317 h_config.value = disable_EAPOL_retries?"1":"0";
13318
13319 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13320 wifi_hostapdWrite(config_file, &h_config, 1);
13321 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13322
13323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13324 return RETURN_OK;
13325}
13326
developer06a01d92022-09-07 16:32:39 +080013327INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13328{
developer587c1b62022-09-27 15:58:59 +080013329 char buf[128] = {0};
13330 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013331 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013332 char password[64] = {0};
13333 char mfp[32] = {0};
13334 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013335 BOOL okc_enable = FALSE;
13336 BOOL sae_MFP = FALSE;
13337 BOOL disable_EAPOL_retries = TRUE;
13338 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013339 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013340 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013341
13342 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13343
13344 multiple_set = TRUE;
13345 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13346 if (security->mode == wifi_security_mode_none) {
13347 strcpy(wpa_mode, "None");
13348 } else if (security->mode == wifi_security_mode_wpa_personal)
13349 strcpy(wpa_mode, "WPA-Personal");
13350 else if (security->mode == wifi_security_mode_wpa2_personal)
13351 strcpy(wpa_mode, "WPA2-Personal");
13352 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13353 strcpy(wpa_mode, "WPA-WPA2-Personal");
13354 else if (security->mode == wifi_security_mode_wpa_enterprise)
13355 strcpy(wpa_mode, "WPA-Enterprise");
13356 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13357 strcpy(wpa_mode, "WPA2-Enterprise");
13358 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13359 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013360 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013361 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013362 okc_enable = TRUE;
13363 sae_MFP = TRUE;
13364 sae_pwe = 2;
13365 disable_EAPOL_retries = FALSE;
13366 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013367 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013368 okc_enable = TRUE;
13369 sae_MFP = TRUE;
13370 sae_pwe = 2;
13371 disable_EAPOL_retries = FALSE;
13372 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013373 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013374 sae_MFP = TRUE;
13375 sae_pwe = 2;
13376 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013377 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013378 strcpy(wpa_mode, "OWE");
13379 sae_MFP = TRUE;
13380 sae_pwe = 2;
13381 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013382 }
13383
13384 band = wifi_index_to_band(ap_index);
13385 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13386 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13387 return RETURN_ERR;
13388 }
developer587c1b62022-09-27 15:58:59 +080013389
13390 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013391 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013392 wifi_setSAEMFP(ap_index, sae_MFP);
13393 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013394 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013395
developerae432c62023-04-24 11:07:20 +080013396 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013397 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) {
13398 int key_len = strlen(security->u.key.key);
13399 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13400 if (key_len == 64) { // set wpa_psk
13401 strncpy(password, security->u.key.key, 64); // 64 characters
13402 password[64] = '\0';
13403 wifi_setApSecurityPreSharedKey(ap_index, password);
13404 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13405 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13406 strncpy(password, security->u.key.key, 63);
13407 password[63] = '\0';
13408 wifi_setApSecurityKeyPassphrase(ap_index, password);
13409 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13410 } else
13411 return RETURN_ERR;
13412 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013413 }
13414 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13415 params.name = "sae_password";
13416 params.value = security->u.key.key;
13417 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013418 } else { // remove sae_password
13419 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13420 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013421 }
13422 }
developer587c1b62022-09-27 15:58:59 +080013423
13424 if (security->mode != wifi_security_mode_none) {
13425 memset(&params, 0, sizeof(params));
13426 params.name = "wpa_pairwise";
13427 if (security->encr == wifi_encryption_tkip)
13428 params.value = "TKIP";
13429 else if (security->encr == wifi_encryption_aes)
13430 params.value = "CCMP";
13431 else if (security->encr == wifi_encryption_aes_tkip)
13432 params.value = "TKIP CCMP";
13433 wifi_hostapdWrite(config_file, &params, 1);
13434 }
13435
13436 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013437 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013438 else if (security->mfp == wifi_mfp_cfg_optional)
13439 strcpy(mfp, "Optional");
13440 else if (security->mfp == wifi_mfp_cfg_required)
13441 strcpy(mfp, "Required");
13442 wifi_setApSecurityMFPConfig(ap_index, mfp);
13443
13444 memset(&params, 0, sizeof(params));
13445 params.name = "transition_disable";
13446 if (security->wpa3_transition_disable == TRUE)
13447 params.value = "0x01";
13448 else
13449 params.value = "0x00";
13450 wifi_hostapdWrite(config_file, &params, 1);
13451
13452 memset(&params, 0, sizeof(params));
13453 params.name = "wpa_group_rekey";
13454 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13455 params.value = buf;
13456 wifi_hostapdWrite(config_file, &params, 1);
13457
13458 memset(&params, 0, sizeof(params));
13459 params.name = "wpa_strict_rekey";
13460 params.value = security->strict_rekey?"1":"0";
13461 wifi_hostapdWrite(config_file, &params, 1);
13462
13463 memset(&params, 0, sizeof(params));
13464 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013465 if (security->eapol_key_retries == 0)
13466 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013467 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13468 params.value = buf;
13469 wifi_hostapdWrite(config_file, &params, 1);
13470
13471 memset(&params, 0, sizeof(params));
13472 params.name = "disable_pmksa_caching";
13473 params.value = security->disable_pmksa_caching?"1":"0";
13474 wifi_hostapdWrite(config_file, &params, 1);
13475
developer23e71282023-01-18 10:25:19 +080013476 if (multiple_set == FALSE) {
13477 wifi_setApEnable(ap_index, FALSE);
13478 wifi_setApEnable(ap_index, TRUE);
13479 }
developer587c1b62022-09-27 15:58:59 +080013480
13481 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13482
developer06a01d92022-09-07 16:32:39 +080013483 return RETURN_OK;
13484}
13485
13486INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13487{
developer9df4e652022-10-11 11:27:38 +080013488 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013489 char config_file[128] = {0};
13490 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013491 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013492
13493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13494 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13495 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13496 security->mode = wifi_security_mode_none;
13497 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013498 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013499 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013500 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013501 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013502 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013503 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013504 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013505 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013506 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013507 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013508 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013509 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013510 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013511 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013512 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013513 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013514 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013515 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013516 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013517 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013518 }
13519
13520 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13521 if (security->mode == wifi_security_mode_none)
13522 security->encr = wifi_encryption_none;
13523 else {
13524 if (strcmp(buf, "TKIP") == 0)
13525 security->encr = wifi_encryption_tkip;
13526 else if (strcmp(buf, "CCMP") == 0)
13527 security->encr = wifi_encryption_aes;
13528 else
13529 security->encr = wifi_encryption_aes_tkip;
13530 }
13531
developer9df4e652022-10-11 11:27:38 +080013532 if (security->mode != wifi_encryption_none) {
13533 memset(buf, 0, sizeof(buf));
13534 // wpa3 can use one or both configs as password, so we check sae_password first.
13535 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013536 if (strlen(buf) != 0) {
13537 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13538 security->u.key.type = wifi_security_key_type_sae;
13539 set_sae = TRUE;
13540 strncpy(security->u.key.key, buf, sizeof(buf));
13541 }
13542 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13543 if (strlen(buf) != 0){
13544 if (set_sae == TRUE)
13545 security->u.key.type = wifi_security_key_type_psk_sae;
13546 else if (strlen(buf) == 64)
13547 security->u.key.type = wifi_security_key_type_psk;
13548 else
13549 security->u.key.type = wifi_security_key_type_pass;
13550 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013551 }
developer9df4e652022-10-11 11:27:38 +080013552 security->u.key.key[255] = '\0';
13553 }
13554
developer587c1b62022-09-27 15:58:59 +080013555 memset(buf, 0, sizeof(buf));
13556 wifi_getApSecurityMFPConfig(ap_index, buf);
13557 if (strcmp(buf, "Disabled") == 0)
13558 security->mfp = wifi_mfp_cfg_disabled;
13559 else if (strcmp(buf, "Optional") == 0)
13560 security->mfp = wifi_mfp_cfg_optional;
13561 else if (strcmp(buf, "Required") == 0)
13562 security->mfp = wifi_mfp_cfg_required;
13563
13564 memset(buf, 0, sizeof(buf));
13565 security->wpa3_transition_disable = FALSE;
13566 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13567 disable = strtol(buf, NULL, 16);
13568 if (disable != 0)
13569 security->wpa3_transition_disable = TRUE;
13570
13571 memset(buf, 0, sizeof(buf));
13572 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13573 if (strlen(buf) == 0)
13574 security->rekey_interval = 86400;
13575 else
13576 security->rekey_interval = strtol(buf, NULL, 10);
13577
13578 memset(buf, 0, sizeof(buf));
13579 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13580 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013581 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013582 else
13583 security->strict_rekey = strtol(buf, NULL, 10);
13584
13585 memset(buf, 0, sizeof(buf));
13586 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13587 if (strlen(buf) == 0)
13588 security->eapol_key_retries = 4;
13589 else
13590 security->eapol_key_retries = strtol(buf, NULL, 10);
13591
13592 memset(buf, 0, sizeof(buf));
13593 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13594 if (strlen(buf) == 0)
13595 security->disable_pmksa_caching = FALSE;
13596 else
13597 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13598
13599 /* TODO
13600 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13601 */
13602 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13603 security->eap_identity_req_timeout = 0;
13604 security->eap_identity_req_retries = 0;
13605 security->eap_req_timeout = 0;
13606 security->eap_req_retries = 0;
13607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013608 return RETURN_OK;
13609}
13610
13611#endif /* WIFI_HAL_VERSION_3 */
13612
13613#ifdef WIFI_HAL_VERSION_3_PHASE2
13614INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13615{
developerd946fd62022-12-08 18:03:28 +080013616 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013617 char cmd[128] = {0};
13618 char buf[128] = {0};
13619 char *mac_addr = NULL;
13620 BOOL status = FALSE;
13621 size_t len = 0;
13622
13623 if(ap_index > MAX_APS)
13624 return RETURN_ERR;
13625
13626 *output_numDevices = 0;
13627 wifi_getApEnable(ap_index, &status);
13628 if (status == FALSE)
13629 return RETURN_OK;
13630
developerac6f1142022-12-20 19:26:35 +080013631 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013632 return RETURN_ERR;
13633 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013634 _syscmd(cmd, buf, sizeof(buf));
13635
13636 mac_addr = strtok(buf, "\n");
13637 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13638 *output_numDevices = i + 1;
13639 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13640 addr_ptr = output_deviceMacAddressArray[i];
13641 mac_addr_aton(addr_ptr, mac_addr);
13642 mac_addr = strtok(NULL, "\n");
13643 }
13644
13645 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013646}
13647#else
13648INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13649{
developerd946fd62022-12-08 18:03:28 +080013650 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013651 char cmd[128];
13652 BOOL status = false;
13653
13654 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13655 return RETURN_ERR;
13656
13657 output_buf[0] = '\0';
13658
13659 wifi_getApEnable(ap_index,&status);
13660 if (!status)
13661 return RETURN_OK;
13662
developerac6f1142022-12-20 19:26:35 +080013663 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013664 return RETURN_ERR;
13665 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013666 _syscmd(cmd, output_buf, output_buf_size);
13667
13668 return RETURN_OK;
13669}
13670#endif
developer2f513ab2022-09-13 14:26:06 +080013671
13672INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13673{
13674 char output[16]={'\0'};
13675 char config_file[MAX_BUF_SIZE] = {0};
13676
13677 if (!enable)
13678 return RETURN_ERR;
13679
13680 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13681 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13682
13683 if (strlen(output) == 0)
13684 *enable = FALSE;
13685 else if (strncmp(output, "1", 1) == 0)
13686 *enable = TRUE;
13687 else
13688 *enable = FALSE;
13689
13690 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13691 return RETURN_OK;
13692}
developer2d9c30f2022-09-13 15:06:14 +080013693
13694INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13695{
developer804c64f2022-10-19 13:54:40 +080013696 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013697 return RETURN_ERR;
13698 *output_enable=TRUE;
13699 return RETURN_OK;
13700}
developerfd7d2892022-09-13 16:44:53 +080013701
13702INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13703{
13704 char cmd[128] = {0};
13705 char buf[128] = {0};
13706 char line[128] = {0};
13707 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013708 FILE *f = NULL;
13709 int index = 0;
13710 int exp = 0;
13711 int mantissa = 0;
13712 int duration = 0;
13713 int radio_index = 0;
13714 int max_radio_num = 0;
13715 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013716 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013717 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13718
13719 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013720
developerfd7d2892022-09-13 16:44:53 +080013721 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013722
13723 phyId = radio_index_to_phy(radio_index);
13724 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013725 _syscmd(cmd, buf, sizeof(buf));
13726 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13727 if (*numSessionReturned > maxNumberSessions)
13728 *numSessionReturned = maxNumberSessions;
13729 else if (*numSessionReturned < 1) {
13730 *numSessionReturned = 0;
13731 return RETURN_OK;
13732 }
13733
developer033b37b2022-10-18 11:27:46 +080013734 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 +080013735 if ((f = popen(cmd, "r")) == NULL) {
13736 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13737 return RETURN_ERR;
13738 }
13739
13740 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013741 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013742 char *tmp = NULL;
13743 strcpy(buf, line);
13744 tmp = strtok(buf, " ");
13745 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13746 tmp = strtok(NULL, " ");
13747 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13748 tmp = strtok(NULL, " ");
13749 if (strstr(tmp, "t")) {
13750 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13751 }
13752 if (strstr(tmp, "a")) {
13753 twtSessions[index].twtParameters.operation.announced = TRUE;
13754 }
13755 tmp = strtok(NULL, " ");
13756 exp = strtol(tmp, NULL, 10);
13757 tmp = strtok(NULL, " ");
13758 mantissa = strtol(tmp, NULL, 10);
13759 tmp = strtok(NULL, " ");
13760 duration = strtol(tmp, NULL, 10);
13761
13762 // only implicit supported
13763 twtSessions[index].twtParameters.operation.implicit = TRUE;
13764 // only individual agreement supported
13765 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13766
13767 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13768 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013769 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013770 // Overflow handling
13771 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13772 } else {
13773 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13774 }
13775 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13776 index++;
13777 }
13778
13779 pclose(f);
13780 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13781 return RETURN_OK;
13782}