blob: 7a5e659d06ebd01a188ebc21f4b02a7a2f470ba8 [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
developer804c64f2022-10-19 13:54:40 +080097#define MAX_APS MAX_NUM_RADIOS*5
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
developer0947e1a2022-09-13 14:15:25 +0800106#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800107
108//Uncomment to enable debug logs
109//#define WIFI_DEBUG
110
111#ifdef WIFI_DEBUG
112#define wifi_dbg_printf printf
113#define WIFI_ENTRY_EXIT_DEBUG printf
114#else
115#define wifi_dbg_printf(format, args...) printf("")
116#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
117#endif
118
119#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
120#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
121#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
122#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
123#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
124#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
125#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
126#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
127#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
128#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
129
developer4fb0b922022-09-30 14:29:09 +0800130#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800131
132#define BW_FNAME "/nvram/bw_file.txt"
133
134#define PS_MAX_TID 16
135
136static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
137 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
138 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
139 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
141 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
142 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
143 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
144 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
153};
154
155typedef unsigned long long u64;
156
157/* Enum to define WiFi Bands */
158typedef enum
159{
160 band_invalid = -1,
161 band_2_4 = 0,
162 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800163 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800164} wifi_band;
165
developerdb744382022-09-13 15:34:54 +0800166typedef enum {
167 WIFI_MODE_A = 0x01,
168 WIFI_MODE_B = 0x02,
169 WIFI_MODE_G = 0x04,
170 WIFI_MODE_N = 0x08,
171 WIFI_MODE_AC = 0x10,
172 WIFI_MODE_AX = 0x20,
173} wifi_ieee80211_Mode;
174
developer06a01d92022-09-07 16:32:39 +0800175#ifdef WIFI_HAL_VERSION_3
176
177// Return number of elements in array
178#ifndef ARRAY_SIZE
179#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
180#endif /* ARRAY_SIZE */
181
182#ifndef ARRAY_AND_SIZE
183#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
184#endif /* ARRAY_AND_SIZE */
185
186#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
187
188typedef struct {
189 int32_t value;
190 int32_t param;
191 intptr_t key;
192 intptr_t data;
193} wifi_secur_list;
194
developerfa41b1f2023-01-06 10:25:51 +0800195static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
196static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer06a01d92022-09-07 16:32:39 +0800197wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
198wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
199char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800200static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800201
202static wifi_secur_list map_security[] =
203{
204 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
205 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
206 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
207 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
208 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800212 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800214 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800215 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800216};
217
218wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
219{
220 wifi_secur_list *item;
221 int i;
222
223 for (item = list,i = 0;i < list_sz; item++, i++) {
224 if ((int)(item->key) == key) {
225 return item;
226 }
227 }
228
229 return NULL;
230}
231
232char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
233{
234 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
235
236 if (!item) {
237 return "";
238 }
239
240 return (char *)(item->data);
241}
242
243wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
244{
245 wifi_secur_list *item;
246 int i;
247
248 for (item = list,i = 0;i < list_sz; item++, i++) {
249 if (strcmp((char *)(item->data), str) == 0) {
250 return item;
251 }
252 }
253
254 return NULL;
255}
256#endif /* WIFI_HAL_VERSION_3 */
257
258#ifdef HAL_NETLINK_IMPL
259typedef struct {
260 int id;
261 struct nl_sock* socket;
262 struct nl_cb* cb;
263} Netlink;
264
265static int mac_addr_aton(unsigned char *mac_addr, char *arg)
266{
267 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800268 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 +0800269 mac_addr[0] = mac_addr_int[0];
270 mac_addr[1] = mac_addr_int[1];
271 mac_addr[2] = mac_addr_int[2];
272 mac_addr[3] = mac_addr_int[3];
273 mac_addr[4] = mac_addr_int[4];
274 mac_addr[5] = mac_addr_int[5];
275 return 0;
276}
277
278static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
279{
280 unsigned int mac_addr_int[6]={};
281 mac_addr_int[0] = arg[0];
282 mac_addr_int[1] = arg[1];
283 mac_addr_int[2] = arg[2];
284 mac_addr_int[3] = arg[3];
285 mac_addr_int[4] = arg[4];
286 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800287 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 +0800288 return;
289}
290
291static int ieee80211_frequency_to_channel(int freq)
292{
developerf5745ee2022-10-05 16:09:53 +0800293 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800294 if (freq == 2484)
295 return 14;
developerf5745ee2022-10-05 16:09:53 +0800296 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
297 else if (freq == 5935)
298 return 2;
developer06a01d92022-09-07 16:32:39 +0800299 else if (freq < 2484)
300 return (freq - 2407) / 5;
301 else if (freq >= 4910 && freq <= 4980)
302 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800303 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800304 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800305 else if (freq <= 45000) /* DMG band lower limit */
306 /* see 802.11ax D6.1 27.3.23.2 */
307 return (freq - 5950) / 5;
308 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800309 return (freq - 56160) / 2160;
310 else
311 return 0;
312}
313
314static int initSock80211(Netlink* nl) {
315 nl->socket = nl_socket_alloc();
316 if (!nl->socket) {
317 fprintf(stderr, "Failing to allocate the sock\n");
318 return -ENOMEM;
319 }
320
321 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
322
323 if (genl_connect(nl->socket)) {
324 fprintf(stderr, "Failed to connect\n");
325 nl_close(nl->socket);
326 nl_socket_free(nl->socket);
327 return -ENOLINK;
328 }
329
330 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
331 if (nl->id< 0) {
332 fprintf(stderr, "interface not found.\n");
333 nl_close(nl->socket);
334 nl_socket_free(nl->socket);
335 return -ENOENT;
336 }
337
338 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
339 if ((!nl->cb)) {
340 fprintf(stderr, "Failed to allocate netlink callback.\n");
341 nl_close(nl->socket);
342 nl_socket_free(nl->socket);
343 return ENOMEM;
344 }
345
346 return nl->id;
347}
348
349static int nlfree(Netlink *nl)
350{
351 nl_cb_put(nl->cb);
352 nl_close(nl->socket);
353 nl_socket_free(nl->socket);
354 return 0;
355}
356
357static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
358 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
359 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
360 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
361};
362
363static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
364};
365
366static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
367};
368
369typedef struct _wifi_channelStats_loc {
370 INT array_size;
371 INT ch_number;
372 BOOL ch_in_pool;
373 INT ch_noise;
374 BOOL ch_radar_noise;
375 INT ch_max_80211_rssi;
376 INT ch_non_80211_noise;
377 INT ch_utilization;
378 ULLONG ch_utilization_total;
379 ULLONG ch_utilization_busy;
380 ULLONG ch_utilization_busy_tx;
381 ULLONG ch_utilization_busy_rx;
382 ULLONG ch_utilization_busy_self;
383 ULLONG ch_utilization_busy_ext;
384} wifi_channelStats_t_loc;
385
386typedef struct wifi_device_info {
387 INT wifi_devIndex;
388 UCHAR wifi_devMacAddress[6];
389 CHAR wifi_devIPAddress[64];
390 BOOL wifi_devAssociatedDeviceAuthentiationState;
391 INT wifi_devSignalStrength;
392 INT wifi_devTxRate;
393 INT wifi_devRxRate;
394} wifi_device_info_t;
395
396#endif
397
398//For 5g Alias Interfaces
399static BOOL priv_flag = TRUE;
400static BOOL pub_flag = TRUE;
401static BOOL Radio_flag = TRUE;
402//wifi_setApBeaconRate(1, beaconRate);
403
developer1e5aa162022-09-13 16:06:24 +0800404BOOL multiple_set = FALSE;
405
developer06a01d92022-09-07 16:32:39 +0800406struct params
407{
408 char * name;
409 char * value;
410};
411
412static int _syscmd(char *cmd, char *retBuf, int retBufSize)
413{
414 FILE *f;
415 char *ptr = retBuf;
416 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
417
418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
419 if((f = popen(cmd, "r")) == NULL) {
420 fprintf(stderr,"\npopen %s error\n", cmd);
421 return RETURN_ERR;
422 }
423
424 while(!feof(f))
425 {
426 *ptr = 0;
427 if(bufSize>=128) {
428 bufbytes=128;
429 } else {
430 bufbytes=bufSize-1;
431 }
432
433 fgets(ptr,bufbytes,f);
434 readbytes=strlen(ptr);
435
436 if(!readbytes)
437 break;
438
439 bufSize-=readbytes;
440 ptr += readbytes;
441 }
442 cmd_ret = pclose(f);
443 retBuf[retBufSize-1]=0;
444 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
445
446 return cmd_ret >> 8;
447}
448
developer033b37b2022-10-18 11:27:46 +0800449INT radio_index_to_phy(int radioIndex)
450{
451 char cmd[128] = {0};
452 char buf[64] = {0};
453 int phyIndex = 0;
454 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
455 _syscmd(cmd, buf, sizeof(buf));
456
457 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800458 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800459 return RETURN_ERR;
460 }
461 sscanf(buf, "phy%d", &phyIndex);
462
463 return phyIndex;
464}
developer026ac9e2022-11-07 13:46:24 +0800465
developer431128d2022-12-16 15:30:41 +0800466INT wifi_getMaxRadioNumber(INT *max_radio_num)
467{
468 char cmd[64] = {0};
469 char buf[4] = {0};
470
471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
472
473 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
474 _syscmd(cmd, buf, sizeof(buf));
475 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
476
477 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
478
479 return RETURN_OK;
480}
481
482wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800483{
484 char cmd[128] = {0};
485 char buf[64] = {0};
developer026ac9e2022-11-07 13:46:24 +0800486 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800487 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800488 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800489 int radioIndex = 0;
490 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800491 wifi_band band = band_invalid;
492
493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800494
developer431128d2022-12-16 15:30:41 +0800495 wifi_getMaxRadioNumber(&max_radio_num);
496 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800497 phyIndex = radio_index_to_phy(radioIndex);
developer5884e982022-10-06 10:52:50 +0800498 while(i < 10){
developer026ac9e2022-11-07 13:46:24 +0800499 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800500 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800501 nl80211_band = strtol(buf, NULL, 10);
502 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800503 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800504 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800505 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800506 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800507 band = band_6;
508
509 if(band != band_invalid)
510 break;
511
512 i++;
513 sleep(1);
514 }
developerc707e972022-09-13 15:38:02 +0800515
516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
517 return band;
518}
519
developer06a01d92022-09-07 16:32:39 +0800520static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
521{
522 char cmd[MAX_CMD_SIZE]={'\0'};
523 char buf[MAX_BUF_SIZE]={'\0'};
524 int ret = 0;
525
developerd946fd62022-12-08 18:03:28 +0800526 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
developer06a01d92022-09-07 16:32:39 +0800527 ret = _syscmd(cmd, buf, sizeof(buf));
528 if ((ret != 0) && (strlen(buf) == 0))
529 return -1;
530 snprintf(output, output_size, "%s", buf);
531
532 return 0;
533}
534
535static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
536{
537 char cmd[MAX_CMD_SIZE]={'\0'};
538 char buf[MAX_BUF_SIZE]={'\0'};
539
540 for(int i=0;i<item_count;i++)
541 {
542 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
543 if (strlen(buf) == 0) //Insert
544 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
545 else //Update
546 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developer5884e982022-10-06 10:52:50 +0800547
developer06a01d92022-09-07 16:32:39 +0800548 if(_syscmd(cmd, buf, sizeof(buf)))
549 return -1;
550 }
551
552 return 0;
553}
554
developerd946fd62022-12-08 18:03:28 +0800555//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800556static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800557{
558 char config_file[128] = {0};
559
560 if (interface_name == NULL)
561 return RETURN_ERR;
562
563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
564
565 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
566 wifi_hostapdRead(config_file, "interface", interface_name, 16);
567 if (strlen(interface_name) == 0)
568 return RETURN_ERR;
569
570 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
571 return RETURN_OK;
572}
573
developerac6f1142022-12-20 19:26:35 +0800574// wifi agent will call this function, do not change the parameter
575void GetInterfaceName(char *interface_name, char *conf_file)
576{
577 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
578 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
580}
581
developer06a01d92022-09-07 16:32:39 +0800582static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
583{
developerd946fd62022-12-08 18:03:28 +0800584 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800585 if (multiple_set == TRUE)
586 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800587 char cmd[MAX_CMD_SIZE]="", output[32]="";
588 FILE *fp;
589 int i;
590 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800591 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800592 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800593 for(i=0; i<item_count; i++, list++)
594 {
developerd946fd62022-12-08 18:03:28 +0800595 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800596 if((fp = popen(cmd, "r"))==NULL)
597 {
598 perror("popen failed");
599 return -1;
600 }
601 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
602 {
603 pclose(fp);
604 perror("fgets failed");
605 return -1;
606 }
607 pclose(fp);
608 }
609 return 0;
610}
611
612static int wifi_reloadAp(int apIndex)
613{
developerd946fd62022-12-08 18:03:28 +0800614 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800615 if (multiple_set == TRUE)
616 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800617 char cmd[MAX_CMD_SIZE]="";
618 char buf[MAX_BUF_SIZE]="";
619
developerac6f1142022-12-20 19:26:35 +0800620 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800621 return RETURN_ERR;
622 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800623 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
624 return RETURN_ERR;
625
developerd946fd62022-12-08 18:03:28 +0800626 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800627 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
628 return RETURN_ERR;
629
developerd946fd62022-12-08 18:03:28 +0800630 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800631 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
632 return RETURN_ERR;
633
634 return RETURN_OK;
635}
636
developer06a01d92022-09-07 16:32:39 +0800637INT File_Reading(CHAR *file, char *Value)
638{
639 FILE *fp = NULL;
640 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
641 int count = 0;
642
643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
644 fp = popen(file,"r");
645 if(fp == NULL)
646 return RETURN_ERR;
647
648 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
649 {
650 for(count=0;buf[count]!='\n';count++)
651 copy_buf[count]=buf[count];
652 copy_buf[count]='\0';
653 }
654 strcpy(Value,copy_buf);
655 pclose(fp);
656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
657
658 return RETURN_OK;
659}
660
661void wifi_RestartHostapd_2G()
662{
663 int Public2GApIndex = 4;
664
665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
666 wifi_setApEnable(Public2GApIndex, FALSE);
667 wifi_setApEnable(Public2GApIndex, TRUE);
668 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
669}
670
671void wifi_RestartHostapd_5G()
672{
673 int Public5GApIndex = 5;
674
675 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
676 wifi_setApEnable(Public5GApIndex, FALSE);
677 wifi_setApEnable(Public5GApIndex, TRUE);
678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
679}
680
681void wifi_RestartPrivateWifi_2G()
682{
683 int PrivateApIndex = 0;
684
685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
686 wifi_setApEnable(PrivateApIndex, FALSE);
687 wifi_setApEnable(PrivateApIndex, TRUE);
688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
689}
690
691void wifi_RestartPrivateWifi_5G()
692{
693 int Private5GApIndex = 1;
694
695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
696 wifi_setApEnable(Private5GApIndex, FALSE);
697 wifi_setApEnable(Private5GApIndex, TRUE);
698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
699}
700
701static int writeBandWidth(int radioIndex,char *bw_value)
702{
703 char buf[MAX_BUF_SIZE];
704 char cmd[MAX_CMD_SIZE];
705
706 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
707 if(_syscmd(cmd, buf, sizeof(buf)))
708 {
709 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
710 _syscmd(cmd, buf, sizeof(buf));
711 return RETURN_OK;
712 }
713
714 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
715 _syscmd(cmd,buf,sizeof(buf));
716 return RETURN_OK;
717}
718
719static int readBandWidth(int radioIndex,char *bw_value)
720{
developer30423732022-12-01 16:17:49 +0800721 char buf[MAX_BUF_SIZE] = {0};
722 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800723 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
724 _syscmd(cmd,buf,sizeof(buf));
725 if(NULL!=strstr(buf,"20MHz"))
726 {
727 strcpy(bw_value,"20MHz");
728 }
729 else if(NULL!=strstr(buf,"40MHz"))
730 {
731 strcpy(bw_value,"40MHz");
732 }
733 else if(NULL!=strstr(buf,"80MHz"))
734 {
735 strcpy(bw_value,"80MHz");
736 }
737 else
738 {
739 return RETURN_ERR;
740 }
741 return RETURN_OK;
742}
743
developer264159b2022-11-02 09:41:35 +0800744// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800745INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
746{
developer5f222492022-09-13 15:21:52 +0800747 struct params params={'\0'};
748 char config_file[MAX_BUF_SIZE] = {0};
749 char buf[MAX_BUF_SIZE] = {'\0'};
750
751 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800752 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800753 if (strlen (beaconRate) >= 5) {
754 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
755 buf[strlen(beaconRate) - 4] = '\0';
756 } else if (strlen(beaconRate) > 0)
757 strcpy(buf, beaconRate);
758 else
759 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800760
761 params.name = "beacon_rate";
762 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
763 if (strncmp(buf, "5.5", 3) == 0) {
764 snprintf(buf, sizeof(buf), "55");
765 params.value = buf;
766 } else {
767 strcat(buf, "0");
768 params.value = buf;
769 }
770
771 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
772 wifi_hostapdWrite(config_file, &params, 1);
773 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
775
776 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800777}
778
779INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
780{
developer1d57d002022-10-12 18:03:15 +0800781 char config_file[128] = {'\0'};
782 char temp_output[128] = {'\0'};
783 char buf[128] = {'\0'};
784 char cmd[128] = {'\0'};
785 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800786 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800787
788 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
789 if (NULL == beaconRate)
790 return RETURN_ERR;
791
792 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
793 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800794 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800795 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
796 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800797 if (strncmp(buf, "55", 2) == 0)
798 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
799 else {
800 rate = strtol(buf, NULL, 10)/10;
801 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
802 }
developer5f222492022-09-13 15:21:52 +0800803 } else {
developer1d57d002022-10-12 18:03:15 +0800804 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800805 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 +0800806 _syscmd(cmd, buf, sizeof(buf));
807 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800808 }
809 strncpy(beaconRate, temp_output, sizeof(temp_output));
810 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
811
812 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800813}
814
815INT wifi_setLED(INT radioIndex, BOOL enable)
816{
817 return 0;
818}
819INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
820{
821 return RETURN_OK;
822}
823/**********************************************************************************
824 *
825 * Wifi Subsystem level function prototypes
826 *
827**********************************************************************************/
828//---------------------------------------------------------------------------------------------------
829//Wifi system api
830//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
831INT wifi_getHalVersion(CHAR *output_string) //RDKB
832{
833 if(!output_string)
834 return RETURN_ERR;
835 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
836
837 return RETURN_OK;
838}
839
840
841/* wifi_factoryReset() function */
842/**
843* @description Clears internal variables to implement a factory reset of the Wi-Fi
844* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
845*
846* @param None
847*
848* @return The status of the operation.
849* @retval RETURN_OK if successful.
850* @retval RETURN_ERR if any error is detected
851*
852* @execution Synchronous
853* @sideeffect None
854*
855* @note This function must not suspend and must not invoke any blocking system
856* calls. It should probably just send a message to a driver event handler task.
857*
858*/
859INT wifi_factoryReset()
860{
861 char cmd[128];
862
863 /*delete running hostapd conf files*/
864 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
865 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
866 system(cmd);
867 system("systemctl restart hostapd.service");
868
869 return RETURN_OK;
870}
871
872/* wifi_factoryResetRadios() function */
873/**
874* @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.
875*
876* @param None
877* @return The status of the operation
878* @retval RETURN_OK if successful
879* @retval RETURN_ERR if any error is detected
880*
881* @execution Synchronous
882*
883* @sideeffect None
884*
885* @note This function must not suspend and must not invoke any blocking system
886* calls. It should probably just send a message to a driver event handler task.
887*
888*/
889INT wifi_factoryResetRadios()
890{
891 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
892 return RETURN_OK;
893
894 return RETURN_ERR;
895}
896
897
898/* wifi_factoryResetRadio() function */
899/**
900* @description Restore selected radio parameters without touching access point parameters
901*
902* @param radioIndex - Index of Wi-Fi Radio channel
903*
904* @return The status of the operation.
905* @retval RETURN_OK if successful.
906* @retval RETURN_ERR if any error is detected
907*
908* @execution Synchronous.
909* @sideeffect None.
910*
911* @note This function must not suspend and must not invoke any blocking system
912* calls. It should probably just send a message to a driver event handler task.
913*
914*/
915INT wifi_factoryResetRadio(int radioIndex) //RDKB
916{
developer5ff7f5f2022-09-13 15:12:16 +0800917 system("systemctl stop hostapd.service");
918
developer06a01d92022-09-07 16:32:39 +0800919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
920 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800921 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800922 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800923 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800924 else
925 return RETURN_ERR;
926
developer5ff7f5f2022-09-13 15:12:16 +0800927 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
929 return RETURN_OK;
930}
931
932/* wifi_initRadio() function */
933/**
934* Description: This function call initializes the specified radio.
935* Implementation specifics may dictate the functionality since
936* different hardware implementations may have different initilization requirements.
937* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
938*
939* @return The status of the operation.
940* @retval RETURN_OK if successful.
941* @retval RETURN_ERR if any error is detected
942*
943* @execution Synchronous.
944* @sideeffect None.
945*
946* @note This function must not suspend and must not invoke any blocking system
947* calls. It should probably just send a message to a driver event handler task.
948*
949*/
950INT wifi_initRadio(INT radioIndex)
951{
952 //TODO: Initializes the wifi subsystem (for specified radio)
953 return RETURN_OK;
954}
955void macfilter_init()
956{
957 char count[4]={'\0'};
958 char buf[253]={'\0'};
959 char tmp[19]={'\0'};
960 int dev_count,block,mac_entry=0;
961 char res[4]={'\0'};
962 char acl_file_path[64] = {'\0'};
963 FILE *fp = NULL;
964 int index=0;
965 char iface[10]={'\0'};
966 char config_file[MAX_BUF_SIZE] = {0};
967
968
969 sprintf(acl_file_path,"/tmp/mac_filter.sh");
970
971 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800972 if (fp == NULL) {
973 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
974 return RETURN_ERR;
975 }
developer06a01d92022-09-07 16:32:39 +0800976 sprintf(buf,"#!/bin/sh \n");
977 fprintf(fp,"%s\n",buf);
978
979 system("chmod 0777 /tmp/mac_filter.sh");
980
981 for(index=0;index<=1;index++)
982 {
983 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
984 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
985 sprintf(buf,"syscfg get %dcountfilter",index);
986 _syscmd(buf,count,sizeof(count));
987 mac_entry=atoi(count);
988
989 sprintf(buf,"syscfg get %dblockall",index);
990 _syscmd(buf,res,sizeof(res));
991 block = atoi(res);
992
993 //Allow only those macs mentioned in ACL
994 if(block==1)
995 {
996 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
997 fprintf(fp,"%s\n",buf);
998 for(dev_count=1;dev_count<=mac_entry;dev_count++)
999 {
1000 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1001 _syscmd(buf,tmp,sizeof(tmp));
1002 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1003 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1004 fprintf(fp,"%s\n",buf);
1005 }
1006 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1007 fprintf(fp,"%s\n",buf);
1008 }
1009
1010 //Block all the macs mentioned in ACL
1011 else if(block==2)
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
1016 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1017 {
1018 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1019 _syscmd(buf,tmp,sizeof(tmp));
1020 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1021 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1022 fprintf(fp,"%s\n",buf);
1023 }
1024 }
1025 }
1026 fclose(fp);
1027}
1028
1029// Initializes the wifi subsystem (all radios)
1030INT wifi_init() //RDKB
1031{
1032 char interface[MAX_BUF_SIZE]={'\0'};
1033 char bridge_name[MAX_BUF_SIZE]={'\0'};
1034 INT len=0;
1035
1036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1037 //Not intitializing macfilter for Turris-Omnia Platform for now
1038 //macfilter_init();
1039
1040 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001041 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001042 sleep(2);//sleep to wait for hostapd to start
1043
1044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1045
1046 return RETURN_OK;
1047}
1048
1049/* wifi_reset() function */
1050/**
1051* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1052* Implementation specifics may dictate what is actualy reset since
1053* different hardware implementations may have different requirements.
1054* Parameters : None
1055*
1056* @return The status of the operation.
1057* @retval RETURN_OK if successful.
1058* @retval RETURN_ERR if any error is detected
1059*
1060* @execution Synchronous.
1061* @sideeffect None.
1062*
1063* @note This function must not suspend and must not invoke any blocking system
1064* calls. It should probably just send a message to a driver event handler task.
1065*
1066*/
1067INT wifi_reset()
1068{
1069 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001070 system("systemctl stop hostapd.service");
1071 sleep(2);
1072 system("systemctl start hostapd.service");
1073 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001074 return RETURN_OK;
1075}
1076
1077/* wifi_down() function */
1078/**
1079* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1080* Implementation specifics may dictate some functionality since
1081* different hardware implementations may have different requirements.
1082*
1083* @param None
1084*
1085* @return The status of the operation
1086* @retval RETURN_OK if successful
1087* @retval RETURN_ERR if any error is detected
1088*
1089* @execution Synchronous
1090* @sideeffect None
1091*
1092* @note This function must not suspend and must not invoke any blocking system
1093* calls. It should probably just send a message to a driver event handler task.
1094*
1095*/
1096INT wifi_down()
1097{
1098 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001099 system("systemctl stop hostapd.service");
1100 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001101 return RETURN_OK;
1102}
1103
1104
1105/* wifi_createInitialConfigFiles() function */
1106/**
1107* @description This function creates wifi configuration files. The format
1108* and content of these files are implementation dependent. This function call is
1109* used to trigger this task if necessary. Some implementations may not need this
1110* function. If an implementation does not need to create config files the function call can
1111* do nothing and return RETURN_OK.
1112*
1113* @param None
1114*
1115* @return The status of the operation
1116* @retval RETURN_OK if successful
1117* @retval RETURN_ERR if any error is detected
1118*
1119* @execution Synchronous
1120* @sideeffect None
1121*
1122* @note This function must not suspend and must not invoke any blocking system
1123* calls. It should probably just send a message to a driver event handler task.
1124*
1125*/
1126INT wifi_createInitialConfigFiles()
1127{
1128 //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)
1129 return RETURN_OK;
1130}
1131
1132// outputs the country code to a max 64 character string
1133INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1134{
developerd946fd62022-12-08 18:03:28 +08001135 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001136 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001137 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001138 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001139
developerac6f1142022-12-20 19:26:35 +08001140 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001141 return RETURN_ERR;
1142 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001143 _syscmd(cmd, buf, sizeof(buf));
1144 if(strlen(buf) > 0)
1145 snprintf(output_string, 64, "%s", buf);
1146 else
1147 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001148
1149 return RETURN_OK;
1150}
1151
1152INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1153{
1154 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001155 char str[MAX_BUF_SIZE]={'\0'};
1156 char cmd[MAX_CMD_SIZE]={'\0'};
1157 struct params params;
1158 char config_file[MAX_BUF_SIZE] = {0};
1159
1160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1161 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1162 return RETURN_ERR;
1163
developerb86c6f32022-10-07 14:34:58 +08001164 if (strlen(CountryCode) == 0)
1165 strcpy(CountryCode, "US");
1166
developer7543b3b2022-09-13 13:47:17 +08001167 params.name = "country_code";
1168 params.value = CountryCode;
1169 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1170 int ret = wifi_hostapdWrite(config_file, &params, 1);
1171 if (ret) {
1172 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1173 ,__func__, ret);
1174 }
1175
1176 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1177 if (ret) {
1178 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1179 ,__func__, ret);
1180 }
developer7543b3b2022-09-13 13:47:17 +08001181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1182
developer06a01d92022-09-07 16:32:39 +08001183 return RETURN_OK;
1184}
1185
developera748dcf2022-09-13 15:56:48 +08001186INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1187{
developerd946fd62022-12-08 18:03:28 +08001188 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001189 char channel_util_file[64] = {0};
1190 char cmd[128] = {0};
1191 char buf[128] = {0};
1192 char line[128] = {0};
1193 char *param = NULL, *value = NULL;
1194 int read = 0;
1195 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1196 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1197 size_t len = 0;
1198 FILE *f = NULL;
1199
1200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1201
developerac6f1142022-12-20 19:26:35 +08001202 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001203 return RETURN_ERR;
1204 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001205 _syscmd(cmd, buf, sizeof(buf));
1206 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1207
1208 memset(cmd, 0, sizeof(cmd));
1209 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001210 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001211 if ((f = popen(cmd, "r")) == NULL) {
1212 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1213 return RETURN_ERR;
1214 }
1215
1216 read = getline(&line, &len, f);
1217 while (read != -1) {
1218 param = strtok(line, ":\t");
1219 value = strtok(NULL, " ");
1220 if(strstr(param, "frequency") != NULL) {
1221 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1222 }
1223 if(strstr(param, "noise") != NULL) {
1224 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1225 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1226 }
1227 if(strstr(param, "channel active time") != NULL) {
1228 ActiveTime = strtol(value, NULL, 10);
1229 }
1230 if(strstr(param, "channel busy time") != NULL) {
1231 BusyTime = strtol(value, NULL, 10);
1232 }
1233 if(strstr(param, "channel transmit time") != NULL) {
1234 TransmitTime = strtol(value, NULL, 10);
1235 }
1236 read = getline(&line, &len, f);
1237 }
1238 pclose(f);
1239
1240 // The file should store the last active, busy and transmit time
1241 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1242 f = fopen(channel_util_file, "r");
1243 if (f != NULL) {
1244 read = getline(&line, &len, f);
1245 preActiveTime = strtol(line, NULL, 10);
1246 read = getline(&line, &len, f);
1247 preBusyTime = strtol(line, NULL, 10);
1248 read = getline(&line, &len, f);
1249 preTransmitTime = strtol(line, NULL, 10);
1250 fclose(f);
1251 }
1252
1253 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1254 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1255
1256 f = fopen(channel_util_file, "w");
1257 if (f != NULL) {
1258 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1259 fclose(f);
1260 }
1261 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1262 return RETURN_OK;
1263}
1264
developer06a01d92022-09-07 16:32:39 +08001265/**********************************************************************************
1266 *
1267 * Wifi radio level function prototypes
1268 *
1269**********************************************************************************/
1270
1271//Get the total number of radios in this wifi subsystem
1272INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1273{
1274 if (NULL == output)
1275 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001276 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001277
1278 return RETURN_OK;
1279}
1280
1281//Get the total number of SSID entries in this wifi subsystem
1282INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1283{
1284 if (NULL == output)
1285 return RETURN_ERR;
1286 *output = MAX_APS;
1287
1288 return RETURN_OK;
1289}
1290
1291//Get the Radio enable config parameter
1292INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1293{
developerd946fd62022-12-08 18:03:28 +08001294 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001295 char buf[128] = {0}, cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08001296
1297 if (NULL == output_bool)
1298 return RETURN_ERR;
1299
1300 *output_bool = FALSE;
developer804c64f2022-10-19 13:54:40 +08001301 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001302 return RETURN_ERR;
1303
developerac6f1142022-12-20 19:26:35 +08001304 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001305 return RETURN_ERR;
1306 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
developercf48e482022-09-13 14:49:50 +08001307 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001308
developercf48e482022-09-13 14:49:50 +08001309 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1310 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08001311 return RETURN_OK;
1312}
1313
1314INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1315{
developerd946fd62022-12-08 18:03:28 +08001316 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001317 char cmd[MAX_CMD_SIZE] = {0};
1318 char buf[MAX_CMD_SIZE] = {0};
1319 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001320 int max_radio_num = 0;
1321 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001322
1323 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001324
1325 phyId = radio_index_to_phy(radioIndex);
1326
1327 wifi_getMaxRadioNumber(&max_radio_num);
1328
developer06a01d92022-09-07 16:32:39 +08001329 if(enable==FALSE)
1330 {
developer033b37b2022-10-18 11:27:46 +08001331 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001332 {
developer1e125222022-12-29 09:35:25 +08001333 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1334 return RETURN_ERR;
1335
developer06a01d92022-09-07 16:32:39 +08001336 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001337 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001338 _syscmd(cmd, buf, sizeof(buf));
1339 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001340 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001341
developerd946fd62022-12-08 18:03:28 +08001342 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08001343 _syscmd(cmd, buf, sizeof(buf));
1344 }
developer06a01d92022-09-07 16:32:39 +08001345 }
1346 else
1347 {
developer033b37b2022-10-18 11:27:46 +08001348 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001349 {
developer1e125222022-12-29 09:35:25 +08001350 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1351 return RETURN_ERR;
1352
developer431128d2022-12-16 15:30:41 +08001353 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
developer06a01d92022-09-07 16:32:39 +08001354 ret = _syscmd(cmd, buf, sizeof(buf));
1355 if ( ret == RETURN_ERR)
1356 {
1357 fprintf(stderr, "VAP interface creation failed\n");
1358 continue;
1359 }
developerd946fd62022-12-08 18:03:28 +08001360 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001361 _syscmd(cmd, buf, sizeof(buf));
1362 if(*buf == '1')
1363 {
1364 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001365 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001366 _syscmd(cmd, buf, sizeof(buf));
1367 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001368 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001369 }
1370 }
1371 }
1372
1373 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1374 return RETURN_OK;
1375}
1376
1377//Get the Radio enable status
1378INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1379{
1380 if (NULL == output_bool)
1381 return RETURN_ERR;
1382
1383 return wifi_getRadioEnable(radioIndex, output_bool);
1384}
1385
1386//Get the Radio Interface name from platform, eg "wlan0"
1387INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1388{
developer804c64f2022-10-19 13:54:40 +08001389 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001390 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001391 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001392}
1393
1394//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1395//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.
1396INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1397{
developerbcc556a2022-09-22 20:02:45 +08001398 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1399 // For max bit rate, we should always choose the best MCS
1400 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001401 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001402 char *tmp = NULL;
1403 UINT mode_map = 0;
1404 UINT num_subcarrier = 0;
1405 UINT code_bits = 0;
1406 float code_rate = 0; // use max code rate
1407 int NSS = 0;
1408 UINT Symbol_duration = 0;
1409 UINT GI_duration = 0;
1410 wifi_band band = band_invalid;
1411 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1412 BOOL enable = FALSE;
1413 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001414
1415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1416 if (NULL == output_string)
1417 return RETURN_ERR;
1418
developerbcc556a2022-09-22 20:02:45 +08001419 wifi_getRadioEnable(radioIndex, &enable);
1420 if (enable == FALSE) {
1421 snprintf(output_string, 64, "0 Mb/s");
1422 return RETURN_OK;
1423 }
1424
1425 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1426 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1427 return RETURN_ERR;
1428 }
1429
1430 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1431 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1432 return RETURN_ERR;
1433 }
1434
1435 if (gi == wifi_guard_interval_3200)
1436 GI_duration = 32;
1437 else if (gi == wifi_guard_interval_1600)
1438 GI_duration = 16;
1439 else if (gi == wifi_guard_interval_800)
1440 GI_duration = 8;
1441 else // auto, 400
1442 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001443
developerbcc556a2022-09-22 20:02:45 +08001444 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1445 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1446 return RETURN_ERR;
1447 }
1448
1449 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1450 strcpy(channel_bandwidth_str, "160");
1451
1452 if (mode_map & WIFI_MODE_AX) {
1453 if (strstr(channel_bandwidth_str, "160") != NULL)
1454 num_subcarrier = 1960;
1455 else if (strstr(channel_bandwidth_str, "80") != NULL)
1456 num_subcarrier = 980;
1457 else if (strstr(channel_bandwidth_str, "40") != NULL)
1458 num_subcarrier = 468;
1459 else if (strstr(channel_bandwidth_str, "20") != NULL)
1460 num_subcarrier = 234;
1461 code_bits = 10;
1462 code_rate = (float)5/6;
1463 Symbol_duration = 128;
1464 } else if (mode_map & WIFI_MODE_AC) {
1465 if (strstr(channel_bandwidth_str, "160") != NULL)
1466 num_subcarrier = 468;
1467 else if (strstr(channel_bandwidth_str, "80") != NULL)
1468 num_subcarrier = 234;
1469 else if (strstr(channel_bandwidth_str, "40") != NULL)
1470 num_subcarrier = 108;
1471 else if (strstr(channel_bandwidth_str, "20") != NULL)
1472 num_subcarrier = 52;
1473 code_bits = 8;
1474 code_rate = (float)5/6;
1475 Symbol_duration = 32;
1476 } else if (mode_map & WIFI_MODE_N) {
1477 if (strstr(channel_bandwidth_str, "160") != NULL)
1478 num_subcarrier = 468;
1479 else if (strstr(channel_bandwidth_str, "80") != NULL)
1480 num_subcarrier = 234;
1481 else if (strstr(channel_bandwidth_str, "40") != NULL)
1482 num_subcarrier = 108;
1483 else if (strstr(channel_bandwidth_str, "20") != NULL)
1484 num_subcarrier = 52;
1485 code_bits = 6;
1486 code_rate = (float)3/4;
1487 Symbol_duration = 32;
1488 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1489 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1490 snprintf(output_string, 64, "65 Mb/s");
1491 return RETURN_OK;
1492 } else {
1493 snprintf(output_string, 64, "0 Mb/s");
1494 return RETURN_OK;
1495 }
developer06a01d92022-09-07 16:32:39 +08001496
developerbcc556a2022-09-22 20:02:45 +08001497 // Spatial streams
1498 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1499 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1500 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001501 }
developerbcc556a2022-09-22 20:02:45 +08001502
1503 // multiple 10 is to align duration unit (0.1 us)
1504 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1505 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1506
developer06a01d92022-09-07 16:32:39 +08001507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1508
1509 return RETURN_OK;
1510}
1511#if 0
1512INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1513{
1514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1515 char cmd[64];
1516 char buf[1024];
1517 int apIndex;
1518
1519 if (NULL == output_string)
1520 return RETURN_ERR;
1521
1522 apIndex=(radioIndex==0)?0:1;
1523
developerd946fd62022-12-08 18:03:28 +08001524 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001525 _syscmd(cmd,buf, sizeof(buf));
1526
1527 snprintf(output_string, 64, "%s", buf);
1528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1529 return RETURN_OK;
1530}
1531#endif
1532
1533
1534//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1535//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.
1536INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1537{
developer963da0c2022-09-13 15:58:27 +08001538 wifi_band band = band_invalid;
1539
developer06a01d92022-09-07 16:32:39 +08001540 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1541 if (NULL == output_string)
1542 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001543
1544 band = wifi_index_to_band(radioIndex);
1545
1546 memset(output_string, 0, 10);
1547 if (band == band_2_4)
1548 strcpy(output_string, "2.4GHz");
1549 else if (band == band_5)
1550 strcpy(output_string, "5GHz");
1551 else if (band == band_6)
1552 strcpy(output_string, "6GHz");
1553 else
1554 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1556
1557 return RETURN_OK;
1558#if 0
1559 char buf[MAX_BUF_SIZE]={'\0'};
1560 char str[MAX_BUF_SIZE]={'\0'};
1561 char cmd[MAX_CMD_SIZE]={'\0'};
1562 char *ch=NULL;
1563 char *ch2=NULL;
1564
1565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1566 if (NULL == output_string)
1567 return RETURN_ERR;
1568
1569
1570 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1571
1572 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1573 {
1574 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1575 return RETURN_ERR;
1576 }
1577 ch=strchr(buf,'\n');
1578 *ch='\0';
1579 ch=strchr(buf,'=');
1580 if(ch==NULL)
1581 return RETURN_ERR;
1582
1583
1584 ch++;
1585
1586 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1587 strcpy(buf,"0");
1588 if(strlen(ch) == 1)
1589 ch=strcat(buf,ch);
1590
1591
1592 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1593
1594 if(_syscmd(cmd,str,64) == RETURN_ERR)
1595 {
1596 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1597 return RETURN_ERR;
1598 }
1599
1600
1601 ch2=strchr(str,'\n');
1602 //replace \n with \0
1603 *ch2='\0';
1604 ch2=strchr(str,'=');
1605 if(ch2==NULL)
1606 {
1607 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1608 return RETURN_ERR;
1609 }
1610 else
1611 wifi_dbg_printf("%s",ch2+1);
1612
1613
1614 ch2++;
1615
1616
1617 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1618
1619 memset(buf,'\0',sizeof(buf));
1620 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1621 {
1622 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1623 return RETURN_ERR;
1624 }
1625 if (strstr(buf,"2.4") != NULL )
1626 strcpy(output_string,"2.4GHz");
1627 else if(strstr(buf,"5.") != NULL )
1628 strcpy(output_string,"5GHz");
1629 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1630
1631 return RETURN_OK;
1632#endif
1633}
1634
1635//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1636//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.
1637INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1638{
developerb7593de2022-10-18 09:51:57 +08001639 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1641 if (NULL == output_string)
1642 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001643 band = wifi_index_to_band(radioIndex);
1644
1645 if (band == band_2_4)
1646 snprintf(output_string, 64, "2.4GHz");
1647 else if (band == band_5)
1648 snprintf(output_string, 64, "5GHz");
1649 else if (band == band_6)
1650 snprintf(output_string, 64, "6GHz");
1651
developer06a01d92022-09-07 16:32:39 +08001652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1653
1654 return RETURN_OK;
1655#if 0
1656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1657 char buf[MAX_BUF_SIZE]={'\0'};
1658 char str[MAX_BUF_SIZE]={'\0'};
1659 char cmd[MAX_CMD_SIZE]={'\0'};
1660 char *ch=NULL;
1661 char *ch2=NULL;
1662 char ch1[5]="0";
1663
1664 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1665
1666 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1667 {
1668 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1669 return RETURN_ERR;
1670 }
1671
1672 ch=strchr(buf,'\n');
1673 *ch='\0';
1674 ch=strchr(buf,'=');
1675 if(ch==NULL)
1676 return RETURN_ERR;
1677 ch++;
1678
1679 if(strlen(ch)==1)
1680 {
1681 strcat(ch1,ch);
1682
1683 }
1684 else
1685 {
1686 strcpy(ch1,ch);
1687 }
1688
1689
1690
1691 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1692 if(_syscmd(cmd,str,64) == RETURN_ERR)
1693 {
1694 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1695 return RETURN_ERR;
1696 }
1697
1698
1699 ch2=strchr(str,'\n');
1700 //replace \n with \0
1701 *ch2='\0';
1702 ch2=strchr(str,'=');
1703 if(ch2==NULL)
1704 {
1705 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1706 return RETURN_ERR;
1707 }
1708 else
1709 wifi_dbg_printf("%s",ch2+1);
1710 ch2++;
1711
1712
1713 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1714 memset(buf,'\0',sizeof(buf));
1715 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1716 {
1717 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1718 return RETURN_ERR;
1719 }
1720
1721
1722 if(strstr(buf,"2.4")!=NULL)
1723 {
1724 strcpy(output_string,"2.4GHz");
1725 }
1726 if(strstr(buf,"5.")!=NULL)
1727 {
1728 strcpy(output_string,"5GHz");
1729 }
1730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1731 return RETURN_OK;
1732#endif
1733}
1734
1735//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1736//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.
1737INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1738{
developer963da0c2022-09-13 15:58:27 +08001739 char cmd[128]={0};
1740 char buf[128]={0};
1741 char temp_output[128] = {0};
1742 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001743 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001744
1745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001746 if (NULL == output_string)
1747 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001748
1749 band = wifi_index_to_band(radioIndex);
1750 if (band == band_2_4) {
1751 strcat(temp_output, "b,g,");
1752 } else if (band == band_5) {
1753 strcat(temp_output, "a,");
1754 }
developer033b37b2022-10-18 11:27:46 +08001755 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001756 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001757 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 +08001758 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001759 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001760 strcat(temp_output, "n,");
1761 }
developer06a01d92022-09-07 16:32:39 +08001762
developer963da0c2022-09-13 15:58:27 +08001763 // vht capabilities
1764 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001765 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 +08001766 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001767 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001768 strcat(temp_output, "ac,");
1769 }
1770 }
1771
1772 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001773 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 +08001774 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001775 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001776 strcat(temp_output, "ax,");
1777 }
1778
1779 // Remove the last comma
1780 if (strlen(temp_output) != 0)
1781 temp_output[strlen(temp_output)-1] = '\0';
1782 strncpy(output_string, temp_output, strlen(temp_output));
1783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001784 return RETURN_OK;
1785}
1786
1787//Get the radio operating mode, and pure mode flag. eg: "ac"
1788//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.
1789INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1790{
1791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1792 if (NULL == output_string)
1793 return RETURN_ERR;
1794
1795 if (radioIndex == 0) {
1796 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1797 *gOnly = FALSE;
1798 *nOnly = TRUE;
1799 *acOnly = FALSE;
1800 } else {
1801 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1802 *gOnly = FALSE;
1803 *nOnly = FALSE;
1804 *acOnly = FALSE;
1805 }
1806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1807
1808 return RETURN_OK;
1809#if 0
1810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1811 char buf[64] = {0};
1812 char config_file[MAX_BUF_SIZE] = {0};
1813
1814 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1815 return RETURN_ERR;
1816
1817 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1818 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1819
1820 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1821 if (strlen(buf) == 0)
1822 {
1823 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1824 return RETURN_ERR;
1825 }
1826 if(strcmp(buf,"g")==0)
1827 {
1828 wifi_dbg_printf("\nG\n");
1829 *gOnly=TRUE;
1830 *nOnly=FALSE;
1831 *acOnly=FALSE;
1832 }
1833 else if(strcmp(buf,"n")==0)
1834 {
1835 wifi_dbg_printf("\nN\n");
1836 *gOnly=FALSE;
1837 *nOnly=TRUE;
1838 *acOnly=FALSE;
1839 }
1840 else if(strcmp(buf,"ac")==0)
1841 {
1842 wifi_dbg_printf("\nac\n");
1843 *gOnly=FALSE;
1844 *nOnly=FALSE;
1845 *acOnly=TRUE;
1846 }
1847 /* hostapd-5G.conf has "a" as hw_mode */
1848 else if(strcmp(buf,"a")==0)
1849 {
1850 wifi_dbg_printf("\na\n");
1851 *gOnly=FALSE;
1852 *nOnly=FALSE;
1853 *acOnly=FALSE;
1854 }
1855 else
1856 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1857
1858 //for a,n mode
1859 if(radioIndex == 1)
1860 {
1861 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1862 if(strcmp(buf,"1")==0)
1863 {
1864 strncpy(output_string, "n", 1);
1865 *nOnly=FALSE;
1866 }
1867 }
1868
1869 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1871 return RETURN_OK;
1872#endif
1873}
1874
developerdb744382022-09-13 15:34:54 +08001875INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1876{
1877 char cmd[128] = {0};
1878 char buf[64] = {0};
1879 char config_file[64] = {0};
1880 wifi_band band;
1881
1882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1883 if(NULL == output_string || NULL == pureMode)
1884 return RETURN_ERR;
1885
1886 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001887 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerdb744382022-09-13 15:34:54 +08001888 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1889 _syscmd(cmd, buf, sizeof(buf));
1890
1891 band = wifi_index_to_band(radioIndex);
1892 // puremode is a bit map
1893 *pureMode = 0;
1894 if (band == band_2_4) {
1895 strcat(output_string, "b,g");
1896 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1897 if (strstr(buf, "n") != NULL) {
1898 strcat(output_string, ",n");
1899 *pureMode |= WIFI_MODE_N;
1900 }
1901 if (strstr(buf, "ax") != NULL) {
1902 strcat(output_string, ",ax");
1903 *pureMode |= WIFI_MODE_AX;
1904 }
1905 } else if (band == band_5) {
1906 strcat(output_string, "a");
1907 *pureMode |= WIFI_MODE_A;
1908 if (strstr(buf, "n") != NULL) {
1909 strcat(output_string, ",n");
1910 *pureMode |= WIFI_MODE_N;
1911 }
1912 if (strstr(buf, "ac") != NULL) {
1913 strcat(output_string, ",ac");
1914 *pureMode |= WIFI_MODE_AC;
1915 }
1916 if (strstr(buf, "ax") != NULL) {
1917 strcat(output_string, ",ax");
1918 *pureMode |= WIFI_MODE_AX;
1919 }
1920 } else if (band == band_6) {
1921 if (strstr(buf, "ax") != NULL) {
1922 strcat(output_string, "ax");
1923 *pureMode |= WIFI_MODE_AX;
1924 }
1925 }
1926
1927 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1928 return RETURN_OK;
1929}
1930
1931// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001932INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1933{
1934 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1935 if (strcmp (channelMode,"11A") == 0)
1936 {
1937 writeBandWidth(radioIndex,"20MHz");
1938 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1939 printf("\nChannel Mode is 802.11a (5GHz)\n");
1940 }
1941 else if (strcmp (channelMode,"11NAHT20") == 0)
1942 {
1943 writeBandWidth(radioIndex,"20MHz");
1944 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1945 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1946 }
1947 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1948 {
1949 writeBandWidth(radioIndex,"40MHz");
1950 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1951 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1952 }
1953 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1954 {
1955 writeBandWidth(radioIndex,"40MHz");
1956 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1957 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1958 }
1959 else if (strcmp (channelMode,"11ACVHT20") == 0)
1960 {
1961 writeBandWidth(radioIndex,"20MHz");
1962 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1963 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1964 }
1965 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1966 {
1967 writeBandWidth(radioIndex,"40MHz");
1968 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1969 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1970 }
1971 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1972 {
1973 writeBandWidth(radioIndex,"40MHz");
1974 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1975 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1976 }
1977 else if (strcmp (channelMode,"11ACVHT80") == 0)
1978 {
1979 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1980 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1981 }
1982 else if (strcmp (channelMode,"11ACVHT160") == 0)
1983 {
1984 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1985 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1986 }
1987 else if (strcmp (channelMode,"11B") == 0)
1988 {
1989 writeBandWidth(radioIndex,"20MHz");
1990 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1991 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1992 }
1993 else if (strcmp (channelMode,"11G") == 0)
1994 {
1995 writeBandWidth(radioIndex,"20MHz");
1996 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1997 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1998 }
1999 else if (strcmp (channelMode,"11NGHT20") == 0)
2000 {
2001 writeBandWidth(radioIndex,"20MHz");
2002 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2003 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2004 }
2005 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2006 {
2007 writeBandWidth(radioIndex,"40MHz");
2008 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2009 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2010 }
2011 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2012 {
2013 writeBandWidth(radioIndex,"40MHz");
2014 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2015 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2016 }
2017 else
2018 {
2019 return RETURN_ERR;
2020 }
2021 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2022
2023 return RETURN_OK;
2024}
2025
developerdb744382022-09-13 15:34:54 +08002026// Set the radio operating mode, and pure mode flag.
2027INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2028{
2029 int num_hostapd_support_mode = 3; // n, ac, ax
2030 struct params list[num_hostapd_support_mode];
2031 char config_file[64] = {0};
2032 char bandwidth[16] = {0};
2033 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002034
developerdb744382022-09-13 15:34:54 +08002035
2036 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2037 // Set radio mode
2038 list[0].name = "ieee80211n";
2039 list[1].name = "ieee80211ac";
2040 list[2].name = "ieee80211ax";
2041 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2042
2043 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002044 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002045 list[0].value = "1";
2046 else
2047 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002048 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002049 list[1].value = "1";
2050 else
2051 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002052 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002053 list[2].value = "1";
2054 else
2055 list[2].value = "0";
2056 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2057
2058 if (channelMode == NULL || strlen(channelMode) == 0)
2059 return RETURN_OK;
2060 // Set bandwidth
2061 if (strstr(channelMode, "40") != NULL)
2062 strcpy(bandwidth, "40MHz");
2063 else if (strstr(channelMode, "80") != NULL)
2064 strcpy(bandwidth, "80MHz");
2065 else if (strstr(channelMode, "160") != NULL)
2066 strcpy(bandwidth, "160MHz");
2067 else // 11A, 11B, 11G....
2068 strcpy(bandwidth, "20MHz");
2069
2070 writeBandWidth(radioIndex, bandwidth);
2071 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2072
2073 wifi_reloadAp(radioIndex);
2074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2075
2076 return RETURN_OK;
2077}
2078
developer1d12ebf2022-10-04 15:13:38 +08002079INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2080
2081 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002082 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002083 struct params params = {0};
2084 wifi_band band = band_invalid;
2085
2086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2087
2088 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002089
2090 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002091 return RETURN_ERR;
2092 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2093 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002094 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2095 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002096
2097 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2098 params.name = "hw_mode";
2099 params.value = hw_mode;
2100 wifi_hostapdWrite(config_file, &params, 1);
2101 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2102
developeref938762022-10-19 17:21:01 +08002103 if (band == band_2_4) {
2104 if (strncmp(hw_mode, "b", 1) == 0) {
2105 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2106 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2107 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2108 snprintf(buf, sizeof(buf), "%s", "1,2");
2109 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2110 } else {
2111 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2112
2113 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2114 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2115 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2116 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2117 }
2118 }
2119
developer1d12ebf2022-10-04 15:13:38 +08002120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2121 return RETURN_OK;
2122}
2123
developere8988ba2022-10-18 17:42:30 +08002124INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2125{
2126 char config_file[64] = {0};
2127 struct params params = {0};
2128 wifi_band band = band_invalid;
2129
2130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2131
2132 band = wifi_index_to_band(radioIndex);
developer30423732022-12-01 16:17:49 +08002133 if (band != band_2_4)
2134 return RETURN_OK;
developere8988ba2022-10-18 17:42:30 +08002135
2136 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2137 params.name = "noscan";
2138 params.value = noscan;
2139 wifi_hostapdWrite(config_file, &params, 1);
2140 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2141
2142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2143 return RETURN_OK;
2144}
2145
developer06a01d92022-09-07 16:32:39 +08002146//Get the list of supported channel. eg: "1-11"
2147//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.
2148INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2149{
developer6318ed52022-09-13 15:17:58 +08002150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002151 if (NULL == output_string)
2152 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002153 char cmd[256] = {0};
2154 char buf[128] = {0};
2155 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002156 int phyId = 0;
2157
developer6318ed52022-09-13 15:17:58 +08002158 // Parse possible channel number and separate them with commas.
2159 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002160 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002161 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002162 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002163 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 +08002164 else
developer033b37b2022-10-18 11:27:46 +08002165 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 +08002166
2167 _syscmd(cmd,buf,sizeof(buf));
2168 strncpy(output_string, buf, sizeof(buf));
2169
2170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2171 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002172}
2173
2174//Get the list for used channel. eg: "1,6,9,11"
2175//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.
2176INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2177{
developerd946fd62022-12-08 18:03:28 +08002178 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002179 char cmd[128] = {0};
2180 char buf[128] = {0};
2181 char config_file[64] = {0};
2182 int channel = 0;
2183 int freq = 0;
2184 int bandwidth = 0;
2185 int center_freq = 0;
2186 int center_channel = 0;
2187 int channel_delta = 0;
2188 wifi_band band = band_invalid;
2189
2190 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2191
developer06a01d92022-09-07 16:32:39 +08002192 if (NULL == output_string)
2193 return RETURN_ERR;
2194
developerac6f1142022-12-20 19:26:35 +08002195 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002196 return RETURN_ERR;
2197 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002198 _syscmd(cmd, buf, sizeof(buf));
2199 if (strlen(buf) == 0) {
2200 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2201 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002202 }
developerf5745ee2022-10-05 16:09:53 +08002203 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2204
2205 if (bandwidth == 20) {
2206 snprintf(output_string, 256, "%d", channel);
2207 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002208 }
developerf5745ee2022-10-05 16:09:53 +08002209
2210 center_channel = ieee80211_frequency_to_channel(center_freq);
2211
2212 band = wifi_index_to_band(radioIndex);
2213 if (band == band_2_4 && bandwidth == 40) {
2214 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2215 memset(buf, 0, sizeof(buf));
2216 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2217
developerf22724d2022-12-22 17:24:14 +08002218 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002219 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002220 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002221 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2222 } else {
2223 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2224 return RETURN_ERR;
2225 }
2226 } else if (band == band_5 || band == band_6){
2227 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2228 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2229 channel_delta = (bandwidth-20)/10;
2230 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2231 } else
2232 return RETURN_ERR;
2233
2234 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002235 return RETURN_OK;
2236}
2237
2238//Get the running channel number
2239INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2240{
developer5b398df2022-11-17 20:39:48 +08002241 char channel_str[16] = {0};
2242 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002243
developer5b398df2022-11-17 20:39:48 +08002244 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002245 return RETURN_ERR;
2246
developer5b398df2022-11-17 20:39:48 +08002247 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2248 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002249
developer5b398df2022-11-17 20:39:48 +08002250 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002251
developer06a01d92022-09-07 16:32:39 +08002252 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002253}
2254
2255
2256INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2257{
2258 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002259 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002260
2261 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2262 if (NULL == output_ulong)
2263 return RETURN_ERR;
2264
developer06a01d92022-09-07 16:32:39 +08002265 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002266 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2267 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002268 _syscmd(cmd,buf,sizeof(buf));
2269 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2270 if (*output_ulong == 0) {
2271 return RETURN_ERR;
2272 }
2273
2274 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2275 return RETURN_OK;
2276}
2277
2278//Storing the previous channel value
2279INT wifi_storeprevchanval(INT radioIndex)
2280{
2281 char buf[256] = {0};
2282 char output[4]={'\0'};
2283 char config_file[MAX_BUF_SIZE] = {0};
2284 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2285 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2286 if(radioIndex == 0)
2287 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2288 else if(radioIndex == 1)
2289 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2290 system(buf);
2291 Radio_flag = FALSE;
2292 return RETURN_OK;
2293}
2294
2295//Set the running channel number
2296INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2297{
developer76989232022-10-04 14:13:19 +08002298 // We only write hostapd config here
2299 char str_channel[8]={0};
2300 char *list_channel;
2301 char config_file[128] = {0};
2302 char possible_channels[256] = {0};
2303 int max_radio_num = 0;
2304 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002305
developer76989232022-10-04 14:13:19 +08002306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002307
developer76989232022-10-04 14:13:19 +08002308 // Check valid
2309 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002310
developer76989232022-10-04 14:13:19 +08002311 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2312 list_channel = strtok(possible_channels, ",");
2313 while(true)
developer06a01d92022-09-07 16:32:39 +08002314 {
developer76989232022-10-04 14:13:19 +08002315 if(list_channel == NULL) { // input not in the list
2316 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2317 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002318 }
developer76989232022-10-04 14:13:19 +08002319 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2320 break;
2321 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002322 }
2323
developer76989232022-10-04 14:13:19 +08002324 list.name = "channel";
2325 list.value = str_channel;
2326 wifi_getMaxRadioNumber(&max_radio_num);
2327 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002328 {
developer76989232022-10-04 14:13:19 +08002329 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2330 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002331 }
2332
developer76989232022-10-04 14:13:19 +08002333 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002334 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002335}
developer06a01d92022-09-07 16:32:39 +08002336
2337INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2338{
developer76989232022-10-04 14:13:19 +08002339 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002340 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002341 char config_file[64];
2342 int max_num_radios = 0;
2343 wifi_band band = band_invalid;
2344
2345 band = wifi_index_to_band(radioIndex);
2346 if (band == band_2_4)
2347 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002348
developer30423732022-12-01 16:17:49 +08002349 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002350 list[0].name = "vht_oper_centr_freq_seg0_idx";
2351 list[0].value = str_idx;
2352 list[1].name = "he_oper_centr_freq_seg0_idx";
2353 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002354
developer76989232022-10-04 14:13:19 +08002355 wifi_getMaxRadioNumber(&max_num_radios);
2356 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002357 {
developer76989232022-10-04 14:13:19 +08002358 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2359 if (band == band_6)
2360 wifi_hostapdWrite(config_file, &list[1], 1);
2361 else
2362 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002363 }
2364
2365 return RETURN_OK;
2366}
2367
2368//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2369//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2370INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2371{
2372 //Set to wifi config only. Wait for wifi reset to apply.
2373 char buf[256] = {0};
2374 char str_channel[256] = {0};
2375 int count = 0;
2376 ULONG Value = 0;
2377 FILE *fp = NULL;
2378 if(enable == TRUE)
2379 {
developer06a01d92022-09-07 16:32:39 +08002380 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002381 }
developer5884e982022-10-06 10:52:50 +08002382 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002383}
2384
developer0b246d12022-09-30 15:24:20 +08002385INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2386{
2387 if (output_bool == NULL)
2388 return RETURN_ERR;
2389
2390 *output_bool = TRUE;
2391
2392 return RETURN_OK;
2393}
2394
developer06a01d92022-09-07 16:32:39 +08002395INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2396{
2397 if (NULL == output_bool)
2398 return RETURN_ERR;
2399 *output_bool=FALSE;
2400 return RETURN_OK;
2401}
2402
2403INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2404{
2405 if (NULL == output_bool)
2406 return RETURN_ERR;
2407 *output_bool=FALSE;
2408 return RETURN_OK;
2409}
2410
2411INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2412{
2413 //Set to wifi config only. Wait for wifi reset to apply.
2414 return RETURN_OK;
2415}
2416
2417INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2418{
2419 return RETURN_OK;
2420}
2421
2422INT wifi_factoryResetAP(int apIndex)
2423{
developer838cca92022-10-03 13:19:57 +08002424 char ap_config_file[64] = {0};
2425 char cmd[128] = {0};
2426
developer06a01d92022-09-07 16:32:39 +08002427 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002428
2429 wifi_setApEnable(apIndex, FALSE);
2430 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2431 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2432 wifi_setApEnable(apIndex, TRUE);
2433
developer06a01d92022-09-07 16:32:39 +08002434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002435
developer06a01d92022-09-07 16:32:39 +08002436 return RETURN_OK;
2437}
2438
2439//To set Band Steering AP group
2440//To-do
2441INT wifi_setBandSteeringApGroup(char *ApGroup)
2442{
2443 return RETURN_OK;
2444}
2445
developer1e5aa162022-09-13 16:06:24 +08002446INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2447{
2448 char config_file[128] = {'\0'};
2449 char buf[128] = {'\0'};
2450
2451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2452 if (dtimInterval == NULL)
2453 return RETURN_ERR;
2454
2455 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2456 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2457
2458 if (strlen(buf) == 0) {
2459 *dtimInterval = 2;
2460 } else {
2461 *dtimInterval = strtoul(buf, NULL, 10);
2462 }
2463
2464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2465 return RETURN_OK;
2466}
2467
developer06a01d92022-09-07 16:32:39 +08002468INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2469{
developer5f222492022-09-13 15:21:52 +08002470 struct params params={0};
2471 char config_file[MAX_BUF_SIZE] = {'\0'};
2472 char buf[MAX_BUF_SIZE] = {'\0'};
2473
2474 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2475 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002476 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002477 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002478 }
2479
2480 params.name = "dtim_period";
2481 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2482 params.value = buf;
2483
2484 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2485 wifi_hostapdWrite(config_file, &params, 1);
2486 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2487
2488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2489 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002490}
2491
2492//Check if the driver support the Dfs
2493INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2494{
developer78a15382022-11-02 10:57:40 +08002495 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002496 if (NULL == output_bool)
2497 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002498 *output_bool=FALSE;
2499
2500 band = wifi_index_to_band(radioIndex);
2501 if (band == band_5)
2502 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002503 return RETURN_OK;
2504}
2505
2506//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.
2507//The value of this parameter is a comma seperated list of channel number
2508INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2509{
2510 if (NULL == output_pool)
2511 return RETURN_ERR;
2512 if (radioIndex==1)
2513 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2514 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2515
2516 return RETURN_OK;
2517}
2518
2519INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2520{
2521 //Set to wifi config. And apply instantly.
2522 return RETURN_OK;
2523}
2524
2525INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2526{
2527 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2528 return RETURN_ERR;
2529 *output_interval_seconds=1800;
2530 *output_dwell_milliseconds=40;
2531
2532 return RETURN_OK;
2533}
2534
2535INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2536{
2537 //Set to wifi config. And apply instantly.
2538 return RETURN_OK;
2539}
2540
developerbfc18512022-10-05 17:54:28 +08002541INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2542{
2543 if (output_bool == NULL)
2544 return RETURN_ERR;
2545 *output_bool = true;
2546 return RETURN_OK;
2547}
2548
2549INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2550{
2551 return RETURN_OK;
2552}
2553
developer06a01d92022-09-07 16:32:39 +08002554//Get the Dfs enable status
2555INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2556{
developer9964b5b2022-09-13 15:59:34 +08002557 char buf[16] = {0};
2558 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002559
2560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2561
developer30423732022-12-01 16:17:49 +08002562 if (output_bool == NULL)
2563 return RETURN_ERR;
2564
developer9964b5b2022-09-13 15:59:34 +08002565 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002566 f = fopen(DFS_ENABLE_FILE, "r");
2567 if (f != NULL) {
2568 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002569 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002570 *output_bool = FALSE;
2571 fclose(f);
2572 }
2573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002574 return RETURN_OK;
2575}
2576
2577//Set the Dfs enable status
2578INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2579{
developer9964b5b2022-09-13 15:59:34 +08002580 char config_file[128] = {0};
2581 FILE *f = NULL;
2582 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002583
2584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2585
developer9964b5b2022-09-13 15:59:34 +08002586 f = fopen(DFS_ENABLE_FILE, "w");
2587 if (f == NULL)
2588 return RETURN_ERR;
2589 fprintf(f, "%d", enable);
2590 fclose(f);
2591
2592 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002593 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002594 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2595 wifi_hostapdWrite(config_file, &params, 1);
2596 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2597
2598 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2599
developer9964b5b2022-09-13 15:59:34 +08002600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002601 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002602}
2603
2604//Check if the driver support the AutoChannelRefreshPeriod
2605INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2606{
2607 if (NULL == output_bool)
2608 return RETURN_ERR;
2609 *output_bool=FALSE; //not support
2610
2611 return RETURN_OK;
2612}
2613
2614//Get the ACS refresh period in seconds
2615INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2616{
2617 if (NULL == output_ulong)
2618 return RETURN_ERR;
2619 *output_ulong=300;
2620
2621 return RETURN_OK;
2622}
2623
2624//Set the ACS refresh period in seconds
2625INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2626{
2627 return RETURN_ERR;
2628}
2629
2630//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2631//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.
2632INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2633{
developer70490032022-09-13 15:45:20 +08002634 char cmd[128] = {0}, buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002635 char extchannel[128] = {0};
developer70490032022-09-13 15:45:20 +08002636 char interface_name[64] = {0};
2637 int ret = 0, len=0;
2638 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002639 wifi_band band;
developer70490032022-09-13 15:45:20 +08002640
2641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2642
developer06a01d92022-09-07 16:32:39 +08002643 if (NULL == output_string)
2644 return RETURN_ERR;
2645
developer70490032022-09-13 15:45:20 +08002646 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2647 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002648
developer70490032022-09-13 15:45:20 +08002649 if (radio_enable != TRUE)
2650 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002651
developerac6f1142022-12-20 19:26:35 +08002652 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002653 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002654 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08002655 ret = _syscmd(cmd, buf, sizeof(buf));
2656 len = strlen(buf);
2657 if((ret != 0) || (len == 0))
2658 {
developerfa41b1f2023-01-06 10:25:51 +08002659 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2660 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002661 }
2662
developerfa41b1f2023-01-06 10:25:51 +08002663 band = wifi_index_to_band(radioIndex);
2664 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
2665 wifi_getRadioExtChannel(radioIndex, extchannel);
2666 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
2667 snprintf(buf, sizeof(buf), "40");
developer06a01d92022-09-07 16:32:39 +08002668 }
developerfa41b1f2023-01-06 10:25:51 +08002669 snprintf(output_string, 64, "%sMHz", buf);
developer06a01d92022-09-07 16:32:39 +08002670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002671
2672 return RETURN_OK;
2673}
2674
2675//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002676INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002677{
developerf7a466e2022-09-29 11:55:56 +08002678 char config_file[128];
2679 char set_value[16];
2680 struct params params[2];
2681 int max_radio_num = 0;
2682
developer06a01d92022-09-07 16:32:39 +08002683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002684
developerf7a466e2022-09-29 11:55:56 +08002685 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002686 return RETURN_ERR;
2687
developerfa41b1f2023-01-06 10:25:51 +08002688 if(strstr(bandwidth,"160") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002689 strcpy(set_value, "2");
2690 else if(strstr(bandwidth,"80") != NULL)
2691 strcpy(set_value, "1");
2692 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2693 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002694 else
2695 {
developerf7a466e2022-09-29 11:55:56 +08002696 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002697 return RETURN_ERR;
2698 }
2699
developerf7a466e2022-09-29 11:55:56 +08002700 params[0].name = "vht_oper_chwidth";
2701 params[0].value = set_value;
2702 params[1].name = "he_oper_chwidth";
2703 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002704
developerf7a466e2022-09-29 11:55:56 +08002705 wifi_getMaxRadioNumber(&max_radio_num);
2706 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002707 {
developerf7a466e2022-09-29 11:55:56 +08002708 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2709 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002710 }
2711
2712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2713 return RETURN_OK;
2714}
2715
2716//Getting current radio extension channel
2717INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2718{
2719 CHAR buf[150] = {0};
2720 CHAR cmd[150] = {0};
2721 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2722 _syscmd(cmd, buf, sizeof(buf));
2723 if(NULL != strstr(buf,"HT40+"))
2724 strcpy(Value,"AboveControlChannel");
2725 else if(NULL != strstr(buf,"HT40-"))
2726 strcpy(Value,"BelowControlChannel");
2727 return RETURN_OK;
2728}
2729
2730//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2731//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.
2732INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2733{
developerfa41b1f2023-01-06 10:25:51 +08002734 char config_file[64] = {0};
2735 char mode_str[16] = {0};
2736 char buf[64] = {0};
2737 wifi_band band;
2738 int channel = 0, centr_channel = 0;
2739 UINT mode_map = 0;
2740
2741 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002742 return RETURN_ERR;
2743
developerfa41b1f2023-01-06 10:25:51 +08002744 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
2745
2746 band = wifi_index_to_band(radioIndex);
2747 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002748 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002749
2750 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2751
2752 snprintf(output_string, 64, "Auto");
2753 if (band == band_2_4 || (!mode_map&WIFI_MODE_AC && !mode_map&WIFI_MODE_AX)) {
2754 // 2G band or ac and ax mode is disable, we will check ht_capab
2755 wifi_halgetRadioExtChannel(config_file, output_string);
2756 if (!mode_map&WIFI_MODE_N)
2757 snprintf(output_string, 64, "Auto");
2758 } else {
2759 // 5G and 6G band with ac or ax mode.
2760 wifi_getRadioChannel(radioIndex, &channel);
2761 if (mode_map&WIFI_MODE_AX)
2762 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2763 else
2764 wifi_hostapdRead(config_file, "vht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2765 centr_channel = strtol(buf, NULL, 10);
2766 if (centr_channel > channel)
2767 snprintf(output_string, 64, "AboveControlChannel");
developer06a01d92022-09-07 16:32:39 +08002768 else
developerfa41b1f2023-01-06 10:25:51 +08002769 snprintf(output_string, 64, "BelowControlChannel");
developer06a01d92022-09-07 16:32:39 +08002770 }
developer06a01d92022-09-07 16:32:39 +08002771
2772 return RETURN_OK;
2773}
2774
2775//Set the extension channel.
2776INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2777{
2778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002779 struct params params={0};
2780 char config_file[64] = {0};
2781 char ext_channel[128]={0};
2782 char buf[128] = {0};
2783 char cmd[128] = {0};
2784 int max_radio_num =0, ret = 0, bandwidth = 0;
2785 unsigned long channel = 0, centr_channel = 0;
2786 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002787 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002788 wifi_band band;
2789
2790 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2791 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2792 _syscmd(cmd, buf, sizeof(buf));
2793 if (strlen(buf) != 0)
2794 stbcEnable = TRUE;
2795 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2796 return RETURN_ERR;
2797 bandwidth = strtol(buf, NULL, 10);
2798 // TDK expected to get error with 20MHz
2799 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2800 return RETURN_ERR;
2801
2802 band = wifi_index_to_band(radioIndex);
2803 if (band == band_invalid)
2804 return RETURN_ERR;
2805
2806 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2807 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002808
developerfa41b1f2023-01-06 10:25:51 +08002809 if (band == band_5) {
2810 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2811 centr_channel = util_unii_5g_centerfreq(buf, channel);
2812 if (centr_channel == 0)
2813 return RETURN_ERR;
2814 }
2815
2816 if(NULL!= strstr(string,"Above")) {
2817 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
2818 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08002819 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002820 } else if(NULL!= strstr(string,"Below")) {
2821 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
2822 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08002823 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002824 } else {
developer033b37b2022-10-18 11:27:46 +08002825 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developerfa41b1f2023-01-06 10:25:51 +08002826 }
developer06a01d92022-09-07 16:32:39 +08002827
2828 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002829
2830 wifi_getMaxRadioNumber(&max_radio_num);
2831 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002832 {
developer033b37b2022-10-18 11:27:46 +08002833 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002834 wifi_hostapdWrite(config_file, &params, 1);
developerfa41b1f2023-01-06 10:25:51 +08002835 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
developer06a01d92022-09-07 16:32:39 +08002836 }
2837
2838 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2840 return RETURN_OK;
2841}
2842
2843//Get the guard interval value. eg "400nsec" or "800nsec"
2844//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.
2845INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2846{
developer454b9462022-09-13 15:29:16 +08002847 wifi_guard_interval_t GI;
2848
2849 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2850
2851 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002852 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002853
2854 if (GI == wifi_guard_interval_400)
2855 strcpy(output_string, "400nsec");
2856 else if (GI == wifi_guard_interval_800)
2857 strcpy(output_string, "800nsec");
2858 else if (GI == wifi_guard_interval_1600)
2859 strcpy(output_string, "1600nsec");
2860 else if (GI == wifi_guard_interval_3200)
2861 strcpy(output_string, "3200nsec");
2862 else
developer78a15382022-11-02 10:57:40 +08002863 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002864
developer454b9462022-09-13 15:29:16 +08002865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002866 return RETURN_OK;
2867}
2868
2869//Set the guard interval value.
2870INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2871{
developer454b9462022-09-13 15:29:16 +08002872 wifi_guard_interval_t GI;
2873 int ret = 0;
2874
2875 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2876
2877 if (strcmp(string, "400nsec") == 0)
2878 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002879 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002880 GI = wifi_guard_interval_800;
2881 else if (strcmp(string , "1600nsec") == 0)
2882 GI = wifi_guard_interval_1600;
2883 else if (strcmp(string , "3200nsec") == 0)
2884 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002885 else
2886 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002887
2888 ret = wifi_setGuardInterval(radioIndex, GI);
2889
2890 if (ret == RETURN_ERR) {
2891 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2892 return RETURN_ERR;
2893 }
2894
2895 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2896 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002897}
2898
2899//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2900INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2901{
developerf49437e2022-09-29 19:58:21 +08002902 char buf[32]={0};
2903 char mcs_file[64] = {0};
2904 char cmd[64] = {0};
2905 int mode_bitmap = 0;
2906
2907 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2908 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002909 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002910 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2911
2912 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2913 _syscmd(cmd, buf, sizeof(buf));
2914 if (strlen(buf) > 0)
2915 *output_int = strtol(buf, NULL, 10);
2916 else {
2917 // output the max MCS for the current radio mode
2918 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2919 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2920 return RETURN_ERR;
2921 }
2922 if (mode_bitmap & WIFI_MODE_AX) {
2923 *output_int = 11;
2924 } else if (mode_bitmap & WIFI_MODE_AC) {
2925 *output_int = 9;
2926 } else if (mode_bitmap & WIFI_MODE_N) {
2927 *output_int = 7;
2928 }
2929 }
2930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002931
2932 return RETURN_OK;
2933}
2934
2935//Set the Modulation Coding Scheme index
2936INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2937{
developerf49437e2022-09-29 19:58:21 +08002938 // 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).
2939 char config_file[64] = {0};
2940 char set_value[16] = {0};
2941 char mcs_file[32] = {0};
2942 wifi_band band = band_invalid;
2943 struct params set_config = {0};
2944 FILE *f = NULL;
2945
2946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2947
2948 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2949
developer78a15382022-11-02 10:57:40 +08002950 // -1 means auto
2951 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08002952 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2953 return RETURN_ERR;
2954 }
2955
developer78a15382022-11-02 10:57:40 +08002956 if (MCS > 9 || MCS == -1)
2957 strcpy(set_value, "2");
2958 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08002959 strcpy(set_value, "1");
2960 else
developer78a15382022-11-02 10:57:40 +08002961 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08002962
2963 set_config.name = "he_basic_mcs_nss_set";
2964 set_config.value = set_value;
2965
2966 wifi_hostapdWrite(config_file, &set_config, 1);
2967 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2968
2969 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2970 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2971 f = fopen(mcs_file, "w");
2972 if (f == NULL) {
2973 fprintf(stderr, "%s: fopen failed\n", __func__);
2974 return RETURN_ERR;
2975 }
2976 fprintf(f, "%d", MCS);
2977 fclose(f);
2978
2979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2980 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002981}
2982
2983//Get supported Transmit Power list, eg : "0,25,50,75,100"
2984//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.
2985INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2986{
2987 if (NULL == output_list)
2988 return RETURN_ERR;
2989 snprintf(output_list, 64,"0,25,50,75,100");
2990 return RETURN_OK;
2991}
2992
developera5005b62022-09-13 15:43:35 +08002993//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002994//The transmite power level is in units of full power for this radio.
2995INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2996{
developerd946fd62022-12-08 18:03:28 +08002997 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002998 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002999 char buf[16]={0};
3000 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003001
developera5005b62022-09-13 15:43:35 +08003002 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003003 return RETURN_ERR;
3004
developerac6f1142022-12-20 19:26:35 +08003005 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003006 return RETURN_ERR;
3007 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 +08003008 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003009
developera5005b62022-09-13 15:43:35 +08003010 *output_ulong = strtol(buf, NULL, 10);
3011
3012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003013 return RETURN_OK;
3014}
3015
3016//Set Transmit Power
3017//The transmite power level is in units of full power for this radio.
3018INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3019{
developerd946fd62022-12-08 18:03:28 +08003020 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003021 char *support;
developer06a01d92022-09-07 16:32:39 +08003022 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003023 char buf[128]={0};
3024 char txpower_str[64] = {0};
3025 int txpower = 0;
3026 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08003027 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003028
3029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003030
developerac6f1142022-12-20 19:26:35 +08003031 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003032 return RETURN_ERR;
3033 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 +08003034 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003035 maximum_tx = strtol(buf, NULL, 10);
3036
3037 // Get the Tx power supported list and check that is the input in the list
3038 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3039 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3040 support = strtok(buf, ",");
3041 while(true)
3042 {
3043 if(support == NULL) { // input not in the list
3044 wifi_dbg_printf("Input value is invalid.\n");
3045 return RETURN_ERR;
3046 }
3047 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3048 break;
3049 }
3050 support = strtok(NULL, ",");
3051 }
3052 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003053 phyId = radio_index_to_phy(radioIndex);
3054 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003055 _syscmd(cmd, buf, sizeof(buf));
3056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003057
3058 return RETURN_OK;
3059}
3060
3061//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3062INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3063{
3064 if (NULL == Supported)
3065 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003066 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003067
3068 return RETURN_OK;
3069}
3070
3071//Get 80211h feature enable
3072INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3073{
developer3885fec2022-09-13 15:13:47 +08003074 char buf[64]={'\0'};
3075 char config_file[64] = {'\0'};
3076
3077 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3078 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003079 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003080
3081 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3082 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003083
developer3885fec2022-09-13 15:13:47 +08003084 if (strncmp(buf, "1", 1) == 0)
3085 *enable = TRUE;
3086 else
3087 *enable = FALSE;
3088
3089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003090 return RETURN_OK;
3091}
3092
3093//Set 80211h feature enable
3094INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3095{
developer3885fec2022-09-13 15:13:47 +08003096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3097 struct params params={'\0'};
3098 char config_file[MAX_BUF_SIZE] = {0};
3099
3100 params.name = "ieee80211h";
3101
3102 if (enable) {
3103 params.value = "1";
3104 } else {
3105 params.value = "0";
3106 }
3107
3108 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3109 wifi_hostapdWrite(config_file, &params, 1);
3110
3111 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3113 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003114}
3115
3116//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.
3117INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3118{
3119 if (NULL == output)
3120 return RETURN_ERR;
3121 *output=100;
3122
3123 return RETURN_OK;
3124}
3125
3126//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.
3127INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3128{
3129 if (NULL == output)
3130 return RETURN_ERR;
3131 *output = -99;
3132
3133 return RETURN_OK;
3134}
3135
3136INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3137{
3138 return RETURN_ERR;
3139}
3140
3141
3142//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3143INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3144{
developerd946fd62022-12-08 18:03:28 +08003145 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003146 char cmd[MAX_BUF_SIZE]={'\0'};
3147 char buf[MAX_CMD_SIZE]={'\0'};
3148
3149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3150 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003151 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003152
developerac6f1142022-12-20 19:26:35 +08003153 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003154 return RETURN_ERR;
3155 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 +08003156 _syscmd(cmd, buf, sizeof(buf));
3157 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003158
developer5f222492022-09-13 15:21:52 +08003159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003160 return RETURN_OK;
3161}
3162
3163INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3164{
developer5f222492022-09-13 15:21:52 +08003165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3166 struct params params={'\0'};
3167 char buf[MAX_BUF_SIZE] = {'\0'};
3168 char config_file[MAX_BUF_SIZE] = {'\0'};
3169
developer5b398df2022-11-17 20:39:48 +08003170 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3171 return RETURN_ERR;
3172
developer5f222492022-09-13 15:21:52 +08003173 params.name = "beacon_int";
3174 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3175 params.value = buf;
3176
3177 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3178 wifi_hostapdWrite(config_file, &params, 1);
3179
3180 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3182 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003183}
3184
3185//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.
3186INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3187{
developer06a01d92022-09-07 16:32:39 +08003188 //TODO: need to revisit below implementation
3189 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003190 char temp_output[128] = {0};
3191 char temp_TransmitRates[64] = {0};
3192 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003193
3194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3195 if (NULL == output)
3196 return RETURN_ERR;
3197 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003198 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3199
3200 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3201 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3202 } else {
3203 temp = strtok(temp_TransmitRates," ");
3204 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003205 {
developere9d0abd2022-09-13 15:40:57 +08003206 // Convert 100 kbps to Mbps
3207 temp[strlen(temp)-1]=0;
3208 if((temp[0]=='5') && (temp[1]=='\0'))
3209 {
3210 temp="5.5";
3211 }
3212 strcat(temp_output,temp);
3213 temp = strtok(NULL," ");
3214 if(temp!=NULL)
3215 {
3216 strcat(temp_output,",");
3217 }
developer06a01d92022-09-07 16:32:39 +08003218 }
developere9d0abd2022-09-13 15:40:57 +08003219 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003220 }
developer06a01d92022-09-07 16:32:39 +08003221 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003222 return RETURN_OK;
3223}
3224
3225INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3226{
3227 char *temp;
3228 char temp1[128];
3229 char temp_output[128];
3230 char temp_TransmitRates[128];
3231 char set[128];
3232 char sub_set[128];
3233 int set_count=0,subset_count=0;
3234 int set_index=0,subset_index=0;
3235 char *token;
3236 int flag=0, i=0;
3237 struct params params={'\0'};
3238 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003239 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003240
3241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3242 if(NULL == TransmitRates)
3243 return RETURN_ERR;
3244 strcpy(sub_set,TransmitRates);
3245
3246 //Allow only supported Data transmit rate to be set
3247 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3248 token = strtok(sub_set,",");
3249 while( token != NULL ) /* split the basic rate to be set, by comma */
3250 {
3251 sub_set[subset_count]=atoi(token);
3252 subset_count++;
3253 token=strtok(NULL,",");
3254 }
3255 token=strtok(set,",");
3256 while(token!=NULL) /* split the supported rate by comma */
3257 {
3258 set[set_count]=atoi(token);
3259 set_count++;
3260 token=strtok(NULL,",");
3261 }
3262 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3263 {
3264 for(set_index=0;set_index < set_count;set_index++)
3265 {
3266 flag=0;
3267 if(sub_set[subset_index]==set[set_index])
3268 break;
3269 else
3270 flag=1; /* No match found */
3271 }
3272 if(flag==1)
3273 return RETURN_ERR; //If value not found return Error
3274 }
3275 strcpy(temp_TransmitRates,TransmitRates);
3276
3277 for(i=0;i<strlen(temp_TransmitRates);i++)
3278 {
3279 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003280 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003281 {
3282 continue;
3283 }
3284 else
3285 {
3286 return RETURN_ERR;
3287 }
3288 }
3289 strcpy(temp_output,"");
3290 temp = strtok(temp_TransmitRates,",");
3291 while(temp!=NULL)
3292 {
3293 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003294 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003295 {
developeref938762022-10-19 17:21:01 +08003296 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003297 {
3298 return RETURN_ERR;
3299 }
3300 }
3301
3302 if(strcmp(temp,"5.5")==0)
3303 {
3304 strcpy(temp1,"55");
3305 }
3306 else
3307 {
3308 strcat(temp1,"0");
3309 }
3310 strcat(temp_output,temp1);
3311 temp = strtok(NULL,",");
3312 if(temp!=NULL)
3313 {
3314 strcat(temp_output," ");
3315 }
3316 }
3317 strcpy(TransmitRates,temp_output);
3318
3319 params.name= "basic_rates";
3320 params.value =TransmitRates;
3321
3322 wifi_dbg_printf("\n%s:",__func__);
3323 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3324 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3325 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3326 wifi_hostapdWrite(config_file,&params,1);
3327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3328 return RETURN_OK;
3329}
3330
3331//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003332INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003333{
3334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3335 FILE *fp = NULL;
3336 char path[256] = {0}, output_string[256] = {0};
3337 int count = 0;
3338 char *interface = NULL;
3339
3340 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3341 if (fp == NULL)
3342 {
3343 printf("Failed to run command in Function %s\n", __FUNCTION__);
3344 return RETURN_ERR;
3345 }
3346 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3347 {
3348 interface = strchr(path, '=');
3349
3350 if (interface != NULL)
3351 {
3352 strcpy(output_string, interface + 1);
3353 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3354 interface_name[count] = output_string[count];
3355
3356 interface_name[count] = '\0';
3357 }
3358 }
3359 pclose(fp);
3360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3361 return RETURN_OK;
3362}
3363
3364INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3365{
3366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3367 output_struct->radio_BytesSent = 0;
3368 output_struct->radio_BytesReceived = 0;
3369 output_struct->radio_PacketsSent = 0;
3370 output_struct->radio_PacketsReceived = 0;
3371 output_struct->radio_ErrorsSent = 0;
3372 output_struct->radio_ErrorsReceived = 0;
3373 output_struct->radio_DiscardPacketsSent = 0;
3374 output_struct->radio_DiscardPacketsReceived = 0;
3375 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3376 return RETURN_OK;
3377}
3378
3379
3380INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3381{
3382 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3383 CHAR buf[MAX_CMD_SIZE] = {0};
3384 CHAR Value[MAX_BUF_SIZE] = {0};
3385 FILE *fp = NULL;
3386
3387 if (ifname == NULL || strlen(ifname) <= 1)
3388 return RETURN_OK;
3389
3390 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3391 system(buf);
3392
3393 fp = fopen("/tmp/Radio_Stats.txt", "r");
3394 if(fp == NULL)
3395 {
3396 printf("/tmp/Radio_Stats.txt not exists \n");
3397 return RETURN_ERR;
3398 }
3399 fclose(fp);
3400
3401 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3402 File_Reading(buf, Value);
3403 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3404
3405 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3406 File_Reading(buf, Value);
3407 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3408
3409 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3410 File_Reading(buf, Value);
3411 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3412
3413 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3414 File_Reading(buf, Value);
3415 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3416
3417 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3418 File_Reading(buf, Value);
3419 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3420
3421 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3422 File_Reading(buf, Value);
3423 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3424
3425 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3426 File_Reading(buf, Value);
3427 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3428
3429 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3430 File_Reading(buf, Value);
3431 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3432
3433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3434 return RETURN_OK;
3435}
3436
3437INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3438{
3439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3440 CHAR buf[MAX_CMD_SIZE] = {0};
3441 FILE *fp = NULL;
3442 INT count = 0;
3443
3444 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3445 {
3446 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3447 File_Reading(buf, status);
3448 }
3449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3450 return RETURN_OK;
3451}
3452
3453//Get detail radio traffic static info
3454INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3455{
3456
3457#if 0
3458 //ifconfig radio_x
3459 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3460 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3461 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3462 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3463
3464 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3465 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3466 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.
3467 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.
3468
3469 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3470 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].
3471 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3472 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.
3473 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
3474 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
3475 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
3476 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
3477 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
3478
3479 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
3480 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
3481 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
3482 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.
3483
3484 return RETURN_OK;
3485#endif
3486
developera91d99f2022-09-29 15:59:10 +08003487 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003488 BOOL iface_status = FALSE;
3489 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003490
3491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3492 if (NULL == output_struct)
3493 return RETURN_ERR;
3494
developerac6f1142022-12-20 19:26:35 +08003495 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08003496 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003497
developera91d99f2022-09-29 15:59:10 +08003498 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003499
developera91d99f2022-09-29 15:59:10 +08003500 if (iface_status == TRUE)
3501 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3502 else
3503 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003504
developera91d99f2022-09-29 15:59:10 +08003505 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3506 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3507 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3508 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3509 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3510 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3511 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3512 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003513
3514 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3515 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].
3516 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3517 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.
3518 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
3519 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
3520 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
3521 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
3522 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
3523
3524 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
3525 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
3526 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
3527 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.
3528
3529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3530
3531 return RETURN_OK;
3532}
3533
3534//Set radio traffic static Measureing rules
3535INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3536{
3537 //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
3538 // Else, save the MeasuringRate and MeasuringInterval for future usage
3539
3540 return RETURN_OK;
3541}
3542
3543//To start or stop RadioTrafficStats
3544INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3545{
3546 //zqiu: If the RadioTrafficStats process running
3547 // if(enable)
3548 // return RETURN_OK.
3549 // else
3550 // Stop RadioTrafficStats process
3551 // Else
3552 // if(enable)
3553 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3554 // else
3555 // return RETURN_OK.
3556
3557 return RETURN_OK;
3558}
3559
3560//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
3561INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3562{
3563 //zqiu: Please ignor signalIndex.
3564 if (NULL == SignalLevel)
3565 return RETURN_ERR;
3566 *SignalLevel=(radioIndex==0)?-19:-19;
3567
3568 return RETURN_OK;
3569}
3570
3571//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3572INT wifi_applyRadioSettings(INT radioIndex)
3573{
3574 return RETURN_OK;
3575}
3576
3577//Get the radio index assocated with this SSID entry
3578INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3579{
developer5b398df2022-11-17 20:39:48 +08003580 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003581 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003582 int max_radio_num = 0;
3583 wifi_getMaxRadioNumber(&max_radio_num);
3584 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003585 return RETURN_OK;
3586}
3587
3588//Device.WiFi.SSID.{i}.Enable
3589//Get SSID enable configuration parameters (not the SSID enable status)
3590INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3591{
3592 if (NULL == output_bool)
3593 return RETURN_ERR;
3594
developer06a01d92022-09-07 16:32:39 +08003595 return wifi_getApEnable(ssidIndex, output_bool);
3596}
3597
3598//Device.WiFi.SSID.{i}.Enable
3599//Set SSID enable configuration parameters
3600INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3601{
developer06a01d92022-09-07 16:32:39 +08003602 return wifi_setApEnable(ssidIndex, enable);
3603}
3604
3605//Device.WiFi.SSID.{i}.Status
3606//Get the SSID enable status
3607INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3608{
3609 char cmd[MAX_CMD_SIZE]={0};
3610 char buf[MAX_BUF_SIZE]={0};
3611 BOOL output_bool;
3612
3613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3614 if (NULL == output_string)
3615 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003616
developer06a01d92022-09-07 16:32:39 +08003617 wifi_getApEnable(ssidIndex,&output_bool);
3618 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3619
3620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3621 return RETURN_OK;
3622}
3623
3624// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3625INT wifi_getSSIDName(INT apIndex, CHAR *output)
3626{
3627 char config_file[MAX_BUF_SIZE] = {0};
3628
3629 if (NULL == output)
3630 return RETURN_ERR;
3631
3632 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3633 wifi_hostapdRead(config_file,"ssid",output,32);
3634
3635 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3636 return RETURN_OK;
3637}
3638
3639// Set a max 32 byte string and sets an internal variable to the SSID name
3640INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3641{
3642 char str[MAX_BUF_SIZE]={'\0'};
3643 char cmd[MAX_CMD_SIZE]={'\0'};
3644 struct params params;
3645 char config_file[MAX_BUF_SIZE] = {0};
3646
3647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3648 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3649 return RETURN_ERR;
3650
3651 params.name = "ssid";
3652 params.value = ssid_string;
3653 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3654 wifi_hostapdWrite(config_file, &params, 1);
3655 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3657
3658 return RETURN_OK;
3659}
3660
3661//Get the BSSID
3662INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3663{
3664 char cmd[MAX_CMD_SIZE]="";
3665
3666 if (NULL == output_string)
3667 return RETURN_ERR;
3668
3669 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3670 {
developer1d57d002022-10-12 18:03:15 +08003671 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 +08003672 _syscmd(cmd, output_string, 64);
3673 return RETURN_OK;
3674 }
3675 strncpy(output_string, "\0", 1);
3676
3677 return RETURN_ERR;
3678}
3679
3680//Get the MAC address associated with this Wifi SSID
3681INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3682{
3683 wifi_getBaseBSSID(ssidIndex,output_string);
3684 return RETURN_OK;
3685}
3686
3687//Get the basic SSID traffic static info
3688//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3689//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3690INT wifi_applySSIDSettings(INT ssidIndex)
3691{
developerd946fd62022-12-08 18:03:28 +08003692 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003693 BOOL status = false;
3694 char cmd[MAX_CMD_SIZE] = {0};
3695 char buf[MAX_CMD_SIZE] = {0};
3696 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003697 int max_radio_num = 0;
3698 int radioIndex = 0;
3699
3700 wifi_getMaxRadioNumber(&max_radio_num);
3701
3702 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003703
3704 wifi_getApEnable(ssidIndex,&status);
3705 // Do not apply when ssid index is disabled
3706 if (status == false)
3707 return RETURN_OK;
3708
3709 /* Doing full remove and add for ssid Index
3710 * Not all hostapd options are supported with reload
3711 * for example macaddr_acl
3712 */
3713 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3714 return RETURN_ERR;
3715
3716 ret = wifi_setApEnable(ssidIndex,true);
3717
3718 /* Workaround for hostapd issue with multiple bss definitions
3719 * when first created interface will be removed
3720 * then all vaps other vaps on same phy are removed
3721 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003722 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003723 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003724 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003725 return RETURN_ERR;
3726 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003727 _syscmd(cmd, buf, sizeof(buf));
3728 if(*buf == '1')
3729 wifi_setApEnable(apIndex, true);
3730 }
3731
3732 return ret;
3733}
3734
developera3c68b92022-09-13 15:27:29 +08003735struct channels_noise {
3736 int channel;
3737 int noise;
3738};
3739
3740// Return noise array for each channel
3741int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3742{
developerd946fd62022-12-08 18:03:28 +08003743 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003744 FILE *f = NULL;
3745 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003746 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003747 size_t len = 0;
3748 ssize_t read = 0;
3749 int tmp = 0, arr_index = -1;
3750
developerac6f1142022-12-20 19:26:35 +08003751 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003752 return RETURN_ERR;
3753 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003754
3755 if ((f = popen(cmd, "r")) == NULL) {
3756 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3757 return RETURN_ERR;
3758 }
developer5550e242022-09-30 09:59:32 +08003759
3760 while(fgets(line, sizeof(line), f) != NULL) {
3761 if(arr_index < channels_num){
3762 sscanf(line, "%d", &tmp);
3763 if (tmp > 0) { // channel frequency, the first line must be frequency
3764 arr_index++;
3765 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3766 } else { // noise
3767 channels_noise_arr[arr_index].noise = tmp;
3768 }
3769 }else{
3770 break;
developera3c68b92022-09-13 15:27:29 +08003771 }
3772 }
developera3c68b92022-09-13 15:27:29 +08003773 pclose(f);
3774 return RETURN_OK;
3775}
3776
developer06a01d92022-09-07 16:32:39 +08003777//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3778//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3779INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3780{
developera3c68b92022-09-13 15:27:29 +08003781 int index = -1;
3782 wifi_neighbor_ap2_t *scan_array = NULL;
3783 char cmd[256]={0};
3784 char buf[128]={0};
3785 char file_name[32] = {0};
3786 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003787 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003788 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003789 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003790 int freq=0;
3791 FILE *f = NULL;
3792 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003793 int channels_num = 0;
3794 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003795 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003796 bool filter_enable = false;
3797 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003798 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003799
developer615510b2022-09-27 10:14:35 +08003800 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003801
developerac6f1142022-12-20 19:26:35 +08003802 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003803 return RETURN_ERR;
3804
developera3c68b92022-09-13 15:27:29 +08003805 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3806 f = fopen(file_name, "r");
3807 if (f != NULL) {
3808 fgets(filter_SSID, sizeof(file_name), f);
3809 if (strlen(filter_SSID) != 0)
3810 filter_enable = true;
3811 fclose(f);
3812 }
3813
developer033b37b2022-10-18 11:27:46 +08003814 phyId = radio_index_to_phy(radioIndex);
3815 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003816 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003817 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003818
developer5550e242022-09-30 09:59:32 +08003819
developer06a01d92022-09-07 16:32:39 +08003820
developerd946fd62022-12-08 18:03:28 +08003821 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3822 // 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 +08003823 fprintf(stderr, "cmd: %s\n", cmd);
3824 if ((f = popen(cmd, "r")) == NULL) {
3825 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3826 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003827 }
developer5550e242022-09-30 09:59:32 +08003828
3829 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3830 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3831
developer615510b2022-09-27 10:14:35 +08003832 ret = fgets(line, sizeof(line), f);
3833 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003834 if(strstr(line, "BSS") != NULL) { // new neighbor info
3835 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3836 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3837 // 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 +08003838
developera3c68b92022-09-13 15:27:29 +08003839 if (!filter_BSS) {
3840 index++;
3841 wifi_neighbor_ap2_t *tmp;
3842 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3843 if (tmp == NULL) { // no more memory to use
3844 index--;
3845 wifi_dbg_printf("%s: realloc failed\n", __func__);
3846 break;
3847 }
3848 scan_array = tmp;
3849 }
3850 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3851
3852 filter_BSS = false;
3853 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3854 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3855 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3856 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3857 } else if (strstr(line, "freq") != NULL) {
3858 sscanf(line," freq: %d", &freq);
3859 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3860
3861 if (freq >= 2412 && freq <= 2484) {
3862 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3863 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3864 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3865 }
3866 else if (freq >= 5160 && freq <= 5805) {
3867 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3868 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3869 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3870 }
3871
3872 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003873 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003874 for (int i = 0; i < channels_num; i++) {
3875 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3876 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3877 break;
3878 }
3879 }
3880 }
3881 } else if (strstr(line, "beacon interval") != NULL) {
3882 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3883 } else if (strstr(line, "signal") != NULL) {
3884 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3885 } else if (strstr(line,"SSID") != NULL) {
3886 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3887 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3888 filter_BSS = true;
3889 }
3890 } else if (strstr(line, "Supported rates") != NULL) {
3891 char SRate[80] = {0}, *tmp = NULL;
3892 memset(buf, 0, sizeof(buf));
3893 strcpy(SRate, line);
3894 tmp = strtok(SRate, ":");
3895 tmp = strtok(NULL, ":");
3896 strcpy(buf, tmp);
3897 memset(SRate, 0, sizeof(SRate));
3898
3899 tmp = strtok(buf, " \n");
3900 while (tmp != NULL) {
3901 strcat(SRate, tmp);
3902 if (SRate[strlen(SRate) - 1] == '*') {
3903 SRate[strlen(SRate) - 1] = '\0';
3904 }
3905 strcat(SRate, ",");
3906
3907 tmp = strtok(NULL, " \n");
3908 }
3909 SRate[strlen(SRate) - 1] = '\0';
3910 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3911 } else if (strstr(line, "DTIM") != NULL) {
3912 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3913 } else if (strstr(line, "VHT capabilities") != NULL) {
3914 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3915 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3916 } else if (strstr(line, "HT capabilities") != NULL) {
3917 strcat(scan_array[index].ap_SupportedStandards, ",n");
3918 strcpy(scan_array[index].ap_OperatingStandards, "n");
3919 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003920 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003921 sscanf(line," * channel width: %d", &vht_channel_width);
3922 if(vht_channel_width == 1) {
3923 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3924 } else {
3925 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3926 }
3927 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3928 continue;
3929 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003930 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003931 sscanf(line," * secondary channel offset: %s", &buf);
3932 if (!strcmp(buf, "above")) {
3933 //40Mhz +
3934 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3935 }
3936 else if (!strcmp(buf, "below")) {
3937 //40Mhz -
3938 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3939 } else {
3940 //20Mhz
3941 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3942 }
3943 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3944 continue;
3945 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003946 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3947 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3948 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003949 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3950 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003951 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003952 else
developer615510b2022-09-27 10:14:35 +08003953 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003954 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003955 if (strstr(line, "HE80/5GHz") != NULL) {
3956 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3957 ret = fgets(line, sizeof(line), f);
3958 } else
3959 continue;
developera3c68b92022-09-13 15:27:29 +08003960 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003961 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003962 }
developer615510b2022-09-27 10:14:35 +08003963 continue;
developera3c68b92022-09-13 15:27:29 +08003964 } else if (strstr(line, "WPA") != NULL) {
3965 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3966 } else if (strstr(line, "RSN") != NULL) {
3967 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3968 } else if (strstr(line, "Group cipher") != NULL) {
3969 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3970 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3971 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3972 }
3973 }
developer615510b2022-09-27 10:14:35 +08003974 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003975 }
3976
3977 if (!filter_BSS) {
3978 *output_array_size = index + 1;
3979 } else {
3980 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3981 *output_array_size = index;
3982 }
3983 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003984 pclose(f);
developer5550e242022-09-30 09:59:32 +08003985 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003987 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003988}
3989
3990//>> Deprecated: used for old RDKB code.
3991INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3992{
3993 INT status = RETURN_ERR;
3994
3995 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3996 output_struct->wifi_PLCPErrorCount = 0;
3997 output_struct->wifi_FCSErrorCount = 0;
3998 output_struct->wifi_InvalidMACCount = 0;
3999 output_struct->wifi_PacketsOtherReceived = 0;
4000 output_struct->wifi_Noise = 0;
4001 status = RETURN_OK;
4002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4003 return status;
4004}
4005
4006INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4007{
developerd946fd62022-12-08 18:03:28 +08004008 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004009 char cmd[128] = {0};
4010 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004011 char *pos = NULL;
4012
4013 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4014 if (NULL == output_struct)
4015 return RETURN_ERR;
4016
developerac6f1142022-12-20 19:26:35 +08004017 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004018 return RETURN_ERR;
4019
developer06a01d92022-09-07 16:32:39 +08004020 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4021
developerd946fd62022-12-08 18:03:28 +08004022 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004023 _syscmd(cmd, buf, sizeof(buf));
4024
4025 pos = buf;
4026 if ((pos = strstr(pos, "RX packets:")) == NULL)
4027 return RETURN_ERR;
4028 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4029
4030 if ((pos = strstr(pos, "TX packets:")) == NULL)
4031 return RETURN_ERR;
4032 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4033
4034 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4035 return RETURN_ERR;
4036 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4037
4038 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4039 return RETURN_ERR;
4040 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4041
developerd946fd62022-12-08 18:03:28 +08004042 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004043 _syscmd(cmd, buf, sizeof(buf));
4044 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4045
4046#if 0
4047 //TODO: need to revisit below implementation
4048 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4049 char interface_name[MAX_BUF_SIZE] = {0};
4050 char interface_status[MAX_BUF_SIZE] = {0};
4051 char Value[MAX_BUF_SIZE] = {0};
4052 char buf[MAX_CMD_SIZE] = {0};
4053 char cmd[MAX_CMD_SIZE] = {0};
4054 FILE *fp = NULL;
4055
4056 if (NULL == output_struct) {
4057 return RETURN_ERR;
4058 }
4059
4060 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4061
4062 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4063 {
4064 if(apIndex == 0) //private_wifi for 2.4G
4065 {
developerac6f1142022-12-20 19:26:35 +08004066 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004067 }
4068 else if(apIndex == 1) //private_wifi for 5G
4069 {
developerac6f1142022-12-20 19:26:35 +08004070 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004071 }
4072 else if(apIndex == 4) //public_wifi for 2.4G
4073 {
4074 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4075 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4076 {
4077 return RETURN_ERR;
4078 }
4079 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004080 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004081 else//tenda
developerac6f1142022-12-20 19:26:35 +08004082 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004083 }
4084 else if(apIndex == 5) //public_wifi for 5G
4085 {
developerac6f1142022-12-20 19:26:35 +08004086 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004087 }
4088
4089 GetIfacestatus(interface_name, interface_status);
4090
4091 if(0 != strcmp(interface_status, "1"))
4092 return RETURN_ERR;
4093
4094 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4095 system(cmd);
4096
4097 fp = fopen("/tmp/SSID_Stats.txt", "r");
4098 if(fp == NULL)
4099 {
4100 printf("/tmp/SSID_Stats.txt not exists \n");
4101 return RETURN_ERR;
4102 }
4103 fclose(fp);
4104
4105 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4106 File_Reading(buf, Value);
4107 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4108
4109 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4110 File_Reading(buf, Value);
4111 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4112
4113 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4114 File_Reading(buf, Value);
4115 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4116
4117 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4118 File_Reading(buf, Value);
4119 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4120
4121 /* There is no specific parameter from caller to associate the value wifi_Associations */
4122 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4123 //_syscmd(cmd, buf, sizeof(buf));
4124 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4125 }
4126#endif
4127 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4128 return RETURN_OK;
4129}
4130
4131INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4132{
4133 char interface_name[MAX_BUF_SIZE] = {0};
4134 char interface_status[MAX_BUF_SIZE] = {0};
4135 char Value[MAX_BUF_SIZE] = {0};
4136 char buf[MAX_CMD_SIZE] = {0};
4137 char cmd[MAX_CMD_SIZE] = {0};
4138 FILE *fp = NULL;
4139
4140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4141 if (NULL == output_struct)
4142 return RETURN_ERR;
4143
4144 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4145
developerac6f1142022-12-20 19:26:35 +08004146 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004147 return RETURN_ERR;
4148 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004149
developerd946fd62022-12-08 18:03:28 +08004150 if(0 != strcmp(interface_status, "1"))
4151 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004152
developerd946fd62022-12-08 18:03:28 +08004153 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4154 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004155
developerd946fd62022-12-08 18:03:28 +08004156 fp = fopen("/tmp/SSID_Stats.txt", "r");
4157 if(fp == NULL)
4158 {
4159 printf("/tmp/SSID_Stats.txt not exists \n");
4160 return RETURN_ERR;
4161 }
4162 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004163
developerd946fd62022-12-08 18:03:28 +08004164 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4165 File_Reading(buf, Value);
4166 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004167
developerd946fd62022-12-08 18:03:28 +08004168 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4169 File_Reading(buf, Value);
4170 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004171
developerd946fd62022-12-08 18:03:28 +08004172 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4173 File_Reading(buf, Value);
4174 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004175
developerd946fd62022-12-08 18:03:28 +08004176 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4177 File_Reading(buf, Value);
4178 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004179
4180 output_struct->wifi_UnicastPacketsSent = 0;
4181 output_struct->wifi_UnicastPacketsReceived = 0;
4182 output_struct->wifi_MulticastPacketsSent = 0;
4183 output_struct->wifi_MulticastPacketsReceived = 0;
4184 output_struct->wifi_BroadcastPacketsSent = 0;
4185 output_struct->wifi_BroadcastPacketsRecevied = 0;
4186 output_struct->wifi_UnknownPacketsReceived = 0;
4187
4188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4189 return RETURN_OK;
4190}
4191
4192INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4193{
4194 INT status = RETURN_ERR;
4195
4196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4197 //Below values should get updated from hal
4198 output_struct->wifi_RetransCount=0;
4199 output_struct->wifi_FailedRetransCount=0;
4200 output_struct->wifi_RetryCount=0;
4201 output_struct->wifi_MultipleRetryCount=0;
4202 output_struct->wifi_ACKFailureCount=0;
4203 output_struct->wifi_AggregatedPacketCount=0;
4204
4205 status = RETURN_OK;
4206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4207
4208 return status;
4209}
4210
4211INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4212{
4213 INT status = RETURN_ERR;
4214 UINT index;
4215 wifi_neighbor_ap_t *pt=NULL;
4216
4217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4218 *output_array_size=2;
4219 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4220 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4221 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4222 strcpy(pt->ap_Radio,"");
4223 strcpy(pt->ap_SSID,"");
4224 strcpy(pt->ap_BSSID,"");
4225 strcpy(pt->ap_Mode,"");
4226 pt->ap_Channel=1;
4227 pt->ap_SignalStrength=0;
4228 strcpy(pt->ap_SecurityModeEnabled,"");
4229 strcpy(pt->ap_EncryptionMode,"");
4230 strcpy(pt->ap_OperatingFrequencyBand,"");
4231 strcpy(pt->ap_SupportedStandards,"");
4232 strcpy(pt->ap_OperatingStandards,"");
4233 strcpy(pt->ap_OperatingChannelBandwidth,"");
4234 pt->ap_BeaconPeriod=1;
4235 pt->ap_Noise=0;
4236 strcpy(pt->ap_BasicDataTransferRates,"");
4237 strcpy(pt->ap_SupportedDataTransferRates,"");
4238 pt->ap_DTIMPeriod=1;
4239 pt->ap_ChannelUtilization = 1;
4240 }
4241
4242 status = RETURN_OK;
4243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4244
4245 return status;
4246}
4247
4248//----------------- AP HAL -------------------------------
4249
4250//>> Deprecated: used for old RDKB code.
4251INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4252{
4253 if (NULL == output_ulong || NULL == output_struct)
4254 return RETURN_ERR;
4255 *output_ulong = 0;
4256 *output_struct = NULL;
4257 return RETURN_OK;
4258}
4259
4260#ifdef HAL_NETLINK_IMPL
4261static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4262 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4263 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4264 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4265 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4266 char mac_addr[20];
4267 static int count=0;
4268 int rate=0;
4269
4270 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4271
4272 nla_parse(tb,
4273 NL80211_ATTR_MAX,
4274 genlmsg_attrdata(gnlh, 0),
4275 genlmsg_attrlen(gnlh, 0),
4276 NULL);
4277
4278 if(!tb[NL80211_ATTR_STA_INFO]) {
4279 fprintf(stderr, "sta stats missing!\n");
4280 return NL_SKIP;
4281 }
4282
4283
4284 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4285 fprintf(stderr, "failed to parse nested attributes!\n");
4286 return NL_SKIP;
4287 }
4288
4289 //devIndex starts from 1
4290 if( ++count == out->wifi_devIndex )
4291 {
4292 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4293 //Getting the mac addrress
4294 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4295
4296 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4297 fprintf(stderr, "failed to parse nested rate attributes!");
4298 return NL_SKIP;
4299 }
4300
4301 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4302 if(rinfo[NL80211_RATE_INFO_BITRATE])
4303 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4304 out->wifi_devTxRate = rate/10;
4305 }
4306
4307 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4308 fprintf(stderr, "failed to parse nested rate attributes!");
4309 return NL_SKIP;
4310 }
4311
4312 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4313 if(rinfo[NL80211_RATE_INFO_BITRATE])
4314 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4315 out->wifi_devRxRate = rate/10;
4316 }
4317 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4318 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4319
4320 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4321 count = 0; //starts the count for next cycle
4322 return NL_STOP;
4323 }
4324
4325 return NL_SKIP;
4326
4327}
4328#endif
4329
4330INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4331{
4332#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004333 Netlink nl = {0};
4334 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004335 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004336
developer30423732022-12-01 16:17:49 +08004337 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004338 info.wifi_devIndex = devIndex;
4339
developerac6f1142022-12-20 19:26:35 +08004340 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004341 return RETURN_ERR;
4342
4343 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004344
4345 nl.id = initSock80211(&nl);
4346
4347 if (nl.id < 0) {
4348 fprintf(stderr, "Error initializing netlink \n");
4349 return -1;
4350 }
4351
4352 struct nl_msg* msg = nlmsg_alloc();
4353
4354 if (!msg) {
4355 fprintf(stderr, "Failed to allocate netlink message.\n");
4356 nlfree(&nl);
4357 return -2;
4358 }
4359
4360 genlmsg_put(msg,
4361 NL_AUTO_PORT,
4362 NL_AUTO_SEQ,
4363 nl.id,
4364 0,
4365 NLM_F_DUMP,
4366 NL80211_CMD_GET_STATION,
4367 0);
4368
4369 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4370 nl_send_auto(nl.socket, msg);
4371 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4372 nl_recvmsgs(nl.socket, nl.cb);
4373 nlmsg_free(msg);
4374 nlfree(&nl);
4375
4376 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4377 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4378 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4379 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4380 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4381 return RETURN_OK;
4382#else
4383 //iw utility to retrieve station information
4384#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4385#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4386#define MACFILE "/tmp/wifi_AssoMac.txt"
4387#define TXRATEFILE "/tmp/wifi_txrate.txt"
4388#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4389 FILE *file = NULL;
4390 char if_name[10] = {'\0'};
4391 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004392 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004393 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004394 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004395
developerac6f1142022-12-20 19:26:35 +08004396 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004397 return RETURN_ERR;
4398
4399 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004400
4401 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4402 file = popen(pipeCmd, "r");
4403
4404 if(file == NULL)
4405 return RETURN_ERR; //popen failed
4406
4407 fgets(line, sizeof line, file);
4408 device = atoi(line);
4409 pclose(file);
4410
4411 if(device == 0)
4412 return RETURN_ERR; //No devices are connected
4413
4414 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4415 system(pipeCmd);
4416
4417 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4418
4419 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4420
4421 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4422
4423 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4424
4425 //devIndex starts from 1, ++count
4426 if((file = fopen(SIGNALFILE, "r")) != NULL )
4427 {
4428 for(count =0;fgets(line, sizeof line, file) != NULL;)
4429 {
4430 if (++count == devIndex)
4431 {
4432 output_struct->wifi_devSignalStrength = atoi(line);
4433 break;
4434 }
4435 }
4436 fclose(file);
4437 }
4438 else
4439 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4440
4441 if((file = fopen(MACFILE, "r")) != NULL )
4442 {
4443 for(count =0;fgets(line, sizeof line, file) != NULL;)
4444 {
4445 if (++count == devIndex)
4446 {
4447 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]);
4448 break;
4449 }
4450 }
4451 fclose(file);
4452 }
4453 else
4454 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4455
4456 if((file = fopen(TXRATEFILE, "r")) != NULL )
4457 {
4458 for(count =0;fgets(line, sizeof line, file) != NULL;)
4459 {
4460 if (++count == devIndex)
4461 {
4462 output_struct->wifi_devTxRate = atoi(line);
4463 break;
4464 }
4465 }
4466 fclose(file);
4467 }
4468 else
4469 fprintf(stderr,"fopen wifi_txrate.txt failed");
4470
4471 if((file = fopen(RXRATEFILE, "r")) != NULL)
4472 {
4473 for(count =0;fgets(line, sizeof line, file) != NULL;)
4474 {
4475 if (++count == devIndex)
4476 {
4477 output_struct->wifi_devRxRate = atoi(line);
4478 break;
4479 }
4480 }
4481 fclose(file);
4482 }
4483 else
4484 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4485
4486 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4487
4488 return RETURN_OK;
4489#endif
4490}
4491
4492INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4493{
4494 if (NULL == device)
4495 return RETURN_ERR;
4496 return RETURN_OK;
4497}
4498//<<
4499
4500
4501//--------------wifi_ap_hal-----------------------------
4502//enables CTS protection for the radio used by this AP
4503INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4504{
4505 //save config and Apply instantly
4506 return RETURN_ERR;
4507}
4508
4509// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4510INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4511{
developer463d39a2022-09-13 15:32:51 +08004512 char config_file[64] = {'\0'};
4513 char buf[64] = {'\0'};
4514 struct params list;
4515
4516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4517 list.name = "ht_coex";
4518 snprintf(buf, sizeof(buf), "%d", enable);
4519 list.value = buf;
4520
4521 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4522 wifi_hostapdWrite(config_file, &list, 1);
4523 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4524
4525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4526
4527 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004528}
4529
4530//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4531INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4532{
developerea4bcce2022-09-13 15:26:13 +08004533 char config_file[MAX_BUF_SIZE] = {'\0'};
4534 char buf[MAX_BUF_SIZE] = {'\0'};
4535 struct params list;
4536
4537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4538 if (threshold < 256 || threshold > 2346 )
4539 return RETURN_ERR;
4540 list.name = "fragm_threshold";
4541 snprintf(buf, sizeof(buf), "%d", threshold);
4542 list.value = buf;
4543
4544 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4545 wifi_hostapdWrite(config_file, &list, 1);
4546 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004547
developerea4bcce2022-09-13 15:26:13 +08004548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004549
4550 return RETURN_OK;
4551}
4552
4553// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4554INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4555{
developer51a927d2022-09-13 15:42:22 +08004556 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004557 char cmd[512] = {'\0'};
4558 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004559 char stbc_config[16] = {'\0'};
4560 wifi_band band;
4561 int iterator = 0;
4562 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004563 int ant_count = 0;
4564 int ant_bitmap = 0;
4565 struct params list;
developer51a927d2022-09-13 15:42:22 +08004566
4567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4568
4569 band = wifi_index_to_band(radioIndex);
4570 if (band == band_invalid)
4571 return RETURN_ERR;
4572
4573 if (band == band_2_4)
4574 iterator = 1;
4575 else if (band == band_5)
4576 iterator = 2;
4577 else
4578 return RETURN_OK;
4579
developer110b8a32022-12-26 15:56:44 +08004580 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4581 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4582 ant_count += ant_bitmap & 1;
4583
4584 if (ant_count == 1 && STBC_Enable == TRUE) {
4585 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4586 return RETURN_OK;
4587 }
4588
developer51a927d2022-09-13 15:42:22 +08004589 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4590
4591 // set ht and vht config
4592 for (int i = 0; i < iterator; i++) {
4593 memset(stbc_config, 0, sizeof(stbc_config));
4594 memset(cmd, 0, sizeof(cmd));
4595 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004596 list.name = (i == 0)?"ht_capab":"vht_capab";
4597 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004598 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4599 _syscmd(cmd, buf, sizeof(buf));
4600 if (strlen(buf) != 0)
4601 current_stbc = TRUE;
4602 if (current_stbc == STBC_Enable)
4603 continue;
4604
4605 if (STBC_Enable == TRUE) {
4606 // Append the STBC flags in capab config
4607 memset(cmd, 0, sizeof(cmd));
4608 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004609 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004610 else
developer6372c2b2022-10-27 17:39:51 +08004611 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 +08004612 _syscmd(cmd, buf, sizeof(buf));
4613 } else if (STBC_Enable == FALSE) {
4614 // Remove the STBC flags and remain other flags in capab
4615 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004616 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004617 _syscmd(cmd, buf, sizeof(buf));
4618 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004619 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004620 _syscmd(cmd, buf, sizeof(buf));
4621 }
developer110b8a32022-12-26 15:56:44 +08004622 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4623 list.value = buf;
4624 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004625 }
4626
4627 wifi_reloadAp(radioIndex);
4628
4629 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4630 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004631}
4632
4633// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4634INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4635{
developerfe7aefc2022-12-23 17:13:37 +08004636 char cmd[128] = {0};
4637 char buf[128] = {0};
4638 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004639
4640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4641
4642 if(output_bool == NULL)
4643 return RETURN_ERR;
4644
developerfe7aefc2022-12-23 17:13:37 +08004645 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4646 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004647
developerfe7aefc2022-12-23 17:13:37 +08004648 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4649 _syscmd(cmd, buf, sizeof(buf));
4650
4651 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004652 *output_bool = TRUE;
4653 else
4654 *output_bool = FALSE;
4655
4656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4657 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004658}
4659
4660// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4661INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4662{
developerfe7aefc2022-12-23 17:13:37 +08004663 char config_file[128] = {0};
4664 struct params list = {0};
4665 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004666
4667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4668
developerfe7aefc2022-12-23 17:13:37 +08004669 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004670 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004671
developerfe7aefc2022-12-23 17:13:37 +08004672 if (amsduEnable == enable)
4673 return RETURN_OK;
4674
4675 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4676 list.name = "amsdu";
4677 list.value = amsduEnable? "1":"0";
4678 wifi_hostapdWrite(config_file, &list, 1);
4679 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4680 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004681
4682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4683 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004684}
4685
4686//P2 // outputs the number of Tx streams
4687INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4688{
developer2de97692022-09-26 14:00:03 +08004689 char buf[8] = {0};
4690 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004691 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004692
4693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4694
developer033b37b2022-10-18 11:27:46 +08004695 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004696 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004697 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004698
developer110b8a32022-12-26 15:56:44 +08004699 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004700
4701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4702
4703 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004704}
4705
developer110b8a32022-12-26 15:56:44 +08004706INT fitChainMask(INT radioIndex, int antcount)
4707{
4708 char buf[128] = {0};
4709 char cmd[128] = {0};
4710 char config_file[64] = {0};
4711 wifi_band band;
4712 struct params list[2] = {0};
4713
4714 band = wifi_index_to_band(radioIndex);
4715 if (band == band_invalid)
4716 return RETURN_ERR;
4717
4718 list[0].name = "he_mu_beamformer";
4719 list[1].name = "he_su_beamformer";
4720
4721 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4722 if (antcount == 1) {
4723 // remove config about multiple antennas
4724 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4725 _syscmd(cmd, buf, sizeof(buf));
4726
4727 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4728 _syscmd(cmd, buf, sizeof(buf));
4729
4730 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4731 _syscmd(cmd, buf, sizeof(buf));
4732
4733 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4734 _syscmd(cmd, buf, sizeof(buf));
4735
4736 list[0].value = "0";
4737 list[1].value = "0";
4738 } else {
4739 // 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.
4740 if (band == band_2_4 || band == band_5) {
4741 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4742 _syscmd(cmd, buf, sizeof(buf));
4743 if (strlen(buf) > 0) {
4744 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4745 _syscmd(cmd, buf, sizeof(buf));
4746 }
4747 }
4748 if (band == band_5) {
4749 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4750 _syscmd(cmd, buf, sizeof(buf));
4751 if (strlen(buf) > 0) {
4752 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4753 _syscmd(cmd, buf, sizeof(buf));
4754 }
4755 }
4756
4757 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4758 _syscmd(cmd, buf, sizeof(buf));
4759 if (strlen(buf) == 0) {
4760 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4761 _syscmd(cmd, buf, sizeof(buf));
4762 }
4763
4764 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4765 _syscmd(cmd, buf, sizeof(buf));
4766 if (strlen(buf) == 0) {
4767 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4768 _syscmd(cmd, buf, sizeof(buf));
4769 }
4770
4771 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4772 _syscmd(cmd, buf, sizeof(buf));
4773 if (strlen(buf) == 0) {
4774 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4775 } else {
4776 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4777 }
4778 _syscmd(cmd, buf, sizeof(buf));
4779
4780 list[0].value = "1";
4781 list[1].value = "1";
4782 }
4783 wifi_hostapdWrite(config_file, list, 2);
4784}
4785
developer06a01d92022-09-07 16:32:39 +08004786//P2 // sets the number of Tx streams to an enviornment variable
4787INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4788{
developer2de97692022-09-26 14:00:03 +08004789 char cmd[128] = {0};
4790 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004791 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08004792 int cur_mask = 0;
4793 int antcount = 0;
4794 wifi_band band;
developer2de97692022-09-26 14:00:03 +08004795
4796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4797
developer110b8a32022-12-26 15:56:44 +08004798 if (numStreams <= 0) {
4799 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08004800 return RETURN_ERR;
4801 }
developer110b8a32022-12-26 15:56:44 +08004802
4803 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4804 if (cur_mask == numStreams)
4805 return RETURN_OK;
4806
developer2de97692022-09-26 14:00:03 +08004807 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004808
4809 phyId = radio_index_to_phy(radioIndex);
4810 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004811 _syscmd(cmd, buf, sizeof(buf));
4812
4813 if (strlen(buf) > 0) {
4814 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4815 return RETURN_ERR;
4816 }
developer2de97692022-09-26 14:00:03 +08004817
developer110b8a32022-12-26 15:56:44 +08004818 // if chain mask changed, we need to make the hostapd config valid.
4819 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
4820 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08004821 }
developer110b8a32022-12-26 15:56:44 +08004822 fitChainMask(radioIndex, antcount);
4823
4824 wifi_setRadioEnable(radioIndex, TRUE);
4825
developer2de97692022-09-26 14:00:03 +08004826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4827 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004828}
4829
4830//P2 // outputs the number of Rx streams
4831INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4832{
developer110b8a32022-12-26 15:56:44 +08004833 char buf[8] = {0};
4834 char cmd[128] = {0};
4835 int phyId = 0;
4836
developer2de97692022-09-26 14:00:03 +08004837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004838
4839 phyId = radio_index_to_phy(radioIndex);
4840 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
4841 _syscmd(cmd, buf, sizeof(buf));
4842
4843 *output_int = (INT)strtol(buf, NULL, 16);
4844
developer2de97692022-09-26 14:00:03 +08004845 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004846
developer06a01d92022-09-07 16:32:39 +08004847 return RETURN_OK;
4848}
4849
4850//P2 // sets the number of Rx streams to an enviornment variable
4851INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4852{
developer2de97692022-09-26 14:00:03 +08004853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4854 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4855 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4856 return RETURN_ERR;
4857 }
4858 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004859 return RETURN_ERR;
4860}
4861
4862//Get radio RDG enable setting
4863INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4864{
4865 if (NULL == output_bool)
4866 return RETURN_ERR;
4867 *output_bool = TRUE;
4868 return RETURN_OK;
4869}
4870
4871//Get radio RDG enable setting
4872INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4873{
4874 if (NULL == output_bool)
4875 return RETURN_ERR;
4876 *output_bool = TRUE;
4877 return RETURN_OK;
4878}
4879
4880//Set radio RDG enable setting
4881INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4882{
4883 return RETURN_ERR;
4884}
4885
4886//Get radio ADDBA enable setting
4887INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4888{
4889 if (NULL == output_bool)
4890 return RETURN_ERR;
4891 *output_bool = TRUE;
4892 return RETURN_OK;
4893}
4894
4895//Set radio ADDBA enable setting
4896INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4897{
4898 return RETURN_ERR;
4899}
4900
4901//Get radio auto block ack enable setting
4902INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4903{
4904 if (NULL == output_bool)
4905 return RETURN_ERR;
4906 *output_bool = TRUE;
4907 return RETURN_OK;
4908}
4909
4910//Set radio auto block ack enable setting
4911INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4912{
4913 return RETURN_ERR;
4914}
4915
4916//Get radio 11n pure mode enable support
4917INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4918{
4919 if (NULL == output_bool)
4920 return RETURN_ERR;
4921 *output_bool = TRUE;
4922 return RETURN_OK;
4923}
4924
4925//Get radio 11n pure mode enable setting
4926INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4927{
4928 if (NULL == output_bool)
4929 return RETURN_ERR;
4930 *output_bool = TRUE;
4931 return RETURN_OK;
4932}
4933
4934//Set radio 11n pure mode enable setting
4935INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4936{
4937 return RETURN_ERR;
4938}
4939
4940//Get radio IGMP snooping enable setting
4941INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4942{
developerd946fd62022-12-08 18:03:28 +08004943 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004944 char cmd[128]={0};
4945 char buf[4]={0};
4946 bool bridge = FALSE, mac80211 = FALSE;
4947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4948
4949 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004950 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004951
4952 *output_bool = FALSE;
4953
4954 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4955 _syscmd(cmd, buf, sizeof(buf));
4956 if (strncmp(buf, "1", 1) == 0)
4957 bridge = TRUE;
4958
developerac6f1142022-12-20 19:26:35 +08004959 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004960 return RETURN_ERR;
4961 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 +08004962 _syscmd(cmd, buf, sizeof(buf));
4963 if (strncmp(buf, "1", 1) == 0)
4964 mac80211 = TRUE;
4965
4966 if (bridge && mac80211)
4967 *output_bool = TRUE;
4968
4969 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004970 return RETURN_OK;
4971}
4972
4973//Set radio IGMP snooping enable setting
4974INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4975{
developerd946fd62022-12-08 18:03:28 +08004976 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004977 char cmd[128]={0};
4978 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004979 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004980 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4981
4982 // bridge
4983 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4984 _syscmd(cmd, buf, sizeof(buf));
4985
developer804c64f2022-10-19 13:54:40 +08004986 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004987 // mac80211
developer804c64f2022-10-19 13:54:40 +08004988 for (int i = 0; i < max_num_radios; i++) {
developerac6f1142022-12-20 19:26:35 +08004989 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004990 return RETURN_ERR;
4991 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 +08004992 _syscmd(cmd, buf, sizeof(buf));
4993 }
4994 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4995 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004996}
4997
4998//Get the Reset count of radio
4999INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5000{
5001 if (NULL == output_int)
5002 return RETURN_ERR;
5003 *output_int = (radioIndex==0)? 1: 3;
5004
5005 return RETURN_OK;
5006}
5007
5008
5009//---------------------------------------------------------------------------------------------------
5010//
5011// Additional Wifi AP level APIs used for Access Point devices
5012//
5013//---------------------------------------------------------------------------------------------------
5014
5015// creates a new ap and pushes these parameters to the hardware
5016INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5017{
developer7930d352022-12-21 17:55:42 +08005018 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005019 return RETURN_OK;
5020}
5021
5022// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5023INT wifi_deleteAp(INT apIndex)
5024{
developerd946fd62022-12-08 18:03:28 +08005025 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005026 char buf[1024];
5027 char cmd[128];
5028
developerac6f1142022-12-20 19:26:35 +08005029 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005030 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08005031 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005032 _syscmd(cmd, buf, sizeof(buf));
5033
5034 wifi_removeApSecVaribles(apIndex);
5035
5036 return RETURN_OK;
5037}
5038
5039// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5040INT wifi_getApName(INT apIndex, CHAR *output_string)
5041{
developerd946fd62022-12-08 18:03:28 +08005042 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005043 if(NULL == output_string)
5044 return RETURN_ERR;
5045
developerac6f1142022-12-20 19:26:35 +08005046 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005047 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005048 else
5049 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005050 return RETURN_OK;
5051}
5052
5053// Outputs the index number in that corresponds to the SSID string
5054INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5055{
developerd946fd62022-12-08 18:03:28 +08005056 char cmd [128] = {0};
5057 char buf[32] = {0};
5058 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005059 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005060
developerd946fd62022-12-08 18:03:28 +08005061 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5062 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005063
developerac6f1142022-12-20 19:26:35 +08005064 if (strlen(buf) != 0) {
5065 apIndex_str = strtok(buf, "\n");
5066 *output_int = strtoul(apIndex_str, NULL, 10);
5067 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005068 }
developer67b8ee92022-12-20 10:48:43 +08005069
5070 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5071 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5072 if (apIndex_str) {
5073 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5074 return RETURN_OK;
5075 }
developerd946fd62022-12-08 18:03:28 +08005076 *output_int = -1;
5077 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005078}
5079
5080INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5081{
5082 return wifi_getIndexFromName(inputSsidString, output_int);
5083}
5084
5085// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5086INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5087{
5088 char buf[MAX_BUF_SIZE] = {0};
5089 char cmd[MAX_CMD_SIZE] = {0};
5090 char config_file[MAX_BUF_SIZE] = {0};
5091
5092 if(NULL == output_string)
5093 return RETURN_ERR;
5094
5095 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5096 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5097 if((strcmp(buf,"3")==0))
5098 snprintf(output_string, 32, "WPAand11i");
5099 else if((strcmp(buf,"2")==0))
5100 snprintf(output_string, 32, "11i");
5101 else if((strcmp(buf,"1")==0))
5102 snprintf(output_string, 32, "WPA");
5103 else
5104 snprintf(output_string, 32, "None");
5105
5106 return RETURN_OK;
5107}
5108
5109// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5110INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5111{
5112 char config_file[MAX_BUF_SIZE] = {0};
5113 struct params list;
5114
5115 if (NULL == beaconTypeString)
5116 return RETURN_ERR;
5117 list.name = "wpa";
5118 list.value = "0";
5119
5120 if((strcmp(beaconTypeString,"WPAand11i")==0))
5121 list.value="3";
5122 else if((strcmp(beaconTypeString,"11i")==0))
5123 list.value="2";
5124 else if((strcmp(beaconTypeString,"WPA")==0))
5125 list.value="1";
5126
5127 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5128 wifi_hostapdWrite(config_file, &list, 1);
5129 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5130 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5131 return RETURN_OK;
5132}
5133
5134// sets the beacon interval on the hardware for this AP
5135INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5136{
developer5f222492022-09-13 15:21:52 +08005137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5138 struct params params={'\0'};
5139 char buf[MAX_BUF_SIZE] = {'\0'};
5140 char config_file[MAX_BUF_SIZE] = {'\0'};
5141
5142 params.name = "beacon_int";
5143 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5144 params.value = buf;
5145
5146 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5147 wifi_hostapdWrite(config_file, &params, 1);
5148
5149 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5151 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005152}
5153
5154INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5155{
developer5b398df2022-11-17 20:39:48 +08005156 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5157 return RETURN_ERR;
5158 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005159}
5160
5161// Get the packet size threshold supported.
5162INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5163{
5164 //save config and apply instantly
5165 if (NULL == output_bool)
5166 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005167 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005168 return RETURN_OK;
5169}
5170
5171// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5172INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5173{
developerd946fd62022-12-08 18:03:28 +08005174 char interface_name[16] = {0};
developer514406b2022-12-05 17:20:21 +08005175 char buf[16] = {0};
5176 char config_file[128] = {0};
5177 struct params param = {0};
5178
5179 if (threshold > 65535) {
5180 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5181 return RETURN_ERR;
5182 }
developer06a01d92022-09-07 16:32:39 +08005183
developerac6f1142022-12-20 19:26:35 +08005184 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005185 return RETURN_ERR;
5186 snprintf(config_file, sizeof(config_file), "%s.conf", interface_name);
developer514406b2022-12-05 17:20:21 +08005187 snprintf(buf, sizeof(buf), "%u", threshold);
5188 param.name = "rts_threshold";
5189 param.value = buf;
5190 wifi_hostapdWrite(config_file, &param, 1);
5191 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5192 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005193
5194 return RETURN_OK;
5195}
5196
5197// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5198INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5199{
5200 if (NULL == output_string)
5201 return RETURN_ERR;
5202 snprintf(output_string, 32, "TKIPandAESEncryption");
5203 return RETURN_OK;
5204
5205}
5206
5207// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5208INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5209{
5210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005211 char *param_name = NULL;
5212 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005213
5214 if(NULL == output_string)
5215 return RETURN_ERR;
5216
5217 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5218 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5219
5220 if(strcmp(buf,"0")==0)
5221 {
5222 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5223 snprintf(output_string, 32, "None");
5224 return RETURN_OK;
5225 }
5226 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5227 param_name = "rsn_pairwise";
5228 else if((strcmp(buf,"1")==0))
5229 param_name = "wpa_pairwise";
5230 else
5231 return RETURN_ERR;
5232 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005233 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005234 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5235 param_name = "wpa_pairwise";
5236 memset(output_string, '\0', 32);
5237 wifi_hostapdRead(config_file, param_name, output_string, 32);
5238 }
developer06a01d92022-09-07 16:32:39 +08005239 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5240
5241 if(strcmp(output_string,"TKIP") == 0)
5242 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5243 else if(strcmp(output_string,"CCMP") == 0)
5244 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5245 else if(strcmp(output_string,"TKIP CCMP") == 0)
5246 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5247
5248 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5249 return RETURN_OK;
5250}
5251
5252// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5253INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5254{
5255 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5256 struct params params={'\0'};
5257 char output_string[32];
5258 char config_file[MAX_BUF_SIZE] = {0};
5259
5260 memset(output_string,'\0',32);
5261 wifi_getApWpaEncryptionMode(apIndex,output_string);
5262
5263 if(strcmp(encMode, "TKIPEncryption") == 0)
5264 params.value = "TKIP";
5265 else if(strcmp(encMode,"AESEncryption") == 0)
5266 params.value = "CCMP";
5267 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5268 params.value = "TKIP CCMP";
5269
5270 if((strcmp(output_string,"WPAand11i")==0))
5271 {
5272 params.name = "wpa_pairwise";
5273 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5274 wifi_hostapdWrite(config_file, &params, 1);
5275 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5276
developer30423732022-12-01 16:17:49 +08005277 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005278 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5279 wifi_hostapdWrite(config_file, &params, 1);
5280 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5281
5282 return RETURN_OK;
5283 }
5284 else if((strcmp(output_string,"11i")==0))
5285 {
5286 params.name = "rsn_pairwise";
5287 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5288 wifi_hostapdWrite(config_file, &params, 1);
5289 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5290 return RETURN_OK;
5291 }
5292 else if((strcmp(output_string,"WPA")==0))
5293 {
5294 params.name = "wpa_pairwise";
5295 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5296 wifi_hostapdWrite(config_file, &params, 1);
5297 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5298 return RETURN_OK;
5299 }
5300
5301 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5302 return RETURN_OK;
5303}
5304
5305// deletes internal security varable settings for this ap
5306INT wifi_removeApSecVaribles(INT apIndex)
5307{
5308 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005309 //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 +08005310 //_syscmd(cmd, buf, sizeof(buf));
5311
developerd946fd62022-12-08 18:03:28 +08005312 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005313 //_syscmd(cmd, buf, sizeof(buf));
5314 return RETURN_ERR;
5315}
5316
5317// changes the hardware settings to disable encryption on this ap
5318INT wifi_disableApEncryption(INT apIndex)
5319{
5320 //Apply instantly
5321 return RETURN_ERR;
5322}
5323
5324// set the authorization mode on this ap
5325// mode mapping as: 1: open, 2: shared, 4:auto
5326INT wifi_setApAuthMode(INT apIndex, INT mode)
5327{
developeraf95c502022-09-13 16:18:22 +08005328 struct params params={0};
5329 char config_file[64] = {0};
5330 int ret;
5331
5332 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5333
5334 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5335 params.name = "auth_algs";
5336
5337 if (mode & 1 && mode & 2)
5338 params.value = "3";
5339 else if (mode & 2)
5340 params.value = "2";
5341 else if (mode & 1)
5342 params.value = "1";
5343 else
5344 params.value = "0";
5345
5346 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5347 wifi_hostapdWrite(config_file, &params, 1);
5348 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5350
5351 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005352}
5353
5354// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5355INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5356{
5357 //save to wifi config, and wait for wifi restart to apply
5358 struct params params={'\0'};
5359 char config_file[MAX_BUF_SIZE] = {0};
5360 int ret;
5361
5362 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5363 if(authMode == NULL)
5364 return RETURN_ERR;
5365
5366 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5367 params.name = "wpa_key_mgmt";
5368
5369 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5370 params.value = "WPA-PSK";
5371 else if(strcmp(authMode,"EAPAuthentication") == 0)
5372 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005373 else if (strcmp(authMode, "SAEAuthentication") == 0)
5374 params.value = "SAE";
5375 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5376 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005377 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5378 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005379 else if (strcmp(authMode, "Enhanced_Open") == 0)
5380 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005381 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5382 return RETURN_OK; //This is taken careof in beaconType
5383
5384 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5385 ret=wifi_hostapdWrite(config_file,&params,1);
5386 if(!ret)
5387 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5388 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5389
5390 return ret;
5391}
5392
5393// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5394INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5395{
5396 //save to wifi config, and wait for wifi restart to apply
5397 char BeaconType[50] = {0};
5398 char config_file[MAX_BUF_SIZE] = {0};
5399
5400 *authMode = 0;
5401 wifi_getApBeaconType(apIndex,BeaconType);
5402 printf("%s____%s \n",__FUNCTION__,BeaconType);
5403
5404 if(strcmp(BeaconType,"None") == 0)
5405 strcpy(authMode,"None");
5406 else
5407 {
5408 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5409 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5410 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5411 if(strcmp(authMode,"WPA-PSK") == 0)
5412 strcpy(authMode,"SharedAuthentication");
5413 else if(strcmp(authMode,"WPA-EAP") == 0)
5414 strcpy(authMode,"EAPAuthentication");
5415 }
5416
5417 return RETURN_OK;
5418}
5419
5420// Outputs the number of stations associated per AP
5421INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5422{
developerd946fd62022-12-08 18:03:28 +08005423 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005424 char cmd[128]={0};
5425 char buf[128]={0};
5426 BOOL status = false;
5427
5428 if(apIndex > MAX_APS)
5429 return RETURN_ERR;
5430
5431 wifi_getApEnable(apIndex,&status);
5432 if (!status)
5433 return RETURN_OK;
5434
developerd946fd62022-12-08 18:03:28 +08005435 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005436 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005437 return RETURN_ERR;
5438 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005439 _syscmd(cmd, buf, sizeof(buf));
5440 sscanf(buf,"%lu", output_ulong);
5441
5442 return RETURN_OK;
5443}
5444
5445// manually removes any active wi-fi association with the device specified on this ap
5446INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5447{
developerd946fd62022-12-08 18:03:28 +08005448 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005449 char buf[126]={'\0'};
5450
developerac6f1142022-12-20 19:26:35 +08005451 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005452 return RETURN_ERR;
5453 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005454 system(buf);
5455
5456 return RETURN_OK;
5457}
5458
5459// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5460INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5461{
5462 if(NULL == output_int)
5463 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005464 int max_radio_num = 0;
5465 wifi_getMaxRadioNumber(&max_radio_num);
5466 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005467 return RETURN_OK;
5468}
5469
5470// sets the radio index for the specific ap
5471INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5472{
5473 //set to config only and wait for wifi reset to apply settings
5474 return RETURN_ERR;
5475}
5476
5477// Get the ACL MAC list per AP
5478INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5479{
developerd946fd62022-12-08 18:03:28 +08005480 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005481 char cmd[MAX_CMD_SIZE]={'\0'};
5482 int ret = 0;
5483
developerac6f1142022-12-20 19:26:35 +08005484 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005485 return RETURN_ERR;
5486 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005487 ret = _syscmd(cmd,macArray,buf_size);
5488 if (ret != 0)
5489 return RETURN_ERR;
5490
5491 return RETURN_OK;
5492}
5493
developere6aafda2022-09-13 14:59:28 +08005494INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5495{
developerd946fd62022-12-08 18:03:28 +08005496 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005497 char cmd[MAX_CMD_SIZE]={'\0'};
5498 int ret = 0;
5499
developerac6f1142022-12-20 19:26:35 +08005500 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005501 return RETURN_ERR;
5502 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005503 ret = _syscmd(cmd,macArray,buf_size);
5504 if (ret != 0)
5505 return RETURN_ERR;
5506
5507 return RETURN_OK;
5508}
5509
5510
developer06a01d92022-09-07 16:32:39 +08005511// Get the list of stations associated per AP
5512INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5513{
developerd946fd62022-12-08 18:03:28 +08005514 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005515 char cmd[128];
5516
5517 if(apIndex > 3) //Currently supporting apIndex upto 3
5518 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005519 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005520 return RETURN_ERR;
5521 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5522 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005523 _syscmd(cmd, macArray, buf_size);
5524
5525 return RETURN_OK;
5526}
5527
5528// adds the mac address to the filter list
5529//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5530INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5531{
5532 char cmd[MAX_CMD_SIZE]={'\0'};
5533 char buf[MAX_BUF_SIZE]={'\0'};
5534
5535#if 0
developerd946fd62022-12-08 18:03:28 +08005536 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005537 if(_syscmd(cmd,buf,sizeof(buf)))
5538 return RETURN_ERR;
5539#endif
5540 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5541 if(_syscmd(cmd,buf,sizeof(buf)))
5542 return RETURN_ERR;
5543
5544 return RETURN_OK;
5545}
5546
5547// deletes the mac address from the filter list
5548//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5549INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5550{
5551 char cmd[MAX_CMD_SIZE]={'\0'};
5552 char buf[MAX_BUF_SIZE]={'\0'};
5553
5554#if 0
developerd946fd62022-12-08 18:03:28 +08005555 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005556 if(_syscmd(cmd,buf,sizeof(buf)))
5557 return RETURN_ERR;
5558
5559#endif
5560 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5561 if(_syscmd(cmd,buf,sizeof(buf)))
5562 return RETURN_ERR;
5563
5564 return RETURN_OK;
5565}
5566
5567// outputs the number of devices in the filter list
5568INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5569{
developere6aafda2022-09-13 14:59:28 +08005570 char cmd[MAX_BUF_SIZE]={0};
5571 char buf[MAX_CMD_SIZE]={0};
5572
5573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5574 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005575 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005576
5577 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5578 _syscmd(cmd, buf, sizeof(buf));
5579
5580 *output_uint = atoi(buf);
5581
5582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5583 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005584}
5585
5586INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5587{
5588 char cmd[128]={'\0'};
5589 char buf[128]={'\0'};
5590
5591 if(strcmp(action,"DENY")==0)
5592 {
5593 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5594 system(buf);
5595 return RETURN_OK;
5596 }
5597
5598 if(strcmp(action,"ALLOW")==0)
5599 {
5600 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5601 system(buf);
5602 return RETURN_OK;
5603 }
5604
5605 return RETURN_ERR;
5606
5607}
5608
5609// enable kick for devices on acl black list
5610INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5611{
5612 char aclArray[512] = {0}, *acl = NULL;
5613 char assocArray[512] = {0}, *asso = NULL;
5614
developere6aafda2022-09-13 14:59:28 +08005615 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005616 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5617
5618 // if there are no devices connected there is nothing to do
5619 if (strlen(assocArray) < 17)
5620 return RETURN_OK;
5621
5622 if (enable == TRUE)
5623 {
5624 //kick off the MAC which is in ACL array (deny list)
5625 acl = strtok(aclArray, "\r\n");
5626 while (acl != NULL) {
5627 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5628 wifi_kickApAssociatedDevice(apIndex, acl);
5629
5630 acl = strtok(NULL, "\r\n");
5631 }
developere6aafda2022-09-13 14:59:28 +08005632 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005633 }
5634 else
5635 {
developere6aafda2022-09-13 14:59:28 +08005636 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005637 }
5638
5639#if 0
5640 //TODO: need to revisit below implementation
5641 char aclArray[512]={0}, *acl=NULL;
5642 char assocArray[512]={0}, *asso=NULL;
5643 char buf[256]={'\0'};
5644 char action[10]={'\0'};
5645 FILE *fr=NULL;
5646 char interface[10]={'\0'};
5647 char config_file[MAX_BUF_SIZE] = {0};
5648
5649 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5650 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5651 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5652 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5653
5654 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5655 system(buf);
5656 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5657 system(buf);
5658 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5659 system(buf);
5660 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5661 system(buf);
5662 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5663 system(buf);
5664
5665 if ( enable == TRUE )
5666 {
5667 int device_count=0;
5668 strcpy(action,"DENY");
5669 //kick off the MAC which is in ACL array (deny list)
5670 acl = strtok (aclArray,",");
5671 while (acl != NULL) {
5672 if(strlen(acl)>=17)
5673 {
5674 apply_rules(apIndex, acl,action,interface);
5675 device_count++;
5676 //Register mac to be blocked ,in syscfg.db persistent storage
5677 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5678 system(buf);
5679 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5680 system(buf);
5681 system("syscfg commit");
5682
5683 wifi_kickApAssociatedDevice(apIndex, acl);
5684 }
5685 acl = strtok (NULL, ",");
5686 }
5687 }
5688 else
5689 {
5690 int device_count=0;
5691 char cmdmac[20]={'\0'};
5692 strcpy(action,"ALLOW");
5693 //kick off the MAC which is not in ACL array (allow list)
5694 acl = strtok (aclArray,",");
5695 while (acl != NULL) {
5696 if(strlen(acl)>=17)
5697 {
5698 apply_rules(apIndex, acl,action,interface);
5699 device_count++;
5700 //Register mac to be Allowed ,in syscfg.db persistent storage
5701 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5702 system(buf);
5703 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5704 system(buf);
5705 sprintf(cmdmac,"%s",acl);
5706 }
5707 acl = strtok (NULL, ",");
5708 }
5709 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5710 system(buf);
5711
5712 //Disconnect the mac which is not in ACL
5713 asso = strtok (assocArray,",");
5714 while (asso != NULL) {
5715 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5716 wifi_kickApAssociatedDevice(apIndex, asso);
5717 asso = strtok (NULL, ",");
5718 }
5719 }
5720#endif
5721 return RETURN_OK;
5722}
5723
5724INT wifi_setPreferPrivateConnection(BOOL enable)
5725{
developer06a01d92022-09-07 16:32:39 +08005726 return RETURN_OK;
5727}
5728
5729// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5730INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5731{
developerd946fd62022-12-08 18:03:28 +08005732 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005733 int items = 1;
5734 struct params list[2];
5735 char buf[MAX_BUF_SIZE] = {0};
5736 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005737 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005738
5739 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005740
developer10adcc12022-09-13 14:39:17 +08005741 if (filterMode == 0) {
5742 sprintf(buf, "%d", 0);
5743 list[0].value = buf;
5744
5745 char cmd[128], rtn[128];
developerac6f1142022-12-20 19:26:35 +08005746 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005747 return RETURN_ERR;
5748 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
developer10adcc12022-09-13 14:39:17 +08005749 _syscmd(cmd, rtn, sizeof(rtn));
5750 memset(cmd,0,sizeof(cmd));
5751 // Delete deny_mac_file in hostapd configuration
5752 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5753 _syscmd(cmd, rtn, sizeof(rtn));
5754 }
5755 else if (filterMode == 1) {
5756 sprintf(buf, "%d", filterMode);
5757 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005758 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5759 list[1].name = "accept_mac_file";
5760 list[1].value = acl_file;
5761 items = 2;
developer10adcc12022-09-13 14:39:17 +08005762 } else if (filterMode == 2) {
5763 //TODO: deny_mac_file
5764 sprintf(buf, "%d", 0);
5765 list[0].value = buf;
5766 list[1].name = "deny_mac_file";
5767 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5768 list[1].value = deny_file;
5769 items = 2;
5770 } else {
5771 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005772 }
developer10adcc12022-09-13 14:39:17 +08005773
developer06a01d92022-09-07 16:32:39 +08005774 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5775 wifi_hostapdWrite(config_file, list, items);
5776
5777 return RETURN_OK;
5778
5779#if 0
5780 if(apIndex==0 || apIndex==1)
5781 {
5782 //set the filtermode
5783 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5784 system(buf);
5785 system("syscfg commit");
5786
5787 if(filterMode==0)
5788 {
5789 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5790 system(buf);
5791 return RETURN_OK;
5792 }
5793 }
5794 return RETURN_OK;
5795#endif
5796}
5797
5798// 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.
5799INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5800{
5801 return RETURN_ERR;
5802}
5803
5804// gets the vlan ID for this ap from an internal enviornment variable
5805INT wifi_getApVlanID(INT apIndex, INT *output_int)
5806{
developer30423732022-12-01 16:17:49 +08005807 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005808 {
5809 *output_int=100;
5810 return RETURN_OK;
5811 }
5812
5813 return RETURN_ERR;
5814}
5815
5816// sets the vlan ID for this ap to an internal enviornment variable
5817INT wifi_setApVlanID(INT apIndex, INT vlanId)
5818{
5819 //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)
5820 return RETURN_ERR;
5821}
5822
5823// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5824INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5825{
5826 snprintf(bridgeName, 32, "brlan0");
5827 snprintf(IP, 32, "10.0.0.1");
5828 snprintf(subnet, 32, "255.255.255.0");
5829
5830 return RETURN_OK;
5831}
5832
5833//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5834INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5835{
5836 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5837 return RETURN_ERR;
5838}
5839
5840// reset the vlan configuration for this ap
5841INT wifi_resetApVlanCfg(INT apIndex)
5842{
developerf5fef612022-09-20 19:38:26 +08005843 char original_config_file[64] = {0};
5844 char current_config_file[64] = {0};
5845 char buf[64] = {0};
5846 char cmd[64] = {0};
5847 char vlan_file[64] = {0};
5848 char vlan_tagged_interface[16] = {0};
5849 char vlan_bridge[16] = {0};
5850 char vlan_naming[16] = {0};
5851 struct params list[4] = {0};
5852 wifi_band band;
5853
5854 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5855
5856 band = wifi_index_to_band(apIndex);
5857 if (band == band_2_4)
5858 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08005859 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08005860 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08005861 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08005862 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5863
5864 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5865
5866 if (strlen(vlan_file) == 0)
5867 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005868
developerf5fef612022-09-20 19:38:26 +08005869 // The file should exist or this vap would not work.
5870 if (access(vlan_file, F_OK) != 0) {
5871 sprintf(cmd, "touch %s", vlan_file);
5872 _syscmd(cmd, buf, sizeof(buf));
5873 }
5874 list[0].name = "vlan_file";
5875 list[0].value = vlan_file;
5876
5877 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5878 list[1].name = "vlan_tagged_interface";
5879 list[1].value = vlan_tagged_interface;
5880
5881 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5882 list[2].name = "vlan_bridge";
5883 list[2].value = vlan_bridge;
5884
5885 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5886 list[3].name = "vlan_naming";
5887 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005888
developerf5fef612022-09-20 19:38:26 +08005889 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5890 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005891 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005892 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005893
developerf5fef612022-09-20 19:38:26 +08005894 // restart this ap
5895 wifi_setApEnable(apIndex, FALSE);
5896 wifi_setApEnable(apIndex, TRUE);
5897
5898 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5899
5900 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005901}
5902
5903// 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.
5904INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5905{
5906 return RETURN_ERR;
5907}
5908
5909// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5910INT wifi_startHostApd()
5911{
5912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5913 system("systemctl start hostapd.service");
5914 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5915 return RETURN_OK;
5916 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5917}
5918
5919// stops hostapd
5920INT wifi_stopHostApd()
5921{
5922 char cmd[128] = {0};
5923 char buf[128] = {0};
5924
5925 sprintf(cmd,"systemctl stop hostapd");
5926 _syscmd(cmd, buf, sizeof(buf));
5927
5928 return RETURN_OK;
5929}
5930
5931// restart hostapd dummy function
5932INT wifi_restartHostApd()
5933{
5934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5935 system("systemctl restart hostapd-global");
5936 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5937
5938 return RETURN_OK;
5939}
5940
5941static int align_hostapd_config(int index)
5942{
5943 ULONG lval;
5944 wifi_getRadioChannel(index%2, &lval);
5945 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08005946 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005947}
5948
5949// sets the AP enable status variable for the specified ap.
5950INT wifi_setApEnable(INT apIndex, BOOL enable)
5951{
developerd946fd62022-12-08 18:03:28 +08005952 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005953 char config_file[MAX_BUF_SIZE] = {0};
5954 char cmd[MAX_CMD_SIZE] = {0};
5955 char buf[MAX_BUF_SIZE] = {0};
5956 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005957 int max_radio_num = 0;
5958 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005959
5960 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005961
5962 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005963 if (enable == status)
5964 return RETURN_OK;
5965
developerac6f1142022-12-20 19:26:35 +08005966 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005967 return RETURN_ERR;
5968
developer06a01d92022-09-07 16:32:39 +08005969 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005970 int radioIndex = apIndex % max_radio_num;
5971 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005972 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5973 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08005974 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005975 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005976 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005977 _syscmd(cmd, buf, sizeof(buf));
5978 }
5979 else {
developerd946fd62022-12-08 18:03:28 +08005980 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005981 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08005982 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08005983 _syscmd(cmd, buf, sizeof(buf));
5984 }
developer431128d2022-12-16 15:30:41 +08005985 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08005986 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08005987 _syscmd(cmd, buf, sizeof(buf));
5988 //Wait for wifi up/down to apply
5989 return RETURN_OK;
5990}
5991
5992// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5993INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5994{
developerd946fd62022-12-08 18:03:28 +08005995 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005996 char cmd[MAX_CMD_SIZE] = {'\0'};
5997 char buf[MAX_BUF_SIZE] = {'\0'};
5998
5999 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6000 return RETURN_ERR;
6001
6002 *output_bool = 0;
6003
6004 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6005 {
developerac6f1142022-12-20 19:26:35 +08006006 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006007 *output_bool = FALSE;
6008 return RETURN_OK;
6009 }
6010 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006011 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6012 }
6013
6014 return RETURN_OK;
6015}
6016
6017// Outputs the AP "Enabled" "Disabled" status from driver
6018INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6019{
6020 char cmd[128] = {0};
6021 char buf[128] = {0};
6022 BOOL output_bool;
6023
6024 if ( NULL == output_string)
6025 return RETURN_ERR;
6026 wifi_getApEnable(apIndex,&output_bool);
6027
6028 if(output_bool == 1)
6029 snprintf(output_string, 32, "Up");
6030 else
6031 snprintf(output_string, 32, "Disable");
6032
6033 return RETURN_OK;
6034}
6035
6036//Indicates whether or not beacons include the SSID name.
6037// outputs a 1 if SSID on the AP is enabled, else outputs 0
6038INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6039{
6040 //get the running status
6041 char config_file[MAX_BUF_SIZE] = {0};
6042 char buf[16] = {0};
6043
6044 if (!output)
6045 return RETURN_ERR;
6046
6047 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6048 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006049 // default is enable
6050 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6051 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006052
6053 return RETURN_OK;
6054}
6055
6056// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6057INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6058{
6059 //store the config, apply instantly
6060 char config_file[MAX_BUF_SIZE] = {0};
6061 struct params list;
6062
6063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6064 list.name = "ignore_broadcast_ssid";
6065 list.value = enable?"0":"1";
6066
6067 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6068 wifi_hostapdWrite(config_file, &list, 1);
6069 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6070 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006071 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006072 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6073
6074 return RETURN_OK;
6075}
6076
6077//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6078INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6079{
6080 //get the running status
6081 if(!output_uint)
6082 return RETURN_ERR;
6083 *output_uint=16;
6084 return RETURN_OK;
6085}
6086
6087INT wifi_setApRetryLimit(INT apIndex, UINT number)
6088{
6089 //apply instantly
6090 return RETURN_ERR;
6091}
6092
6093//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6094INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6095{
6096 if(!output)
6097 return RETURN_ERR;
6098 *output=TRUE;
6099 return RETURN_OK;
6100}
6101
6102//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6103INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6104{
6105 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006106 char cmd[128] = {0};
6107 char buf[128] = {0};
6108 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006109 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006110
developer0b246d12022-09-30 15:24:20 +08006111 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006112
developer0b246d12022-09-30 15:24:20 +08006113 wifi_getMaxRadioNumber(&max_radio_num);
6114 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006115 phyId = radio_index_to_phy(radioIndex);
6116 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006117 _syscmd(cmd,buf, sizeof(buf));
6118
6119 if (strlen(buf) > 0)
6120 *output = true;
6121
6122 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006123
developer06a01d92022-09-07 16:32:39 +08006124 return RETURN_OK;
6125}
6126
6127//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6128INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6129{
6130 //get the running status from driver
6131 if(!output)
6132 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006133
6134 char config_file[MAX_BUF_SIZE] = {0};
6135 char buf[16] = {0};
6136
6137 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6138 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006139 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006140 *output = TRUE;
6141 else
6142 *output = FALSE;
6143
developer06a01d92022-09-07 16:32:39 +08006144 return RETURN_OK;
6145}
6146
6147// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6148INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6149{
6150 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006151 char config_file[MAX_BUF_SIZE] = {0};
6152 struct params list;
6153
6154 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6155 list.name = "wmm_enabled";
6156 list.value = enable?"1":"0";
6157
6158 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6159 wifi_hostapdWrite(config_file, &list, 1);
6160 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6161 wifi_reloadAp(apIndex);
6162 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6163
6164 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006165}
6166
6167//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.
6168INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6169{
6170 //get the running status from driver
6171 if(!output)
6172 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006173
6174 char config_file[128] = {0};
6175 char buf[16] = {0};
6176
6177 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6178 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6179 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6180 *output = TRUE;
6181 else
6182 *output = FALSE;
6183
developer06a01d92022-09-07 16:32:39 +08006184 return RETURN_OK;
6185}
6186
6187// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6188INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6189{
6190 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006191 char config_file[MAX_BUF_SIZE] = {0};
6192 struct params list;
6193
6194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6195 list.name = "uapsd_advertisement_enabled";
6196 list.value = enable?"1":"0";
6197
6198 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6199 wifi_hostapdWrite(config_file, &list, 1);
6200 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6201 wifi_reloadAp(apIndex);
6202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6203
6204 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006205}
6206
developer6daeb3f2022-09-30 13:36:39 +08006207// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006208INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6209{
developerd946fd62022-12-08 18:03:28 +08006210 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006211 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6212 char cmd[128] = {0};
6213 char buf[128] = {0};
6214 char ack_filepath[128] = {0};
6215 uint16_t bitmap = 0;
6216 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6217 FILE *f = NULL;
6218
6219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6220
6221 // Get current setting
6222 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6223 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6224 _syscmd(cmd, buf, sizeof(buf));
6225 if (strlen(buf) > 0)
6226 bitmap = strtoul(buf, NULL, 10);
6227
6228 bitmap = strtoul(buf, NULL, 10);
6229
6230 if (ackPolicy == TRUE) { // True, unset this class
6231 bitmap &= ~class_map[class];
6232 } else { // False, set this class
6233 bitmap |= class_map[class];
6234 }
6235
6236 f = fopen(ack_filepath, "w");
6237 if (f == NULL) {
6238 fprintf(stderr, "%s: fopen failed\n", __func__);
6239 return RETURN_ERR;
6240 }
6241 fprintf(f, "%hu", bitmap);
6242 fclose(f);
6243
developerac6f1142022-12-20 19:26:35 +08006244 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006245 return RETURN_ERR;
6246 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006247 _syscmd(cmd, buf, sizeof(buf));
6248
6249 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6250 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006251}
6252
6253//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.
6254INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6255{
6256 //get the running status from driver
6257 if(!output_uint)
6258 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006259
6260 char output[16]={'\0'};
6261 char config_file[MAX_BUF_SIZE] = {0};
6262
6263 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6264 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6265 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6266 else {
6267 int device_num = atoi(output);
6268 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6269 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6270 return RETURN_ERR;
6271 }
6272 else {
6273 *output_uint = device_num;
6274 }
6275 }
6276
developer06a01d92022-09-07 16:32:39 +08006277 return RETURN_OK;
6278}
6279
6280INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6281{
6282 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006283 char str[MAX_BUF_SIZE]={'\0'};
6284 char cmd[MAX_CMD_SIZE]={'\0'};
6285 struct params params;
6286 char config_file[MAX_BUF_SIZE] = {0};
6287
6288 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006289 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006290 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6291 return RETURN_ERR;
6292 }
6293 sprintf(str, "%d", number);
6294 params.name = "max_num_sta";
6295 params.value = str;
6296
6297 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6298 int ret = wifi_hostapdWrite(config_file, &params, 1);
6299 if (ret) {
6300 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6301 ,__func__, ret);
6302 }
6303
6304 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6305 if (ret) {
6306 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6307 ,__func__, ret);
6308 }
6309 wifi_reloadAp(apIndex);
6310 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6311
6312 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006313}
6314
6315//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.
6316INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6317{
6318 //get the current threshold
6319 if(!output_uint)
6320 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006321 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6322 if (*output_uint == 0)
6323 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006324 return RETURN_OK;
6325}
6326
6327INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6328{
6329 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006330 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6331 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006332 return RETURN_ERR;
6333}
6334
6335//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.
6336INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6337{
6338 if(!output_uint)
6339 return RETURN_ERR;
6340 *output_uint = 3;
6341 return RETURN_OK;
6342}
6343
6344//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6345INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6346{
6347 if(!output_uint)
6348 return RETURN_ERR;
6349 *output_uint = 3;
6350 return RETURN_OK;
6351}
6352
6353//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.
6354INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6355{
6356 if(!output_in_seconds)
6357 return RETURN_ERR;
6358 *output_in_seconds = 0;
6359 return RETURN_OK;
6360}
6361
6362//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
6363INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6364{
6365 if(!output || apIndex>=MAX_APS)
6366 return RETURN_ERR;
6367 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006368 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006369 return RETURN_OK;
6370}
6371
6372//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6373INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6374{
developer587c1b62022-09-27 15:58:59 +08006375 char config_file[128] = {0};
6376 char wpa[16] = {0};
6377 char key_mgmt[64] = {0};
6378 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006379 if (!output)
6380 return RETURN_ERR;
6381
6382 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006383 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006384
developer587c1b62022-09-27 15:58:59 +08006385 strcpy(output, "None");//Copying "None" to output string for default case
6386 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006387 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006388 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006389 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006390 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006391 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006392 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006393 snprintf(output, 32, "WPA-WPA2-Personal");
6394
6395 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006396 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006397 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006398 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006399 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006400 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006401 snprintf(output, 32, "WPA-WPA2-Enterprise");
6402 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006403 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006404 snprintf(output, 32, "WPA3-Personal");
6405 else
developer4a359672022-10-13 15:30:46 +08006406 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006407 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6408 snprintf(output, 32, "WPA3-Enterprise");
6409 }
developer06a01d92022-09-07 16:32:39 +08006410
6411 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6412 return RETURN_OK;
6413#if 0
6414 //TODO: need to revisit below implementation
6415 char securityType[32], authMode[32];
6416 int enterpriseMode=0;
6417
6418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6419 if(!output)
6420 return RETURN_ERR;
6421
6422 wifi_getApBeaconType(apIndex, securityType);
6423 strcpy(output,"None");//By default, copying "None" to output string
6424 if (strncmp(securityType,"None", strlen("None")) == 0)
6425 return RETURN_OK;
6426
6427 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6428 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6429
6430 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6431 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6432 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6433 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6434 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6435 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6436 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6437
6438 return RETURN_OK;
6439#endif
6440}
6441
6442INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6443{
6444 char securityType[32];
6445 char authMode[32];
6446
6447 //store settings and wait for wifi up to apply
6448 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6449 if(!encMode)
6450 return RETURN_ERR;
6451
developer06a01d92022-09-07 16:32:39 +08006452 if (strcmp(encMode, "None")==0)
6453 {
6454 strcpy(securityType,"None");
6455 strcpy(authMode,"None");
6456 }
6457 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6458 {
6459 strcpy(securityType,"WPAand11i");
6460 strcpy(authMode,"PSKAuthentication");
6461 }
6462 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6463 {
6464 strcpy(securityType,"WPAand11i");
6465 strcpy(authMode,"EAPAuthentication");
6466 }
6467 else if (strcmp(encMode, "WPA-Personal")==0)
6468 {
6469 strcpy(securityType,"WPA");
6470 strcpy(authMode,"PSKAuthentication");
6471 }
6472 else if (strcmp(encMode, "WPA-Enterprise")==0)
6473 {
6474 strcpy(securityType,"WPA");
6475 strcpy(authMode,"EAPAuthentication");
6476 }
6477 else if (strcmp(encMode, "WPA2-Personal")==0)
6478 {
6479 strcpy(securityType,"11i");
6480 strcpy(authMode,"PSKAuthentication");
6481 }
6482 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6483 {
6484 strcpy(securityType,"11i");
6485 strcpy(authMode,"EAPAuthentication");
6486 }
developer587c1b62022-09-27 15:58:59 +08006487 else if (strcmp(encMode, "WPA3-Personal") == 0)
6488 {
6489 strcpy(securityType,"11i");
6490 strcpy(authMode,"SAEAuthentication");
6491 }
developer4a359672022-10-13 15:30:46 +08006492 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006493 {
6494 strcpy(securityType, "11i");
6495 strcpy(authMode, "PSK-SAEAuthentication");
6496 }
developer587c1b62022-09-27 15:58:59 +08006497 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6498 {
6499 strcpy(securityType,"11i");
6500 strcpy(authMode,"EAP_192-bit_Authentication");
6501 }
developer5c9fee82023-01-13 14:44:16 +08006502 else if (strcmp(encMode, "OWE") == 0)
6503 {
6504 strcpy(securityType,"11i");
6505 strcpy(authMode,"Enhanced_Open");
6506 }
developer06a01d92022-09-07 16:32:39 +08006507 else
6508 {
6509 strcpy(securityType,"None");
6510 strcpy(authMode,"None");
6511 }
6512 wifi_setApBeaconType(apIndex, securityType);
6513 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6515
6516 return RETURN_OK;
6517}
6518
6519
6520//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6521// output_string must be pre-allocated as 64 character string by caller
6522// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6523INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6524{
developer30423732022-12-01 16:17:49 +08006525 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006526 char config_file[MAX_BUF_SIZE] = {0};
6527
6528 if(output_string==NULL)
6529 return RETURN_ERR;
6530
6531 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6532 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6533
6534 if(strcmp(buf,"0")==0)
6535 {
6536 printf("wpa_mode is %s ......... \n",buf);
6537 return RETURN_ERR;
6538 }
6539
6540 wifi_dbg_printf("\nFunc=%s\n",__func__);
6541 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6542 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6543 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6544
6545 return RETURN_OK;
6546}
6547
6548// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6549// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6550INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6551{
6552 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6553 struct params params={'\0'};
6554 int ret;
6555 char config_file[MAX_BUF_SIZE] = {0};
6556
6557 if(NULL == preSharedKey)
6558 return RETURN_ERR;
6559
6560 params.name = "wpa_passphrase";
6561
6562 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6563 {
6564 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6565 return RETURN_ERR;
6566 }
6567 params.value = preSharedKey;
6568 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6569 ret = wifi_hostapdWrite(config_file, &params, 1);
6570 if(!ret)
6571 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6572 return ret;
6573 //TODO: call hostapd_cli for dynamic_config_control
6574}
6575
6576//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6577// outputs the passphrase, maximum 63 characters
6578INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6579{
6580 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6581
6582 wifi_dbg_printf("\nFunc=%s\n",__func__);
6583 if (NULL == output_string)
6584 return RETURN_ERR;
6585
6586 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6587 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6588 if(strcmp(buf,"0")==0)
6589 {
6590 printf("wpa_mode is %s ......... \n",buf);
6591 return RETURN_ERR;
6592 }
6593
6594 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6595 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6596
6597 return RETURN_OK;
6598}
6599
6600// sets the passphrase enviornment variable, max 63 characters
6601INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6602{
6603 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6604 struct params params={'\0'};
6605 char config_file[MAX_BUF_SIZE] = {0};
6606 int ret;
6607
6608 if(NULL == passPhrase)
6609 return RETURN_ERR;
6610
6611 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6612 {
6613 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6614 return RETURN_ERR;
6615 }
6616 params.name = "wpa_passphrase";
6617 params.value = passPhrase;
6618 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6619 ret=wifi_hostapdWrite(config_file,&params,1);
6620 if(!ret)
6621 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6622
6623 return ret;
6624}
6625
6626//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.
6627INT wifi_setApSecurityReset(INT apIndex)
6628{
developer8d583982022-09-20 11:28:22 +08006629 char original_config_file[64] = {0};
6630 char current_config_file[64] = {0};
6631 char buf[64] = {0};
6632 char cmd[64] = {0};
6633 char wpa[4] = {0};
6634 char wpa_psk[64] = {0};
6635 char wpa_passphrase[64] = {0};
6636 char wpa_psk_file[128] = {0};
6637 char wpa_key_mgmt[64] = {0};
6638 char wpa_pairwise[32] = {0};
6639 wifi_band band;
6640 struct params list[6];
6641
6642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6643
6644 band = wifi_index_to_band(apIndex);
6645 if (band == band_2_4)
6646 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006647 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006648 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006649 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006650 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6651 else
6652 return RETURN_ERR;
6653
6654 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6655 list[0].name = "wpa";
6656 list[0].value = wpa;
6657
6658 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6659 list[1].name = "wpa_psk";
6660 list[1].value = wpa_psk;
6661
6662 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6663 list[2].name = "wpa_passphrase";
6664 list[2].value = wpa_passphrase;
6665
6666 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6667
6668 if (strlen(wpa_psk_file) == 0)
6669 strcpy(wpa_psk_file, PSK_FILE);
6670
6671 if (access(wpa_psk_file, F_OK) != 0) {
6672 sprintf(cmd, "touch %s", wpa_psk_file);
6673 _syscmd(cmd, buf, sizeof(buf));
6674 }
6675 list[3].name = "wpa_psk_file";
6676 list[3].value = wpa_psk_file;
6677
6678 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6679 list[4].name = "wpa_key_mgmt";
6680 list[4].value = wpa_key_mgmt;
6681
6682 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6683 list[5].name = "wpa_pairwise";
6684 list[5].value = wpa_pairwise;
6685
6686 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6687 wifi_hostapdWrite(current_config_file, list, 6);
6688
6689 wifi_setApEnable(apIndex, FALSE);
6690 wifi_setApEnable(apIndex, TRUE);
6691
6692 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6693 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006694}
6695
6696//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).
6697INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6698{
developer8f2ddd52022-09-13 15:39:24 +08006699 char config_file[64] = {0};
6700 char buf[64] = {0};
6701 char cmd[256] = {0};
6702
6703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6704
developer06a01d92022-09-07 16:32:39 +08006705 if(!IP_output || !Port_output || !RadiusSecret_output)
6706 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006707
developer8f2ddd52022-09-13 15:39:24 +08006708 // Read the first matched config
6709 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6710 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6711 _syscmd(cmd, buf, sizeof(buf));
6712 strncpy(IP_output, buf, 64);
6713
6714 memset(buf, 0, sizeof(buf));
6715 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6716 _syscmd(cmd, buf, sizeof(buf));
6717 *Port_output = atoi(buf);
6718
6719 memset(buf, 0, sizeof(buf));
6720 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6721 _syscmd(cmd, buf, sizeof(buf));
6722 strncpy(RadiusSecret_output, buf, 64);
6723
6724 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006725 return RETURN_OK;
6726}
6727
6728INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6729{
developer8f2ddd52022-09-13 15:39:24 +08006730 char config_file[64] = {0};
6731 char port_str[8] = {0};
6732 char cmd[256] = {0};
6733 char buf[128] = {0};
6734
6735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6736
6737 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6738
6739 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6740 _syscmd(cmd, buf, sizeof(buf));
6741 memset(cmd, 0, sizeof(cmd));
6742
6743 snprintf(port_str, sizeof(port_str), "%d", port);
6744 if (strlen(buf) == 0)
6745 // Append
6746 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6747 "auth_server_addr=%s\\n"
6748 "auth_server_port=%s\\n"
6749 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6750 else {
6751 // Delete the three lines setting after the "# radius 1" comment
6752 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6753 _syscmd(cmd, buf, sizeof(buf));
6754 memset(cmd, 0, sizeof(cmd));
6755 // Use "# radius 1" comment to find the location to insert the radius setting
6756 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6757 "# radius 1\\n"
6758 "auth_server_addr=%s\\n"
6759 "auth_server_port=%s\\n"
6760 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6761 }
6762 if(_syscmd(cmd, buf, sizeof(buf))) {
6763 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6764 return RETURN_ERR;
6765 }
6766
6767 wifi_reloadAp(apIndex);
6768 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6769 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006770}
6771
6772INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6773{
developer8f2ddd52022-09-13 15:39:24 +08006774 char config_file[64] = {0};
6775 char buf[64] = {0};
6776 char cmd[256] = {0};
6777
6778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6779
developer06a01d92022-09-07 16:32:39 +08006780 if(!IP_output || !Port_output || !RadiusSecret_output)
6781 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006782
6783 // Read the second matched config
6784 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6785 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6786 _syscmd(cmd, buf, sizeof(buf));
6787 strncpy(IP_output, buf, 64);
6788
6789 memset(buf, 0, sizeof(buf));
6790 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6791 _syscmd(cmd, buf, sizeof(buf));
6792 *Port_output = atoi(buf);
6793
6794 memset(buf, 0, sizeof(buf));
6795 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6796 _syscmd(cmd, buf, sizeof(buf));
6797 strncpy(RadiusSecret_output, buf, 64);
6798
6799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006800 return RETURN_OK;
6801}
6802
6803INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6804{
developer8f2ddd52022-09-13 15:39:24 +08006805 char config_file[64] = {0};
6806 char port_str[8] = {0};
6807 char cmd[256] = {0};
6808 char buf[128] = {0};
6809
6810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6811
6812 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6813
6814 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6815 _syscmd(cmd, buf, sizeof(buf));
6816 memset(cmd, 0, sizeof(cmd));
6817
6818 snprintf(port_str, sizeof(port_str), "%d", port);
6819 if (strlen(buf) == 0)
6820 // Append
6821 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6822 "auth_server_addr=%s\\n"
6823 "auth_server_port=%s\\n"
6824 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6825 else {
6826 // Delete the three lines setting after the "# radius 2" comment
6827 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6828 _syscmd(cmd, buf, sizeof(buf));
6829 memset(cmd, 0, sizeof(cmd));
6830 // Use "# radius 2" comment to find the location to insert the radius setting
6831 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6832 "# radius 2\\n"
6833 "auth_server_addr=%s\\n"
6834 "auth_server_port=%s\\n"
6835 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6836 }
6837 if(_syscmd(cmd, buf, sizeof(buf))) {
6838 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6839 return RETURN_ERR;
6840 }
6841
6842 wifi_reloadAp(apIndex);
6843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6844 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006845}
6846
6847//RadiusSettings
6848INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6849{
6850 if(!output)
6851 return RETURN_ERR;
6852
6853 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6854 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6855 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6856 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6857 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6858 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.
6859 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6860 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6861 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6862 //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.
6863
6864 return RETURN_OK;
6865}
6866
6867INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6868{
6869 //store the paramters, and apply instantly
6870 return RETURN_ERR;
6871}
6872
6873//Device.WiFi.AccessPoint.{i}.WPS.Enable
6874//Enables or disables WPS functionality for this access point.
6875// outputs the WPS enable state of this ap in output_bool
6876INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6877{
developerd946fd62022-12-08 18:03:28 +08006878 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006879 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006880 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006881 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08006882 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006883 return RETURN_ERR;
6884 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006885 _syscmd(cmd, buf, sizeof(buf));
6886 if(strstr(buf, "configured"))
6887 *output_bool=TRUE;
6888 else
6889 *output_bool=FALSE;
6890
6891 return RETURN_OK;
6892}
6893
6894//Device.WiFi.AccessPoint.{i}.WPS.Enable
6895// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6896INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6897{
6898 char config_file[MAX_BUF_SIZE] = {0};
6899 struct params params;
6900
developer06a01d92022-09-07 16:32:39 +08006901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6902 //store the paramters, and wait for wifi up to apply
6903 params.name = "wps_state";
6904 params.value = enable ? "2":"0";
6905
6906 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6907 wifi_hostapdWrite(config_file, &params, 1);
6908 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6909 wifi_reloadAp(apIndex);
6910
6911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6912 return RETURN_OK;
6913}
6914
6915//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
6916INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6917{
6918 if(!output)
6919 return RETURN_ERR;
6920 snprintf(output, 128, "PushButton,PIN");
6921 return RETURN_OK;
6922}
6923
6924//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6925//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.
6926// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6927INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6928{
6929 if(!output)
6930 return RETURN_ERR;
6931 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6932
6933 return RETURN_OK;
6934}
6935
6936//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6937// 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
6938INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6939{
6940 //apply instantly. No setting need to be stored.
6941 char methods[MAX_BUF_SIZE], *token, *next_token;
6942 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6943 struct params params;
6944
developer5b398df2022-11-17 20:39:48 +08006945 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006946 return RETURN_ERR;
6947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6948 //store the paramters, and wait for wifi up to apply
6949
6950 snprintf(methods, sizeof(methods), "%s", methodString);
6951 for(token=methods; *token; token=next_token)
6952 {
6953 strtok_r(token, ",", &next_token);
6954 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6955 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6956 else if(*token=='E')
6957 {
6958 if(!strcmp(methods, "Ethernet"))
6959 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6960 else if(!strcmp(methods, "ExternalNFCToken"))
6961 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6962 else
6963 printf("%s: Unknown WpsConfigMethod\n", __func__);
6964 }
6965 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6966 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6967 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6968 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6969 else if(*token=='P' )
6970 {
6971 if(!strcmp(token, "PushButton"))
6972 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6973 else if(!strcmp(token, "PIN"))
6974 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6975 else
6976 printf("%s: Unknown WpsConfigMethod\n", __func__);
6977 }
6978 else
6979 printf("%s: Unknown WpsConfigMethod\n", __func__);
6980 }
6981 params.name = "config_methods";
6982 params.value = config_methods;
6983 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6984 wifi_hostapdWrite(config_file, &params, 1);
6985 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6987
6988 return RETURN_OK;
6989}
6990
6991// outputs the pin value, ulong_pin must be allocated by the caller
6992INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6993{
6994 char buf[MAX_BUF_SIZE] = {0};
6995 char cmd[MAX_CMD_SIZE] = {0};
6996
developer5b398df2022-11-17 20:39:48 +08006997 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08006998 return RETURN_ERR;
6999 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7000 _syscmd(cmd, buf, sizeof(buf));
7001 if(strlen(buf) > 0)
7002 *output_ulong=strtoul(buf, NULL, 10);
7003
7004 return RETURN_OK;
7005}
7006
7007// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7008INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7009{
7010 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7011 char ap_pin[16] = {0};
7012 char buf[MAX_BUF_SIZE] = {0};
7013 char config_file[MAX_BUF_SIZE] = {0};
7014 ULONG prev_pin = 0;
7015 struct params params;
7016
developer06a01d92022-09-07 16:32:39 +08007017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7018 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7019 params.name = "ap_pin";
7020 params.value = ap_pin;
7021 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7022 wifi_hostapdWrite(config_file, &params, 1);
7023 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7024 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7025
7026 return RETURN_OK;
7027}
7028
7029// Output string is either Not configured or Configured, max 32 characters
7030INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7031{
developerd946fd62022-12-08 18:03:28 +08007032 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007033 char cmd[MAX_CMD_SIZE];
7034 char buf[MAX_BUF_SIZE]={0};
7035
developer5b398df2022-11-17 20:39:48 +08007036 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007037 return RETURN_ERR;
7038 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7039 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007040 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007041 return RETURN_ERR;
7042 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007043 _syscmd(cmd, buf, sizeof(buf));
7044
developer348e3d92022-09-13 14:48:41 +08007045 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007046 snprintf(output_string, 32, "Configured");
7047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7048
7049 return RETURN_OK;
7050}
7051
7052// sets the WPS pin for this AP
7053INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7054{
developerd946fd62022-12-08 18:03:28 +08007055 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007056 char cmd[MAX_CMD_SIZE];
7057 char buf[MAX_BUF_SIZE]={0};
7058 BOOL enable;
7059
developer06a01d92022-09-07 16:32:39 +08007060 wifi_getApEnable(apIndex, &enable);
7061 if (!enable)
7062 return RETURN_ERR;
7063 wifi_getApWpsEnable(apIndex, &enable);
7064 if (!enable)
7065 return RETURN_ERR;
7066
developerac6f1142022-12-20 19:26:35 +08007067 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007068 return RETURN_ERR;
7069 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007070 _syscmd(cmd, buf, sizeof(buf));
7071 if((strstr(buf, "OK"))!=NULL)
7072 return RETURN_OK;
7073
7074 return RETURN_ERR;
7075}
7076
7077// This function is called when the WPS push button has been pressed for this AP
7078INT wifi_setApWpsButtonPush(INT apIndex)
7079{
7080 char cmd[MAX_CMD_SIZE];
7081 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007082 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007083 BOOL enable=FALSE;
7084
developer06a01d92022-09-07 16:32:39 +08007085 wifi_getApEnable(apIndex, &enable);
7086 if (!enable)
7087 return RETURN_ERR;
7088
7089 wifi_getApWpsEnable(apIndex, &enable);
7090 if (!enable)
7091 return RETURN_ERR;
7092
developerac6f1142022-12-20 19:26:35 +08007093 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007094 return RETURN_ERR;
7095
7096 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
developer06a01d92022-09-07 16:32:39 +08007097 _syscmd(cmd, buf, sizeof(buf));
7098
7099 if((strstr(buf, "OK"))!=NULL)
7100 return RETURN_OK;
7101 return RETURN_ERR;
7102}
7103
7104// cancels WPS mode for this AP
7105INT wifi_cancelApWPS(INT apIndex)
7106{
developerd946fd62022-12-08 18:03:28 +08007107 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007108 char cmd[MAX_CMD_SIZE];
7109 char buf[MAX_BUF_SIZE]={0};
7110
developerac6f1142022-12-20 19:26:35 +08007111 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007112 return RETURN_ERR;
7113 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007114 _syscmd(cmd,buf, sizeof(buf));
7115
7116 if((strstr(buf, "OK"))!=NULL)
7117 return RETURN_OK;
7118 return RETURN_ERR;
7119}
7120
7121//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7122//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7123INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7124{
developerd946fd62022-12-08 18:03:28 +08007125 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007126 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007127 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007128 char cmd[256] = {0}, buf[2048] = {0};
7129 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007130 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007131 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007132 wifi_associated_dev_t *dev=NULL;
7133
7134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7135 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007136 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007137 return RETURN_ERR;
7138 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007139 _syscmd(cmd,buf,sizeof(buf));
7140 *output_array_size = atoi(buf);
7141
7142 if (*output_array_size <= 0)
7143 return RETURN_OK;
7144
7145 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7146 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007147 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007148 _syscmd(cmd,buf,sizeof(buf));
7149 f = fopen("/tmp/connected_devices.txt", "r");
7150 if (f==NULL)
7151 {
7152 *output_array_size=0;
7153 return RETURN_ERR;
7154 }
developer30423732022-12-01 16:17:49 +08007155 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007156 {
7157 param = strtok(line,"=");
7158 value = strtok(NULL,"=");
7159
7160 if( strcmp("flags",param) == 0 )
7161 {
7162 value[strlen(value)-1]='\0';
7163 if(strstr (value,"AUTHORIZED") != NULL )
7164 {
7165 dev[auth_temp].cli_AuthenticationState = 1;
7166 dev[auth_temp].cli_Active = 1;
7167 auth_temp++;
7168 read_flag=1;
7169 }
7170 }
7171 if(read_flag==1)
7172 {
7173 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7174 {
7175 value[strlen(value)-1]='\0';
7176 sscanf(value, "%x:%x:%x:%x:%x:%x",
7177 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7178 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7179 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7180 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7181 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7182 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7183 mac_temp++;
7184 read_flag=0;
7185 }
7186 }
7187 }
7188 *output_array_size = auth_temp;
7189 auth_temp=0;
7190 mac_temp=0;
7191 free(line);
7192 fclose(f);
7193 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7194 return RETURN_OK;
7195}
7196
7197#define MACADDRESS_SIZE 6
7198
7199INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7200{
7201 FILE *fp = NULL;
7202 char str[MAX_BUF_SIZE] = {0};
7203 int wificlientindex = 0 ;
7204 int count = 0;
7205 int signalstrength = 0;
7206 int arr[MACADDRESS_SIZE] = {0};
7207 unsigned char mac[MACADDRESS_SIZE] = {0};
7208 UINT wifi_count = 0;
7209 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7210 char pipeCmd[MAX_CMD_SIZE] = {0};
7211
7212 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7213 *output_array_size = 0;
7214 *associated_dev_array = NULL;
7215
7216 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7217 fp = popen(pipeCmd, "r");
7218 if (fp == NULL)
7219 {
7220 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7221 return RETURN_ERR;
7222 }
7223
7224 /* Read the output a line at a time - output it. */
7225 fgets(str, sizeof(str)-1, fp);
7226 wifi_count = (unsigned int) atoi ( str );
7227 *output_array_size = wifi_count;
7228 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7229 pclose(fp);
7230
7231 if(wifi_count == 0)
7232 {
7233 return RETURN_OK;
7234 }
7235 else
7236 {
7237 wifi_associated_dev3_t* temp = NULL;
7238 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7239 if(temp == NULL)
7240 {
7241 printf("Error Statement. Insufficient memory \n");
7242 return RETURN_ERR;
7243 }
7244
7245 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7246 system(pipeCmd);
7247 memset(pipeCmd,0,sizeof(pipeCmd));
7248 if(apIndex == 0)
7249 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7250 else if(apIndex == 1)
7251 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7252 system(pipeCmd);
7253
7254 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7255 if(fp == NULL)
7256 {
7257 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007258 free(temp);
developer06a01d92022-09-07 16:32:39 +08007259 return RETURN_ERR;
7260 }
7261 fclose(fp);
7262
developer30423732022-12-01 16:17:49 +08007263 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007264 fp = popen(pipeCmd, "r");
7265 if(fp)
7266 {
7267 for(count =0 ; count < wifi_count; count++)
7268 {
7269 fgets(str, MAX_BUF_SIZE, fp);
7270 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7271 {
7272 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7273 {
7274 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7275
7276 }
7277 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7278 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]);
7279 }
7280 temp[count].cli_AuthenticationState = 1; //TODO
7281 temp[count].cli_Active = 1; //TODO
7282 }
7283 pclose(fp);
7284 }
7285
developer30423732022-12-01 16:17:49 +08007286 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 +08007287 fp = popen(pipeCmd, "r");
7288 if(fp)
7289 {
7290 pclose(fp);
7291 }
7292 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7293 if(fp)
7294 {
7295 for(count =0 ; count < wifi_count ;count++)
7296 {
7297 fgets(str, MAX_BUF_SIZE, fp);
7298 signalstrength = atoi(str);
7299 temp[count].cli_SignalStrength = signalstrength;
7300 temp[count].cli_RSSI = signalstrength;
7301 temp[count].cli_SNR = signalstrength + 95;
7302 }
7303 pclose(fp);
7304 }
7305
7306
7307 if((apIndex == 0) || (apIndex == 4))
7308 {
7309 for(count =0 ; count < wifi_count ;count++)
7310 {
7311 strcpy(temp[count].cli_OperatingStandard,"g");
7312 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7313 }
7314
7315 //BytesSent
developer30423732022-12-01 16:17:49 +08007316 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 +08007317 fp = popen(pipeCmd, "r");
7318 if(fp)
7319 {
7320 pclose(fp);
7321 }
7322 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7323 if(fp)
7324 {
7325 for (count = 0; count < wifi_count; count++)
7326 {
7327 fgets(str, MAX_BUF_SIZE, fp);
7328 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7329 }
7330 pclose(fp);
7331 }
7332
7333 //BytesReceived
developer30423732022-12-01 16:17:49 +08007334 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 +08007335 fp = popen(pipeCmd, "r");
7336 if (fp)
7337 {
7338 pclose(fp);
7339 }
7340 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7341 if (fp)
7342 {
7343 for (count = 0; count < wifi_count; count++)
7344 {
7345 fgets(str, MAX_BUF_SIZE, fp);
7346 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7347 }
7348 pclose(fp);
7349 }
7350
7351 //PacketsSent
developer30423732022-12-01 16:17:49 +08007352 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 +08007353 fp = popen(pipeCmd, "r");
7354 if (fp)
7355 {
7356 pclose(fp);
7357 }
7358
7359 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7360 if (fp)
7361 {
7362 for (count = 0; count < wifi_count; count++)
7363 {
7364 fgets(str, MAX_BUF_SIZE, fp);
7365 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7366 }
7367 pclose(fp);
7368 }
7369
7370 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007371 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 +08007372 fp = popen(pipeCmd, "r");
7373 if (fp)
7374 {
7375 pclose(fp);
7376 }
7377 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7378 if (fp)
7379 {
7380 for (count = 0; count < wifi_count; count++)
7381 {
7382 fgets(str, MAX_BUF_SIZE, fp);
7383 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7384 }
7385 pclose(fp);
7386 }
7387
7388 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007389 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 +08007390 fp = popen(pipeCmd, "r");
7391 if (fp)
7392 {
7393 pclose(fp);
7394 }
7395 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7396 if (fp)
7397 {
7398 for (count = 0; count < wifi_count; count++)
7399 {
7400 fgets(str, MAX_BUF_SIZE, fp);
7401 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7402 }
7403 pclose(fp);
7404 }
7405
7406 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007407 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 +08007408 fp = popen(pipeCmd, "r");
7409 if (fp)
7410 {
7411 pclose(fp);
7412 }
7413 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7414 if (fp)
7415 {
7416 for (count = 0; count < wifi_count; count++)
7417 {
7418 fgets(str, MAX_BUF_SIZE, fp);
7419 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7420 }
7421 pclose(fp);
7422 }
7423
7424 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007425 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 +08007426 fp = popen(pipeCmd, "r");
7427 if (fp)
7428 {
7429 pclose(fp);
7430 }
7431 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7432 if (fp)
7433 {
7434 for (count = 0; count < wifi_count; count++)
7435 {
7436 fgets(str, MAX_BUF_SIZE, fp);
7437 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7438 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7439 }
7440 pclose(fp);
7441 }
7442
7443 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007444 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 +08007445 fp = popen(pipeCmd, "r");
7446 if (fp)
7447 {
7448 pclose(fp);
7449 }
7450 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7451 if (fp)
7452 {
7453 for (count = 0; count < wifi_count; count++)
7454 {
7455 fgets(str, MAX_BUF_SIZE, fp);
7456 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7457 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7458 }
7459 pclose(fp);
7460 }
7461
7462 }
7463 else if ((apIndex == 1) || (apIndex == 5))
7464 {
7465 for (count = 0; count < wifi_count; count++)
7466 {
7467 strcpy(temp[count].cli_OperatingStandard, "a");
7468 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7469 temp[count].cli_BytesSent = 0;
7470 temp[count].cli_BytesReceived = 0;
7471 temp[count].cli_LastDataUplinkRate = 0;
7472 temp[count].cli_LastDataDownlinkRate = 0;
7473 temp[count].cli_PacketsSent = 0;
7474 temp[count].cli_PacketsReceived = 0;
7475 temp[count].cli_ErrorsSent = 0;
7476 }
7477 }
7478
7479 for (count = 0; count < wifi_count; count++)
7480 {
7481 temp[count].cli_Retransmissions = 0;
7482 temp[count].cli_DataFramesSentAck = 0;
7483 temp[count].cli_DataFramesSentNoAck = 0;
7484 temp[count].cli_MinRSSI = 0;
7485 temp[count].cli_MaxRSSI = 0;
7486 strncpy(temp[count].cli_InterferenceSources, "", 64);
7487 memset(temp[count].cli_IPAddress, 0, 64);
7488 temp[count].cli_RetransCount = 0;
7489 temp[count].cli_FailedRetransCount = 0;
7490 temp[count].cli_RetryCount = 0;
7491 temp[count].cli_MultipleRetryCount = 0;
7492 }
7493 *associated_dev_array = temp;
7494 }
7495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7496 return RETURN_OK;
7497}
7498
7499int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7500{
7501 FILE *fp = NULL;
7502 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7503 char cmd[MAX_CMD_SIZE];
7504 int count = 0;
7505
7506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7507 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7508 fp = popen(cmd,"r");
7509 if(fp == NULL)
7510 {
7511 printf("Failed to run command in Function %s\n",__FUNCTION__);
7512 return 0;
7513 }
7514 if(fgets(path, sizeof(path)-1, fp) != NULL)
7515 {
7516 for(count=0;path[count]!='\n';count++)
7517 status[count]=path[count];
7518 status[count]='\0';
7519 }
7520 strcpy(wifi_status,status);
7521 pclose(fp);
7522 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7523 return RETURN_OK;
7524}
7525
7526/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7527struct hostapd_sta_param {
7528 char key[50];
7529 char value[100];
7530}
7531
7532static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7533 int i = 0;
7534
7535 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7536 if (strncmp(params[i].key,key,50) == 0){
7537 return &params[i].value;
7538 }
7539 i++;
7540 }
7541 return NULL;
7542
7543} */
7544
7545static unsigned int count_occurences(const char *buf, const char *word)
7546{
7547 unsigned int n = 0;
7548 char *ptr = strstr(buf, word);
7549
7550 while (ptr++) {
7551 n++;
7552 ptr = strstr(ptr, word);
7553 }
7554
7555 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7556 return n;
7557}
7558
7559static const char *get_line_from_str_buf(const char *buf, char *line)
7560{
7561 int i;
7562 int n = strlen(buf);
7563
7564 for (i = 0; i < n; i++) {
7565 line[i] = buf[i];
7566 if (buf[i] == '\n') {
7567 line[i] = '\0';
7568 return &buf[i + 1];
7569 }
7570 }
7571
7572 return NULL;
7573}
7574
7575INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7576{
7577 unsigned int assoc_cnt = 0;
7578 char interface_name[50] = {0};
7579 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7580 char cmd[MAX_CMD_SIZE] = {'\0'};
7581 char line[256] = {'\0'};
7582 int i = 0;
7583 int ret = 0;
7584 const char *ptr = NULL;
7585 char *key = NULL;
7586 char *val = NULL;
7587 wifi_associated_dev3_t *temp = NULL;
7588 int rssi;
7589
7590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7591
7592 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7593 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7594 return RETURN_ERR;
7595 }
7596
7597 // Example filtered output of 'iw dev' command:
7598 // Station 0a:69:72:10:d2:fa (on wifi0)
7599 // signal avg:-67 [-71, -71] dBm
7600 // Station 28:c2:1f:25:5f:99 (on wifi0)
7601 // signal avg:-67 [-71, -70] dBm
7602 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7603 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7604 return RETURN_ERR;
7605 }
7606
7607 ret = _syscmd(cmd, buf, sizeof(buf));
7608 if (ret == RETURN_ERR) {
7609 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7610 return RETURN_ERR;
7611 }
7612
7613 *output_array_size = count_occurences(buf, "Station");
7614 if (*output_array_size == 0) return RETURN_OK;
7615
7616 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7617 if (temp == NULL) {
7618 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7619 return RETURN_ERR;
7620 }
7621 *associated_dev_array = temp;
7622
7623 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7624 ptr = get_line_from_str_buf(buf, line);
7625 i = -1;
7626 while (ptr) {
7627 if (strstr(line, "Station")) {
7628 i++;
7629 key = strtok(line, " ");
7630 val = strtok(NULL, " ");
7631 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7632 &temp[i].cli_MACAddress[0],
7633 &temp[i].cli_MACAddress[1],
7634 &temp[i].cli_MACAddress[2],
7635 &temp[i].cli_MACAddress[3],
7636 &temp[i].cli_MACAddress[4],
7637 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7638 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7639 free(*associated_dev_array);
7640 return RETURN_ERR;
7641 }
7642 }
7643 else if (i < 0) {
7644 ptr = get_line_from_str_buf(ptr, line);
7645 continue; // We didn't detect 'station' entry yet
7646 }
7647 else if (strstr(line, "signal avg")) {
7648 key = strtok(line, ":");
7649 val = strtok(NULL, " ");
7650 if (sscanf(val, "%d", &rssi) <= 0 ) {
7651 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7652 free(*associated_dev_array);
7653 return RETURN_ERR;
7654 }
7655 temp[i].cli_RSSI = rssi;
7656 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7657 }
7658 // Here other fields can be parsed if added to filter of 'iw dev' command
7659
7660 ptr = get_line_from_str_buf(ptr, line);
7661 };
7662
7663 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7664
7665 return RETURN_OK;
7666}
7667
7668#if 0
7669//To-do
7670INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7671{
7672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7673
7674 //Using different approach to get required WiFi Parameters from system available commands
7675#if 0
7676 FILE *f;
7677 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7678 char cmd[256], buf[2048];
7679 char *param , *value, *line=NULL;
7680 size_t len = 0;
7681 ssize_t nread;
7682 wifi_associated_dev3_t *dev=NULL;
7683 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007684 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007685 _syscmd(cmd,buf,sizeof(buf));
7686 *output_array_size = atoi(buf);
7687
7688 if (*output_array_size <= 0)
7689 return RETURN_OK;
7690
7691 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7692 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007693 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007694 _syscmd(cmd,buf,sizeof(buf));
7695 f = fopen("/tmp/connected_devices.txt", "r");
7696 if (f==NULL)
7697 {
7698 *output_array_size=0;
7699 return RETURN_ERR;
7700 }
7701 while ((nread = getline(&line, &len, f)) != -1)
7702 {
7703 param = strtok(line,"=");
7704 value = strtok(NULL,"=");
7705
7706 if( strcmp("flags",param) == 0 )
7707 {
7708 value[strlen(value)-1]='\0';
7709 if(strstr (value,"AUTHORIZED") != NULL )
7710 {
7711 dev[auth_temp].cli_AuthenticationState = 1;
7712 dev[auth_temp].cli_Active = 1;
7713 auth_temp++;
7714 read_flag=1;
7715 }
7716 }
7717 if(read_flag==1)
7718 {
7719 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7720 {
7721 value[strlen(value)-1]='\0';
7722 sscanf(value, "%x:%x:%x:%x:%x:%x",
7723 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7724 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7725 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7726 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7727 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7728 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7729
7730 }
7731 else if( strcmp("rx_packets",param) == 0 )
7732 {
7733 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7734 }
7735
7736 else if( strcmp("tx_packets",param) == 0 )
7737 {
7738 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7739 }
7740
7741 else if( strcmp("rx_bytes",param) == 0 )
7742 {
7743 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7744 }
7745
7746 else if( strcmp("tx_bytes",param) == 0 )
7747 {
7748 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7749 mac_temp++;
7750 read_flag=0;
7751 }
7752 }
7753 }
7754
7755 *output_array_size = auth_temp;
7756 auth_temp=0;
7757 mac_temp=0;
7758 free(line);
7759 fclose(f);
7760#endif
7761 char interface_name[MAX_BUF_SIZE] = {0};
7762 char wifi_status[MAX_BUF_SIZE] = {0};
7763 char hostapdconf[MAX_BUF_SIZE] = {0};
7764
7765 wifi_associated_dev3_t *dev_array = NULL;
7766 ULONG wifi_count = 0;
7767
7768 *associated_dev_array = NULL;
7769 *output_array_size = 0;
7770
7771 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7772 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7773 {
7774 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7775
developerac6f1142022-12-20 19:26:35 +08007776 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08007777
7778 if(strlen(interface_name) > 1)
7779 {
7780 wifihal_interfacestatus(wifi_status,interface_name);
7781 if(strcmp(wifi_status,"RUNNING") == 0)
7782 {
7783 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7784
7785 *associated_dev_array = dev_array;
7786 *output_array_size = wifi_count;
7787 }
7788 else
7789 {
7790 *associated_dev_array = NULL;
7791 }
7792 }
7793 }
7794
7795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7796 return RETURN_OK;
7797}
7798#endif
7799
7800/* getIPAddress function */
7801/**
7802* @description Returning IpAddress of the Matched String
7803*
7804* @param
7805* @str Having MacAddress
7806* @ipaddr Having ipaddr
7807* @return The status of the operation
7808* @retval RETURN_OK if successful
7809* @retval RETURN_ERR if any error is detected
7810*
7811*/
7812
7813INT getIPAddress(char *str,char *ipaddr)
7814{
7815 FILE *fp = NULL;
7816 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7817 int LeaseTime = 0,ret = 0;
7818 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7819 {
7820 return RETURN_ERR;
7821 }
7822
7823 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7824 {
7825 /*
7826 Sample:sss
7827 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7828 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7829 */
7830 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08007831 &(LeaseTime),
7832 phyAddr,
7833 ipAddr,
7834 hostName
7835 );
developer06a01d92022-09-07 16:32:39 +08007836 if(ret != 4)
7837 continue;
7838 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08007839 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08007840 }
developerd946fd62022-12-08 18:03:28 +08007841 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08007842 return RETURN_OK;
7843}
7844
7845/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7846/**
7847* @description Returning Inactive wireless connected clients informations
7848*
7849* @param
7850* @filename Holding private_wifi 2g/5g content files
7851* @associated_dev_array Having inactiv wireless clients informations
7852* @output_array_size Returning Inactive wireless counts
7853* @return The status of the operation
7854* @retval RETURN_OK if successful
7855* @retval RETURN_ERR if any error is detected
7856*
7857*/
7858
7859INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7860{
7861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7862 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7863 FILE *fp = NULL;
7864 int arr[MACADDRESS_SIZE] = {0};
7865 unsigned char mac[MACADDRESS_SIZE] = {0};
7866 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7867 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7868 fp = popen(buf,"r");
7869 if(fp == NULL)
7870 return RETURN_ERR;
7871 else
7872 {
7873 fgets(path,sizeof(path),fp);
7874 maccount = atoi(path);
7875 }
7876 pclose(fp);
7877 *output_array_size = maccount;
7878 wifi_associated_dev3_t* temp = NULL;
7879 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7880 *associated_dev_array = temp;
7881 if(temp == NULL)
7882 {
7883 printf("Error Statement. Insufficient memory \n");
7884 return RETURN_ERR;
7885 }
7886 memset(buf,0,sizeof(buf));
7887 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7888 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08007889 if (fp == NULL) {
7890 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7891 return RETURN_ERR;
7892 }
developer06a01d92022-09-07 16:32:39 +08007893 for(count = 0; count < maccount ; count++)
7894 {
7895 fgets(path,sizeof(path),fp);
7896 for(i = 0; path[i]!='\n';i++)
7897 str[i]=path[i];
7898 str[i]='\0';
7899 getIPAddress(str,ipaddr);
7900 memset(buf,0,sizeof(buf));
7901 if(strlen(ipaddr) > 0)
7902 {
7903 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7904 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7905 {
7906 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7907 {
7908 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7909 {
7910 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7911
7912 }
7913 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7914 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]);
7915 }
7916 temp[count].cli_AuthenticationState = 0; //TODO
7917 temp[count].cli_Active = 0; //TODO
7918 temp[count].cli_SignalStrength = 0;
7919 }
7920 else //Active wireless clients info
7921 {
7922 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7923 {
7924 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7925 {
7926 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7927
7928 }
7929 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7930 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]);
7931 }
7932 temp[count].cli_Active = 1;
7933 }
7934 }
7935 memset(ipaddr,0,sizeof(ipaddr));
7936 }
7937 pclose(fp);
7938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7939 return RETURN_OK;
7940}
7941//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7942//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7943//To get Band Steering Capability
7944INT wifi_getBandSteeringCapability(BOOL *support)
7945{
7946 *support = FALSE;
7947 return RETURN_OK;
7948}
7949
7950
7951//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7952//To get Band Steering enable status
7953INT wifi_getBandSteeringEnable(BOOL *enable)
7954{
7955 *enable = FALSE;
7956 return RETURN_OK;
7957}
7958
7959//To turn on/off Band steering
7960INT wifi_setBandSteeringEnable(BOOL enable)
7961{
7962 return RETURN_OK;
7963}
7964
7965//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7966//To get Band Steering AP group
7967INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7968{
7969 if (NULL == output_ApGroup)
7970 return RETURN_ERR;
7971
7972 strcpy(output_ApGroup, "1,2");
7973 return RETURN_OK;
7974}
7975
7976//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7977//to set and read the band steering BandUtilizationThreshold parameters
7978INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7979{
7980 return RETURN_ERR;
7981}
7982
7983INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7984{
7985 return RETURN_ERR;
7986}
7987
7988//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7989//to set and read the band steering RSSIThreshold parameters
7990INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7991{
7992 return RETURN_ERR;
7993}
7994
7995INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7996{
7997 return RETURN_ERR;
7998}
7999
8000
8001//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8002//to set and read the band steering physical modulation rate threshold parameters
8003INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8004{
8005 //If chip is not support, return -1
8006 return RETURN_ERR;
8007}
8008
8009INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8010{
8011 //If chip is not support, return -1
8012 return RETURN_ERR;
8013}
8014
8015//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8016//to set and read the inactivity time (in seconds) for steering under overload condition
8017INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8018{
8019 return RETURN_ERR;
8020}
8021
8022INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8023{
8024 return RETURN_ERR;
8025}
8026
8027//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8028//to set and read the inactivity time (in seconds) for steering under Idle condition
8029INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8030{
8031 return RETURN_ERR;
8032}
8033
8034INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8035{
8036 return RETURN_ERR;
8037}
8038
8039//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8040//pClientMAC[64]
8041//pSourceSSIDIndex[64]
8042//pDestSSIDIndex[64]
8043//pSteeringReason[256]
8044INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8045{
8046 //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
8047 *pSteeringTime=time(NULL);
8048 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8049 return RETURN_OK;
8050}
8051
8052INT wifi_ifConfigDown(INT apIndex)
8053{
8054 INT status = RETURN_OK;
8055 char cmd[64];
8056
8057 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8058 printf("%s: %s\n", __func__, cmd);
8059 system(cmd);
8060
8061 return status;
8062}
8063
8064INT wifi_ifConfigUp(INT apIndex)
8065{
developerd946fd62022-12-08 18:03:28 +08008066 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008067 char cmd[128];
8068 char buf[1024];
8069
developerac6f1142022-12-20 19:26:35 +08008070 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008071 return RETURN_ERR;
8072 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008073 _syscmd(cmd, buf, sizeof(buf));
8074 return 0;
8075}
8076
8077//>> Deprecated. Replace with wifi_applyRadioSettings
8078INT wifi_pushBridgeInfo(INT apIndex)
8079{
developerd946fd62022-12-08 18:03:28 +08008080 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008081 char ip[32] = {0};
8082 char subnet[32] = {0};
8083 char bridge[32] = {0};
8084 int vlanId = 0;
8085 char cmd[128] = {0};
8086 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008087
8088 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8089 wifi_getApVlanID(apIndex,&vlanId);
8090
developerac6f1142022-12-20 19:26:35 +08008091 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008092 return RETURN_ERR;
8093 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008094 _syscmd(cmd,buf, sizeof(buf));
8095
8096 return 0;
8097}
8098
8099INT wifi_pushChannel(INT radioIndex, UINT channel)
8100{
developerd946fd62022-12-08 18:03:28 +08008101 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008102 char cmd[128];
8103 char buf[1024];
8104 int apIndex;
8105
8106 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008107 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008108 return RETURN_ERR;
8109 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008110 _syscmd(cmd,buf, sizeof(buf));
8111
8112 return 0;
8113}
8114
8115INT wifi_pushChannelMode(INT radioIndex)
8116{
8117 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8118 return RETURN_ERR;
8119}
8120
8121INT wifi_pushDefaultValues(INT radioIndex)
8122{
8123 //Apply Comcast specified default radio settings instantly
8124 //AMPDU=1
8125 //AMPDUFrames=32
8126 //AMPDULim=50000
8127 //txqueuelen=1000
8128
8129 return RETURN_ERR;
8130}
8131
8132INT wifi_pushTxChainMask(INT radioIndex)
8133{
8134 //Apply default TxChainMask instantly
8135 return RETURN_ERR;
8136}
8137
8138INT wifi_pushRxChainMask(INT radioIndex)
8139{
8140 //Apply default RxChainMask instantly
8141 return RETURN_ERR;
8142}
8143
8144INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8145{
8146 INT status;
8147
8148 status = wifi_setSSIDName(apIndex,ssid);
8149 wifi_setApEnable(apIndex,FALSE);
8150 wifi_setApEnable(apIndex,TRUE);
8151
8152 return status;
8153}
8154
8155INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8156{
8157 //Apply default Ssid Advertisement instantly
8158 return RETURN_ERR;
8159}
8160
8161INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8162{
8163 INT status = RETURN_ERR;
8164 *output = 0;
8165 return RETURN_ERR;
8166}
8167
8168INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8169{
8170 return RETURN_OK;
8171}
8172
8173INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8174{
8175 return RETURN_OK;
8176}
8177
8178//To-do
8179INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8180{
developereb199ae2022-09-13 14:04:27 +08008181 char output[16]={'\0'};
8182 char config_file[MAX_BUF_SIZE] = {0};
8183
8184 if (!output_string)
8185 return RETURN_ERR;
8186
8187 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8188 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8189
8190 if (strlen(output) == 0)
8191 snprintf(output_string, 64, "Disabled");
8192 else if (strncmp(output, "0", 1) == 0)
8193 snprintf(output_string, 64, "Disabled");
8194 else if (strncmp(output, "1", 1) == 0)
8195 snprintf(output_string, 64, "Optional");
8196 else if (strncmp(output, "2", 1) == 0)
8197 snprintf(output_string, 64, "Required");
8198 else {
8199 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8200 return RETURN_ERR;
8201 }
8202
8203 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008204 return RETURN_OK;
8205}
8206INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8207{
developereb199ae2022-09-13 14:04:27 +08008208 char str[MAX_BUF_SIZE]={'\0'};
8209 char cmd[MAX_CMD_SIZE]={'\0'};
8210 struct params params;
8211 char config_file[MAX_BUF_SIZE] = {0};
8212
8213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8214 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8215 return RETURN_ERR;
8216
8217 params.name = "ieee80211w";
8218 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8219 params.value = "0";
8220 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8221 params.value = "1";
8222 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8223 params.value = "2";
8224 else{
8225 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8226 return RETURN_ERR;
8227 }
8228 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8229 wifi_hostapdWrite(config_file, &params, 1);
8230 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008231 return RETURN_OK;
8232}
8233INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8234{
8235 char output[16]={'\0'};
8236 char config_file[MAX_BUF_SIZE] = {0};
8237
8238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8239 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8240 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8241
8242 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8243 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8244
8245 return RETURN_OK;
8246}
8247
8248INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8249{
8250 return RETURN_OK;
8251}
8252
8253INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8254{
8255 return RETURN_OK;
8256}
8257
8258INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8259{
8260 return RETURN_OK;
8261}
8262
8263INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8264{
8265 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8266 char config_file[MAX_BUF_SIZE] = {0};
8267
8268 if (NULL == output)
8269 return RETURN_ERR;
8270 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8271 wifi_hostapdRead(config_file,"hw_mode",output,64);
8272
8273 if(strcmp(output,"b")==0)
8274 sprintf(output, "%s", "1,2,5.5,11");
8275 else if (strcmp(output,"a")==0)
8276 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8277 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8278 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8279
8280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8281 return RETURN_OK;
8282}
8283
8284INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8285{
8286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8287 char *temp;
8288 char temp_output[128];
8289 char temp_TransmitRates[128];
8290 char config_file[MAX_BUF_SIZE] = {0};
8291
8292 if (NULL == output)
8293 return RETURN_ERR;
8294
8295 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8296 wifi_hostapdRead(config_file,"supported_rates",output,64);
8297
developer5b398df2022-11-17 20:39:48 +08008298 if (strlen(output) == 0) {
8299 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8300 return RETURN_OK;
8301 }
developer06a01d92022-09-07 16:32:39 +08008302 strcpy(temp_TransmitRates,output);
8303 strcpy(temp_output,"");
8304 temp = strtok(temp_TransmitRates," ");
8305 while(temp!=NULL)
8306 {
8307 temp[strlen(temp)-1]=0;
8308 if((temp[0]=='5') && (temp[1]=='\0'))
8309 {
8310 temp="5.5";
8311 }
8312 strcat(temp_output,temp);
8313 temp = strtok(NULL," ");
8314 if(temp!=NULL)
8315 {
8316 strcat(temp_output,",");
8317 }
8318 }
8319 strcpy(output,temp_output);
8320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8321
8322 return RETURN_OK;
8323}
8324
8325INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8326{
8327 return RETURN_OK;
8328}
8329
8330
8331INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8332{
8333 int i=0;
8334 char *temp;
developeref938762022-10-19 17:21:01 +08008335 char temp1[128] = {0};
8336 char temp_output[128] = {0};
8337 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008338 struct params params={'\0'};
8339 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008340 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008341
8342 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8343 if(NULL == output)
8344 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008345 strcpy(temp_TransmitRates,output);
8346
8347 for(i=0;i<strlen(temp_TransmitRates);i++)
8348 {
developeref938762022-10-19 17:21:01 +08008349 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008350 {
8351 continue;
8352 }
8353 else
8354 {
8355 return RETURN_ERR;
8356 }
8357 }
8358 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008359 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008360 while(temp!=NULL)
8361 {
8362 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008363 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008364 {
developeref938762022-10-19 17:21:01 +08008365 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008366 {
8367 return RETURN_ERR;
8368 }
8369 }
8370
8371 if(strcmp(temp,"5.5")==0)
8372 {
8373 strcpy(temp1,"55");
8374 }
8375 else
8376 {
8377 strcat(temp1,"0");
8378 }
8379 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008380 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008381 if(temp!=NULL)
8382 {
8383 strcat(temp_output," ");
8384 }
8385 }
8386 strcpy(output,temp_output);
8387
developer06a01d92022-09-07 16:32:39 +08008388 params.name = "supported_rates";
8389 params.value = output;
8390
8391 wifi_dbg_printf("\n%s:",__func__);
8392 wifi_dbg_printf("params.value=%s\n",params.value);
8393 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8394 wifi_hostapdWrite(config_file,&params,1);
8395 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8396
8397 return RETURN_OK;
8398}
8399
8400
8401static char *sncopy(char *dst, int dst_sz, const char *src)
8402{
8403 if (src && dst && dst_sz > 0) {
8404 strncpy(dst, src, dst_sz);
8405 dst[dst_sz - 1] = '\0';
8406 }
8407 return dst;
8408}
8409
8410static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8411{
8412 if (0 == strcmp(ht_mode, "HT40") ||
8413 0 == strcmp(ht_mode, "HT80") ||
8414 0 == strcmp(ht_mode, "HT160")) {
8415 switch (channel) {
8416 case 1 ... 7:
8417 case 36:
8418 case 44:
8419 case 52:
8420 case 60:
8421 case 100:
8422 case 108:
8423 case 116:
8424 case 124:
8425 case 132:
8426 case 140:
8427 case 149:
8428 case 157:
8429 return 1;
8430 case 8 ... 13:
8431 case 40:
8432 case 48:
8433 case 56:
8434 case 64:
8435 case 104:
8436 case 112:
8437 case 120:
8438 case 128:
8439 case 136:
8440 case 144:
8441 case 153:
8442 case 161:
8443 return -1;
8444 default:
8445 return -EINVAL;
8446 }
8447 }
8448
8449 return -EINVAL;
8450}
8451
developerb7593de2022-10-18 09:51:57 +08008452static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8453{
8454 int idx = channel%8;
8455 if (0 == strcmp(ht_mode, "HT40") ||
8456 0 == strcmp(ht_mode, "HT80") ||
8457 0 == strcmp(ht_mode, "HT160")) {
8458 switch (idx) {
8459 case 1:
8460 return 1;
8461 case 5:
8462 return -1;
8463 default:
8464 return -EINVAL;
8465 }
8466 }
8467
8468 return -EINVAL;
8469}
developer06a01d92022-09-07 16:32:39 +08008470static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8471{
8472 if (NULL == hw_mode) return;
8473
8474 if (0 == strcmp(hw_mode, "ac"))
8475 sncopy(bw_mode, bw_mode_len, "ht vht");
8476
8477 if (0 == strcmp(hw_mode, "n"))
8478 sncopy(bw_mode, bw_mode_len, "ht");
8479
8480 return;
8481}
8482
8483static int util_chan_to_freq(int chan)
8484{
8485 if (chan == 14)
8486 return 2484;
8487 else if (chan < 14)
8488 return 2407 + chan * 5;
8489 else if (chan >= 182 && chan <= 196)
8490 return 4000 + chan * 5;
8491 else
8492 return 5000 + chan * 5;
8493 return 0;
8494}
8495
developerb7593de2022-10-18 09:51:57 +08008496static int util_6G_chan_to_freq(int chan)
8497{
8498 if (chan)
8499 return 5950 + chan * 5;
8500 else
8501 return 0;
8502
8503}
developer06a01d92022-09-07 16:32:39 +08008504const int *util_unii_5g_chan2list(int chan, int width)
8505{
8506 static const int lists[] = {
8507 // <width>, <chan1>, <chan2>..., 0,
8508 20, 36, 0,
8509 20, 40, 0,
8510 20, 44, 0,
8511 20, 48, 0,
8512 20, 52, 0,
8513 20, 56, 0,
8514 20, 60, 0,
8515 20, 64, 0,
8516 20, 100, 0,
8517 20, 104, 0,
8518 20, 108, 0,
8519 20, 112, 0,
8520 20, 116, 0,
8521 20, 120, 0,
8522 20, 124, 0,
8523 20, 128, 0,
8524 20, 132, 0,
8525 20, 136, 0,
8526 20, 140, 0,
8527 20, 144, 0,
8528 20, 149, 0,
8529 20, 153, 0,
8530 20, 157, 0,
8531 20, 161, 0,
8532 20, 165, 0,
8533 40, 36, 40, 0,
8534 40, 44, 48, 0,
8535 40, 52, 56, 0,
8536 40, 60, 64, 0,
8537 40, 100, 104, 0,
8538 40, 108, 112, 0,
8539 40, 116, 120, 0,
8540 40, 124, 128, 0,
8541 40, 132, 136, 0,
8542 40, 140, 144, 0,
8543 40, 149, 153, 0,
8544 40, 157, 161, 0,
8545 80, 36, 40, 44, 48, 0,
8546 80, 52, 56, 60, 64, 0,
8547 80, 100, 104, 108, 112, 0,
8548 80, 116, 120, 124, 128, 0,
8549 80, 132, 136, 140, 144, 0,
8550 80, 149, 153, 157, 161, 0,
8551 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8552 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8553 -1 // final delimiter
8554 };
8555 const int *start;
8556 const int *p;
8557
8558 for (p = lists; *p != -1; p++) {
8559 if (*p == width) {
8560 for (start = ++p; *p != 0; p++) {
8561 if (*p == chan)
8562 return start;
8563 }
8564 }
8565 // move to the end of channel list of given width
8566 while (*p != 0) {
8567 p++;
8568 }
8569 }
8570
8571 return NULL;
8572}
8573
8574static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8575{
8576 if (NULL == ht_mode)
8577 return 0;
8578
8579 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8580 const int *chans = util_unii_5g_chan2list(channel, width);
8581 int sum = 0;
8582 int cnt = 0;
8583
8584 if (NULL == chans)
8585 return 0;
8586
8587 while (*chans) {
8588 sum += *chans;
8589 cnt++;
8590 chans++;
8591 }
developer30423732022-12-01 16:17:49 +08008592 if (cnt == 0)
8593 return 0;
developer06a01d92022-09-07 16:32:39 +08008594 return sum / cnt;
8595}
8596
developerb7593de2022-10-18 09:51:57 +08008597static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8598{
8599 if (NULL == ht_mode)
8600 return 0;
8601
8602 int width = strtol((ht_mode + 2), NULL, 10);
8603
8604 int idx = 0 ;
8605 int centerchan = 0;
8606 int chan_ofs = 1;
8607
8608 if (width == 40){
8609 idx = ((channel/4) + chan_ofs)%2;
8610 switch (idx) {
8611 case 0:
8612 centerchan = (channel - 2);
8613 break;
8614 case 1:
8615 centerchan = (channel + 2);
8616 break;
8617 default:
8618 return -EINVAL;
8619 }
8620 }else if (width == 80){
8621 idx = ((channel/4) + chan_ofs)%4;
8622 switch (idx) {
8623 case 0:
8624 centerchan = (channel - 6);
8625 break;
8626 case 1:
8627 centerchan = (channel + 6);
8628 break;
8629 case 2:
8630 centerchan = (channel + 2);
8631 break;
8632 case 3:
8633 centerchan = (channel - 2);
8634 break;
8635 default:
8636 return -EINVAL;
8637 }
8638 }else if (width == 160){
8639 switch (channel) {
8640 case 1 ... 29:
8641 centerchan = 15;
8642 break;
8643 case 33 ... 61:
8644 centerchan = 47;
8645 break;
8646 case 65 ... 93:
8647 centerchan = 79;
8648 break;
8649 case 97 ... 125:
8650 centerchan = 111;
8651 break;
8652 case 129 ... 157:
8653 centerchan = 143;
8654 break;
8655 case 161 ... 189:
8656 centerchan = 175;
8657 break;
8658 case 193 ... 221:
8659 centerchan = 207;
8660 break;
8661 default:
8662 return -EINVAL;
8663 }
8664 }
8665 return centerchan;
8666}
developer06a01d92022-09-07 16:32:39 +08008667static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8668{
8669 BOOL onlyG, onlyN, onlyA;
8670 CHAR tmp[64];
8671 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8672 if (ret == RETURN_OK) {
8673 sncopy(hw_mode, hw_mode_size, tmp);
8674 }
8675 return ret;
8676}
8677
8678INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8679{
8680 // Sample commands:
8681 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8682 // hostapd_cli -i wifi0 chan_switch 30 2437
8683 char cmd[MAX_CMD_SIZE] = {0};
8684 char buf[MAX_BUF_SIZE] = {0};
8685 int freq = 0, ret = 0;
8686 char center_freq1_str[32] = ""; // center_freq1=%d
8687 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8688 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8689 char hw_mode[16] = ""; // n|ac
8690 char bw_mode[16] = ""; // ht|ht vht
8691 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008692 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008693 int sec_chan_offset;
8694 int width;
developer4fb0b922022-09-30 14:29:09 +08008695 char config_file[64] = {0};
8696 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008697 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008698 wifi_band band = band_invalid;
8699 int center_chan = 0;
8700 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008701
developer4fb0b922022-09-30 14:29:09 +08008702 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008703
developerac6f1142022-12-20 19:26:35 +08008704 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008705 return RETURN_ERR;
8706
developer06a01d92022-09-07 16:32:39 +08008707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8708
developerb7593de2022-10-18 09:51:57 +08008709 band = wifi_index_to_band(radioIndex);
8710
developer5884e982022-10-06 10:52:50 +08008711 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008712
8713 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008714 if (channel){
developerb7593de2022-10-18 09:51:57 +08008715 if (band == band_6){
8716 freq = util_6G_chan_to_freq(channel);
8717 }else{
8718 freq = util_chan_to_freq(channel);
8719 }
developer5884e982022-10-06 10:52:50 +08008720 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008721
developer5884e982022-10-06 10:52:50 +08008722 // Provide bandwith if specified
8723 if (channel_width_MHz > 20) {
8724 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8725 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8726 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008727
developer5884e982022-10-06 10:52:50 +08008728 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8729 }else if (channel_width_MHz == 20){
8730 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8731 }
developer06a01d92022-09-07 16:32:39 +08008732
developerb7593de2022-10-18 09:51:57 +08008733
developer5884e982022-10-06 10:52:50 +08008734 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008735 if (band == band_6){
8736 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8737 if(center_chan){
8738 center_freq1 = util_6G_chan_to_freq(center_chan);
8739 }
8740 }else{
8741 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8742 if(center_chan){
8743 center_freq1 = util_chan_to_freq(center_chan);
8744 }
developer5884e982022-10-06 10:52:50 +08008745 }
developerb7593de2022-10-18 09:51:57 +08008746
8747 if (center_freq1)
8748 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8749
8750 }
8751
8752 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8753 if (band == band_6){
8754 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8755 }else{
8756 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008757 }
developerb7593de2022-10-18 09:51:57 +08008758 if (sec_chan_offset != -EINVAL)
8759 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008760
developer5884e982022-10-06 10:52:50 +08008761 // Only the first AP, other are hanging on the same radio
8762 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08008763 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8764 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08008765 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8766 wifi_dbg_printf("execute: '%s'\n", cmd);
8767 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08008768 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08008769
developer5884e982022-10-06 10:52:50 +08008770 ret = wifi_setRadioChannel(radioIndex, channel);
8771 if (ret != RETURN_OK) {
8772 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8773 return RETURN_ERR;
8774 }
8775
8776 if (sec_chan_offset == 1) ext_str = "Above";
8777 else if (sec_chan_offset == -1) ext_str = "Below";
8778
8779 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008780
developer5884e982022-10-06 10:52:50 +08008781 } else {
8782 if (channel_width_MHz > 20)
8783 ext_str = "Above";
8784 }
developer4fb0b922022-09-30 14:29:09 +08008785
developer06a01d92022-09-07 16:32:39 +08008786 wifi_setRadioExtChannel(radioIndex, ext_str);
8787
developer06a01d92022-09-07 16:32:39 +08008788 char mhz_str[16];
8789 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8790 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8791
8792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8793
8794 return RETURN_OK;
8795}
8796
8797INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8798{
developer615510b2022-09-27 10:14:35 +08008799 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008800 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008801 char cmd[256]={0};
8802 char buf[128]={0};
8803 char file_name[32] = {0};
8804 char filter_SSID[32] = {0};
8805 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08008806 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08008807 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008808 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008809 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008810 size_t len=0;
8811 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008812 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008813 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008814 bool filter_enable = false;
8815 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008816 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008817
developer615510b2022-09-27 10:14:35 +08008818 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008819
developer615510b2022-09-27 10:14:35 +08008820 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8821 f = fopen(file_name, "r");
8822 if (f != NULL) {
8823 fgets(filter_SSID, sizeof(file_name), f);
8824 if (strlen(filter_SSID) != 0)
8825 filter_enable = true;
8826 fclose(f);
8827 }
8828
developerac6f1142022-12-20 19:26:35 +08008829 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008830 return RETURN_ERR;
8831
developer033b37b2022-10-18 11:27:46 +08008832 phyId = radio_index_to_phy(radio_index);
8833
8834 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008835 _syscmd(cmd, buf, sizeof(buf));
8836 channels_num = strtol(buf, NULL, 10);
8837
developerd946fd62022-12-08 18:03:28 +08008838 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8839 // 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 +08008840 fprintf(stderr, "cmd: %s\n", cmd);
8841 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008842 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8843 return RETURN_ERR;
8844 }
developer5550e242022-09-30 09:59:32 +08008845
8846 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8847 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8848
developer615510b2022-09-27 10:14:35 +08008849 ret = fgets(line, sizeof(line), f);
8850 while (ret != NULL) {
8851 if(strstr(line, "BSS") != NULL) { // new neighbor info
8852 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8853 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8854 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8855
8856 if (!filter_BSS) {
8857 index++;
8858 wifi_neighbor_ap2_t *tmp;
8859 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8860 if (tmp == NULL) { // no more memory to use
8861 index--;
8862 wifi_dbg_printf("%s: realloc failed\n", __func__);
8863 break;
8864 }
8865 scan_array = tmp;
8866 }
8867 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008868
developer615510b2022-09-27 10:14:35 +08008869 filter_BSS = false;
8870 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8871 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8872 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8873 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8874 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008875 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008876 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008877
developer615510b2022-09-27 10:14:35 +08008878 if (freq >= 2412 && freq <= 2484) {
8879 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8880 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8881 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8882 }
8883 else if (freq >= 5160 && freq <= 5805) {
8884 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8885 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8886 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8887 }
developer06a01d92022-09-07 16:32:39 +08008888
developer615510b2022-09-27 10:14:35 +08008889 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008890 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008891 for (int i = 0; i < channels_num; i++) {
8892 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8893 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8894 break;
8895 }
8896 }
developer06a01d92022-09-07 16:32:39 +08008897 }
developer615510b2022-09-27 10:14:35 +08008898 } else if (strstr(line, "beacon interval") != NULL) {
8899 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8900 } else if (strstr(line, "signal") != NULL) {
8901 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8902 } else if (strstr(line,"SSID") != NULL) {
8903 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8904 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8905 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008906 }
developer615510b2022-09-27 10:14:35 +08008907 } else if (strstr(line, "Supported rates") != NULL) {
8908 char SRate[80] = {0}, *tmp = NULL;
8909 memset(buf, 0, sizeof(buf));
8910 strcpy(SRate, line);
8911 tmp = strtok(SRate, ":");
8912 tmp = strtok(NULL, ":");
8913 strcpy(buf, tmp);
8914 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008915
developer615510b2022-09-27 10:14:35 +08008916 tmp = strtok(buf, " \n");
8917 while (tmp != NULL) {
8918 strcat(SRate, tmp);
8919 if (SRate[strlen(SRate) - 1] == '*') {
8920 SRate[strlen(SRate) - 1] = '\0';
8921 }
8922 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008923
developer615510b2022-09-27 10:14:35 +08008924 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008925 }
developer615510b2022-09-27 10:14:35 +08008926 SRate[strlen(SRate) - 1] = '\0';
8927 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8928 } else if (strstr(line, "DTIM") != NULL) {
8929 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8930 } else if (strstr(line, "VHT capabilities") != NULL) {
8931 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8932 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8933 } else if (strstr(line, "HT capabilities") != NULL) {
8934 strcat(scan_array[index].ap_SupportedStandards, ",n");
8935 strcpy(scan_array[index].ap_OperatingStandards, "n");
8936 } else if (strstr(line, "VHT operation") != NULL) {
8937 ret = fgets(line, sizeof(line), f);
8938 sscanf(line," * channel width: %d", &vht_channel_width);
8939 if(vht_channel_width == 1) {
8940 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8941 } else {
8942 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8943 }
8944 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8945 continue;
8946 } else if (strstr(line, "HT operation") != NULL) {
8947 ret = fgets(line, sizeof(line), f);
8948 sscanf(line," * secondary channel offset: %s", &buf);
8949 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008950 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008951 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 +08008952 }
developer615510b2022-09-27 10:14:35 +08008953 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008954 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008955 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8956 } else {
8957 //20Mhz
8958 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 +08008959 }
developer615510b2022-09-27 10:14:35 +08008960 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008961 continue;
developer615510b2022-09-27 10:14:35 +08008962 } else if (strstr(line, "HE capabilities") != NULL) {
8963 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8964 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8965 ret = fgets(line, sizeof(line), f);
8966 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8967 if (strstr(line, "HE40/2.4GHz") != NULL)
8968 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8969 else
8970 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8971 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8972 if (strstr(line, "HE80/5GHz") != NULL) {
8973 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8974 ret = fgets(line, sizeof(line), f);
8975 } else
8976 continue;
8977 if (strstr(line, "HE160/5GHz") != NULL)
8978 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008979 }
developer615510b2022-09-27 10:14:35 +08008980 continue;
8981 } else if (strstr(line, "WPA") != NULL) {
8982 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8983 } else if (strstr(line, "RSN") != NULL) {
8984 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8985 } else if (strstr(line, "Group cipher") != NULL) {
8986 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8987 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8988 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008989 }
developer06a01d92022-09-07 16:32:39 +08008990 }
developer615510b2022-09-27 10:14:35 +08008991 ret = fgets(line, sizeof(line), f);
8992 }
8993
8994 if (!filter_BSS) {
8995 *output_array_size = index + 1;
8996 } else {
8997 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8998 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008999 }
developer06a01d92022-09-07 16:32:39 +08009000 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009001 pclose(f);
developer5550e242022-09-30 09:59:32 +08009002 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009003 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009004 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009005}
developer615510b2022-09-27 10:14:35 +08009006
developer06a01d92022-09-07 16:32:39 +08009007INT wifi_getApAssociatedDeviceStats(
9008 INT apIndex,
9009 mac_address_t *clientMacAddress,
9010 wifi_associated_dev_stats_t *associated_dev_stats,
9011 u64 *handle)
9012{
9013 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9014 char interface_name[50] = {0};
9015 char cmd[1024] = {0};
9016 char mac_str[18] = {0};
9017 char *key = NULL;
9018 char *val = NULL;
9019 FILE *f = NULL;
9020 char *line = NULL;
9021 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009022
9023 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9024 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9025 return RETURN_ERR;
9026 }
9027
9028 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9029 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9030 if((f = popen(cmd, "r")) == NULL) {
9031 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9032 return RETURN_ERR;
9033 }
9034
developer30423732022-12-01 16:17:49 +08009035 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009036 key = strtok(line,":");
9037 val = strtok(NULL,":");
9038
9039 if(!strncmp(key,"rx bytes",8))
9040 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9041 if(!strncmp(key,"tx bytes",8))
9042 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9043 if(!strncmp(key,"rx packets",10))
9044 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9045 if(!strncmp(key,"tx packets",10))
9046 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9047 if(!strncmp(key,"tx retries",10))
9048 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9049 if(!strncmp(key,"tx failed",9))
9050 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9051 if(!strncmp(key,"rx drop misc",13))
9052 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9053 if(!strncmp(key,"rx bitrate",10)) {
9054 val = strtok(val, " ");
9055 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9056 }
9057 if(!strncmp(key,"tx bitrate",10)) {
9058 val = strtok(val, " ");
9059 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9060 }
9061 }
9062 free(line);
9063 pclose(f);
9064 return RETURN_OK;
9065}
9066
9067INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9068{
developerd946fd62022-12-08 18:03:28 +08009069 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009070 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9071
9072 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9073 if (NULL == output_string)
9074 return RETURN_ERR;
9075
developerac6f1142022-12-20 19:26:35 +08009076 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009077 return RETURN_ERR;
9078 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 +08009079 _syscmd(cmd, buf, sizeof(buf));
9080
9081 //size of SSID name restricted to value less than 32 bytes
9082 snprintf(output_string, 32, "%s", buf);
9083 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9084
9085 return RETURN_OK;
9086}
9087
9088INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9089{
9090 //char cmd[MAX_CMD_SIZE] = {0};
9091 char config_file[MAX_BUF_SIZE] = {0};
9092 char buf[32] = {0};
9093
9094 if (!output_filterMode)
9095 return RETURN_ERR;
9096
9097 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9098 //_syscmd(cmd, buf, sizeof(buf));
9099 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9100 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009101 if(strlen(buf) == 0) {
9102 *output_filterMode = 0;
9103 }
9104 else {
9105 int macaddr_acl_mode = strtol(buf, NULL, 10);
9106 if (macaddr_acl_mode == 1) {
9107 *output_filterMode = 1;
9108 } else if (macaddr_acl_mode == 0) {
9109 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9110 if (strlen(buf) == 0) {
9111 *output_filterMode = 0;
9112 } else {
9113 *output_filterMode = 2;
9114 }
9115 } else {
9116 return RETURN_ERR;
9117 }
9118 }
developer06a01d92022-09-07 16:32:39 +08009119
9120 return RETURN_OK;
9121}
9122
9123INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9124{
9125 FILE *fp = NULL;
9126 char str[MAX_BUF_SIZE] = {0};
9127 int wificlientindex = 0 ;
9128 int count = 0;
9129 int signalstrength = 0;
9130 int arr[MACADDRESS_SIZE] = {0};
9131 unsigned char mac[MACADDRESS_SIZE] = {0};
9132 UINT wifi_count = 0;
9133 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9134 char pipeCmd[MAX_CMD_SIZE] = {0};
9135
9136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9137 *output_array_size = 0;
9138 *associated_dev_array = NULL;
9139 char interface_name[50] = {0};
9140
9141 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9142 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9143 return RETURN_ERR;
9144 }
9145
9146 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9147 fp = popen(pipeCmd, "r");
9148 if (fp == NULL)
9149 {
9150 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9151 return RETURN_ERR;
9152 }
9153
9154 /* Read the output a line at a time - output it. */
9155 fgets(str, sizeof(str)-1, fp);
9156 wifi_count = (unsigned int) atoi ( str );
9157 *output_array_size = wifi_count;
9158 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9159 pclose(fp);
9160
9161 if(wifi_count == 0)
9162 {
9163 return RETURN_OK;
9164 }
9165 else
9166 {
9167 wifi_associated_dev2_t* temp = NULL;
9168 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9169 *associated_dev_array = temp;
9170 if(temp == NULL)
9171 {
9172 printf("Error Statement. Insufficient memory \n");
9173 return RETURN_ERR;
9174 }
9175
9176 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9177 system(pipeCmd);
9178
9179 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9180 if(fp == NULL)
9181 {
9182 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9183 return RETURN_ERR;
9184 }
9185 fclose(fp);
9186
developer30423732022-12-01 16:17:49 +08009187 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009188 fp = popen(pipeCmd, "r");
9189 if(fp)
9190 {
9191 for(count =0 ; count < wifi_count; count++)
9192 {
9193 fgets(str, MAX_BUF_SIZE, fp);
9194 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9195 {
9196 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9197 {
9198 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9199
9200 }
9201 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9202 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]);
9203 }
9204 temp[count].cli_AuthenticationState = 1; //TODO
9205 temp[count].cli_Active = 1; //TODO
9206 }
9207 pclose(fp);
9208 }
9209
9210 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009211 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 +08009212 fp = popen(pipeCmd, "r");
9213 if(fp)
9214 {
9215 pclose(fp);
9216 }
9217 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9218 if(fp)
9219 {
9220 for(count =0 ; count < wifi_count ;count++)
9221 {
9222 fgets(str, MAX_BUF_SIZE, fp);
9223 signalstrength = atoi(str);
9224 temp[count].cli_RSSI = signalstrength;
9225 }
9226 pclose(fp);
9227 }
9228
9229
9230 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009231 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 +08009232 fp = popen(pipeCmd, "r");
9233 if (fp)
9234 {
9235 pclose(fp);
9236 }
9237 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9238 if (fp)
9239 {
9240 for (count = 0; count < wifi_count; count++)
9241 {
9242 fgets(str, MAX_BUF_SIZE, fp);
9243 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9244 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9245 }
9246 pclose(fp);
9247 }
9248
9249 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009250 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 +08009251 fp = popen(pipeCmd, "r");
9252 if (fp)
9253 {
9254 pclose(fp);
9255 }
9256 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9257 if (fp)
9258 {
9259 for (count = 0; count < wifi_count; count++)
9260 {
9261 fgets(str, MAX_BUF_SIZE, fp);
9262 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9263 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9264 }
9265 pclose(fp);
9266 }
9267 }
9268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9269 return RETURN_OK;
9270
9271}
9272
9273INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9274{
9275#if 0
9276 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009277 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009278 _syscmd(cmd, buf, sizeof(buf));*/
9279
9280 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9281 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9282 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9283 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9284
9285 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.
9286 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].
9287 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].
9288 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].
9289 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9290 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9291
9292 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9293 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9294 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9295 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.
9296 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.
9297 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.
9298 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.
9299 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.
9300 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.
9301 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.
9302 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9303#endif
9304
9305 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009306 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009307 char pipeCmd[128] = {0};
9308 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009309 wifi_ssidTrafficStats2_t *out = output_struct;
9310
developerce736392022-09-13 15:24:34 +08009311 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009312 if (!output_struct)
9313 return RETURN_ERR;
9314
developerce736392022-09-13 15:24:34 +08009315 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009316 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009317 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009318 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009319
developer06a01d92022-09-07 16:32:39 +08009320 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009321 if (fp == NULL) {
9322 fprintf(stderr, "%s: popen failed\n", __func__);
9323 return RETURN_ERR;
9324 }
9325 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009326 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009327
developerce736392022-09-13 15:24:34 +08009328 if (strlen(str) == 0) // interface not exist
9329 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009330
developerce736392022-09-13 15:24:34 +08009331 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9332 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009333
developerce736392022-09-13 15:24:34 +08009334 memset(str, 0, sizeof(str));
9335 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009336 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009337 if (fp == NULL) {
9338 fprintf(stderr, "%s: popen failed\n", __func__);
9339 return RETURN_ERR;
9340 }
9341 fgets(str, sizeof(str), fp);
9342
9343 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9344 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009345 pclose(fp);
developerce736392022-09-13 15:24:34 +08009346
9347 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9348 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9349
9350 // Not supported
9351 output_struct->ssid_RetransCount = 0;
9352 output_struct->ssid_FailedRetransCount = 0;
9353 output_struct->ssid_RetryCount = 0;
9354 output_struct->ssid_MultipleRetryCount = 0;
9355 output_struct->ssid_ACKFailureCount = 0;
9356 output_struct->ssid_AggregatedPacketCount = 0;
9357
developer06a01d92022-09-07 16:32:39 +08009358 return RETURN_OK;
9359}
9360
9361//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).
9362INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9363{
9364 char output_val[16]={'\0'};
9365 char config_file[MAX_BUF_SIZE] = {0};
9366
9367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9368 if (!output)
9369 return RETURN_ERR;
9370 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9371 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9372
9373 if( strcmp(output_val,"1") == 0 )
9374 *output = TRUE;
9375 else
9376 *output = FALSE;
9377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9378
9379 return RETURN_OK;
9380}
9381
9382INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9383{
9384 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9385 char str[MAX_BUF_SIZE]={'\0'};
9386 char string[MAX_BUF_SIZE]={'\0'};
9387 char cmd[MAX_CMD_SIZE]={'\0'};
9388 char *ch;
9389 char config_file[MAX_BUF_SIZE] = {0};
9390 struct params params;
9391
9392 if(enable == TRUE)
9393 strcpy(string,"1");
9394 else
9395 strcpy(string,"0");
9396
9397 params.name = "ap_isolate";
9398 params.value = string;
9399
9400 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9401 wifi_hostapdWrite(config_file,&params,1);
9402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9403
9404 return RETURN_OK;
9405}
9406
9407INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9408{
9409 if (NULL == output_dBm)
9410 return RETURN_ERR;
9411
9412 *output_dBm = 0;
9413 return RETURN_OK;
9414}
9415
9416INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9417{
9418 return RETURN_OK;
9419}
9420INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9421{
9422 return RETURN_OK;
9423}
9424INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9425{
9426 return RETURN_OK;
9427}
9428INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9429{
9430 return RETURN_OK;
9431}
9432INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9433{
9434 return RETURN_OK;
9435}
9436INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9437{
9438 char config_file[MAX_BUF_SIZE] = {0};
9439 struct params list;
9440
9441 list.name = "bss_transition";
9442 list.value = activate?"1":"0";
9443 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9444 wifi_hostapdWrite(config_file, &list, 1);
9445
9446 return RETURN_OK;
9447}
9448wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9449
9450void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9451{
9452 return;
9453}
9454
9455INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9456{
9457 // TODO Implement me!
9458 return RETURN_OK;
9459}
9460
9461INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9462{
developera3c68b92022-09-13 15:27:29 +08009463 char file_name[128] = {0};
9464 char buf[128] = {0};
9465 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009466 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009467
9468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9469
developer804c64f2022-10-19 13:54:40 +08009470 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009471 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009472 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009473 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9474 f = fopen(file_name, "w");
9475 if (f == NULL)
9476 return RETURN_ERR;
9477 // For mode == 0 is to disable filter, just don't write to the file.
9478 if (mode)
9479 fprintf(f, "%s", essid);
9480
9481 fclose(f);
9482 }
9483 } else { // special case, need to set AP's SSID as filter for each radio.
9484 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9485 f = fopen(file_name, "w");
9486 if (f == NULL)
9487 return RETURN_ERR;
9488
9489 // For mode == 0 is to disable filter, just don't write to the file.
9490 if (mode)
9491 fprintf(f, "%s", essid);
9492
9493 fclose(f);
9494 }
9495
9496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009497 return RETURN_OK;
9498}
9499
9500INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9501{
9502 // TODO Implement me!
9503 //Apply wifi_pushRadioChannel() instantly
9504 return RETURN_ERR;
9505}
9506
9507INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9508{
9509 // TODO Implement me!
9510 return RETURN_OK;
9511}
9512
9513#ifdef HAL_NETLINK_IMPL
9514static int tidStats_callback(struct nl_msg *msg, void *arg) {
9515 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9516 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9517 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9518 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9519 int rem , tid_index = 0;
9520
9521 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9522 wifi_associated_dev_tid_entry_t *stats_entry;
9523
9524 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9525 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9526 };
9527 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9528 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9529 };
9530
9531 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9532 genlmsg_attrlen(gnlh, 0), NULL);
9533
9534
9535 if (!tb[NL80211_ATTR_STA_INFO]) {
9536 fprintf(stderr, "station stats missing!\n");
9537 return NL_SKIP;
9538 }
9539
9540 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9541 tb[NL80211_ATTR_STA_INFO],
9542 stats_policy)) {
9543 fprintf(stderr, "failed to parse nested attributes!\n");
9544 return NL_SKIP;
9545 }
9546
9547 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9548 {
9549 stats_entry = &out->tid_array[tid_index];
9550
9551 stats_entry->tid = tid_index;
9552 stats_entry->ac = _tid_ac_index_get[tid_index];
9553
9554 if(sinfo[NL80211_STA_INFO_TID_STATS])
9555 {
9556 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9557 printf("failed to parse nested stats attributes!");
9558 return NL_SKIP;
9559 }
9560 }
9561 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9562 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9563
9564 if(tid_index < (PS_MAX_TID - 1))
9565 tid_index++;
9566 }
9567 //ToDo: sum_time_ms, ewma_time_ms
9568 return NL_SKIP;
9569}
9570#endif
9571
9572INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9573{
9574#ifdef HAL_NETLINK_IMPL
9575 Netlink nl;
9576 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009577 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009578
developerac6f1142022-12-20 19:26:35 +08009579 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009580 return RETURN_ERR;
9581
9582 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009583
9584 nl.id = initSock80211(&nl);
9585
9586 if (nl.id < 0) {
9587 fprintf(stderr, "Error initializing netlink \n");
9588 return -1;
9589 }
9590
9591 struct nl_msg* msg = nlmsg_alloc();
9592
9593 if (!msg) {
9594 fprintf(stderr, "Failed to allocate netlink message.\n");
9595 nlfree(&nl);
9596 return -2;
9597 }
9598
9599 genlmsg_put(msg,
9600 NL_AUTO_PORT,
9601 NL_AUTO_SEQ,
9602 nl.id,
9603 0,
9604 0,
9605 NL80211_CMD_GET_STATION,
9606 0);
9607
9608 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9609 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9610 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9611 nl_send_auto(nl.socket, msg);
9612 nl_recvmsgs(nl.socket, nl.cb);
9613 nlmsg_free(msg);
9614 nlfree(&nl);
9615 return RETURN_OK;
9616#else
9617//iw implementation
9618#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9619#define TOTAL_MAX_LINES 50
9620
9621 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009622 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009623 FILE *fp=NULL;
9624 char pipeCmd[1024]= {'\0'};
9625 int lines,tid_index=0;
9626 char mac_addr[20] = {'\0'};
9627
developerac6f1142022-12-20 19:26:35 +08009628 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009629 return RETURN_ERR;
9630
developer06a01d92022-09-07 16:32:39 +08009631 wifi_associated_dev_tid_entry_t *stats_entry;
9632
developer06a01d92022-09-07 16:32:39 +08009633 strcpy(mac_addr,clientMacAddress);
9634
9635 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9636 fp= popen(pipeCmd,"r");
9637 if(fp == NULL)
9638 {
9639 perror("popen for station dump failed\n");
9640 return RETURN_ERR;
9641 }
9642 pclose(fp);
9643
9644 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9645 fp=popen(pipeCmd,"r");
9646 if(fp == NULL)
9647 {
9648 perror("popen for grep station failed\n");
9649 return RETURN_ERR;
9650 }
9651 else if(fgets(buf,sizeof(buf),fp) != NULL)
9652 lines=atoi(buf);
9653 else
9654 {
9655 pclose(fp);
9656 fprintf(stderr,"No devices are connected \n");
9657 return RETURN_ERR;
9658 }
9659 pclose(fp);
9660
9661 if(lines == 1)
9662 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9663
9664 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9665 {
9666 stats_entry = &tid_stats->tid_array[tid_index];
9667 stats_entry->tid = tid_index;
9668
9669 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);
9670
9671 fp=popen(pipeCmd,"r");
9672 if(fp ==NULL)
9673 {
9674 perror("Failed to read from tid file \n");
9675 return RETURN_ERR;
9676 }
9677 else if(fgets(buf,sizeof(buf),fp) != NULL)
9678 stats_entry->num_msdus = atol(buf);
9679
9680 pclose(fp);
9681 stats_entry->ac = _tid_ac_index_get[tid_index];
9682// TODO:
9683// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9684// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9685 }
9686 return RETURN_OK;
9687#endif
9688}
9689
9690
9691INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9692{
developerd946fd62022-12-08 18:03:28 +08009693 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009694 char cmd[128]={0};
9695 char buf[128]={0};
9696 int freq = 0;
9697
9698 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9699
9700 // full mode is used to scan all channels.
9701 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9702 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9703 ieee80211_channel_to_frequency(chan_list[0], &freq);
9704
developerac6f1142022-12-20 19:26:35 +08009705 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009706 return RETURN_ERR;
9707
developer615510b2022-09-27 10:14:35 +08009708 if (freq)
developerd946fd62022-12-08 18:03:28 +08009709 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009710 else
developerd946fd62022-12-08 18:03:28 +08009711 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009712
9713 _syscmd(cmd, buf, sizeof(buf));
9714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9715
developer06a01d92022-09-07 16:32:39 +08009716 return RETURN_OK;
9717}
9718
9719
9720INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9721{
9722 // TODO Implement me!
9723 return RETURN_ERR;
9724}
9725
9726INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9727{
9728 // TODO Implement me!
9729 return RETURN_ERR;
9730}
9731
9732INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9733{
9734 // TODO Implement me!
9735 return RETURN_ERR;
9736}
9737
9738INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9739{
9740 // TODO Implement me!
9741 return RETURN_ERR;
9742}
9743
9744INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9745{
9746 // TODO Implement me!
9747 return RETURN_ERR;
9748}
9749
9750INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9751{
9752 // TODO Implement me!
9753 return RETURN_ERR;
9754}
9755
9756INT wifi_steering_eventUnregister(void)
9757{
9758 // TODO Implement me!
9759 return RETURN_ERR;
9760}
9761
9762INT wifi_delApAclDevices(INT apIndex)
9763{
9764#if 0
9765 char cmd[MAX_BUF_SIZE] = {0};
9766 char buf[MAX_BUF_SIZE] = {0};
9767
9768 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +08009769 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +08009770 if(_syscmd(cmd,buf,sizeof(buf)))
9771 return RETURN_ERR;
9772#endif
developere6aafda2022-09-13 14:59:28 +08009773 char cmd[MAX_CMD_SIZE]={0};
9774 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009775
developere6aafda2022-09-13 14:59:28 +08009776 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9777 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9778 if(_syscmd(cmd, buf, sizeof(buf)))
9779 return RETURN_ERR;
9780 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009781
9782 return RETURN_OK;
9783}
9784
9785#ifdef HAL_NETLINK_IMPL
9786static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9787 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9788 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9789 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9790 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9791 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9792 char mac_addr[20],dev[20];
9793
9794 nla_parse(tb,
9795 NL80211_ATTR_MAX,
9796 genlmsg_attrdata(gnlh, 0),
9797 genlmsg_attrlen(gnlh, 0),
9798 NULL);
9799
9800 if(!tb[NL80211_ATTR_STA_INFO]) {
9801 fprintf(stderr, "sta stats missing!\n");
9802 return NL_SKIP;
9803 }
9804
9805 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9806 fprintf(stderr, "failed to parse nested attributes!\n");
9807 return NL_SKIP;
9808 }
9809 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9810
9811 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9812
9813 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9814 fprintf(stderr, "failed to parse nested rate attributes!");
9815 return NL_SKIP;
9816 }
9817
9818 if(sinfo[NL80211_STA_INFO_TID_STATS])
9819 {
9820 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9821 printf("failed to parse nested stats attributes!");
9822 return NL_SKIP;
9823 }
9824 }
9825
9826 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9827 {
9828 printf("Type is VHT\n");
9829 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9830 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9831
9832 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9833 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9834 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9835 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9836 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9837 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9838 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9839 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9840 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9841 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9842 }
9843 else
9844 {
9845 printf(" OFDM or CCK \n");
9846 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9847 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9848 }
9849
9850 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9851 if(rinfo[NL80211_RATE_INFO_MCS])
9852 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9853 }
9854 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9855 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9856 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9857 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9858
9859 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9860 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9861
9862 if (sinfo[NL80211_STA_INFO_SIGNAL])
9863 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9864 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9865 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9866 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9867 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9868 //rssi_array need to be filled
9869 return NL_SKIP;
9870}
9871#endif
9872
9873INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9874{
9875#ifdef HAL_NETLINK_IMPL
9876 Netlink nl;
developerd946fd62022-12-08 18:03:28 +08009877 char if_name[32];
developerac6f1142022-12-20 19:26:35 +08009878 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009879 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009880
9881 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9882
9883 if (*output_array_size <= 0)
9884 return RETURN_OK;
9885
developer06a01d92022-09-07 16:32:39 +08009886 nl.id = initSock80211(&nl);
9887
9888 if (nl.id < 0) {
9889 fprintf(stderr, "Error initializing netlink \n");
9890 return 0;
9891 }
9892
9893 struct nl_msg* msg = nlmsg_alloc();
9894
9895 if (!msg) {
9896 fprintf(stderr, "Failed to allocate netlink message.\n");
9897 nlfree(&nl);
9898 return 0;
9899 }
9900
9901 genlmsg_put(msg,
9902 NL_AUTO_PORT,
9903 NL_AUTO_SEQ,
9904 nl.id,
9905 0,
9906 0,
9907 NL80211_CMD_GET_STATION,
9908 0);
9909
9910 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9911 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9912 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9913 nl_send_auto(nl.socket, msg);
9914 nl_recvmsgs(nl.socket, nl.cb);
9915 nlmsg_free(msg);
9916 nlfree(&nl);
9917 return RETURN_OK;
9918#else
9919 //TODO Implement me
9920 return RETURN_OK;
9921#endif
9922}
9923
9924#ifdef HAL_NETLINK_IMPL
9925static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9926 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9927 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9928 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9929 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9930 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9931 char mac_addr[20],dev[20];
9932
9933 nla_parse(tb,
9934 NL80211_ATTR_MAX,
9935 genlmsg_attrdata(gnlh, 0),
9936 genlmsg_attrlen(gnlh, 0),
9937 NULL);
9938
9939 if(!tb[NL80211_ATTR_STA_INFO]) {
9940 fprintf(stderr, "sta stats missing!\n");
9941 return NL_SKIP;
9942 }
9943
9944 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9945 fprintf(stderr, "failed to parse nested attributes!\n");
9946 return NL_SKIP;
9947 }
9948
9949 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9950
9951 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9952
9953 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9954 fprintf(stderr, "failed to parse nested rate attributes!");
9955 return NL_SKIP;
9956 }
9957
9958 if(sinfo[NL80211_STA_INFO_TID_STATS])
9959 {
9960 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9961 printf("failed to parse nested stats attributes!");
9962 return NL_SKIP;
9963 }
9964 }
9965 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9966 {
9967 printf("Type is VHT\n");
9968 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9969 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9970
9971 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9972 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9973 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9974 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9975 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9976 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9977 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9978 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9979 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9980 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9981 }
9982 else
9983 {
9984 printf(" OFDM or CCK \n");
9985 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9986 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9987 }
9988
9989 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9990 if(rinfo[NL80211_RATE_INFO_MCS])
9991 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9992 }
9993
9994 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9995 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9996 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9997 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9998
9999 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10000 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10001 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10002
10003 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10004 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10005
10006 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10007 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10008
10009 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10010 ((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]);
10011
10012 return NL_SKIP;
10013}
10014#endif
10015
10016INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10017{
10018#ifdef HAL_NETLINK_IMPL
10019 Netlink nl;
10020 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010021 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010022 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010023 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010024
10025 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10026
10027 if (*output_array_size <= 0)
10028 return RETURN_OK;
10029
developerd946fd62022-12-08 18:03:28 +080010030 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010031
10032 nl.id = initSock80211(&nl);
10033
10034 if(nl.id < 0) {
10035 fprintf(stderr, "Error initializing netlink \n");
10036 return 0;
10037 }
10038
10039 struct nl_msg* msg = nlmsg_alloc();
10040
10041 if(!msg) {
10042 fprintf(stderr, "Failed to allocate netlink message.\n");
10043 nlfree(&nl);
10044 return 0;
10045 }
10046
10047 genlmsg_put(msg,
10048 NL_AUTO_PORT,
10049 NL_AUTO_SEQ,
10050 nl.id,
10051 0,
10052 0,
10053 NL80211_CMD_GET_STATION,
10054 0);
10055
10056 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10057 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10058 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10059 nl_send_auto(nl.socket, msg);
10060 nl_recvmsgs(nl.socket, nl.cb);
10061 nlmsg_free(msg);
10062 nlfree(&nl);
10063 return RETURN_OK;
10064#else
10065 //TODO Implement me
10066 return RETURN_OK;
10067#endif
10068}
10069
10070INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10071{
10072 // TODO Implement me!
10073 char buf[MAX_BUF_SIZE] = {0};
10074 char config_file[MAX_BUF_SIZE] = {0};
10075
10076 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10077 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10078 *activate = (strncmp("1",buf,1) == 0);
10079
10080 return RETURN_OK;
10081}
10082
10083INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10084{
10085 char config_file[MAX_BUF_SIZE] = {0};
10086 struct params list;
10087
10088 list.name = "rrm_neighbor_report";
10089 list.value = activate?"1":"0";
10090 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10091 wifi_hostapdWrite(config_file, &list, 1);
10092
10093 return RETURN_OK;
10094}
10095
10096INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10097{
10098 char buf[32] = {0};
10099 char config_file[MAX_BUF_SIZE] = {0};
10100
10101 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10102 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10103 *activate = (strncmp("1",buf,1) == 0);
10104
10105 return RETURN_OK;
10106}
10107#undef HAL_NETLINK_IMPL
10108#ifdef HAL_NETLINK_IMPL
10109static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10110 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10111 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10112 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10113 char dev[20];
10114 int freq =0 ;
10115 static int i=0;
10116
10117 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10118
10119 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10120 };
10121
10122 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10123
10124 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10125
10126 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10127 fprintf(stderr, "survey data missing!\n");
10128 return NL_SKIP;
10129 }
10130
10131 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10132 {
10133 fprintf(stderr, "failed to parse nested attributes!\n");
10134 return NL_SKIP;
10135 }
10136
10137
10138 if(out[0].array_size == 1 )
10139 {
10140 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10141 {
10142 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10143 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10144 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10145
10146 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10147 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10148 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10149 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10150 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10151 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10152 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10153 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10154 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10155 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10156 if (sinfo[NL80211_SURVEY_INFO_TIME])
10157 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10158 return NL_STOP;
10159 }
10160 }
10161 else
10162 {
10163 if ( i <= out[0].array_size )
10164 {
10165 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10166 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10167 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10168
10169 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10170 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10171 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10172 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10173 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10174 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10175 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10176 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10177 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10178 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10179 if (sinfo[NL80211_SURVEY_INFO_TIME])
10180 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10181 }
10182 }
10183
10184 i++;
10185 return NL_SKIP;
10186}
10187#endif
10188
10189static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10190{
10191 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10192 FILE *fp;
10193
10194 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10195 {
10196 printf("Creating Frequency-Channel Map\n");
10197 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10198 }
10199 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10200 if((fp = popen(command, "r")))
10201 {
10202 fgets(output, sizeof(output), fp);
10203 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010204 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010205 }
10206
10207 return 0;
10208}
10209
10210static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10211{
10212 int freqMHz = -1;
10213 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010214 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010215
10216 ieee80211_channel_to_frequency(channel, &freqMHz);
10217 if (freqMHz == -1) {
10218 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10219 return -1;
10220 }
10221
developer7930d352022-12-21 17:55:42 +080010222 wifi_GetInterfaceName(radioIndex, interface_name);
10223 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010224 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10225 radioIndex, freqMHz);
10226 return -1;
10227 }
10228
10229 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10230 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10231 return -1;
10232 }
10233
10234 return 0;
10235}
10236
10237static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10238{
10239 const char *ptr = buf;
10240 char *key = NULL;
10241 char *val = NULL;
10242 char line[256] = { '\0' };
10243
10244 while (ptr = get_line_from_str_buf(ptr, line)) {
10245 if (strstr(line, "Frequency")) continue;
10246
10247 key = strtok(line, ":");
10248 val = strtok(NULL, " ");
10249 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10250
10251 if (!strcmp(key, "noise")) {
10252 sscanf(val, "%d", &stats->ch_noise);
10253 if (stats->ch_noise == 0) {
10254 // Workaround for missing noise information.
10255 // Assume -95 for 2.4G and -103 for 5G
10256 if (radioIndex == 0) stats->ch_noise = -95;
10257 if (radioIndex == 1) stats->ch_noise = -103;
10258 }
10259 }
10260 else if (!strcmp(key, "channel active time")) {
10261 sscanf(val, "%llu", &stats->ch_utilization_total);
10262 }
10263 else if (!strcmp(key, "channel busy time")) {
10264 sscanf(val, "%llu", &stats->ch_utilization_busy);
10265 }
10266 else if (!strcmp(key, "channel receive time")) {
10267 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10268 }
10269 else if (!strcmp(key, "channel transmit time")) {
10270 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10271 }
10272 };
10273
10274 return 0;
10275}
10276
10277INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10278{
10279 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10280#ifdef HAL_NETLINK_IMPL
10281 Netlink nl;
10282 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010283 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010284
10285 local[0].array_size = array_size;
10286
developerac6f1142022-12-20 19:26:35 +080010287 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010288 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010289
10290 nl.id = initSock80211(&nl);
10291
10292 if (nl.id < 0) {
10293 fprintf(stderr, "Error initializing netlink \n");
10294 return -1;
10295 }
10296
10297 struct nl_msg* msg = nlmsg_alloc();
10298
10299 if (!msg) {
10300 fprintf(stderr, "Failed to allocate netlink message.\n");
10301 nlfree(&nl);
10302 return -2;
10303 }
10304
10305 genlmsg_put(msg,
10306 NL_AUTO_PORT,
10307 NL_AUTO_SEQ,
10308 nl.id,
10309 0,
10310 NLM_F_DUMP,
10311 NL80211_CMD_GET_SURVEY,
10312 0);
10313
10314 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10315 nl_send_auto(nl.socket, msg);
10316 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10317 nl_recvmsgs(nl.socket, nl.cb);
10318 nlmsg_free(msg);
10319 nlfree(&nl);
10320 //Copying the Values
10321 for(int i=0;i<array_size;i++)
10322 {
10323 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10324 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10325 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10326 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10327 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10328 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10329 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10330 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10331 }
10332#else
10333 ULONG channel = 0;
10334 int i;
10335 int number_of_channels = array_size;
10336 char buf[512];
10337 INT ret;
10338 wifi_channelStats_t tmp_stats;
10339
10340 if (number_of_channels == 0) {
10341 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10342 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10343 return RETURN_ERR;
10344 }
10345 number_of_channels = 1;
10346 input_output_channelStats_array[0].ch_number = channel;
10347 }
10348
10349 for (i = 0; i < number_of_channels; i++) {
10350
10351 input_output_channelStats_array[i].ch_noise = 0;
10352 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10353 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10354 input_output_channelStats_array[i].ch_utilization_busy = 0;
10355 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10356 input_output_channelStats_array[i].ch_utilization_total = 0;
10357
10358 memset(buf, 0, sizeof(buf));
10359 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10360 return RETURN_ERR;
10361 }
10362 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10363 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10364 return RETURN_ERR;
10365 }
10366
10367 // XXX: fake missing 'self' counter which is not available in iw survey output
10368 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10369 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10370
10371 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10372 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10373 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10374 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10375 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10376
10377 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",
10378 __func__,
10379 input_output_channelStats_array[i].ch_number,
10380 input_output_channelStats_array[i].ch_noise,
10381 input_output_channelStats_array[i].ch_utilization_total,
10382 input_output_channelStats_array[i].ch_utilization_busy,
10383 input_output_channelStats_array[i].ch_utilization_busy_rx,
10384 input_output_channelStats_array[i].ch_utilization_busy_tx,
10385 input_output_channelStats_array[i].ch_utilization_busy_self,
10386 input_output_channelStats_array[i].ch_utilization_busy_ext);
10387 }
10388#endif
10389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10390 return RETURN_OK;
10391}
10392#define HAL_NETLINK_IMPL
10393
10394/* Hostapd events */
10395
10396#ifndef container_of
10397#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10398#define container_of(ptr, type, member) \
10399 ((type *)((char *)ptr - offset_of(type, member)))
10400#endif /* container_of */
10401
10402struct ctrl {
10403 char sockpath[128];
10404 char sockdir[128];
10405 char bss[IFNAMSIZ];
10406 char reply[4096];
10407 int ssid_index;
10408 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10409 void (*overrun)(struct ctrl *ctrl);
10410 struct wpa_ctrl *wpa;
10411 unsigned int ovfl;
10412 size_t reply_len;
10413 int initialized;
10414 ev_timer retry;
10415 ev_timer watchdog;
10416 ev_stat stat;
10417 ev_io io;
10418};
10419static wifi_newApAssociatedDevice_callback clients_connect_cb;
10420static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10421static struct ctrl wpa_ctrl[MAX_APS];
10422static int initialized;
10423
10424static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10425{
10426 char cbuf[256] = {};
10427 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10428 struct cmsghdr *cmsg;
10429 unsigned int ovfl = ctrl->ovfl;
10430 unsigned int drop;
10431
10432 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10433 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10434 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10435 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10436
10437 drop = ovfl - ctrl->ovfl;
10438 ctrl->ovfl = ovfl;
10439
10440 return drop;
10441}
10442
10443static void ctrl_close(struct ctrl *ctrl)
10444{
10445 if (ctrl->io.cb)
10446 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10447 if (ctrl->retry.cb)
10448 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10449 if (!ctrl->wpa)
10450 return;
10451
10452 wpa_ctrl_detach(ctrl->wpa);
10453 wpa_ctrl_close(ctrl->wpa);
10454 ctrl->wpa = NULL;
10455 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10456}
10457
10458static void ctrl_process(struct ctrl *ctrl)
10459{
10460 const char *str;
10461 int drops;
10462 int level;
10463 int err;
10464
10465 /* Example events:
10466 *
10467 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10468 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10469 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10470 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10471 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10472 */
10473 if (!(str = index(ctrl->reply, '>')))
10474 return;
10475 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10476 return;
10477
10478 str++;
10479
10480 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10481 if (!(str = index(ctrl->reply, ' ')))
10482 return;
10483 wifi_associated_dev_t sta;
10484 memset(&sta, 0, sizeof(sta));
10485
10486 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10487 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10488 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10489
10490 sta.cli_Active=true;
10491
10492 (clients_connect_cb)(ctrl->ssid_index, &sta);
10493 goto handled;
10494 }
10495
10496 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10497 if (!(str = index(ctrl->reply, ' ')))
10498 return;
10499
10500 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10501 goto handled;
10502 }
10503
10504 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10505 printf("CTRL_WPA: handle TERMINATING event\n");
10506 goto retry;
10507 }
10508
10509 if (strncmp("AP-DISABLED", str, 11) == 0) {
10510 printf("CTRL_WPA: handle AP-DISABLED\n");
10511 goto retry;
10512 }
10513
10514 printf("Event not supported!!\n");
10515
10516handled:
10517
10518 if ((drops = ctrl_get_drops(ctrl))) {
10519 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10520 if (ctrl->overrun)
10521 ctrl->overrun(ctrl);
10522 }
10523
10524 return;
10525
10526retry:
10527 printf("WPA_CTRL: closing\n");
10528 ctrl_close(ctrl);
10529 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10530 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10531}
10532
10533static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10534{
10535 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10536 int err;
10537
10538 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10539 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10540 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10541 ctrl->reply[ctrl->reply_len] = 0;
10542 if (err < 0) {
10543 if (errno == EAGAIN || errno == EWOULDBLOCK)
10544 return;
10545 ctrl_close(ctrl);
10546 ev_timer_again(EV_A_ &ctrl->retry);
10547 return;
10548 }
10549
10550 ctrl_process(ctrl);
10551}
10552
10553static int ctrl_open(struct ctrl *ctrl)
10554{
10555 int fd;
10556
10557 if (ctrl->wpa)
10558 return 0;
10559
10560 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10561 if (!ctrl->wpa)
10562 goto err;
10563
10564 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10565 goto err_close;
10566
10567 fd = wpa_ctrl_get_fd(ctrl->wpa);
10568 if (fd < 0)
10569 goto err_detach;
10570
10571 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10572 goto err_detach;
10573
10574 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10575 ev_io_start(EV_DEFAULT_ &ctrl->io);
10576
10577 return 0;
10578
10579err_detach:
10580 wpa_ctrl_detach(ctrl->wpa);
10581err_close:
10582 wpa_ctrl_close(ctrl->wpa);
10583err:
10584 ctrl->wpa = NULL;
10585 return -1;
10586}
10587
10588static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10589{
10590 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10591
10592 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10593 ctrl_open(ctrl);
10594}
10595
10596static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10597{
10598 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10599
10600 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10601 if (ctrl_open(ctrl) == 0) {
10602 printf("WPA_CTRL: retry successful\n");
10603 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10604 }
10605}
10606
10607int ctrl_enable(struct ctrl *ctrl)
10608{
10609 if (ctrl->wpa)
10610 return 0;
10611
10612 if (!ctrl->stat.cb) {
10613 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10614 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10615 }
10616
10617 if (!ctrl->retry.cb) {
10618 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10619 }
10620
10621 return ctrl_open(ctrl);
10622}
10623
10624static void
10625ctrl_msg_cb(char *buf, size_t len)
10626{
10627 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10628
10629 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10630 ctrl_process(ctrl);
10631}
10632
10633static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10634{
10635 int err;
10636
10637 if (!ctrl->wpa)
10638 return -1;
10639 if (*reply_len < 2)
10640 return -1;
10641
10642 (*reply_len)--;
10643 ctrl->reply_len = sizeof(ctrl->reply);
10644 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10645 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10646 if (err < 0)
10647 return err;
10648
10649 if (ctrl->reply_len > *reply_len)
10650 ctrl->reply_len = *reply_len;
10651
10652 *reply_len = ctrl->reply_len;
10653 memcpy(reply, ctrl->reply, *reply_len);
10654 reply[*reply_len - 1] = 0;
10655 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10656 return 0;
10657}
10658
10659static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10660{
10661 const char *pong = "PONG";
10662 const char *ping = "PING";
10663 char reply[1024];
10664 size_t len = sizeof(reply);
10665 int err;
10666 ULONG s, snum;
10667 INT ret;
10668 BOOL status;
10669
10670 printf("WPA_CTRL: watchdog cb\n");
10671
10672 ret = wifi_getSSIDNumberOfEntries(&snum);
10673 if (ret != RETURN_OK) {
10674 printf("%s: failed to get SSID count", __func__);
10675 return;
10676 }
10677
10678 if (snum > MAX_APS) {
10679 printf("more ssid than supported! %lu\n", snum);
10680 return;
10681 }
10682
10683 for (s = 0; s < snum; s++) {
10684 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010685 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010686 continue;
10687 }
10688 if (status == false) continue;
10689
10690 memset(reply, 0, sizeof(reply));
10691 len = sizeof(reply);
10692 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10693 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10694 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10695 continue;
10696
10697 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10698 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010699 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010700 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10701 }
10702}
10703
10704static int init_wpa()
10705{
10706 int ret = 0, i = 0;
10707 ULONG s, snum;
10708
10709 ret = wifi_getSSIDNumberOfEntries(&snum);
10710 if (ret != RETURN_OK) {
10711 printf("%s: failed to get SSID count", __func__);
10712 return RETURN_ERR;
10713 }
10714
10715 if (snum > MAX_APS) {
10716 printf("more ssid than supported! %lu\n", snum);
10717 return RETURN_ERR;
10718 }
10719
10720 for (s = 0; s < snum; s++) {
10721 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10722 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10723 wpa_ctrl[s].ssid_index = s;
10724 ctrl_enable(&wpa_ctrl[s]);
10725 }
10726
10727 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10728 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10729
10730 initialized = 1;
10731 printf("WPA_CTRL: initialized\n");
10732
10733 return RETURN_OK;
10734}
10735
10736void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10737{
10738 clients_connect_cb = callback_proc;
10739 if (!initialized)
10740 init_wpa();
10741}
10742
10743void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10744{
10745 clients_disconnect_cb = callback_proc;
10746 if (!initialized)
10747 init_wpa();
10748}
10749
10750INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10751{
10752 // TODO Implement me!
10753 return RETURN_ERR;
10754}
10755
10756INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10757{
10758 // TODO Implement me!
10759 return RETURN_ERR;
10760}
10761
10762INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10763{
10764 int i;
10765 char cmd[256];
10766 char channel_numbers_buf[256];
10767 char dfs_state_buf[256];
10768 char line[256];
10769 const char *ptr;
10770
10771 memset(cmd, 0, sizeof(cmd));
10772 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10773 memset(line, 0, sizeof(line));
10774 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10775 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10776
10777 if (radioIndex == 0) { // 2.4G - all allowed
10778 if (outputMapSize < 11) {
10779 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10780 return RETURN_ERR;
10781 }
10782
10783 for (i = 0; i < 11; i++) {
10784 outputMap[i].ch_number = i + 1;
10785 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10786 }
10787
10788 return RETURN_OK;
10789 }
10790
10791 if (radioIndex == 1) { // 5G
10792// Example output of iw list:
10793//
10794// Frequencies:
10795// * 5180 MHz [36] (17.0 dBm)
10796// * 5200 MHz [40] (17.0 dBm)
10797// * 5220 MHz [44] (17.0 dBm)
10798// * 5240 MHz [48] (17.0 dBm)
10799// * 5260 MHz [52] (23.0 dBm) (radar detection)
10800// DFS state: usable (for 78930 sec)
10801// DFS CAC time: 60000 ms
10802// * 5280 MHz [56] (23.0 dBm) (radar detection)
10803// DFS state: usable (for 78930 sec)
10804// DFS CAC time: 60000 ms
10805// * 5300 MHz [60] (23.0 dBm) (radar detection)
10806// DFS state: usable (for 78930 sec)
10807// DFS CAC time: 60000 ms
10808// * 5320 MHz [64] (23.0 dBm) (radar detection)
10809// DFS state: usable (for 78930 sec)
10810// DFS CAC time: 60000 ms
10811// * 5500 MHz [100] (disabled)
10812// * 5520 MHz [104] (disabled)
10813// * 5540 MHz [108] (disabled)
10814// * 5560 MHz [112] (disabled)
10815//
10816// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10817 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10818 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10819 return RETURN_ERR;
10820 }
10821
10822 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10823 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10824 return RETURN_ERR;
10825 }
10826
10827 ptr = channel_numbers_buf;
10828 i = 0;
10829 while (ptr = get_line_from_str_buf(ptr, line)) {
10830 if (i >= outputMapSize) {
10831 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10832 return RETURN_ERR;
10833 }
10834 sscanf(line, "%d", &outputMap[i].ch_number);
10835
10836 memset(cmd, 0, sizeof(cmd));
10837 // Below command should fetch string for DFS state (usable, available or unavailable)
10838 // Example line: "DFS state: usable (for 78930 sec)"
10839 if (sprintf(cmd,"iw list | grep -A 2 '\\[%d\\]' | tr -d '\\t' | grep 'DFS state' | awk '{print $3}' | tr -d '\\n'", outputMap[i].ch_number) < 0) {
10840 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10841 return RETURN_ERR;
10842 }
10843
10844 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10845 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10846 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10847 return RETURN_ERR;
10848 }
10849
10850 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10851
10852 if (!strcmp(dfs_state_buf, "usable")) {
10853 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10854 } else if (!strcmp(dfs_state_buf, "available")) {
10855 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10856 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10857 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10858 } else {
10859 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10860 }
10861 i++;
10862 }
10863
10864 return RETURN_OK;
10865 }
10866
10867 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10868 return RETURN_ERR;
10869}
10870
10871INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10872{
10873 // TODO Implement me!
10874 return RETURN_ERR;
10875}
10876
10877INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10878{
10879 return RETURN_OK;
10880}
10881
10882INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10883{
10884 // TODO Implement me!
10885 return RETURN_ERR;
10886}
10887
10888INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10889{
10890 // TODO API refrence Implementaion is present on RPI hal
10891 return RETURN_ERR;
10892}
10893
10894INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10895{
developerd946fd62022-12-08 18:03:28 +080010896 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080010897 char cmd[128]={'\0'};
10898 char buf[128]={'\0'};
10899 char *support;
10900 int maximum_tx = 0, current_tx = 0;
10901
10902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10903 if(txpwr_pcntg == NULL)
10904 return RETURN_ERR;
10905
developerac6f1142022-12-20 19:26:35 +080010906 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010907 return RETURN_ERR;
10908
developera5005b62022-09-13 15:43:35 +080010909 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080010910 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 +080010911 _syscmd(cmd, buf, sizeof(buf));
10912 maximum_tx = strtol(buf, NULL, 10);
10913
10914 // Get the current tx power
10915 memset(cmd, 0, sizeof(cmd));
10916 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080010917 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 +080010918 _syscmd(cmd, buf, sizeof(buf));
10919 current_tx = strtol(buf, NULL, 10);
10920
10921 // Get the power supported list and find the current power percentage in supported list
10922 memset(buf, 0, sizeof(buf));
10923 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10924 support = strtok(buf, ",");
10925 while(true)
10926 {
10927 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 +080010928 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010929 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010930 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010931 }
10932 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10933 if (tmp == current_tx) {
10934 *txpwr_pcntg = strtol(support, NULL, 10);
10935 break;
10936 }
10937 support = strtok(NULL, ",");
10938 }
10939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010940 return RETURN_OK;
10941}
10942
10943INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10944{
developer58599c22022-09-13 16:40:34 +080010945 // TODO precac feature.
10946 struct params params = {0};
10947 char config_file[128] = {0};
10948
10949 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10950
10951 params.name = "enable_background_radar";
10952 params.value = enable?"1":"0";
10953 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10954 wifi_hostapdWrite(config_file, &params, 1);
10955 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10956
10957 /* TODO precac feature */
10958
10959 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10960 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010961}
10962
10963INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10964{
developer58599c22022-09-13 16:40:34 +080010965 char config_file[128] = {0};
10966 char buf[64] = {0};
10967
10968 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10969 if (NULL == enable || NULL == precac)
10970 return RETURN_ERR;
10971
10972 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10973 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10974 if (strncmp(enable, "1", 1) == 0)
10975 *enable = true;
10976 else
10977 *enable = false;
10978
10979 /* TODO precac feature */
10980
10981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10982 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010983}
10984
10985INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10986{
developer58599c22022-09-13 16:40:34 +080010987 *supported = TRUE;
10988 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010989}
10990
developer3e6b1692022-09-30 18:04:05 +080010991INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10992{
10993 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10994 struct params params = {0};
10995 char config_file[64] = {0};
10996 char buf[64] = {0};
10997 unsigned int set_mu_type = 0;
10998 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10999
11000 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11001 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11002
11003 if (strlen(buf) > 0)
11004 set_mu_type = strtol(buf, NULL, 10);
11005
11006 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11007 set_mu_type &= ~0x05; // unset bit 0, 2
11008 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11009 set_mu_type |= 0x01;
11010 set_mu_type &= ~0x04;
11011 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11012 set_mu_type &= ~0x01;
11013 set_mu_type |= 0x04;
11014 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11015 set_mu_type |= 0x05; // set bit 0, 2
11016 }
11017
11018 params.name = "hemu_onoff";
11019 sprintf(buf, "%u", set_mu_type);
11020 params.value = buf;
11021 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11022 wifi_hostapdWrite(config_file, &params, 1);
11023 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11024
11025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11026 return RETURN_OK;
11027}
11028
11029INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11030{
11031 struct params params={0};
11032 char config_file[64] = {0};
11033 char buf[64] = {0};
11034 unsigned int get_mu_type = 0;
11035
11036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11037
11038 if (mu_type == NULL)
11039 return RETURN_ERR;
11040
11041 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11042 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11043 get_mu_type = strtol(buf, NULL, 10);
11044
11045 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11046 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11047 else if (get_mu_type & 0x04)
11048 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11049 else if (get_mu_type & 0x01)
11050 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11051 else
11052 *mu_type = WIFI_DL_MU_TYPE_NONE;
11053
11054 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11055 return RETURN_OK;
11056}
11057
11058INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11059{
11060 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11061 struct params params={0};
11062 char config_file[64] = {0};
11063 char buf[64] = {0};
11064 unsigned int set_mu_type = 0;
11065 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11066
11067 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11068 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11069
11070 if (strlen(buf) > 0)
11071 set_mu_type = strtol(buf, NULL, 10);
11072
11073 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11074 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11075 set_mu_type &= ~0x0a;
11076 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11077 set_mu_type |= 0x02;
11078 set_mu_type &= ~0x08;
11079 }
11080
11081 params.name = "hemu_onoff";
11082 sprintf(buf, "%u", set_mu_type);
11083 params.value = buf;
11084 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11085 wifi_hostapdWrite(config_file, &params, 1);
11086 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11087
11088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11089 return RETURN_OK;
11090}
11091
11092INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11093{
11094 struct params params={0};
11095 char config_file[64] = {0};
11096 char buf[64] = {0};
11097 unsigned int get_mu_type = 0;
11098
11099 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11100
11101 if (mu_type == NULL)
11102 return RETURN_ERR;
11103
11104 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11105 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11106
11107 get_mu_type = strtol(buf, NULL, 10);
11108 if (get_mu_type & 0x02)
11109 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11110 else
11111 *mu_type = WIFI_DL_MU_TYPE_NONE;
11112
11113 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11114 return RETURN_OK;
11115}
11116
11117
developer454b9462022-09-13 15:29:16 +080011118INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11119{
11120 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011121 char buf[256] = {0};
11122 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011123 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011124 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011125 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011126 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011127
11128 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11129
developer254882b2022-09-30 17:12:31 +080011130 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011131 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11132 return RETURN_ERR;
11133 }
developer454b9462022-09-13 15:29:16 +080011134
developer254882b2022-09-30 17:12:31 +080011135 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011136 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011137
developer254882b2022-09-30 17:12:31 +080011138 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11139 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011140 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011141 _syscmd(cmd, buf, sizeof(buf));
11142 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11143 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11144 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011145 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 +080011146 _syscmd(cmd, buf, sizeof(buf));
11147 }
11148 if (band == band_5) {
11149 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11150 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011151 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 +080011152 _syscmd(cmd, buf, sizeof(buf));
11153 }
11154 }
11155 }
11156 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011157
developer254882b2022-09-30 17:12:31 +080011158 if (guard_interval == wifi_guard_interval_400)
11159 strcpy(GI, "0.4");
11160 else if (guard_interval == wifi_guard_interval_800)
11161 strcpy(GI, "0.8");
11162 else if (guard_interval == wifi_guard_interval_1600)
11163 strcpy(GI, "1.6");
11164 else if (guard_interval == wifi_guard_interval_3200)
11165 strcpy(GI, "3.2");
11166 else if (guard_interval == wifi_guard_interval_auto)
11167 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011168 // Record GI for get GI function
11169 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11170 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011171 if (f == NULL)
11172 return RETURN_ERR;
11173 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011174 fclose(f);
11175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11176 return RETURN_OK;
11177}
11178
11179INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11180{
11181 char buf[32] = {0};
11182 char cmd[64] = {0};
11183
11184 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11185
11186 if (guard_interval == NULL)
11187 return RETURN_ERR;
11188
11189 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11190 _syscmd(cmd, buf, sizeof(buf));
11191
11192 if (strncmp(buf, "0.4", 3) == 0)
11193 *guard_interval = wifi_guard_interval_400;
11194 else if (strncmp(buf, "0.8", 3) == 0)
11195 *guard_interval = wifi_guard_interval_800;
11196 else if (strncmp(buf, "1.6", 3) == 0)
11197 *guard_interval = wifi_guard_interval_1600;
11198 else if (strncmp(buf, "3.2", 3) == 0)
11199 *guard_interval = wifi_guard_interval_3200;
11200 else
11201 *guard_interval = wifi_guard_interval_auto;
11202
11203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11204 return RETURN_OK;
11205}
11206
developer3cc61d12022-09-13 16:36:05 +080011207INT wifi_setBSSColor(INT radio_index, UCHAR color)
11208{
11209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11210 struct params params = {0};
11211 char config_file[128] = {0};
11212 char bss_color[4] ={0};
11213
11214 params.name = "he_bss_color";
11215 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11216 params.value = bss_color;
11217 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11218 wifi_hostapdWrite(config_file, &params, 1);
11219 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11220
11221 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11222 return RETURN_OK;
11223}
11224
11225INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11226{
11227 char config_file[128] = {0};
11228 char buf[64] = {0};
11229 char temp_output[128] = {'\0'};
11230
11231 wifi_dbg_printf("\nFunc=%s\n", __func__);
11232 if (NULL == color)
11233 return RETURN_ERR;
11234
11235 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11236 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11237
11238 if(strlen(buf) > 0) {
11239 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11240 } else {
11241 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11242 }
11243
11244 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11245 wifi_dbg_printf("\noutput_string=%s\n", color);
11246
11247 return RETURN_OK;
11248}
11249
developer06a01d92022-09-07 16:32:39 +080011250/* multi-psk support */
11251INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11252{
11253 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011254 char interface_name[16] = {0};
11255
developerac6f1142022-12-20 19:26:35 +080011256 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011257 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011258
developerd946fd62022-12-08 18:03:28 +080011259 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11260 interface_name,
developer06a01d92022-09-07 16:32:39 +080011261 mac[0],
11262 mac[1],
11263 mac[2],
11264 mac[3],
11265 mac[4],
11266 mac[5]
11267 );
11268 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11269 _syscmd(cmd, key->wifi_keyId, 64);
11270
11271
11272 return RETURN_OK;
11273}
11274
11275INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11276{
developerd946fd62022-12-08 18:03:28 +080011277 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011278 FILE *fd = NULL;
11279 char fname[100];
11280 char cmd[128] = {0};
11281 char out[64] = {0};
11282 wifi_key_multi_psk_t * key = NULL;
11283 if(keysNumber < 0)
11284 return RETURN_ERR;
11285
developer431128d2022-12-16 15:30:41 +080011286 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011287 fd = fopen(fname, "w");
11288 if (!fd) {
11289 return RETURN_ERR;
11290 }
11291 key= (wifi_key_multi_psk_t *) keys;
11292 for(int i=0; i<keysNumber; ++i, key++) {
11293 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11294 }
11295 fclose(fd);
11296
11297 //reload file
developerac6f1142022-12-20 19:26:35 +080011298 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011299 return RETURN_ERR;
11300 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011301 _syscmd(cmd, out, 64);
11302 return RETURN_OK;
11303}
11304
11305INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11306{
11307 FILE *fd = NULL;
11308 char fname[100];
11309 char * line = NULL;
11310 char * pos = NULL;
11311 size_t len = 0;
11312 ssize_t read = 0;
11313 INT ret = RETURN_OK;
11314 wifi_key_multi_psk_t *keys_it = NULL;
11315
11316 if (keysNumber < 1) {
11317 return RETURN_ERR;
11318 }
11319
developer431128d2022-12-16 15:30:41 +080011320 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011321 fd = fopen(fname, "r");
11322 if (!fd) {
11323 return RETURN_ERR;
11324 }
11325
11326 if (keys == NULL) {
11327 ret = RETURN_ERR;
11328 goto close;
11329 }
11330
11331 keys_it = keys;
11332 while ((read = getline(&line, &len, fd)) != -1) {
11333 //Strip trailing new line if present
11334 if (read > 0 && line[read-1] == '\n') {
11335 line[read-1] = '\0';
11336 }
11337
11338 if(strcmp(line,"keyid=")) {
11339 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11340 if (!(pos = index(line, ' '))) {
11341 ret = RETURN_ERR;
11342 goto close;
11343 }
11344 pos++;
11345 //Here should be 00:00:00:00:00:00
11346 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11347 printf("Not supported MAC: %s\n", pos);
11348 }
11349 if (!(pos = index(pos, ' '))) {
11350 ret = RETURN_ERR;
11351 goto close;
11352 }
11353 pos++;
11354
11355 //The rest is PSK
11356 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11357 keys_it++;
11358
11359 if(--keysNumber <= 0)
11360 break;
11361 }
11362 }
11363
11364close:
11365 free(line);
11366 fclose(fd);
11367 return ret;
11368}
11369/* end of multi-psk support */
11370
11371INT wifi_setNeighborReports(UINT apIndex,
11372 UINT numNeighborReports,
11373 wifi_NeighborReport_t *neighborReports)
11374{
11375 char cmd[256] = { 0 };
11376 char hex_bssid[13] = { 0 };
11377 char bssid[18] = { 0 };
11378 char nr[256] = { 0 };
11379 char ssid[256];
11380 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011381 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011382 INT ret;
11383
11384 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011385 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011386 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011387 return RETURN_ERR;
11388 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 +080011389 system(cmd);
11390
11391 for(unsigned int i = 0; i < numNeighborReports; i++)
11392 {
11393 memset(ssid, 0, sizeof(ssid));
11394 ret = wifi_getSSIDName(apIndex, ssid);
11395 if (ret != RETURN_OK)
11396 return RETURN_ERR;
11397
11398 memset(hex_ssid, 0, sizeof(hex_ssid));
11399 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11400 sprintf(hex_ssid + k,"%02x", ssid[j]);
11401
11402 snprintf(hex_bssid, sizeof(hex_bssid),
11403 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11404 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11405 snprintf(bssid, sizeof(bssid),
11406 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11407 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11408
11409 snprintf(nr, sizeof(nr),
11410 "%s" // bssid
11411 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11412 "%02hhx" // operclass
11413 "%02hhx" // channel
11414 "%02hhx", // phy_mode
11415 hex_bssid,
11416 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11417 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11418 neighborReports[i].opClass,
11419 neighborReports[i].channel,
11420 neighborReports[i].phyTable);
11421
11422 snprintf(cmd, sizeof(cmd),
11423 "hostapd_cli set_neighbor "
11424 "%s " // bssid
11425 "ssid=%s " // ssid
11426 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011427 "-i %s",
11428 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011429
11430 if (WEXITSTATUS(system(cmd)) != 0)
11431 {
11432 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11433 }
11434 }
11435
11436 return RETURN_OK;
11437}
11438
11439INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11440{
11441 return RETURN_OK;
11442}
11443
11444#ifdef _WIFI_HAL_TEST_
11445int main(int argc,char **argv)
11446{
11447 int index;
11448 INT ret=0;
11449 char buf[1024]="";
11450
11451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11452 if(argc<3)
11453 {
11454 if(argc==2)
11455 {
11456 if(!strcmp(argv[1], "init"))
11457 return wifi_init();
11458 if(!strcmp(argv[1], "reset"))
11459 return wifi_reset();
11460 if(!strcmp(argv[1], "wifi_getHalVersion"))
11461 {
11462 char buffer[64];
11463 if(wifi_getHalVersion(buffer)==RETURN_OK)
11464 printf("Version: %s\n", buffer);
11465 else
11466 printf("Error in wifi_getHalVersion\n");
11467 return RETURN_OK;
11468 }
11469 }
11470 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11471 exit(-1);
11472 }
11473
11474 index = atoi(argv[2]);
11475 if(strstr(argv[1], "wifi_getApName")!=NULL)
11476 {
11477 wifi_getApName(index,buf);
11478 printf("Ap name is %s \n",buf);
11479 return 0;
11480 }
11481 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11482 {
11483 BOOL b = FALSE;
11484 BOOL *output_bool = &b;
11485 wifi_getRadioAutoChannelEnable(index,output_bool);
11486 printf("Channel enabled = %d \n",b);
11487 return 0;
11488 }
11489 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11490 {
11491 wifi_getApWpaEncryptionMode(index,buf);
11492 printf("encryption enabled = %s\n",buf);
11493 return 0;
11494 }
11495 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11496 {
11497 BOOL b = FALSE;
11498 BOOL *output_bool = &b;
11499 wifi_getApSsidAdvertisementEnable(index,output_bool);
11500 printf("advertisment enabled = %d\n",b);
11501 return 0;
11502 }
11503 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11504 {
11505 if(argc <= 3 )
11506 {
11507 printf("Insufficient arguments \n");
11508 exit(-1);
11509 }
11510
11511 char sta[20] = {'\0'};
11512 ULLONG handle= 0;
11513 strcpy(sta,argv[3]);
11514 mac_address_t st;
11515 mac_addr_aton(st,sta);
11516
11517 wifi_associated_dev_tid_stats_t tid_stats;
11518 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11519 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11520 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);
11521 }
11522
11523 if(strstr(argv[1], "getApEnable")!=NULL) {
11524 BOOL enable;
11525 ret=wifi_getApEnable(index, &enable);
11526 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11527 }
11528 else if(strstr(argv[1], "setApEnable")!=NULL) {
11529 BOOL enable = atoi(argv[3]);
11530 ret=wifi_setApEnable(index, enable);
11531 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11532 }
11533 else if(strstr(argv[1], "getApStatus")!=NULL) {
11534 char status[64];
11535 ret=wifi_getApStatus(index, status);
11536 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11537 }
11538 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11539 {
11540 wifi_getSSIDNameStatus(index,buf);
11541 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11542 return 0;
11543 }
11544 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11545 wifi_ssidTrafficStats2_t stats={0};
11546 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11547 printf("%s %d: returns %d\n", argv[1], index, ret);
11548 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11549 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11550 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11551 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11552 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11553 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11554 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11555 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11556 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11557 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11558 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11559 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11560 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11561 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11562 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11563 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11564 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11565 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11566 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11567 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11568 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11569 }
11570 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11571 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11572 UINT array_size=0;
11573 UINT i=0;
11574 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11575 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11576 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11577 printf(" neighbor %d:\n", i);
11578 printf(" ap_SSID =%s\n", pt->ap_SSID);
11579 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11580 printf(" ap_Mode =%s\n", pt->ap_Mode);
11581 printf(" ap_Channel =%d\n", pt->ap_Channel);
11582 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11583 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11584 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11585 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11586 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11587 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11588 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11589 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11590 printf(" ap_Noise =%d\n", pt->ap_Noise);
11591 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11592 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11593 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11594 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11595 }
11596 if(neighbor_ap_array)
11597 free(neighbor_ap_array); //make sure to free the list
11598 }
11599 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11600 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11601 UINT array_size=0;
11602 UINT i=0;
11603 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11604 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11605 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11606 printf(" associated_dev %d:\n", i);
11607 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11608 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11609 printf(" cli_SNR =%d\n", pt->cli_SNR);
11610 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11611 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11612 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11613 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11614 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11615 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11616 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11617 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11618 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11619 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11620 }
11621 if(associated_dev_array)
11622 free(associated_dev_array); //make sure to free the list
11623 }
11624
11625 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11626 {
11627#define MAX_ARRAY_SIZE 64
11628 int i, array_size;
11629 char *p, *ch_str;
11630 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11631
11632 if(argc != 5)
11633 {
11634 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11635 exit(-1);
11636 }
11637 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11638
11639 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11640 {
11641 strtok_r(ch_str, ",", &p);
11642 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11643 }
11644 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11645 if(!array_size)
11646 array_size=1;//Need to print current channel statistics
11647 for(i=0; i<array_size; i++)
11648 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11649 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11650 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11651 input_output_channelStats_array[i].ch_number,\
11652 input_output_channelStats_array[i].ch_noise,\
11653 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11654 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11655 input_output_channelStats_array[i].ch_utilization_busy,\
11656 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11657 input_output_channelStats_array[i].ch_utilization_total);
11658 }
11659
11660 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11661 {
11662 if(argc <= 3 )
11663 {
11664 printf("Insufficient arguments \n");
11665 exit(-1);
11666 }
11667 char mac_addr[20] = {'\0'};
11668 wifi_device_t output_struct;
11669 int dev_index = atoi(argv[3]);
11670
11671 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11672 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11673 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);
11674 }
11675
11676 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11677 {
11678 if (argc <= 3)
11679 {
11680 printf("Insufficient arguments\n");
11681 exit(-1);
11682 }
11683 char args[256];
11684 wifi_NeighborReport_t *neighborReports;
11685
11686 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11687 if (!neighborReports)
11688 {
11689 printf("Failed to allocate memory");
11690 exit(-1);
11691 }
11692
11693 for (int i = 3; i < argc; ++i)
11694 {
11695 char *val;
11696 int j = 0;
11697 memset(args, 0, sizeof(args));
11698 strncpy(args, argv[i], sizeof(args));
11699 val = strtok(args, ";");
11700 while (val != NULL)
11701 {
11702 if (j == 0)
11703 {
11704 mac_addr_aton(neighborReports[i - 3].bssid, val);
11705 } else if (j == 1)
11706 {
11707 neighborReports[i - 3].info = strtol(val, NULL, 16);
11708 } else if (j == 2)
11709 {
11710 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11711 } else if (j == 3)
11712 {
11713 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11714 } else if (j == 4)
11715 {
11716 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11717 } else {
11718 printf("Insufficient arguments]n\n");
11719 exit(-1);
11720 }
11721 val = strtok(NULL, ";");
11722 j++;
11723 }
11724 }
11725
11726 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11727 if (ret != RETURN_OK)
11728 {
11729 printf("wifi_setNeighborReports ret = %d", ret);
11730 exit(-1);
11731 }
11732 }
11733 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11734 {
11735 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11736 printf("%s.\n", buf);
11737 else
11738 printf("Error returned\n");
11739 }
11740 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11741 {
11742 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11743 printf("%s.\n", buf);
11744 else
11745 printf("Error returned\n");
11746 }
11747 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11748 {
11749 if (argc <= 2)
11750 {
11751 printf("Insufficient arguments\n");
11752 exit(-1);
11753 }
11754 char buf[64]= {'\0'};
11755 wifi_getRadioOperatingChannelBandwidth(index,buf);
11756 printf("Current bandwidth is %s \n",buf);
11757 return 0;
11758 }
11759 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11760 {
11761 if (argc <= 5)
11762 {
11763 printf("Insufficient arguments\n");
11764 exit(-1);
11765 }
11766 UINT channel = atoi(argv[3]);
11767 UINT width = atoi(argv[4]);
11768 UINT beacon = atoi(argv[5]);
11769 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11770 printf("Result = %d", ret);
11771 }
11772
11773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11774 return 0;
11775}
11776
11777#endif
11778
11779#ifdef WIFI_HAL_VERSION_3
11780
developer1e5aa162022-09-13 16:06:24 +080011781INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11782{
11783 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11784 if (bitMap & WIFI_BITRATE_1MBPS)
11785 strcat(BasicRate, "1,");
11786 if (bitMap & WIFI_BITRATE_2MBPS)
11787 strcat(BasicRate, "2,");
11788 if (bitMap & WIFI_BITRATE_5_5MBPS)
11789 strcat(BasicRate, "5.5,");
11790 if (bitMap & WIFI_BITRATE_6MBPS)
11791 strcat(BasicRate, "6,");
11792 if (bitMap & WIFI_BITRATE_9MBPS)
11793 strcat(BasicRate, "9,");
11794 if (bitMap & WIFI_BITRATE_11MBPS)
11795 strcat(BasicRate, "11,");
11796 if (bitMap & WIFI_BITRATE_12MBPS)
11797 strcat(BasicRate, "12,");
11798 if (bitMap & WIFI_BITRATE_18MBPS)
11799 strcat(BasicRate, "18,");
11800 if (bitMap & WIFI_BITRATE_24MBPS)
11801 strcat(BasicRate, "24,");
11802 if (bitMap & WIFI_BITRATE_36MBPS)
11803 strcat(BasicRate, "36,");
11804 if (bitMap & WIFI_BITRATE_48MBPS)
11805 strcat(BasicRate, "48,");
11806 if (bitMap & WIFI_BITRATE_54MBPS)
11807 strcat(BasicRate, "54,");
11808 if (strlen(BasicRate) != 0) // remove last comma
11809 BasicRate[strlen(BasicRate) - 1] = '\0';
11810 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11811 return RETURN_OK;
11812}
11813
11814INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11815{
11816 UINT BitMap = 0;
11817 char *rate;
11818
11819 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11820 rate = strtok(BasicRatesList, ",");
11821 while(rate != NULL)
11822 {
11823 if (strcmp(rate, "1") == 0)
11824 BitMap |= WIFI_BITRATE_1MBPS;
11825 else if (strcmp(rate, "2") == 0)
11826 BitMap |= WIFI_BITRATE_2MBPS;
11827 else if (strcmp(rate, "5.5") == 0)
11828 BitMap |= WIFI_BITRATE_5_5MBPS;
11829 else if (strcmp(rate, "6") == 0)
11830 BitMap |= WIFI_BITRATE_6MBPS;
11831 else if (strcmp(rate, "9") == 0)
11832 BitMap |= WIFI_BITRATE_9MBPS;
11833 else if (strcmp(rate, "11") == 0)
11834 BitMap |= WIFI_BITRATE_11MBPS;
11835 else if (strcmp(rate, "12") == 0)
11836 BitMap |= WIFI_BITRATE_12MBPS;
11837 else if (strcmp(rate, "18") == 0)
11838 BitMap |= WIFI_BITRATE_18MBPS;
11839 else if (strcmp(rate, "24") == 0)
11840 BitMap |= WIFI_BITRATE_24MBPS;
11841 else if (strcmp(rate, "36") == 0)
11842 BitMap |= WIFI_BITRATE_36MBPS;
11843 else if (strcmp(rate, "48") == 0)
11844 BitMap |= WIFI_BITRATE_48MBPS;
11845 else if (strcmp(rate, "54") == 0)
11846 BitMap |= WIFI_BITRATE_54MBPS;
11847 rate = strtok(NULL, ",");
11848 }
11849 *basicRateBitMap = BitMap;
11850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11851 return RETURN_OK;
11852}
11853
11854// 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 +080011855INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11856{
developer1e5aa162022-09-13 16:06:24 +080011857 char buf[128] = {0};
11858 char cmd[128] = {0};
11859 char config_file[64] = {0};
11860 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011861 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011862 wifi_radio_operationParam_t current_param;
11863
11864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11865
11866 multiple_set = TRUE;
11867 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11868 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11869 return RETURN_ERR;
11870 }
11871 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11872 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11873 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11874 return RETURN_ERR;
11875 }
11876 }
developer5884e982022-10-06 10:52:50 +080011877
11878 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11879 bandwidth = 20;
11880 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11881 bandwidth = 40;
11882 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11883 bandwidth = 80;
11884 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11885 bandwidth = 160;
11886 if (operationParam->autoChannelEnabled){
11887 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11888 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11889 return RETURN_ERR;
11890 }
11891 }else{
developer1e5aa162022-09-13 16:06:24 +080011892 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11893 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11894 return RETURN_ERR;
11895 }
11896 }
developer5884e982022-10-06 10:52:50 +080011897
developer1e5aa162022-09-13 16:06:24 +080011898 if (current_param.variant != operationParam->variant) {
11899 // Two different definition bit map, so need to check every bit.
11900 if (operationParam->variant & WIFI_80211_VARIANT_A)
11901 set_mode |= WIFI_MODE_A;
11902 if (operationParam->variant & WIFI_80211_VARIANT_B)
11903 set_mode |= WIFI_MODE_B;
11904 if (operationParam->variant & WIFI_80211_VARIANT_G)
11905 set_mode |= WIFI_MODE_G;
11906 if (operationParam->variant & WIFI_80211_VARIANT_N)
11907 set_mode |= WIFI_MODE_N;
11908 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11909 set_mode |= WIFI_MODE_AC;
11910 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11911 set_mode |= WIFI_MODE_AX;
11912 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11913 memset(buf, 0, sizeof(buf));
11914 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11915 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11916 return RETURN_ERR;
11917 }
11918 }
11919 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11920 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11921 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11922 return RETURN_ERR;
11923 }
11924 }
11925 if (current_param.beaconInterval != operationParam->beaconInterval) {
11926 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11927 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11928 return RETURN_ERR;
11929 }
11930 }
11931 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11932 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11933 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11934 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11935 return RETURN_ERR;
11936 }
11937 }
11938 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11939 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11940 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11941 return RETURN_ERR;
11942 }
11943 }
11944 if (current_param.guardInterval != operationParam->guardInterval) {
11945 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11946 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11947 return RETURN_ERR;
11948 }
11949 }
11950 if (current_param.transmitPower != operationParam->transmitPower) {
11951 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11952 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11953 return RETURN_ERR;
11954 }
11955 }
11956 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11957 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11958 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11959 return RETURN_ERR;
11960 }
11961 }
11962 if (current_param.obssCoex != operationParam->obssCoex) {
11963 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11964 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11965 return RETURN_ERR;
11966 }
11967 }
11968 if (current_param.stbcEnable != operationParam->stbcEnable) {
11969 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11970 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11971 return RETURN_ERR;
11972 }
11973 }
11974 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11975 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11976 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11977 return RETURN_ERR;
11978 }
11979 }
11980
11981 // if enable is true, then restart the radio
11982 wifi_setRadioEnable(index, FALSE);
11983 if (operationParam->enable == TRUE)
11984 wifi_setRadioEnable(index, TRUE);
11985 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11986
developer06a01d92022-09-07 16:32:39 +080011987 return RETURN_OK;
11988}
11989
11990INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11991{
developer1e5aa162022-09-13 16:06:24 +080011992 char band[64] = {0};
11993 char buf[256] = {0};
11994 char config_file[64] = {0};
11995 char cmd[128] = {0};
11996 int ret = RETURN_ERR;
11997 int mode = 0;
11998 ULONG channel = 0;
11999 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012000
12001 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12002 printf("Entering %s index = %d\n", __func__, (int)index);
12003
developer1e5aa162022-09-13 16:06:24 +080012004 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12005 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12006 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012007 {
developer1e5aa162022-09-13 16:06:24 +080012008 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012009 return RETURN_ERR;
12010 }
12011 operationParam->enable = enabled;
12012
12013 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012014 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012015 {
developer1e5aa162022-09-13 16:06:24 +080012016 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012017 return RETURN_ERR;
12018 }
12019
12020 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012021 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012022 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012023 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012024 else if (!strcmp(band, "6GHz"))
12025 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012026 else
12027 {
developer1e5aa162022-09-13 16:06:24 +080012028 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012029 band);
12030 }
12031
developer1e5aa162022-09-13 16:06:24 +080012032 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12033 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12034 operationParam->channel = 0;
12035 operationParam->autoChannelEnabled = TRUE;
12036 } else {
12037 operationParam->channel = strtol(buf, NULL, 10);
12038 operationParam->autoChannelEnabled = FALSE;
12039 }
12040
developer06a01d92022-09-07 16:32:39 +080012041 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012042 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12043 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12044 return RETURN_ERR;
12045 }
developer06a01d92022-09-07 16:32:39 +080012046 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12047 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12048 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012049 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer06a01d92022-09-07 16:32:39 +080012050 else
12051 {
developer1e5aa162022-09-13 16:06:24 +080012052 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12053 return false;
developer06a01d92022-09-07 16:32:39 +080012054 }
12055
developer1e5aa162022-09-13 16:06:24 +080012056 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12057 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12058 return RETURN_ERR;
12059 }
12060 // Two different definition bit map, so need to check every bit.
12061 if (mode & WIFI_MODE_A)
12062 operationParam->variant |= WIFI_80211_VARIANT_A;
12063 if (mode & WIFI_MODE_B)
12064 operationParam->variant |= WIFI_80211_VARIANT_B;
12065 if (mode & WIFI_MODE_G)
12066 operationParam->variant |= WIFI_80211_VARIANT_G;
12067 if (mode & WIFI_MODE_N)
12068 operationParam->variant |= WIFI_80211_VARIANT_N;
12069 if (mode & WIFI_MODE_AC)
12070 operationParam->variant |= WIFI_80211_VARIANT_AC;
12071 if (mode & WIFI_MODE_AX)
12072 operationParam->variant |= WIFI_80211_VARIANT_AX;
12073 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12074 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12075 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012076 }
developer1e5aa162022-09-13 16:06:24 +080012077 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12078 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12079 return RETURN_ERR;
12080 }
12081 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12082 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12083 return RETURN_ERR;
12084 }
developer06a01d92022-09-07 16:32:39 +080012085
developer1e5aa162022-09-13 16:06:24 +080012086 memset(buf, 0, sizeof(buf));
12087 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12088 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12089 return RETURN_ERR;
12090 }
12091 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12092
12093 memset(buf, 0, sizeof(buf));
12094 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12095 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12096 return RETURN_ERR;
12097 }
12098 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12099
12100 memset(buf, 0, sizeof(buf));
12101 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12102 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12103
12104 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12105 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12106 return RETURN_ERR;
12107 }
12108 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12109 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12110 return RETURN_ERR;
12111 }
12112
12113 memset(buf, 0, sizeof(buf));
12114 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12115 if (strcmp(buf, "-1") == 0) {
12116 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12117 operationParam->ctsProtection = FALSE;
12118 } else {
12119 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12120 operationParam->ctsProtection = TRUE;
12121 }
12122
12123 memset(buf, 0, sizeof(buf));
12124 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12125 if (strcmp(buf, "0") == 0)
12126 operationParam->obssCoex = FALSE;
12127 else
12128 operationParam->obssCoex = TRUE;
12129
12130 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12131 _syscmd(cmd, buf, sizeof(buf));
12132 if (strlen(buf) != 0)
12133 operationParam->stbcEnable = TRUE;
12134 else
12135 operationParam->stbcEnable = FALSE;
12136
12137 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12138 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12139 return RETURN_ERR;
12140 }
12141
12142 // Below value is hardcoded
12143
12144 operationParam->numSecondaryChannels = 0;
12145 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12146 operationParam->channelSecondary[i] = 0;
12147 }
12148 operationParam->csa_beacon_count = 15;
12149 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012150
12151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12152 return RETURN_OK;
12153}
12154
12155static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12156{
developerc086fb72022-10-04 10:18:22 +080012157 int max_radio_num = 0;
12158
12159 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012160 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012161 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12162 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012163 }
12164
developerc086fb72022-10-04 10:18:22 +080012165 return (arrayIndex * max_radio_num) + radioIndex;
12166}
developer06a01d92022-09-07 16:32:39 +080012167
developerc086fb72022-10-04 10:18:22 +080012168wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12169 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12170 return WIFI_BITRATE_1MBPS;
12171 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12172 return WIFI_BITRATE_2MBPS;
12173 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12174 return WIFI_BITRATE_5_5MBPS;
12175 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12176 return WIFI_BITRATE_6MBPS;
12177 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12178 return WIFI_BITRATE_9MBPS;
12179 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12180 return WIFI_BITRATE_11MBPS;
12181 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12182 return WIFI_BITRATE_12MBPS;
12183 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12184 return WIFI_BITRATE_18MBPS;
12185 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12186 return WIFI_BITRATE_24MBPS;
12187 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12188 return WIFI_BITRATE_36MBPS;
12189 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12190 return WIFI_BITRATE_48MBPS;
12191 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12192 return WIFI_BITRATE_54MBPS;
12193 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012194}
12195
developer1d57d002022-10-12 18:03:15 +080012196INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12197{
12198 if (beacon == WIFI_BITRATE_1MBPS)
12199 strcpy(beacon_str, "1Mbps");
12200 else if (beacon == WIFI_BITRATE_2MBPS)
12201 strcpy(beacon_str, "2Mbps");
12202 else if (beacon == WIFI_BITRATE_5_5MBPS)
12203 strcpy(beacon_str, "5.5Mbps");
12204 else if (beacon == WIFI_BITRATE_6MBPS)
12205 strcpy(beacon_str, "6Mbps");
12206 else if (beacon == WIFI_BITRATE_9MBPS)
12207 strcpy(beacon_str, "9Mbps");
12208 else if (beacon == WIFI_BITRATE_11MBPS)
12209 strcpy(beacon_str, "11Mbps");
12210 else if (beacon == WIFI_BITRATE_12MBPS)
12211 strcpy(beacon_str, "12Mbps");
12212 else if (beacon == WIFI_BITRATE_18MBPS)
12213 strcpy(beacon_str, "18Mbps");
12214 else if (beacon == WIFI_BITRATE_24MBPS)
12215 strcpy(beacon_str, "24Mbps");
12216 else if (beacon == WIFI_BITRATE_36MBPS)
12217 strcpy(beacon_str, "36Mbps");
12218 else if (beacon == WIFI_BITRATE_48MBPS)
12219 strcpy(beacon_str, "48Mbps");
12220 else if (beacon == WIFI_BITRATE_54MBPS)
12221 strcpy(beacon_str, "54Mbps");
12222 return RETURN_OK;
12223}
12224
developer06a01d92022-09-07 16:32:39 +080012225INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12226{
developerc086fb72022-10-04 10:18:22 +080012227 INT mode = 0;
12228 INT ret = -1;
12229 INT output = 0;
12230 int i = 0;
12231 int vap_index = 0;
12232 BOOL enabled = FALSE;
12233 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012234 wifi_vap_security_t security = {0};
developerc086fb72022-10-04 10:18:22 +080012235 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080012236
12237 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12238 printf("Entering %s index = %d\n", __func__, (int)index);
12239
developer06a01d92022-09-07 16:32:39 +080012240 for (i = 0; i < 5; i++)
12241 {
developerc086fb72022-10-04 10:18:22 +080012242 map->vap_array[i].radio_index = index;
12243
developer06a01d92022-09-07 16:32:39 +080012244 vap_index = array_index_to_vap_index(index, i);
12245 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012246 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012247
developerc086fb72022-10-04 10:18:22 +080012248 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012249
12250 map->vap_array[i].vap_index = vap_index;
12251
12252 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012253 ret = wifi_getApName(vap_index, buf);
12254 if (ret != RETURN_OK) {
12255 printf("%s: wifi_getApName return error\n", __func__);
12256 return RETURN_ERR;
12257 }
12258 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12259
12260 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012261 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012262 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012263 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012264 return RETURN_ERR;
12265 }
12266 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 +080012267
12268 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012269 if (ret != RETURN_OK) {
12270 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012271 return RETURN_ERR;
12272 }
12273 map->vap_array[i].u.bss_info.enabled = enabled;
12274
developerc086fb72022-10-04 10:18:22 +080012275 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12276 if (ret != RETURN_OK) {
12277 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12278 return RETURN_ERR;
12279 }
developer06a01d92022-09-07 16:32:39 +080012280 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012281
12282 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12283 if (ret != RETURN_OK) {
12284 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12285 return RETURN_ERR;
12286 }
12287 map->vap_array[i].u.bss_info.isolation = enabled;
12288
12289 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12290 if (ret != RETURN_OK) {
12291 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12292 return RETURN_ERR;
12293 }
12294 map->vap_array[i].u.bss_info.bssMaxSta = output;
12295
12296 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12297 if (ret != RETURN_OK) {
12298 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12299 return RETURN_ERR;
12300 }
12301 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012302
developerc086fb72022-10-04 10:18:22 +080012303 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12304 if (ret != RETURN_OK) {
12305 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12306 return RETURN_ERR;
12307 }
12308 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012309
developerc086fb72022-10-04 10:18:22 +080012310 ret = wifi_getApSecurity(vap_index, &security);
12311 if (ret != RETURN_OK) {
12312 printf("%s: wifi_getApSecurity return error\n", __func__);
12313 return RETURN_ERR;
12314 }
12315 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012316
developerc086fb72022-10-04 10:18:22 +080012317 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12318 if (ret != RETURN_OK) {
12319 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12320 return RETURN_ERR;
12321 }
12322 if (mode == 0)
12323 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12324 else
12325 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12326 if (mode == 1)
12327 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12328 else if (mode == 2)
12329 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012330
developerc086fb72022-10-04 10:18:22 +080012331 ret = wifi_getApWmmEnable(vap_index, &enabled);
12332 if (ret != RETURN_OK) {
12333 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12334 return RETURN_ERR;
12335 }
12336 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012337
developerc086fb72022-10-04 10:18:22 +080012338 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12339 if (ret != RETURN_OK) {
12340 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012341 return RETURN_ERR;
12342 }
developerc086fb72022-10-04 10:18:22 +080012343 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012344
12345 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012346 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012347 if (ret != RETURN_OK) {
12348 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12349 return RETURN_ERR;
12350 }
12351 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012352
developerc086fb72022-10-04 10:18:22 +080012353 memset(buf, 0, sizeof(buf));
12354 ret = wifi_getBaseBSSID(vap_index, buf);
12355 if (ret != RETURN_OK) {
12356 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12357 return RETURN_ERR;
12358 }
12359 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12360 &map->vap_array[i].u.bss_info.bssid[0],
12361 &map->vap_array[i].u.bss_info.bssid[1],
12362 &map->vap_array[i].u.bss_info.bssid[2],
12363 &map->vap_array[i].u.bss_info.bssid[3],
12364 &map->vap_array[i].u.bss_info.bssid[4],
12365 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012366 // 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]);
12367
12368 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12369 if (ret != RETURN_OK) {
12370 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12371 return RETURN_ERR;
12372 }
12373 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012374
developerc086fb72022-10-04 10:18:22 +080012375 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012376 }
12377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12378 return RETURN_OK;
12379}
12380
developer431128d2022-12-16 15:30:41 +080012381void checkVapStatus(int apIndex, bool *enable)
12382{
12383 char if_name[16] = {0};
12384 char cmd[128] = {0};
12385 char buf[128] = {0};
12386
12387 *enable = FALSE;
developerac6f1142022-12-20 19:26:35 +080012388 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
developer431128d2022-12-16 15:30:41 +080012389 return;
12390
12391 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12392 _syscmd(cmd, buf, sizeof(buf));
12393 if (strlen(buf) > 0)
12394 *enable = TRUE;
12395 return;
12396}
12397
developerd946fd62022-12-08 18:03:28 +080012398static int prepareInterface(UINT apIndex, char *new_interface)
12399{
12400 char cur_interface[16] = {0};
12401 char config_file[128] = {0};
12402 char cmd[128] = {0};
12403 char buf[16] = {0};
12404 int max_radio_num = 0;
12405 int radioIndex = -1;
12406 int phyIndex = -1;
12407
12408 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12409 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12410
12411 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12412 wifi_getMaxRadioNumber(&max_radio_num);
12413 radioIndex = apIndex % max_radio_num;
12414 phyIndex = radio_index_to_phy(radioIndex);
12415 // disable and del old interface, then add new interface
12416 wifi_setApEnable(apIndex, FALSE);
developer431128d2022-12-16 15:30:41 +080012417 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
developerd946fd62022-12-08 18:03:28 +080012418 _syscmd(cmd, buf, sizeof(buf));
12419 }
developer431128d2022-12-16 15:30:41 +080012420 // update the vap status file
12421 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12422 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012423 return RETURN_OK;
12424}
12425
developer06a01d92022-09-07 16:32:39 +080012426INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12427{
developerd946fd62022-12-08 18:03:28 +080012428 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012429 unsigned int i;
12430 wifi_vap_info_t *vap_info = NULL;
12431 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012432 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012433 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012434 char buf[256] = {0};
12435 char cmd[128] = {0};
12436 char config_file[64] = {0};
12437 char bssid[32] = {0};
12438 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012439 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012440
12441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12442 printf("Entering %s index = %d\n", __func__, (int)index);
12443 for (i = 0; i < map->num_vaps; i++)
12444 {
developer1d57d002022-10-12 18:03:15 +080012445 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012446 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012447
12448 // Check vap status file to enable multiple ap if the system boot.
12449 checkVapStatus(vap_info->vap_index, &enable);
12450 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012451 continue;
developer06a01d92022-09-07 16:32:39 +080012452
developer1d57d002022-10-12 18:03:15 +080012453 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12454
developer431128d2022-12-16 15:30:41 +080012455 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12456 enable = FALSE;
12457
12458 // multi-ap first up need to copy current radio config
12459 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012460 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12461 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012462 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12463 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12464 } else {
12465 // Check whether the interface name is valid or this ap change it.
12466 int apIndex = -1;
12467 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12468 if (apIndex != -1 && apIndex != vap_info->vap_index)
12469 continue;
12470 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012471 }
developer06a01d92022-09-07 16:32:39 +080012472
developer1d57d002022-10-12 18:03:15 +080012473 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012474 params[0].name = "interface";
12475 params[0].value = vap_info->vap_name;
12476 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12477 params[1].name = "bssid";
12478 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012479 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012480 params[2].name = "wpa_psk_file";
12481 params[2].value = psk_file;
12482
12483 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12484 wifi_hostapdWrite(config_file, params, 3);
12485
12486 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12487 _syscmd(cmd, buf, sizeof(buf));
12488
12489 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12490 if (ret != RETURN_OK) {
12491 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12492 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012493 }
developer1d57d002022-10-12 18:03:15 +080012494
12495 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12496 if (ret != RETURN_OK) {
12497 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12498 return RETURN_ERR;
12499 }
12500
12501 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12502 if (ret != RETURN_OK) {
12503 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12504 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012505 }
12506
developer1d57d002022-10-12 18:03:15 +080012507 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12508 if (ret != RETURN_OK) {
12509 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12510 return RETURN_ERR;
12511 }
developer06a01d92022-09-07 16:32:39 +080012512
developer1d57d002022-10-12 18:03:15 +080012513 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12514 if (ret != RETURN_OK) {
12515 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12516 return RETURN_ERR;
12517 }
developer06a01d92022-09-07 16:32:39 +080012518
developer1d57d002022-10-12 18:03:15 +080012519 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12520 if (ret != RETURN_OK) {
12521 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12522 return RETURN_ERR;
12523 }
12524
developer804c64f2022-10-19 13:54:40 +080012525 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012526 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012527 }else {
12528 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012529 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012530 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12531 _syscmd(cmd, buf, sizeof(buf));
12532 }else{
developer1d57d002022-10-12 18:03:15 +080012533 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012534 }
developer1d57d002022-10-12 18:03:15 +080012535 }
12536
12537 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12538 if (ret != RETURN_OK) {
12539 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12540 return RETURN_ERR;
12541 }
12542
12543 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12544 if (ret != RETURN_OK) {
12545 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12546 return RETURN_ERR;
12547 }
12548
12549 memset(buf, 0, sizeof(buf));
12550 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12551 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12552 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12553 if (ret != RETURN_OK) {
12554 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12555 return RETURN_ERR;
12556 }
12557
12558 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12559 if (ret != RETURN_OK) {
12560 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12561 return RETURN_ERR;
12562 }
12563
12564 wifi_setApEnable(vap_info->vap_index, TRUE);
12565 multiple_set = FALSE;
12566
12567 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12568 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12569 if (ret != RETURN_OK) {
12570 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12571 return RETURN_ERR;
12572 }
12573
12574 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12575 if (ret != RETURN_OK) {
12576 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12577 return RETURN_ERR;
12578 }
developer06a01d92022-09-07 16:32:39 +080012579
developer1d57d002022-10-12 18:03:15 +080012580 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012581 }
12582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12583 return RETURN_OK;
12584}
12585
12586int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12587{
12588 char *token, *next;
12589 const char s[2] = ",";
12590 int count =0;
12591
12592 /* get the first token */
12593 token = strtok_r(pchannels, s, &next);
12594
12595 /* walk through other tokens */
12596 while( token != NULL && count < MAX_CHANNELS) {
12597 chlistptr->channels_list[count++] = atoi(token);
12598 token = strtok_r(NULL, s, &next);
12599 }
12600
12601 return count;
12602}
12603
12604static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12605{
12606 INT status;
12607 wifi_channels_list_t *chlistp;
12608 CHAR output_string[64];
12609 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080012610 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080012611 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080012612
12613 if(rcap == NULL)
12614 {
12615 return RETURN_ERR;
12616 }
12617
12618 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012619 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012620
developer1e5aa162022-09-13 16:06:24 +080012621 if (band == band_2_4)
12622 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12623 else if (band == band_5)
12624 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12625 else if (band == band_6)
12626 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012627
12628 chlistp = &(rcap->channel_list[0]);
12629 memset(pchannels, 0, sizeof(pchannels));
12630
12631 /* possible number of radio channels */
12632 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12633 {
12634 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12635 }
12636 /* Number of channels and list*/
12637 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12638
12639 /* autoChannelSupported */
12640 /* always ON with wifi_getRadioAutoChannelSupported */
12641 rcap->autoChannelSupported = TRUE;
12642
12643 /* DCSSupported */
12644 /* always ON with wifi_getRadioDCSSupported */
12645 rcap->DCSSupported = TRUE;
12646
12647 /* zeroDFSSupported - TBD */
12648 rcap->zeroDFSSupported = FALSE;
12649
12650 /* Supported Country List*/
12651 memset(output_string, 0, sizeof(output_string));
12652 status = wifi_getRadioCountryCode(radioIndex, output_string);
12653 if( status != 0 ) {
12654 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12655 return RETURN_ERR;
12656 } else {
12657 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12658 }
12659 if(!strcmp(output_string,"US")){
12660 rcap->countrySupported[0] = wifi_countrycode_US;
12661 rcap->countrySupported[1] = wifi_countrycode_CA;
12662 } else if (!strcmp(output_string,"CA")) {
12663 rcap->countrySupported[0] = wifi_countrycode_CA;
12664 rcap->countrySupported[1] = wifi_countrycode_US;
12665 } else {
12666 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12667 }
12668
12669 rcap->numcountrySupported = 2;
12670
12671 /* csi */
12672 rcap->csi.maxDevices = 8;
12673 rcap->csi.soudingFrameSupported = TRUE;
12674
developer7930d352022-12-21 17:55:42 +080012675 wifi_GetInterfaceName(radioIndex, interface_name);
12676 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080012677
12678 /* channelWidth - all supported bandwidths */
12679 int i=0;
12680 rcap->channelWidth[i] = 0;
12681 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12682 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12683 WIFI_CHANNELBANDWIDTH_40MHZ);
12684
12685 }
developer1e5aa162022-09-13 16:06:24 +080012686 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012687 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12688 WIFI_CHANNELBANDWIDTH_40MHZ |
12689 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12690 }
12691
12692
12693 /* mode - all supported variants */
12694 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12695 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012696 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012697 }
12698 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012699 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12700 }
12701 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12702 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012703 }
12704 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12705 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12706
12707 /* supportedBitRate - all supported bitrates */
12708 rcap->supportedBitRate[i] = 0;
12709 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12710 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12711 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12712 }
developer1e5aa162022-09-13 16:06:24 +080012713 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012714 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12715 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12716 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12717 }
12718
12719
12720 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12721 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12722 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12723 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12724 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12725 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12726 rcap->cipherSupported = 0;
12727 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12728 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12729
12730 return RETURN_OK;
12731}
12732
12733INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12734{
developer30423732022-12-01 16:17:49 +080012735 INT status = 0, radioIndex = 0;
12736 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080012737 int iter = 0;
developer30423732022-12-01 16:17:49 +080012738 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080012739 int max_num_radios;
developer30423732022-12-01 16:17:49 +080012740 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080012741
12742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12743
12744 memset(cap, 0, sizeof(wifi_hal_capability_t));
12745
12746 /* version */
12747 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12748 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12749
12750 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080012751 wifi_getMaxRadioNumber(&max_num_radios);
12752 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080012753
12754 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12755 {
12756 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12757 if (status != 0) {
12758 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12759 return RETURN_ERR;
12760 }
12761
12762 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12763 {
developer804c64f2022-10-19 13:54:40 +080012764 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012765 {
12766 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12767 return RETURN_ERR;
12768 }
12769 iface_info = &cap->wifi_prop.interface_map[iter];
12770 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12771 iface_info->rdk_radio_index = radioIndex;
12772 memset(output, 0, sizeof(output));
12773 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12774 {
12775 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12776 }
12777 // TODO: bridge name
12778 // TODO: vlan id
12779 // TODO: primary
12780 iface_info->index = array_index_to_vap_index(radioIndex, j);
12781 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080012782 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012783 {
12784 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12785 }
12786 iter++;
12787 }
12788 }
12789
12790 cap->BandSteeringSupported = FALSE;
12791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12792 return RETURN_OK;
12793}
12794
developer9df4e652022-10-11 11:27:38 +080012795INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12796{
12797 struct params h_config={0};
12798 char config_file[64] = {0};
12799
12800 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12801
12802 h_config.name = "okc";
12803 h_config.value = okc_enable?"1":"0";
12804
12805 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12806 wifi_hostapdWrite(config_file, &h_config, 1);
12807 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12808
12809 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12810 return RETURN_OK;
12811}
12812
12813INT wifi_setSAEMFP(int ap_index, BOOL enable)
12814{
12815 struct params h_config={0};
12816 char config_file[64] = {0};
12817 char buf[128] = {0};
12818
12819 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12820
12821 h_config.name = "sae_require_mfp";
12822 h_config.value = enable?"1":"0";
12823
12824 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12825 wifi_hostapdWrite(config_file, &h_config, 1);
12826 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12827
12828 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12829 return RETURN_OK;
12830}
12831
12832INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12833{
12834 struct params h_config={0};
12835 char config_file[64] = {0};
12836 char buf[128] = {0};
12837
12838 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12839
12840 h_config.name = "sae_pwe";
12841 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12842 h_config.value = buf;
12843
12844 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12845 wifi_hostapdWrite(config_file, &h_config, 1);
12846 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12847
12848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12849 return RETURN_OK;
12850}
12851
12852INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12853{
12854 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12855 struct params h_config={0};
12856 char config_file[64] = {0};
12857
12858 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12859
12860 h_config.name = "wpa_disable_eapol_key_retries";
12861 h_config.value = disable_EAPOL_retries?"1":"0";
12862
12863 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12864 wifi_hostapdWrite(config_file, &h_config, 1);
12865 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12866
12867 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12868 return RETURN_OK;
12869}
12870
developer06a01d92022-09-07 16:32:39 +080012871INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12872{
developer587c1b62022-09-27 15:58:59 +080012873 char buf[128] = {0};
12874 char config_file[128] = {0};
12875 char password[64] = {0};
12876 char mfp[32] = {0};
12877 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012878 BOOL okc_enable = FALSE;
12879 BOOL sae_MFP = FALSE;
12880 BOOL disable_EAPOL_retries = TRUE;
12881 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012882 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012883 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012884
12885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12886
12887 multiple_set = TRUE;
12888 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12889 if (security->mode == wifi_security_mode_none) {
12890 strcpy(wpa_mode, "None");
12891 } else if (security->mode == wifi_security_mode_wpa_personal)
12892 strcpy(wpa_mode, "WPA-Personal");
12893 else if (security->mode == wifi_security_mode_wpa2_personal)
12894 strcpy(wpa_mode, "WPA2-Personal");
12895 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12896 strcpy(wpa_mode, "WPA-WPA2-Personal");
12897 else if (security->mode == wifi_security_mode_wpa_enterprise)
12898 strcpy(wpa_mode, "WPA-Enterprise");
12899 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12900 strcpy(wpa_mode, "WPA2-Enterprise");
12901 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12902 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012903 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012904 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012905 okc_enable = TRUE;
12906 sae_MFP = TRUE;
12907 sae_pwe = 2;
12908 disable_EAPOL_retries = FALSE;
12909 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012910 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012911 okc_enable = TRUE;
12912 sae_MFP = TRUE;
12913 sae_pwe = 2;
12914 disable_EAPOL_retries = FALSE;
12915 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012916 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012917 sae_MFP = TRUE;
12918 sae_pwe = 2;
12919 disable_EAPOL_retries = FALSE;
developer5c9fee82023-01-13 14:44:16 +080012920 } else if (security->mode == wifi_security_mode_owe) {
12921 strcpy(wpa_mode, "OWE");
12922 sae_MFP = TRUE;
12923 sae_pwe = 2;
12924 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080012925 }
12926
12927 band = wifi_index_to_band(ap_index);
12928 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12929 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12930 return RETURN_ERR;
12931 }
developer587c1b62022-09-27 15:58:59 +080012932
12933 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012934 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012935 wifi_setSAEMFP(ap_index, sae_MFP);
12936 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012937 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012938
developer5c9fee82023-01-13 14:44:16 +080012939 if (security->mode != wifi_security_mode_none || security->mode != wifi_security_mode_owe) {
developer9df4e652022-10-11 11:27:38 +080012940 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12941 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12942 password[63] = '\0';
12943 wifi_setApSecurityKeyPassphrase(ap_index, password);
12944 }
12945 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12946 params.name = "sae_password";
12947 params.value = security->u.key.key;
12948 wifi_hostapdWrite(config_file, &params, 1);
12949 }
12950 }
developer587c1b62022-09-27 15:58:59 +080012951
12952 if (security->mode != wifi_security_mode_none) {
12953 memset(&params, 0, sizeof(params));
12954 params.name = "wpa_pairwise";
12955 if (security->encr == wifi_encryption_tkip)
12956 params.value = "TKIP";
12957 else if (security->encr == wifi_encryption_aes)
12958 params.value = "CCMP";
12959 else if (security->encr == wifi_encryption_aes_tkip)
12960 params.value = "TKIP CCMP";
12961 wifi_hostapdWrite(config_file, &params, 1);
12962 }
12963
12964 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012965 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012966 else if (security->mfp == wifi_mfp_cfg_optional)
12967 strcpy(mfp, "Optional");
12968 else if (security->mfp == wifi_mfp_cfg_required)
12969 strcpy(mfp, "Required");
12970 wifi_setApSecurityMFPConfig(ap_index, mfp);
12971
12972 memset(&params, 0, sizeof(params));
12973 params.name = "transition_disable";
12974 if (security->wpa3_transition_disable == TRUE)
12975 params.value = "0x01";
12976 else
12977 params.value = "0x00";
12978 wifi_hostapdWrite(config_file, &params, 1);
12979
12980 memset(&params, 0, sizeof(params));
12981 params.name = "wpa_group_rekey";
12982 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12983 params.value = buf;
12984 wifi_hostapdWrite(config_file, &params, 1);
12985
12986 memset(&params, 0, sizeof(params));
12987 params.name = "wpa_strict_rekey";
12988 params.value = security->strict_rekey?"1":"0";
12989 wifi_hostapdWrite(config_file, &params, 1);
12990
12991 memset(&params, 0, sizeof(params));
12992 params.name = "wpa_pairwise_update_count";
12993 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12994 params.value = buf;
12995 wifi_hostapdWrite(config_file, &params, 1);
12996
12997 memset(&params, 0, sizeof(params));
12998 params.name = "disable_pmksa_caching";
12999 params.value = security->disable_pmksa_caching?"1":"0";
13000 wifi_hostapdWrite(config_file, &params, 1);
13001
13002 wifi_setApEnable(ap_index, FALSE);
13003 wifi_setApEnable(ap_index, TRUE);
13004
13005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13006
developer06a01d92022-09-07 16:32:39 +080013007 return RETURN_OK;
13008}
13009
13010INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13011{
developer9df4e652022-10-11 11:27:38 +080013012 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013013 char config_file[128] = {0};
13014 int disable = 0;
13015 // struct params params = {0};
13016
13017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13018 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13019 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13020 security->mode = wifi_security_mode_none;
13021 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013022 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013023 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013024 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013025 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013026 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013027 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013028 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013029 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013030 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013031 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013032 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013033 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013034 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013035 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013036 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013037 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013038 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013039 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013040 else if (!strcmp(buf, "OWE"))
13041 security->mode = wifi_security_mode_owe;
developer587c1b62022-09-27 15:58:59 +080013042 }
13043
13044 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13045 if (security->mode == wifi_security_mode_none)
13046 security->encr = wifi_encryption_none;
13047 else {
13048 if (strcmp(buf, "TKIP") == 0)
13049 security->encr = wifi_encryption_tkip;
13050 else if (strcmp(buf, "CCMP") == 0)
13051 security->encr = wifi_encryption_aes;
13052 else
13053 security->encr = wifi_encryption_aes_tkip;
13054 }
13055
developer9df4e652022-10-11 11:27:38 +080013056 if (security->mode != wifi_encryption_none) {
13057 memset(buf, 0, sizeof(buf));
13058 // wpa3 can use one or both configs as password, so we check sae_password first.
13059 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13060 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13061 security->u.key.type = wifi_security_key_type_sae;
13062 } else {
13063 security->u.key.type = wifi_security_key_type_psk;
13064 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13065 }
13066 strncpy(security->u.key.key, buf, sizeof(buf));
13067 security->u.key.key[255] = '\0';
13068 }
13069
developer587c1b62022-09-27 15:58:59 +080013070 memset(buf, 0, sizeof(buf));
13071 wifi_getApSecurityMFPConfig(ap_index, buf);
13072 if (strcmp(buf, "Disabled") == 0)
13073 security->mfp = wifi_mfp_cfg_disabled;
13074 else if (strcmp(buf, "Optional") == 0)
13075 security->mfp = wifi_mfp_cfg_optional;
13076 else if (strcmp(buf, "Required") == 0)
13077 security->mfp = wifi_mfp_cfg_required;
13078
13079 memset(buf, 0, sizeof(buf));
13080 security->wpa3_transition_disable = FALSE;
13081 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13082 disable = strtol(buf, NULL, 16);
13083 if (disable != 0)
13084 security->wpa3_transition_disable = TRUE;
13085
13086 memset(buf, 0, sizeof(buf));
13087 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13088 if (strlen(buf) == 0)
13089 security->rekey_interval = 86400;
13090 else
13091 security->rekey_interval = strtol(buf, NULL, 10);
13092
13093 memset(buf, 0, sizeof(buf));
13094 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13095 if (strlen(buf) == 0)
13096 security->strict_rekey = 1;
13097 else
13098 security->strict_rekey = strtol(buf, NULL, 10);
13099
13100 memset(buf, 0, sizeof(buf));
13101 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13102 if (strlen(buf) == 0)
13103 security->eapol_key_retries = 4;
13104 else
13105 security->eapol_key_retries = strtol(buf, NULL, 10);
13106
13107 memset(buf, 0, sizeof(buf));
13108 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13109 if (strlen(buf) == 0)
13110 security->disable_pmksa_caching = FALSE;
13111 else
13112 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13113
13114 /* TODO
13115 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13116 */
13117 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13118 security->eap_identity_req_timeout = 0;
13119 security->eap_identity_req_retries = 0;
13120 security->eap_req_timeout = 0;
13121 security->eap_req_retries = 0;
13122 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013123 return RETURN_OK;
13124}
13125
13126#endif /* WIFI_HAL_VERSION_3 */
13127
13128#ifdef WIFI_HAL_VERSION_3_PHASE2
13129INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13130{
developerd946fd62022-12-08 18:03:28 +080013131 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013132 char cmd[128] = {0};
13133 char buf[128] = {0};
13134 char *mac_addr = NULL;
13135 BOOL status = FALSE;
13136 size_t len = 0;
13137
13138 if(ap_index > MAX_APS)
13139 return RETURN_ERR;
13140
13141 *output_numDevices = 0;
13142 wifi_getApEnable(ap_index, &status);
13143 if (status == FALSE)
13144 return RETURN_OK;
13145
developerac6f1142022-12-20 19:26:35 +080013146 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013147 return RETURN_ERR;
13148 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013149 _syscmd(cmd, buf, sizeof(buf));
13150
13151 mac_addr = strtok(buf, "\n");
13152 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13153 *output_numDevices = i + 1;
13154 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13155 addr_ptr = output_deviceMacAddressArray[i];
13156 mac_addr_aton(addr_ptr, mac_addr);
13157 mac_addr = strtok(NULL, "\n");
13158 }
13159
13160 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013161}
13162#else
13163INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13164{
developerd946fd62022-12-08 18:03:28 +080013165 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013166 char cmd[128];
13167 BOOL status = false;
13168
13169 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13170 return RETURN_ERR;
13171
13172 output_buf[0] = '\0';
13173
13174 wifi_getApEnable(ap_index,&status);
13175 if (!status)
13176 return RETURN_OK;
13177
developerac6f1142022-12-20 19:26:35 +080013178 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013179 return RETURN_ERR;
13180 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013181 _syscmd(cmd, output_buf, output_buf_size);
13182
13183 return RETURN_OK;
13184}
13185#endif
developer2f513ab2022-09-13 14:26:06 +080013186
13187INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13188{
13189 char output[16]={'\0'};
13190 char config_file[MAX_BUF_SIZE] = {0};
13191
13192 if (!enable)
13193 return RETURN_ERR;
13194
13195 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13196 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13197
13198 if (strlen(output) == 0)
13199 *enable = FALSE;
13200 else if (strncmp(output, "1", 1) == 0)
13201 *enable = TRUE;
13202 else
13203 *enable = FALSE;
13204
13205 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13206 return RETURN_OK;
13207}
developer2d9c30f2022-09-13 15:06:14 +080013208
13209INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13210{
developer804c64f2022-10-19 13:54:40 +080013211 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013212 return RETURN_ERR;
13213 *output_enable=TRUE;
13214 return RETURN_OK;
13215}
developerfd7d2892022-09-13 16:44:53 +080013216
13217INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13218{
13219 char cmd[128] = {0};
13220 char buf[128] = {0};
13221 char line[128] = {0};
13222 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013223 FILE *f = NULL;
13224 int index = 0;
13225 int exp = 0;
13226 int mantissa = 0;
13227 int duration = 0;
13228 int radio_index = 0;
13229 int max_radio_num = 0;
13230 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013231 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013232 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13233
13234 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013235
developerfd7d2892022-09-13 16:44:53 +080013236 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013237
13238 phyId = radio_index_to_phy(radio_index);
13239 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013240 _syscmd(cmd, buf, sizeof(buf));
13241 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13242 if (*numSessionReturned > maxNumberSessions)
13243 *numSessionReturned = maxNumberSessions;
13244 else if (*numSessionReturned < 1) {
13245 *numSessionReturned = 0;
13246 return RETURN_OK;
13247 }
13248
developer033b37b2022-10-18 11:27:46 +080013249 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 +080013250 if ((f = popen(cmd, "r")) == NULL) {
13251 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13252 return RETURN_ERR;
13253 }
13254
13255 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013256 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013257 char *tmp = NULL;
13258 strcpy(buf, line);
13259 tmp = strtok(buf, " ");
13260 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13261 tmp = strtok(NULL, " ");
13262 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13263 tmp = strtok(NULL, " ");
13264 if (strstr(tmp, "t")) {
13265 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13266 }
13267 if (strstr(tmp, "a")) {
13268 twtSessions[index].twtParameters.operation.announced = TRUE;
13269 }
13270 tmp = strtok(NULL, " ");
13271 exp = strtol(tmp, NULL, 10);
13272 tmp = strtok(NULL, " ");
13273 mantissa = strtol(tmp, NULL, 10);
13274 tmp = strtok(NULL, " ");
13275 duration = strtol(tmp, NULL, 10);
13276
13277 // only implicit supported
13278 twtSessions[index].twtParameters.operation.implicit = TRUE;
13279 // only individual agreement supported
13280 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13281
13282 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13283 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013284 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013285 // Overflow handling
13286 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13287 } else {
13288 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13289 }
13290 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13291 index++;
13292 }
13293
13294 pclose(f);
13295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13296 return RETURN_OK;
13297}