blob: be99139b0f48ce698f843d45716cfa0ec2c79e44 [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
195wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
196wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
197char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800198static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800199
200static wifi_secur_list map_security[] =
201{
202 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
203 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
204 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
205 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
206 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
207 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
208 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800210 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800212 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800213 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800214};
215
216wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
217{
218 wifi_secur_list *item;
219 int i;
220
221 for (item = list,i = 0;i < list_sz; item++, i++) {
222 if ((int)(item->key) == key) {
223 return item;
224 }
225 }
226
227 return NULL;
228}
229
230char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
231{
232 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
233
234 if (!item) {
235 return "";
236 }
237
238 return (char *)(item->data);
239}
240
241wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
242{
243 wifi_secur_list *item;
244 int i;
245
246 for (item = list,i = 0;i < list_sz; item++, i++) {
247 if (strcmp((char *)(item->data), str) == 0) {
248 return item;
249 }
250 }
251
252 return NULL;
253}
254#endif /* WIFI_HAL_VERSION_3 */
255
256#ifdef HAL_NETLINK_IMPL
257typedef struct {
258 int id;
259 struct nl_sock* socket;
260 struct nl_cb* cb;
261} Netlink;
262
263static int mac_addr_aton(unsigned char *mac_addr, char *arg)
264{
265 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800266 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 +0800267 mac_addr[0] = mac_addr_int[0];
268 mac_addr[1] = mac_addr_int[1];
269 mac_addr[2] = mac_addr_int[2];
270 mac_addr[3] = mac_addr_int[3];
271 mac_addr[4] = mac_addr_int[4];
272 mac_addr[5] = mac_addr_int[5];
273 return 0;
274}
275
276static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
277{
278 unsigned int mac_addr_int[6]={};
279 mac_addr_int[0] = arg[0];
280 mac_addr_int[1] = arg[1];
281 mac_addr_int[2] = arg[2];
282 mac_addr_int[3] = arg[3];
283 mac_addr_int[4] = arg[4];
284 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800285 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 +0800286 return;
287}
288
289static int ieee80211_frequency_to_channel(int freq)
290{
developerf5745ee2022-10-05 16:09:53 +0800291 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800292 if (freq == 2484)
293 return 14;
developerf5745ee2022-10-05 16:09:53 +0800294 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
295 else if (freq == 5935)
296 return 2;
developer06a01d92022-09-07 16:32:39 +0800297 else if (freq < 2484)
298 return (freq - 2407) / 5;
299 else if (freq >= 4910 && freq <= 4980)
300 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800301 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800302 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800303 else if (freq <= 45000) /* DMG band lower limit */
304 /* see 802.11ax D6.1 27.3.23.2 */
305 return (freq - 5950) / 5;
306 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800307 return (freq - 56160) / 2160;
308 else
309 return 0;
310}
311
312static int initSock80211(Netlink* nl) {
313 nl->socket = nl_socket_alloc();
314 if (!nl->socket) {
315 fprintf(stderr, "Failing to allocate the sock\n");
316 return -ENOMEM;
317 }
318
319 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
320
321 if (genl_connect(nl->socket)) {
322 fprintf(stderr, "Failed to connect\n");
323 nl_close(nl->socket);
324 nl_socket_free(nl->socket);
325 return -ENOLINK;
326 }
327
328 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
329 if (nl->id< 0) {
330 fprintf(stderr, "interface not found.\n");
331 nl_close(nl->socket);
332 nl_socket_free(nl->socket);
333 return -ENOENT;
334 }
335
336 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
337 if ((!nl->cb)) {
338 fprintf(stderr, "Failed to allocate netlink callback.\n");
339 nl_close(nl->socket);
340 nl_socket_free(nl->socket);
341 return ENOMEM;
342 }
343
344 return nl->id;
345}
346
347static int nlfree(Netlink *nl)
348{
349 nl_cb_put(nl->cb);
350 nl_close(nl->socket);
351 nl_socket_free(nl->socket);
352 return 0;
353}
354
355static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
356 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
357 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
358 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
359};
360
361static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
362};
363
364static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
365};
366
367typedef struct _wifi_channelStats_loc {
368 INT array_size;
369 INT ch_number;
370 BOOL ch_in_pool;
371 INT ch_noise;
372 BOOL ch_radar_noise;
373 INT ch_max_80211_rssi;
374 INT ch_non_80211_noise;
375 INT ch_utilization;
376 ULLONG ch_utilization_total;
377 ULLONG ch_utilization_busy;
378 ULLONG ch_utilization_busy_tx;
379 ULLONG ch_utilization_busy_rx;
380 ULLONG ch_utilization_busy_self;
381 ULLONG ch_utilization_busy_ext;
382} wifi_channelStats_t_loc;
383
384typedef struct wifi_device_info {
385 INT wifi_devIndex;
386 UCHAR wifi_devMacAddress[6];
387 CHAR wifi_devIPAddress[64];
388 BOOL wifi_devAssociatedDeviceAuthentiationState;
389 INT wifi_devSignalStrength;
390 INT wifi_devTxRate;
391 INT wifi_devRxRate;
392} wifi_device_info_t;
393
394#endif
395
396//For 5g Alias Interfaces
397static BOOL priv_flag = TRUE;
398static BOOL pub_flag = TRUE;
399static BOOL Radio_flag = TRUE;
400//wifi_setApBeaconRate(1, beaconRate);
401
developer1e5aa162022-09-13 16:06:24 +0800402BOOL multiple_set = FALSE;
403
developer06a01d92022-09-07 16:32:39 +0800404struct params
405{
406 char * name;
407 char * value;
408};
409
410static int _syscmd(char *cmd, char *retBuf, int retBufSize)
411{
412 FILE *f;
413 char *ptr = retBuf;
414 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
415
416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
417 if((f = popen(cmd, "r")) == NULL) {
418 fprintf(stderr,"\npopen %s error\n", cmd);
419 return RETURN_ERR;
420 }
421
422 while(!feof(f))
423 {
424 *ptr = 0;
425 if(bufSize>=128) {
426 bufbytes=128;
427 } else {
428 bufbytes=bufSize-1;
429 }
430
431 fgets(ptr,bufbytes,f);
432 readbytes=strlen(ptr);
433
434 if(!readbytes)
435 break;
436
437 bufSize-=readbytes;
438 ptr += readbytes;
439 }
440 cmd_ret = pclose(f);
441 retBuf[retBufSize-1]=0;
442 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
443
444 return cmd_ret >> 8;
445}
446
developer033b37b2022-10-18 11:27:46 +0800447INT radio_index_to_phy(int radioIndex)
448{
449 char cmd[128] = {0};
450 char buf[64] = {0};
451 int phyIndex = 0;
452 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
453 _syscmd(cmd, buf, sizeof(buf));
454
455 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800456 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800457 return RETURN_ERR;
458 }
459 sscanf(buf, "phy%d", &phyIndex);
460
461 return phyIndex;
462}
developer026ac9e2022-11-07 13:46:24 +0800463
developer431128d2022-12-16 15:30:41 +0800464INT wifi_getMaxRadioNumber(INT *max_radio_num)
465{
466 char cmd[64] = {0};
467 char buf[4] = {0};
468
469 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
470
471 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
472 _syscmd(cmd, buf, sizeof(buf));
473 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
474
475 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
476
477 return RETURN_OK;
478}
479
480wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800481{
482 char cmd[128] = {0};
483 char buf[64] = {0};
developer026ac9e2022-11-07 13:46:24 +0800484 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800485 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800486 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800487 int radioIndex = 0;
488 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800489 wifi_band band = band_invalid;
490
491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800492
developer431128d2022-12-16 15:30:41 +0800493 wifi_getMaxRadioNumber(&max_radio_num);
494 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800495 phyIndex = radio_index_to_phy(radioIndex);
developer5884e982022-10-06 10:52:50 +0800496 while(i < 10){
developer026ac9e2022-11-07 13:46:24 +0800497 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 +0800498 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800499 nl80211_band = strtol(buf, NULL, 10);
500 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800501 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800502 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800503 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800504 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800505 band = band_6;
506
507 if(band != band_invalid)
508 break;
509
510 i++;
511 sleep(1);
512 }
developerc707e972022-09-13 15:38:02 +0800513
514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
515 return band;
516}
517
developer06a01d92022-09-07 16:32:39 +0800518static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
519{
520 char cmd[MAX_CMD_SIZE]={'\0'};
521 char buf[MAX_BUF_SIZE]={'\0'};
522 int ret = 0;
523
developerd946fd62022-12-08 18:03:28 +0800524 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 +0800525 ret = _syscmd(cmd, buf, sizeof(buf));
526 if ((ret != 0) && (strlen(buf) == 0))
527 return -1;
528 snprintf(output, output_size, "%s", buf);
529
530 return 0;
531}
532
533static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
534{
535 char cmd[MAX_CMD_SIZE]={'\0'};
536 char buf[MAX_BUF_SIZE]={'\0'};
537
538 for(int i=0;i<item_count;i++)
539 {
540 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
541 if (strlen(buf) == 0) //Insert
542 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
543 else //Update
544 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 +0800545
developer06a01d92022-09-07 16:32:39 +0800546 if(_syscmd(cmd, buf, sizeof(buf)))
547 return -1;
548 }
549
550 return 0;
551}
552
developerd946fd62022-12-08 18:03:28 +0800553//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800554static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800555{
556 char config_file[128] = {0};
557
558 if (interface_name == NULL)
559 return RETURN_ERR;
560
561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
562
563 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
564 wifi_hostapdRead(config_file, "interface", interface_name, 16);
565 if (strlen(interface_name) == 0)
566 return RETURN_ERR;
567
568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
569 return RETURN_OK;
570}
571
developerac6f1142022-12-20 19:26:35 +0800572// wifi agent will call this function, do not change the parameter
573void GetInterfaceName(char *interface_name, char *conf_file)
574{
575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
576 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
577 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
578}
579
developer06a01d92022-09-07 16:32:39 +0800580static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
581{
developerd946fd62022-12-08 18:03:28 +0800582 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800583 if (multiple_set == TRUE)
584 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800585 char cmd[MAX_CMD_SIZE]="", output[32]="";
586 FILE *fp;
587 int i;
588 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800589 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800590 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800591 for(i=0; i<item_count; i++, list++)
592 {
developerd946fd62022-12-08 18:03:28 +0800593 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800594 if((fp = popen(cmd, "r"))==NULL)
595 {
596 perror("popen failed");
597 return -1;
598 }
599 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
600 {
601 pclose(fp);
602 perror("fgets failed");
603 return -1;
604 }
605 pclose(fp);
606 }
607 return 0;
608}
609
610static int wifi_reloadAp(int apIndex)
611{
developerd946fd62022-12-08 18:03:28 +0800612 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800613 if (multiple_set == TRUE)
614 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800615 char cmd[MAX_CMD_SIZE]="";
616 char buf[MAX_BUF_SIZE]="";
617
developerac6f1142022-12-20 19:26:35 +0800618 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800619 return RETURN_ERR;
620 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800621 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
622 return RETURN_ERR;
623
developerd946fd62022-12-08 18:03:28 +0800624 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800625 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
626 return RETURN_ERR;
627
developerd946fd62022-12-08 18:03:28 +0800628 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800629 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
630 return RETURN_ERR;
631
632 return RETURN_OK;
633}
634
developer06a01d92022-09-07 16:32:39 +0800635INT File_Reading(CHAR *file, char *Value)
636{
637 FILE *fp = NULL;
638 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
639 int count = 0;
640
641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
642 fp = popen(file,"r");
643 if(fp == NULL)
644 return RETURN_ERR;
645
646 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
647 {
648 for(count=0;buf[count]!='\n';count++)
649 copy_buf[count]=buf[count];
650 copy_buf[count]='\0';
651 }
652 strcpy(Value,copy_buf);
653 pclose(fp);
654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
655
656 return RETURN_OK;
657}
658
659void wifi_RestartHostapd_2G()
660{
661 int Public2GApIndex = 4;
662
663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
664 wifi_setApEnable(Public2GApIndex, FALSE);
665 wifi_setApEnable(Public2GApIndex, TRUE);
666 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
667}
668
669void wifi_RestartHostapd_5G()
670{
671 int Public5GApIndex = 5;
672
673 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
674 wifi_setApEnable(Public5GApIndex, FALSE);
675 wifi_setApEnable(Public5GApIndex, TRUE);
676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
677}
678
679void wifi_RestartPrivateWifi_2G()
680{
681 int PrivateApIndex = 0;
682
683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
684 wifi_setApEnable(PrivateApIndex, FALSE);
685 wifi_setApEnable(PrivateApIndex, TRUE);
686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
687}
688
689void wifi_RestartPrivateWifi_5G()
690{
691 int Private5GApIndex = 1;
692
693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
694 wifi_setApEnable(Private5GApIndex, FALSE);
695 wifi_setApEnable(Private5GApIndex, TRUE);
696 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
697}
698
699static int writeBandWidth(int radioIndex,char *bw_value)
700{
701 char buf[MAX_BUF_SIZE];
702 char cmd[MAX_CMD_SIZE];
703
704 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
705 if(_syscmd(cmd, buf, sizeof(buf)))
706 {
707 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
708 _syscmd(cmd, buf, sizeof(buf));
709 return RETURN_OK;
710 }
711
712 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
713 _syscmd(cmd,buf,sizeof(buf));
714 return RETURN_OK;
715}
716
717static int readBandWidth(int radioIndex,char *bw_value)
718{
developer30423732022-12-01 16:17:49 +0800719 char buf[MAX_BUF_SIZE] = {0};
720 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800721 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
722 _syscmd(cmd,buf,sizeof(buf));
723 if(NULL!=strstr(buf,"20MHz"))
724 {
725 strcpy(bw_value,"20MHz");
726 }
727 else if(NULL!=strstr(buf,"40MHz"))
728 {
729 strcpy(bw_value,"40MHz");
730 }
731 else if(NULL!=strstr(buf,"80MHz"))
732 {
733 strcpy(bw_value,"80MHz");
734 }
735 else
736 {
737 return RETURN_ERR;
738 }
739 return RETURN_OK;
740}
741
developer264159b2022-11-02 09:41:35 +0800742// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800743INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
744{
developer5f222492022-09-13 15:21:52 +0800745 struct params params={'\0'};
746 char config_file[MAX_BUF_SIZE] = {0};
747 char buf[MAX_BUF_SIZE] = {'\0'};
748
749 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800750 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800751 if (strlen (beaconRate) >= 5) {
752 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
753 buf[strlen(beaconRate) - 4] = '\0';
754 } else if (strlen(beaconRate) > 0)
755 strcpy(buf, beaconRate);
756 else
757 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800758
759 params.name = "beacon_rate";
760 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
761 if (strncmp(buf, "5.5", 3) == 0) {
762 snprintf(buf, sizeof(buf), "55");
763 params.value = buf;
764 } else {
765 strcat(buf, "0");
766 params.value = buf;
767 }
768
769 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
770 wifi_hostapdWrite(config_file, &params, 1);
771 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
772 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
773
774 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800775}
776
777INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
778{
developer1d57d002022-10-12 18:03:15 +0800779 char config_file[128] = {'\0'};
780 char temp_output[128] = {'\0'};
781 char buf[128] = {'\0'};
782 char cmd[128] = {'\0'};
783 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800784 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800785
786 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
787 if (NULL == beaconRate)
788 return RETURN_ERR;
789
790 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
791 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800792 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800793 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
794 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800795 if (strncmp(buf, "55", 2) == 0)
796 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
797 else {
798 rate = strtol(buf, NULL, 10)/10;
799 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
800 }
developer5f222492022-09-13 15:21:52 +0800801 } else {
developer1d57d002022-10-12 18:03:15 +0800802 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800803 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 +0800804 _syscmd(cmd, buf, sizeof(buf));
805 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800806 }
807 strncpy(beaconRate, temp_output, sizeof(temp_output));
808 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
809
810 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800811}
812
813INT wifi_setLED(INT radioIndex, BOOL enable)
814{
815 return 0;
816}
817INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
818{
819 return RETURN_OK;
820}
821/**********************************************************************************
822 *
823 * Wifi Subsystem level function prototypes
824 *
825**********************************************************************************/
826//---------------------------------------------------------------------------------------------------
827//Wifi system api
828//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
829INT wifi_getHalVersion(CHAR *output_string) //RDKB
830{
831 if(!output_string)
832 return RETURN_ERR;
833 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
834
835 return RETURN_OK;
836}
837
838
839/* wifi_factoryReset() function */
840/**
841* @description Clears internal variables to implement a factory reset of the Wi-Fi
842* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
843*
844* @param None
845*
846* @return The status of the operation.
847* @retval RETURN_OK if successful.
848* @retval RETURN_ERR if any error is detected
849*
850* @execution Synchronous
851* @sideeffect None
852*
853* @note This function must not suspend and must not invoke any blocking system
854* calls. It should probably just send a message to a driver event handler task.
855*
856*/
857INT wifi_factoryReset()
858{
859 char cmd[128];
860
861 /*delete running hostapd conf files*/
862 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
863 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
864 system(cmd);
865 system("systemctl restart hostapd.service");
866
867 return RETURN_OK;
868}
869
870/* wifi_factoryResetRadios() function */
871/**
872* @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.
873*
874* @param None
875* @return The status of the operation
876* @retval RETURN_OK if successful
877* @retval RETURN_ERR if any error is detected
878*
879* @execution Synchronous
880*
881* @sideeffect None
882*
883* @note This function must not suspend and must not invoke any blocking system
884* calls. It should probably just send a message to a driver event handler task.
885*
886*/
887INT wifi_factoryResetRadios()
888{
889 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
890 return RETURN_OK;
891
892 return RETURN_ERR;
893}
894
895
896/* wifi_factoryResetRadio() function */
897/**
898* @description Restore selected radio parameters without touching access point parameters
899*
900* @param radioIndex - Index of Wi-Fi Radio channel
901*
902* @return The status of the operation.
903* @retval RETURN_OK if successful.
904* @retval RETURN_ERR if any error is detected
905*
906* @execution Synchronous.
907* @sideeffect None.
908*
909* @note This function must not suspend and must not invoke any blocking system
910* calls. It should probably just send a message to a driver event handler task.
911*
912*/
913INT wifi_factoryResetRadio(int radioIndex) //RDKB
914{
developer5ff7f5f2022-09-13 15:12:16 +0800915 system("systemctl stop hostapd.service");
916
developer06a01d92022-09-07 16:32:39 +0800917 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
918 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800919 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800920 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800921 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800922 else
923 return RETURN_ERR;
924
developer5ff7f5f2022-09-13 15:12:16 +0800925 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800926 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
927 return RETURN_OK;
928}
929
930/* wifi_initRadio() function */
931/**
932* Description: This function call initializes the specified radio.
933* Implementation specifics may dictate the functionality since
934* different hardware implementations may have different initilization requirements.
935* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
936*
937* @return The status of the operation.
938* @retval RETURN_OK if successful.
939* @retval RETURN_ERR if any error is detected
940*
941* @execution Synchronous.
942* @sideeffect None.
943*
944* @note This function must not suspend and must not invoke any blocking system
945* calls. It should probably just send a message to a driver event handler task.
946*
947*/
948INT wifi_initRadio(INT radioIndex)
949{
950 //TODO: Initializes the wifi subsystem (for specified radio)
951 return RETURN_OK;
952}
953void macfilter_init()
954{
955 char count[4]={'\0'};
956 char buf[253]={'\0'};
957 char tmp[19]={'\0'};
958 int dev_count,block,mac_entry=0;
959 char res[4]={'\0'};
960 char acl_file_path[64] = {'\0'};
961 FILE *fp = NULL;
962 int index=0;
963 char iface[10]={'\0'};
964 char config_file[MAX_BUF_SIZE] = {0};
965
966
967 sprintf(acl_file_path,"/tmp/mac_filter.sh");
968
969 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800970 if (fp == NULL) {
971 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
972 return RETURN_ERR;
973 }
developer06a01d92022-09-07 16:32:39 +0800974 sprintf(buf,"#!/bin/sh \n");
975 fprintf(fp,"%s\n",buf);
976
977 system("chmod 0777 /tmp/mac_filter.sh");
978
979 for(index=0;index<=1;index++)
980 {
981 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
982 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
983 sprintf(buf,"syscfg get %dcountfilter",index);
984 _syscmd(buf,count,sizeof(count));
985 mac_entry=atoi(count);
986
987 sprintf(buf,"syscfg get %dblockall",index);
988 _syscmd(buf,res,sizeof(res));
989 block = atoi(res);
990
991 //Allow only those macs mentioned in ACL
992 if(block==1)
993 {
994 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
995 fprintf(fp,"%s\n",buf);
996 for(dev_count=1;dev_count<=mac_entry;dev_count++)
997 {
998 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
999 _syscmd(buf,tmp,sizeof(tmp));
1000 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1001 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1002 fprintf(fp,"%s\n",buf);
1003 }
1004 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1005 fprintf(fp,"%s\n",buf);
1006 }
1007
1008 //Block all the macs mentioned in ACL
1009 else if(block==2)
1010 {
1011 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1012 fprintf(fp,"%s\n",buf);
1013
1014 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1015 {
1016 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1017 _syscmd(buf,tmp,sizeof(tmp));
1018 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1019 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1020 fprintf(fp,"%s\n",buf);
1021 }
1022 }
1023 }
1024 fclose(fp);
1025}
1026
1027// Initializes the wifi subsystem (all radios)
1028INT wifi_init() //RDKB
1029{
1030 char interface[MAX_BUF_SIZE]={'\0'};
1031 char bridge_name[MAX_BUF_SIZE]={'\0'};
1032 INT len=0;
1033
1034 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1035 //Not intitializing macfilter for Turris-Omnia Platform for now
1036 //macfilter_init();
1037
1038 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001039 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001040 sleep(2);//sleep to wait for hostapd to start
1041
1042 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1043
1044 return RETURN_OK;
1045}
1046
1047/* wifi_reset() function */
1048/**
1049* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1050* Implementation specifics may dictate what is actualy reset since
1051* different hardware implementations may have different requirements.
1052* Parameters : None
1053*
1054* @return The status of the operation.
1055* @retval RETURN_OK if successful.
1056* @retval RETURN_ERR if any error is detected
1057*
1058* @execution Synchronous.
1059* @sideeffect None.
1060*
1061* @note This function must not suspend and must not invoke any blocking system
1062* calls. It should probably just send a message to a driver event handler task.
1063*
1064*/
1065INT wifi_reset()
1066{
1067 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001068 system("systemctl stop hostapd.service");
1069 sleep(2);
1070 system("systemctl start hostapd.service");
1071 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001072 return RETURN_OK;
1073}
1074
1075/* wifi_down() function */
1076/**
1077* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1078* Implementation specifics may dictate some functionality since
1079* different hardware implementations may have different requirements.
1080*
1081* @param None
1082*
1083* @return The status of the operation
1084* @retval RETURN_OK if successful
1085* @retval RETURN_ERR if any error is detected
1086*
1087* @execution Synchronous
1088* @sideeffect None
1089*
1090* @note This function must not suspend and must not invoke any blocking system
1091* calls. It should probably just send a message to a driver event handler task.
1092*
1093*/
1094INT wifi_down()
1095{
1096 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001097 system("systemctl stop hostapd.service");
1098 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001099 return RETURN_OK;
1100}
1101
1102
1103/* wifi_createInitialConfigFiles() function */
1104/**
1105* @description This function creates wifi configuration files. The format
1106* and content of these files are implementation dependent. This function call is
1107* used to trigger this task if necessary. Some implementations may not need this
1108* function. If an implementation does not need to create config files the function call can
1109* do nothing and return RETURN_OK.
1110*
1111* @param None
1112*
1113* @return The status of the operation
1114* @retval RETURN_OK if successful
1115* @retval RETURN_ERR if any error is detected
1116*
1117* @execution Synchronous
1118* @sideeffect None
1119*
1120* @note This function must not suspend and must not invoke any blocking system
1121* calls. It should probably just send a message to a driver event handler task.
1122*
1123*/
1124INT wifi_createInitialConfigFiles()
1125{
1126 //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)
1127 return RETURN_OK;
1128}
1129
1130// outputs the country code to a max 64 character string
1131INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1132{
developerd946fd62022-12-08 18:03:28 +08001133 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001134 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001135 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001136 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001137
developerac6f1142022-12-20 19:26:35 +08001138 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001139 return RETURN_ERR;
1140 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001141 _syscmd(cmd, buf, sizeof(buf));
1142 if(strlen(buf) > 0)
1143 snprintf(output_string, 64, "%s", buf);
1144 else
1145 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001146
1147 return RETURN_OK;
1148}
1149
1150INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1151{
1152 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001153 char str[MAX_BUF_SIZE]={'\0'};
1154 char cmd[MAX_CMD_SIZE]={'\0'};
1155 struct params params;
1156 char config_file[MAX_BUF_SIZE] = {0};
1157
1158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1159 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1160 return RETURN_ERR;
1161
developerb86c6f32022-10-07 14:34:58 +08001162 if (strlen(CountryCode) == 0)
1163 strcpy(CountryCode, "US");
1164
developer7543b3b2022-09-13 13:47:17 +08001165 params.name = "country_code";
1166 params.value = CountryCode;
1167 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1168 int ret = wifi_hostapdWrite(config_file, &params, 1);
1169 if (ret) {
1170 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1171 ,__func__, ret);
1172 }
1173
1174 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1175 if (ret) {
1176 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1177 ,__func__, ret);
1178 }
developer7543b3b2022-09-13 13:47:17 +08001179 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1180
developer06a01d92022-09-07 16:32:39 +08001181 return RETURN_OK;
1182}
1183
developera748dcf2022-09-13 15:56:48 +08001184INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1185{
developerd946fd62022-12-08 18:03:28 +08001186 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001187 char channel_util_file[64] = {0};
1188 char cmd[128] = {0};
1189 char buf[128] = {0};
1190 char line[128] = {0};
1191 char *param = NULL, *value = NULL;
1192 int read = 0;
1193 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1194 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1195 size_t len = 0;
1196 FILE *f = NULL;
1197
1198 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1199
developerac6f1142022-12-20 19:26:35 +08001200 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001201 return RETURN_ERR;
1202 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001203 _syscmd(cmd, buf, sizeof(buf));
1204 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1205
1206 memset(cmd, 0, sizeof(cmd));
1207 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001208 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001209 if ((f = popen(cmd, "r")) == NULL) {
1210 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1211 return RETURN_ERR;
1212 }
1213
1214 read = getline(&line, &len, f);
1215 while (read != -1) {
1216 param = strtok(line, ":\t");
1217 value = strtok(NULL, " ");
1218 if(strstr(param, "frequency") != NULL) {
1219 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1220 }
1221 if(strstr(param, "noise") != NULL) {
1222 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1223 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1224 }
1225 if(strstr(param, "channel active time") != NULL) {
1226 ActiveTime = strtol(value, NULL, 10);
1227 }
1228 if(strstr(param, "channel busy time") != NULL) {
1229 BusyTime = strtol(value, NULL, 10);
1230 }
1231 if(strstr(param, "channel transmit time") != NULL) {
1232 TransmitTime = strtol(value, NULL, 10);
1233 }
1234 read = getline(&line, &len, f);
1235 }
1236 pclose(f);
1237
1238 // The file should store the last active, busy and transmit time
1239 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1240 f = fopen(channel_util_file, "r");
1241 if (f != NULL) {
1242 read = getline(&line, &len, f);
1243 preActiveTime = strtol(line, NULL, 10);
1244 read = getline(&line, &len, f);
1245 preBusyTime = strtol(line, NULL, 10);
1246 read = getline(&line, &len, f);
1247 preTransmitTime = strtol(line, NULL, 10);
1248 fclose(f);
1249 }
1250
1251 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1252 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1253
1254 f = fopen(channel_util_file, "w");
1255 if (f != NULL) {
1256 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1257 fclose(f);
1258 }
1259 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1260 return RETURN_OK;
1261}
1262
developer06a01d92022-09-07 16:32:39 +08001263/**********************************************************************************
1264 *
1265 * Wifi radio level function prototypes
1266 *
1267**********************************************************************************/
1268
1269//Get the total number of radios in this wifi subsystem
1270INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1271{
1272 if (NULL == output)
1273 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001274 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001275
1276 return RETURN_OK;
1277}
1278
1279//Get the total number of SSID entries in this wifi subsystem
1280INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1281{
1282 if (NULL == output)
1283 return RETURN_ERR;
1284 *output = MAX_APS;
1285
1286 return RETURN_OK;
1287}
1288
1289//Get the Radio enable config parameter
1290INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1291{
developerd946fd62022-12-08 18:03:28 +08001292 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001293 char buf[128] = {0}, cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08001294
1295 if (NULL == output_bool)
1296 return RETURN_ERR;
1297
1298 *output_bool = FALSE;
developer804c64f2022-10-19 13:54:40 +08001299 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001300 return RETURN_ERR;
1301
developerac6f1142022-12-20 19:26:35 +08001302 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001303 return RETURN_ERR;
1304 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
developercf48e482022-09-13 14:49:50 +08001305 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001306
developercf48e482022-09-13 14:49:50 +08001307 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1308 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08001309 return RETURN_OK;
1310}
1311
1312INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1313{
developerd946fd62022-12-08 18:03:28 +08001314 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001315 char cmd[MAX_CMD_SIZE] = {0};
1316 char buf[MAX_CMD_SIZE] = {0};
1317 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001318 int max_radio_num = 0;
1319 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001320
1321 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001322
1323 phyId = radio_index_to_phy(radioIndex);
1324
1325 wifi_getMaxRadioNumber(&max_radio_num);
1326
developerac6f1142022-12-20 19:26:35 +08001327 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001328 return RETURN_ERR;
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 {
1333 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001334 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001335 _syscmd(cmd, buf, sizeof(buf));
1336 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001337 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1338 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08001339 _syscmd(cmd, buf, sizeof(buf));
1340 }
developer06a01d92022-09-07 16:32:39 +08001341 }
1342 else
1343 {
developer033b37b2022-10-18 11:27:46 +08001344 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001345 {
developer431128d2022-12-16 15:30:41 +08001346 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
developer06a01d92022-09-07 16:32:39 +08001347 ret = _syscmd(cmd, buf, sizeof(buf));
1348 if ( ret == RETURN_ERR)
1349 {
1350 fprintf(stderr, "VAP interface creation failed\n");
1351 continue;
1352 }
developerd946fd62022-12-08 18:03:28 +08001353 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001354 _syscmd(cmd, buf, sizeof(buf));
1355 if(*buf == '1')
1356 {
1357 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001358 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001359 _syscmd(cmd, buf, sizeof(buf));
1360 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001361 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001362 }
1363 }
1364 }
1365
1366 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1367 return RETURN_OK;
1368}
1369
1370//Get the Radio enable status
1371INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1372{
1373 if (NULL == output_bool)
1374 return RETURN_ERR;
1375
1376 return wifi_getRadioEnable(radioIndex, output_bool);
1377}
1378
1379//Get the Radio Interface name from platform, eg "wlan0"
1380INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1381{
developer804c64f2022-10-19 13:54:40 +08001382 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001383 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001384 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001385}
1386
1387//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1388//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.
1389INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1390{
developerbcc556a2022-09-22 20:02:45 +08001391 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1392 // For max bit rate, we should always choose the best MCS
1393 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001394 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001395 char *tmp = NULL;
1396 UINT mode_map = 0;
1397 UINT num_subcarrier = 0;
1398 UINT code_bits = 0;
1399 float code_rate = 0; // use max code rate
1400 int NSS = 0;
1401 UINT Symbol_duration = 0;
1402 UINT GI_duration = 0;
1403 wifi_band band = band_invalid;
1404 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1405 BOOL enable = FALSE;
1406 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001407
1408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1409 if (NULL == output_string)
1410 return RETURN_ERR;
1411
developerbcc556a2022-09-22 20:02:45 +08001412 wifi_getRadioEnable(radioIndex, &enable);
1413 if (enable == FALSE) {
1414 snprintf(output_string, 64, "0 Mb/s");
1415 return RETURN_OK;
1416 }
1417
1418 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1419 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1420 return RETURN_ERR;
1421 }
1422
1423 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1424 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1425 return RETURN_ERR;
1426 }
1427
1428 if (gi == wifi_guard_interval_3200)
1429 GI_duration = 32;
1430 else if (gi == wifi_guard_interval_1600)
1431 GI_duration = 16;
1432 else if (gi == wifi_guard_interval_800)
1433 GI_duration = 8;
1434 else // auto, 400
1435 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001436
developerbcc556a2022-09-22 20:02:45 +08001437 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1438 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1439 return RETURN_ERR;
1440 }
1441
1442 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1443 strcpy(channel_bandwidth_str, "160");
1444
1445 if (mode_map & WIFI_MODE_AX) {
1446 if (strstr(channel_bandwidth_str, "160") != NULL)
1447 num_subcarrier = 1960;
1448 else if (strstr(channel_bandwidth_str, "80") != NULL)
1449 num_subcarrier = 980;
1450 else if (strstr(channel_bandwidth_str, "40") != NULL)
1451 num_subcarrier = 468;
1452 else if (strstr(channel_bandwidth_str, "20") != NULL)
1453 num_subcarrier = 234;
1454 code_bits = 10;
1455 code_rate = (float)5/6;
1456 Symbol_duration = 128;
1457 } else if (mode_map & WIFI_MODE_AC) {
1458 if (strstr(channel_bandwidth_str, "160") != NULL)
1459 num_subcarrier = 468;
1460 else if (strstr(channel_bandwidth_str, "80") != NULL)
1461 num_subcarrier = 234;
1462 else if (strstr(channel_bandwidth_str, "40") != NULL)
1463 num_subcarrier = 108;
1464 else if (strstr(channel_bandwidth_str, "20") != NULL)
1465 num_subcarrier = 52;
1466 code_bits = 8;
1467 code_rate = (float)5/6;
1468 Symbol_duration = 32;
1469 } else if (mode_map & WIFI_MODE_N) {
1470 if (strstr(channel_bandwidth_str, "160") != NULL)
1471 num_subcarrier = 468;
1472 else if (strstr(channel_bandwidth_str, "80") != NULL)
1473 num_subcarrier = 234;
1474 else if (strstr(channel_bandwidth_str, "40") != NULL)
1475 num_subcarrier = 108;
1476 else if (strstr(channel_bandwidth_str, "20") != NULL)
1477 num_subcarrier = 52;
1478 code_bits = 6;
1479 code_rate = (float)3/4;
1480 Symbol_duration = 32;
1481 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1482 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1483 snprintf(output_string, 64, "65 Mb/s");
1484 return RETURN_OK;
1485 } else {
1486 snprintf(output_string, 64, "0 Mb/s");
1487 return RETURN_OK;
1488 }
developer06a01d92022-09-07 16:32:39 +08001489
developerbcc556a2022-09-22 20:02:45 +08001490 // Spatial streams
1491 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1492 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1493 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001494 }
developerbcc556a2022-09-22 20:02:45 +08001495
1496 // multiple 10 is to align duration unit (0.1 us)
1497 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1498 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1499
developer06a01d92022-09-07 16:32:39 +08001500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1501
1502 return RETURN_OK;
1503}
1504#if 0
1505INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1506{
1507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1508 char cmd[64];
1509 char buf[1024];
1510 int apIndex;
1511
1512 if (NULL == output_string)
1513 return RETURN_ERR;
1514
1515 apIndex=(radioIndex==0)?0:1;
1516
developerd946fd62022-12-08 18:03:28 +08001517 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001518 _syscmd(cmd,buf, sizeof(buf));
1519
1520 snprintf(output_string, 64, "%s", buf);
1521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1522 return RETURN_OK;
1523}
1524#endif
1525
1526
1527//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1528//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.
1529INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1530{
developer963da0c2022-09-13 15:58:27 +08001531 wifi_band band = band_invalid;
1532
developer06a01d92022-09-07 16:32:39 +08001533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1534 if (NULL == output_string)
1535 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001536
1537 band = wifi_index_to_band(radioIndex);
1538
1539 memset(output_string, 0, 10);
1540 if (band == band_2_4)
1541 strcpy(output_string, "2.4GHz");
1542 else if (band == band_5)
1543 strcpy(output_string, "5GHz");
1544 else if (band == band_6)
1545 strcpy(output_string, "6GHz");
1546 else
1547 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1549
1550 return RETURN_OK;
1551#if 0
1552 char buf[MAX_BUF_SIZE]={'\0'};
1553 char str[MAX_BUF_SIZE]={'\0'};
1554 char cmd[MAX_CMD_SIZE]={'\0'};
1555 char *ch=NULL;
1556 char *ch2=NULL;
1557
1558 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1559 if (NULL == output_string)
1560 return RETURN_ERR;
1561
1562
1563 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1564
1565 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1566 {
1567 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1568 return RETURN_ERR;
1569 }
1570 ch=strchr(buf,'\n');
1571 *ch='\0';
1572 ch=strchr(buf,'=');
1573 if(ch==NULL)
1574 return RETURN_ERR;
1575
1576
1577 ch++;
1578
1579 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1580 strcpy(buf,"0");
1581 if(strlen(ch) == 1)
1582 ch=strcat(buf,ch);
1583
1584
1585 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1586
1587 if(_syscmd(cmd,str,64) == RETURN_ERR)
1588 {
1589 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1590 return RETURN_ERR;
1591 }
1592
1593
1594 ch2=strchr(str,'\n');
1595 //replace \n with \0
1596 *ch2='\0';
1597 ch2=strchr(str,'=');
1598 if(ch2==NULL)
1599 {
1600 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1601 return RETURN_ERR;
1602 }
1603 else
1604 wifi_dbg_printf("%s",ch2+1);
1605
1606
1607 ch2++;
1608
1609
1610 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1611
1612 memset(buf,'\0',sizeof(buf));
1613 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1614 {
1615 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1616 return RETURN_ERR;
1617 }
1618 if (strstr(buf,"2.4") != NULL )
1619 strcpy(output_string,"2.4GHz");
1620 else if(strstr(buf,"5.") != NULL )
1621 strcpy(output_string,"5GHz");
1622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1623
1624 return RETURN_OK;
1625#endif
1626}
1627
1628//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1629//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.
1630INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1631{
developerb7593de2022-10-18 09:51:57 +08001632 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1634 if (NULL == output_string)
1635 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001636 band = wifi_index_to_band(radioIndex);
1637
1638 if (band == band_2_4)
1639 snprintf(output_string, 64, "2.4GHz");
1640 else if (band == band_5)
1641 snprintf(output_string, 64, "5GHz");
1642 else if (band == band_6)
1643 snprintf(output_string, 64, "6GHz");
1644
developer06a01d92022-09-07 16:32:39 +08001645 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1646
1647 return RETURN_OK;
1648#if 0
1649 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1650 char buf[MAX_BUF_SIZE]={'\0'};
1651 char str[MAX_BUF_SIZE]={'\0'};
1652 char cmd[MAX_CMD_SIZE]={'\0'};
1653 char *ch=NULL;
1654 char *ch2=NULL;
1655 char ch1[5]="0";
1656
1657 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1658
1659 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1660 {
1661 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1662 return RETURN_ERR;
1663 }
1664
1665 ch=strchr(buf,'\n');
1666 *ch='\0';
1667 ch=strchr(buf,'=');
1668 if(ch==NULL)
1669 return RETURN_ERR;
1670 ch++;
1671
1672 if(strlen(ch)==1)
1673 {
1674 strcat(ch1,ch);
1675
1676 }
1677 else
1678 {
1679 strcpy(ch1,ch);
1680 }
1681
1682
1683
1684 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1685 if(_syscmd(cmd,str,64) == RETURN_ERR)
1686 {
1687 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1688 return RETURN_ERR;
1689 }
1690
1691
1692 ch2=strchr(str,'\n');
1693 //replace \n with \0
1694 *ch2='\0';
1695 ch2=strchr(str,'=');
1696 if(ch2==NULL)
1697 {
1698 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1699 return RETURN_ERR;
1700 }
1701 else
1702 wifi_dbg_printf("%s",ch2+1);
1703 ch2++;
1704
1705
1706 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1707 memset(buf,'\0',sizeof(buf));
1708 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1709 {
1710 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1711 return RETURN_ERR;
1712 }
1713
1714
1715 if(strstr(buf,"2.4")!=NULL)
1716 {
1717 strcpy(output_string,"2.4GHz");
1718 }
1719 if(strstr(buf,"5.")!=NULL)
1720 {
1721 strcpy(output_string,"5GHz");
1722 }
1723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1724 return RETURN_OK;
1725#endif
1726}
1727
1728//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1729//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.
1730INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1731{
developer963da0c2022-09-13 15:58:27 +08001732 char cmd[128]={0};
1733 char buf[128]={0};
1734 char temp_output[128] = {0};
1735 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001736 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001737
1738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001739 if (NULL == output_string)
1740 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001741
1742 band = wifi_index_to_band(radioIndex);
1743 if (band == band_2_4) {
1744 strcat(temp_output, "b,g,");
1745 } else if (band == band_5) {
1746 strcat(temp_output, "a,");
1747 }
developer033b37b2022-10-18 11:27:46 +08001748 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001749 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001750 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 +08001751 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001752 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001753 strcat(temp_output, "n,");
1754 }
developer06a01d92022-09-07 16:32:39 +08001755
developer963da0c2022-09-13 15:58:27 +08001756 // vht capabilities
1757 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001758 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 +08001759 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001760 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001761 strcat(temp_output, "ac,");
1762 }
1763 }
1764
1765 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001766 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 +08001767 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001768 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001769 strcat(temp_output, "ax,");
1770 }
1771
1772 // Remove the last comma
1773 if (strlen(temp_output) != 0)
1774 temp_output[strlen(temp_output)-1] = '\0';
1775 strncpy(output_string, temp_output, strlen(temp_output));
1776 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001777 return RETURN_OK;
1778}
1779
1780//Get the radio operating mode, and pure mode flag. eg: "ac"
1781//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.
1782INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1783{
1784 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1785 if (NULL == output_string)
1786 return RETURN_ERR;
1787
1788 if (radioIndex == 0) {
1789 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1790 *gOnly = FALSE;
1791 *nOnly = TRUE;
1792 *acOnly = FALSE;
1793 } else {
1794 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1795 *gOnly = FALSE;
1796 *nOnly = FALSE;
1797 *acOnly = FALSE;
1798 }
1799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1800
1801 return RETURN_OK;
1802#if 0
1803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1804 char buf[64] = {0};
1805 char config_file[MAX_BUF_SIZE] = {0};
1806
1807 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1808 return RETURN_ERR;
1809
1810 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1811 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1812
1813 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1814 if (strlen(buf) == 0)
1815 {
1816 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1817 return RETURN_ERR;
1818 }
1819 if(strcmp(buf,"g")==0)
1820 {
1821 wifi_dbg_printf("\nG\n");
1822 *gOnly=TRUE;
1823 *nOnly=FALSE;
1824 *acOnly=FALSE;
1825 }
1826 else if(strcmp(buf,"n")==0)
1827 {
1828 wifi_dbg_printf("\nN\n");
1829 *gOnly=FALSE;
1830 *nOnly=TRUE;
1831 *acOnly=FALSE;
1832 }
1833 else if(strcmp(buf,"ac")==0)
1834 {
1835 wifi_dbg_printf("\nac\n");
1836 *gOnly=FALSE;
1837 *nOnly=FALSE;
1838 *acOnly=TRUE;
1839 }
1840 /* hostapd-5G.conf has "a" as hw_mode */
1841 else if(strcmp(buf,"a")==0)
1842 {
1843 wifi_dbg_printf("\na\n");
1844 *gOnly=FALSE;
1845 *nOnly=FALSE;
1846 *acOnly=FALSE;
1847 }
1848 else
1849 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1850
1851 //for a,n mode
1852 if(radioIndex == 1)
1853 {
1854 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1855 if(strcmp(buf,"1")==0)
1856 {
1857 strncpy(output_string, "n", 1);
1858 *nOnly=FALSE;
1859 }
1860 }
1861
1862 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1863 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1864 return RETURN_OK;
1865#endif
1866}
1867
developerdb744382022-09-13 15:34:54 +08001868INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1869{
1870 char cmd[128] = {0};
1871 char buf[64] = {0};
1872 char config_file[64] = {0};
1873 wifi_band band;
1874
1875 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1876 if(NULL == output_string || NULL == pureMode)
1877 return RETURN_ERR;
1878
1879 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001880 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerdb744382022-09-13 15:34:54 +08001881 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1882 _syscmd(cmd, buf, sizeof(buf));
1883
1884 band = wifi_index_to_band(radioIndex);
1885 // puremode is a bit map
1886 *pureMode = 0;
1887 if (band == band_2_4) {
1888 strcat(output_string, "b,g");
1889 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1890 if (strstr(buf, "n") != NULL) {
1891 strcat(output_string, ",n");
1892 *pureMode |= WIFI_MODE_N;
1893 }
1894 if (strstr(buf, "ax") != NULL) {
1895 strcat(output_string, ",ax");
1896 *pureMode |= WIFI_MODE_AX;
1897 }
1898 } else if (band == band_5) {
1899 strcat(output_string, "a");
1900 *pureMode |= WIFI_MODE_A;
1901 if (strstr(buf, "n") != NULL) {
1902 strcat(output_string, ",n");
1903 *pureMode |= WIFI_MODE_N;
1904 }
1905 if (strstr(buf, "ac") != NULL) {
1906 strcat(output_string, ",ac");
1907 *pureMode |= WIFI_MODE_AC;
1908 }
1909 if (strstr(buf, "ax") != NULL) {
1910 strcat(output_string, ",ax");
1911 *pureMode |= WIFI_MODE_AX;
1912 }
1913 } else if (band == band_6) {
1914 if (strstr(buf, "ax") != NULL) {
1915 strcat(output_string, "ax");
1916 *pureMode |= WIFI_MODE_AX;
1917 }
1918 }
1919
1920 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1921 return RETURN_OK;
1922}
1923
1924// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001925INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1926{
1927 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1928 if (strcmp (channelMode,"11A") == 0)
1929 {
1930 writeBandWidth(radioIndex,"20MHz");
1931 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1932 printf("\nChannel Mode is 802.11a (5GHz)\n");
1933 }
1934 else if (strcmp (channelMode,"11NAHT20") == 0)
1935 {
1936 writeBandWidth(radioIndex,"20MHz");
1937 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1938 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1939 }
1940 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1941 {
1942 writeBandWidth(radioIndex,"40MHz");
1943 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1944 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1945 }
1946 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1947 {
1948 writeBandWidth(radioIndex,"40MHz");
1949 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1950 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1951 }
1952 else if (strcmp (channelMode,"11ACVHT20") == 0)
1953 {
1954 writeBandWidth(radioIndex,"20MHz");
1955 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1956 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1957 }
1958 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1959 {
1960 writeBandWidth(radioIndex,"40MHz");
1961 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1962 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1963 }
1964 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1965 {
1966 writeBandWidth(radioIndex,"40MHz");
1967 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1968 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1969 }
1970 else if (strcmp (channelMode,"11ACVHT80") == 0)
1971 {
1972 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1973 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1974 }
1975 else if (strcmp (channelMode,"11ACVHT160") == 0)
1976 {
1977 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1978 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1979 }
1980 else if (strcmp (channelMode,"11B") == 0)
1981 {
1982 writeBandWidth(radioIndex,"20MHz");
1983 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1984 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1985 }
1986 else if (strcmp (channelMode,"11G") == 0)
1987 {
1988 writeBandWidth(radioIndex,"20MHz");
1989 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1990 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1991 }
1992 else if (strcmp (channelMode,"11NGHT20") == 0)
1993 {
1994 writeBandWidth(radioIndex,"20MHz");
1995 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1996 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1997 }
1998 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1999 {
2000 writeBandWidth(radioIndex,"40MHz");
2001 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2002 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2003 }
2004 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2005 {
2006 writeBandWidth(radioIndex,"40MHz");
2007 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2008 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2009 }
2010 else
2011 {
2012 return RETURN_ERR;
2013 }
2014 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2015
2016 return RETURN_OK;
2017}
2018
developerdb744382022-09-13 15:34:54 +08002019// Set the radio operating mode, and pure mode flag.
2020INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2021{
2022 int num_hostapd_support_mode = 3; // n, ac, ax
2023 struct params list[num_hostapd_support_mode];
2024 char config_file[64] = {0};
2025 char bandwidth[16] = {0};
2026 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002027
developerdb744382022-09-13 15:34:54 +08002028
2029 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2030 // Set radio mode
2031 list[0].name = "ieee80211n";
2032 list[1].name = "ieee80211ac";
2033 list[2].name = "ieee80211ax";
2034 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2035
2036 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002037 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002038 list[0].value = "1";
2039 else
2040 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002041 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002042 list[1].value = "1";
2043 else
2044 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002045 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002046 list[2].value = "1";
2047 else
2048 list[2].value = "0";
2049 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2050
2051 if (channelMode == NULL || strlen(channelMode) == 0)
2052 return RETURN_OK;
2053 // Set bandwidth
2054 if (strstr(channelMode, "40") != NULL)
2055 strcpy(bandwidth, "40MHz");
2056 else if (strstr(channelMode, "80") != NULL)
2057 strcpy(bandwidth, "80MHz");
2058 else if (strstr(channelMode, "160") != NULL)
2059 strcpy(bandwidth, "160MHz");
2060 else // 11A, 11B, 11G....
2061 strcpy(bandwidth, "20MHz");
2062
2063 writeBandWidth(radioIndex, bandwidth);
2064 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2065
2066 wifi_reloadAp(radioIndex);
2067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2068
2069 return RETURN_OK;
2070}
2071
developer1d12ebf2022-10-04 15:13:38 +08002072INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2073
2074 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002075 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002076 struct params params = {0};
2077 wifi_band band = band_invalid;
2078
2079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2080
2081 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002082
2083 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002084 return RETURN_ERR;
2085 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2086 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002087 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2088 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002089
2090 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2091 params.name = "hw_mode";
2092 params.value = hw_mode;
2093 wifi_hostapdWrite(config_file, &params, 1);
2094 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2095
developeref938762022-10-19 17:21:01 +08002096 if (band == band_2_4) {
2097 if (strncmp(hw_mode, "b", 1) == 0) {
2098 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2099 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2100 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2101 snprintf(buf, sizeof(buf), "%s", "1,2");
2102 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2103 } else {
2104 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2105
2106 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2107 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2108 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2109 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2110 }
2111 }
2112
developer1d12ebf2022-10-04 15:13:38 +08002113 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2114 return RETURN_OK;
2115}
2116
developere8988ba2022-10-18 17:42:30 +08002117INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2118{
2119 char config_file[64] = {0};
2120 struct params params = {0};
2121 wifi_band band = band_invalid;
2122
2123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2124
2125 band = wifi_index_to_band(radioIndex);
developer30423732022-12-01 16:17:49 +08002126 if (band != band_2_4)
2127 return RETURN_OK;
developere8988ba2022-10-18 17:42:30 +08002128
2129 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2130 params.name = "noscan";
2131 params.value = noscan;
2132 wifi_hostapdWrite(config_file, &params, 1);
2133 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2134
2135 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2136 return RETURN_OK;
2137}
2138
developer06a01d92022-09-07 16:32:39 +08002139//Get the list of supported channel. eg: "1-11"
2140//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.
2141INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2142{
developer6318ed52022-09-13 15:17:58 +08002143 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002144 if (NULL == output_string)
2145 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002146 char cmd[256] = {0};
2147 char buf[128] = {0};
2148 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002149 int phyId = 0;
2150
developer6318ed52022-09-13 15:17:58 +08002151 // Parse possible channel number and separate them with commas.
2152 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002153 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002154 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002155 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002156 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 +08002157 else
developer033b37b2022-10-18 11:27:46 +08002158 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 +08002159
2160 _syscmd(cmd,buf,sizeof(buf));
2161 strncpy(output_string, buf, sizeof(buf));
2162
2163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2164 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002165}
2166
2167//Get the list for used channel. eg: "1,6,9,11"
2168//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.
2169INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2170{
developerd946fd62022-12-08 18:03:28 +08002171 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002172 char cmd[128] = {0};
2173 char buf[128] = {0};
2174 char config_file[64] = {0};
2175 int channel = 0;
2176 int freq = 0;
2177 int bandwidth = 0;
2178 int center_freq = 0;
2179 int center_channel = 0;
2180 int channel_delta = 0;
2181 wifi_band band = band_invalid;
2182
2183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2184
developer06a01d92022-09-07 16:32:39 +08002185 if (NULL == output_string)
2186 return RETURN_ERR;
2187
developerac6f1142022-12-20 19:26:35 +08002188 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002189 return RETURN_ERR;
2190 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002191 _syscmd(cmd, buf, sizeof(buf));
2192 if (strlen(buf) == 0) {
2193 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2194 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002195 }
developerf5745ee2022-10-05 16:09:53 +08002196 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2197
2198 if (bandwidth == 20) {
2199 snprintf(output_string, 256, "%d", channel);
2200 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002201 }
developerf5745ee2022-10-05 16:09:53 +08002202
2203 center_channel = ieee80211_frequency_to_channel(center_freq);
2204
2205 band = wifi_index_to_band(radioIndex);
2206 if (band == band_2_4 && bandwidth == 40) {
2207 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2208 memset(buf, 0, sizeof(buf));
2209 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2210
developerf22724d2022-12-22 17:24:14 +08002211 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002212 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002213 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002214 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2215 } else {
2216 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2217 return RETURN_ERR;
2218 }
2219 } else if (band == band_5 || band == band_6){
2220 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2221 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2222 channel_delta = (bandwidth-20)/10;
2223 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2224 } else
2225 return RETURN_ERR;
2226
2227 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002228 return RETURN_OK;
2229}
2230
2231//Get the running channel number
2232INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2233{
developer5b398df2022-11-17 20:39:48 +08002234 char channel_str[16] = {0};
2235 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002236
developer5b398df2022-11-17 20:39:48 +08002237 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002238 return RETURN_ERR;
2239
developer5b398df2022-11-17 20:39:48 +08002240 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2241 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002242
developer5b398df2022-11-17 20:39:48 +08002243 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002244
developer06a01d92022-09-07 16:32:39 +08002245 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002246}
2247
2248
2249INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2250{
2251 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002252 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002253
2254 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2255 if (NULL == output_ulong)
2256 return RETURN_ERR;
2257
developer06a01d92022-09-07 16:32:39 +08002258 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002259 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2260 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002261 _syscmd(cmd,buf,sizeof(buf));
2262 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2263 if (*output_ulong == 0) {
2264 return RETURN_ERR;
2265 }
2266
2267 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2268 return RETURN_OK;
2269}
2270
2271//Storing the previous channel value
2272INT wifi_storeprevchanval(INT radioIndex)
2273{
2274 char buf[256] = {0};
2275 char output[4]={'\0'};
2276 char config_file[MAX_BUF_SIZE] = {0};
2277 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2278 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2279 if(radioIndex == 0)
2280 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2281 else if(radioIndex == 1)
2282 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2283 system(buf);
2284 Radio_flag = FALSE;
2285 return RETURN_OK;
2286}
2287
2288//Set the running channel number
2289INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2290{
developer76989232022-10-04 14:13:19 +08002291 // We only write hostapd config here
2292 char str_channel[8]={0};
2293 char *list_channel;
2294 char config_file[128] = {0};
2295 char possible_channels[256] = {0};
2296 int max_radio_num = 0;
2297 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002298
developer76989232022-10-04 14:13:19 +08002299 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002300
developer76989232022-10-04 14:13:19 +08002301 // Check valid
2302 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002303
developer76989232022-10-04 14:13:19 +08002304 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2305 list_channel = strtok(possible_channels, ",");
2306 while(true)
developer06a01d92022-09-07 16:32:39 +08002307 {
developer76989232022-10-04 14:13:19 +08002308 if(list_channel == NULL) { // input not in the list
2309 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2310 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002311 }
developer76989232022-10-04 14:13:19 +08002312 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2313 break;
2314 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002315 }
2316
developer76989232022-10-04 14:13:19 +08002317 list.name = "channel";
2318 list.value = str_channel;
2319 wifi_getMaxRadioNumber(&max_radio_num);
2320 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002321 {
developer76989232022-10-04 14:13:19 +08002322 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2323 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002324 }
2325
developer76989232022-10-04 14:13:19 +08002326 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002327 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002328}
developer06a01d92022-09-07 16:32:39 +08002329
2330INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2331{
developer76989232022-10-04 14:13:19 +08002332 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002333 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002334 char config_file[64];
2335 int max_num_radios = 0;
2336 wifi_band band = band_invalid;
2337
2338 band = wifi_index_to_band(radioIndex);
2339 if (band == band_2_4)
2340 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002341
developer30423732022-12-01 16:17:49 +08002342 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002343 list[0].name = "vht_oper_centr_freq_seg0_idx";
2344 list[0].value = str_idx;
2345 list[1].name = "he_oper_centr_freq_seg0_idx";
2346 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002347
developer76989232022-10-04 14:13:19 +08002348 wifi_getMaxRadioNumber(&max_num_radios);
2349 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002350 {
developer76989232022-10-04 14:13:19 +08002351 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2352 if (band == band_6)
2353 wifi_hostapdWrite(config_file, &list[1], 1);
2354 else
2355 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002356 }
2357
2358 return RETURN_OK;
2359}
2360
2361//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2362//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2363INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2364{
2365 //Set to wifi config only. Wait for wifi reset to apply.
2366 char buf[256] = {0};
2367 char str_channel[256] = {0};
2368 int count = 0;
2369 ULONG Value = 0;
2370 FILE *fp = NULL;
2371 if(enable == TRUE)
2372 {
developer06a01d92022-09-07 16:32:39 +08002373 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002374 }
developer5884e982022-10-06 10:52:50 +08002375 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002376}
2377
developer0b246d12022-09-30 15:24:20 +08002378INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2379{
2380 if (output_bool == NULL)
2381 return RETURN_ERR;
2382
2383 *output_bool = TRUE;
2384
2385 return RETURN_OK;
2386}
2387
developer06a01d92022-09-07 16:32:39 +08002388INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2389{
2390 if (NULL == output_bool)
2391 return RETURN_ERR;
2392 *output_bool=FALSE;
2393 return RETURN_OK;
2394}
2395
2396INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2397{
2398 if (NULL == output_bool)
2399 return RETURN_ERR;
2400 *output_bool=FALSE;
2401 return RETURN_OK;
2402}
2403
2404INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2405{
2406 //Set to wifi config only. Wait for wifi reset to apply.
2407 return RETURN_OK;
2408}
2409
2410INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2411{
2412 return RETURN_OK;
2413}
2414
2415INT wifi_factoryResetAP(int apIndex)
2416{
developer838cca92022-10-03 13:19:57 +08002417 char ap_config_file[64] = {0};
2418 char cmd[128] = {0};
2419
developer06a01d92022-09-07 16:32:39 +08002420 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002421
2422 wifi_setApEnable(apIndex, FALSE);
2423 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2424 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2425 wifi_setApEnable(apIndex, TRUE);
2426
developer06a01d92022-09-07 16:32:39 +08002427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002428
developer06a01d92022-09-07 16:32:39 +08002429 return RETURN_OK;
2430}
2431
2432//To set Band Steering AP group
2433//To-do
2434INT wifi_setBandSteeringApGroup(char *ApGroup)
2435{
2436 return RETURN_OK;
2437}
2438
developer1e5aa162022-09-13 16:06:24 +08002439INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2440{
2441 char config_file[128] = {'\0'};
2442 char buf[128] = {'\0'};
2443
2444 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2445 if (dtimInterval == NULL)
2446 return RETURN_ERR;
2447
2448 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2449 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2450
2451 if (strlen(buf) == 0) {
2452 *dtimInterval = 2;
2453 } else {
2454 *dtimInterval = strtoul(buf, NULL, 10);
2455 }
2456
2457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2458 return RETURN_OK;
2459}
2460
developer06a01d92022-09-07 16:32:39 +08002461INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2462{
developer5f222492022-09-13 15:21:52 +08002463 struct params params={0};
2464 char config_file[MAX_BUF_SIZE] = {'\0'};
2465 char buf[MAX_BUF_SIZE] = {'\0'};
2466
2467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2468 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002469 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002470 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002471 }
2472
2473 params.name = "dtim_period";
2474 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2475 params.value = buf;
2476
2477 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2478 wifi_hostapdWrite(config_file, &params, 1);
2479 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2480
2481 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2482 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002483}
2484
2485//Check if the driver support the Dfs
2486INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2487{
developer78a15382022-11-02 10:57:40 +08002488 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002489 if (NULL == output_bool)
2490 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002491 *output_bool=FALSE;
2492
2493 band = wifi_index_to_band(radioIndex);
2494 if (band == band_5)
2495 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002496 return RETURN_OK;
2497}
2498
2499//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.
2500//The value of this parameter is a comma seperated list of channel number
2501INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2502{
2503 if (NULL == output_pool)
2504 return RETURN_ERR;
2505 if (radioIndex==1)
2506 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2507 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2508
2509 return RETURN_OK;
2510}
2511
2512INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2513{
2514 //Set to wifi config. And apply instantly.
2515 return RETURN_OK;
2516}
2517
2518INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2519{
2520 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2521 return RETURN_ERR;
2522 *output_interval_seconds=1800;
2523 *output_dwell_milliseconds=40;
2524
2525 return RETURN_OK;
2526}
2527
2528INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2529{
2530 //Set to wifi config. And apply instantly.
2531 return RETURN_OK;
2532}
2533
developerbfc18512022-10-05 17:54:28 +08002534INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2535{
2536 if (output_bool == NULL)
2537 return RETURN_ERR;
2538 *output_bool = true;
2539 return RETURN_OK;
2540}
2541
2542INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2543{
2544 return RETURN_OK;
2545}
2546
developer06a01d92022-09-07 16:32:39 +08002547//Get the Dfs enable status
2548INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2549{
developer9964b5b2022-09-13 15:59:34 +08002550 char buf[16] = {0};
2551 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002552
2553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2554
developer30423732022-12-01 16:17:49 +08002555 if (output_bool == NULL)
2556 return RETURN_ERR;
2557
developer9964b5b2022-09-13 15:59:34 +08002558 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002559 f = fopen(DFS_ENABLE_FILE, "r");
2560 if (f != NULL) {
2561 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002562 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002563 *output_bool = FALSE;
2564 fclose(f);
2565 }
2566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002567 return RETURN_OK;
2568}
2569
2570//Set the Dfs enable status
2571INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2572{
developer9964b5b2022-09-13 15:59:34 +08002573 char config_file[128] = {0};
2574 FILE *f = NULL;
2575 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002576
2577 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2578
developer9964b5b2022-09-13 15:59:34 +08002579 f = fopen(DFS_ENABLE_FILE, "w");
2580 if (f == NULL)
2581 return RETURN_ERR;
2582 fprintf(f, "%d", enable);
2583 fclose(f);
2584
2585 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002586 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002587 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2588 wifi_hostapdWrite(config_file, &params, 1);
2589 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2590
2591 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2592
developer9964b5b2022-09-13 15:59:34 +08002593 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002594 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002595}
2596
2597//Check if the driver support the AutoChannelRefreshPeriod
2598INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2599{
2600 if (NULL == output_bool)
2601 return RETURN_ERR;
2602 *output_bool=FALSE; //not support
2603
2604 return RETURN_OK;
2605}
2606
2607//Get the ACS refresh period in seconds
2608INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2609{
2610 if (NULL == output_ulong)
2611 return RETURN_ERR;
2612 *output_ulong=300;
2613
2614 return RETURN_OK;
2615}
2616
2617//Set the ACS refresh period in seconds
2618INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2619{
2620 return RETURN_ERR;
2621}
2622
2623//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2624//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.
2625INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2626{
developer70490032022-09-13 15:45:20 +08002627 char cmd[128] = {0}, buf[64] = {0};
2628 char interface_name[64] = {0};
2629 int ret = 0, len=0;
2630 BOOL radio_enable = FALSE;
2631
2632 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2633
developer06a01d92022-09-07 16:32:39 +08002634 if (NULL == output_string)
2635 return RETURN_ERR;
2636
developer70490032022-09-13 15:45:20 +08002637 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2638 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002639
developer70490032022-09-13 15:45:20 +08002640 if (radio_enable != TRUE)
2641 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002642
developerac6f1142022-12-20 19:26:35 +08002643 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002644 return RETURN_ERR;
2645 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6", interface_name);
developer06a01d92022-09-07 16:32:39 +08002646 ret = _syscmd(cmd, buf, sizeof(buf));
2647 len = strlen(buf);
2648 if((ret != 0) || (len == 0))
2649 {
2650 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2651 return RETURN_ERR;
2652 }
2653
2654 buf[len-1] = '\0';
2655 snprintf(output_string, 64, "%sMHz", buf);
2656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2657
2658#if 0
2659 //TODO: revisit below implementation
2660 char output_buf[8]={0};
2661 char bw_value[10];
2662 char config_file[MAX_BUF_SIZE] = {0};
2663
2664 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2665 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2666 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2667 readBandWidth(radioIndex,bw_value);
2668
2669 if(strstr (output_buf,"0") != NULL )
2670 {
2671 strcpy(output_string,bw_value);
2672 }
2673 else if (strstr (output_buf,"1") != NULL)
2674 {
2675 strcpy(output_string,"80MHz");
2676 }
2677 else if (strstr (output_buf,"2") != NULL)
2678 {
2679 strcpy(output_string,"160MHz");
2680 }
2681 else if (strstr (output_buf,"3") != NULL)
2682 {
2683 strcpy(output_string,"80+80");
2684 }
2685 else
2686 {
2687 strcpy(output_string,"Auto");
2688 }
2689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2690#endif
2691
2692 return RETURN_OK;
2693}
2694
2695//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002696INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002697{
developerf7a466e2022-09-29 11:55:56 +08002698 char config_file[128];
2699 char set_value[16];
2700 struct params params[2];
2701 int max_radio_num = 0;
2702
developer06a01d92022-09-07 16:32:39 +08002703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002704
developerf7a466e2022-09-29 11:55:56 +08002705 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002706 return RETURN_ERR;
2707
developerf7a466e2022-09-29 11:55:56 +08002708 if(strstr(bandwidth,"80+80") != NULL)
2709 strcpy(set_value, "3");
2710 else if(strstr(bandwidth,"160") != NULL)
2711 strcpy(set_value, "2");
2712 else if(strstr(bandwidth,"80") != NULL)
2713 strcpy(set_value, "1");
2714 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2715 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002716 else
2717 {
developerf7a466e2022-09-29 11:55:56 +08002718 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002719 return RETURN_ERR;
2720 }
2721
developerf7a466e2022-09-29 11:55:56 +08002722 params[0].name = "vht_oper_chwidth";
2723 params[0].value = set_value;
2724 params[1].name = "he_oper_chwidth";
2725 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002726
developerf7a466e2022-09-29 11:55:56 +08002727 wifi_getMaxRadioNumber(&max_radio_num);
2728 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002729 {
developerf7a466e2022-09-29 11:55:56 +08002730 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2731 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002732 }
2733
2734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2735 return RETURN_OK;
2736}
2737
2738//Getting current radio extension channel
2739INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2740{
2741 CHAR buf[150] = {0};
2742 CHAR cmd[150] = {0};
2743 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2744 _syscmd(cmd, buf, sizeof(buf));
2745 if(NULL != strstr(buf,"HT40+"))
2746 strcpy(Value,"AboveControlChannel");
2747 else if(NULL != strstr(buf,"HT40-"))
2748 strcpy(Value,"BelowControlChannel");
2749 return RETURN_OK;
2750}
2751
2752//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2753//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.
2754INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2755{
2756 if (NULL == output_string)
2757 return RETURN_ERR;
2758
2759 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2760#if 0
2761 CHAR Value[100] = {0};
2762 if (NULL == output_string)
2763 return RETURN_ERR;
2764 if(radioIndex == 0)
2765 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2766 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2767 {
2768 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2769 if(strcmp(Value,"40MHz") == 0)
2770 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2771 else
2772 strcpy(Value,"Auto");
2773 }
2774 strcpy(output_string,Value);
2775#endif
2776
2777 return RETURN_OK;
2778}
2779
2780//Set the extension channel.
2781INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2782{
2783 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2784 struct params params={'\0'};
2785 char config_file[MAX_BUF_SIZE] = {0};
2786 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002787 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002788 params.name = "ht_capab";
2789
developer033b37b2022-10-18 11:27:46 +08002790 if(NULL!= strstr(string,"Above"))
2791 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2792 else if(NULL!= strstr(string,"Below"))
2793 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2794 else
2795 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2796
developer06a01d92022-09-07 16:32:39 +08002797
2798 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002799
2800 wifi_getMaxRadioNumber(&max_radio_num);
2801 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002802 {
developer033b37b2022-10-18 11:27:46 +08002803 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002804 wifi_hostapdWrite(config_file, &params, 1);
2805 }
2806
2807 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2808 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2809 return RETURN_OK;
2810}
2811
2812//Get the guard interval value. eg "400nsec" or "800nsec"
2813//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.
2814INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2815{
developer454b9462022-09-13 15:29:16 +08002816 wifi_guard_interval_t GI;
2817
2818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2819
2820 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002821 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002822
2823 if (GI == wifi_guard_interval_400)
2824 strcpy(output_string, "400nsec");
2825 else if (GI == wifi_guard_interval_800)
2826 strcpy(output_string, "800nsec");
2827 else if (GI == wifi_guard_interval_1600)
2828 strcpy(output_string, "1600nsec");
2829 else if (GI == wifi_guard_interval_3200)
2830 strcpy(output_string, "3200nsec");
2831 else
developer78a15382022-11-02 10:57:40 +08002832 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002833
developer454b9462022-09-13 15:29:16 +08002834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002835 return RETURN_OK;
2836}
2837
2838//Set the guard interval value.
2839INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2840{
developer454b9462022-09-13 15:29:16 +08002841 wifi_guard_interval_t GI;
2842 int ret = 0;
2843
2844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2845
2846 if (strcmp(string, "400nsec") == 0)
2847 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002848 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002849 GI = wifi_guard_interval_800;
2850 else if (strcmp(string , "1600nsec") == 0)
2851 GI = wifi_guard_interval_1600;
2852 else if (strcmp(string , "3200nsec") == 0)
2853 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002854 else
2855 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002856
2857 ret = wifi_setGuardInterval(radioIndex, GI);
2858
2859 if (ret == RETURN_ERR) {
2860 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2861 return RETURN_ERR;
2862 }
2863
2864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2865 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002866}
2867
2868//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2869INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2870{
developerf49437e2022-09-29 19:58:21 +08002871 char buf[32]={0};
2872 char mcs_file[64] = {0};
2873 char cmd[64] = {0};
2874 int mode_bitmap = 0;
2875
2876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2877 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002878 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002879 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2880
2881 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2882 _syscmd(cmd, buf, sizeof(buf));
2883 if (strlen(buf) > 0)
2884 *output_int = strtol(buf, NULL, 10);
2885 else {
2886 // output the max MCS for the current radio mode
2887 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2888 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2889 return RETURN_ERR;
2890 }
2891 if (mode_bitmap & WIFI_MODE_AX) {
2892 *output_int = 11;
2893 } else if (mode_bitmap & WIFI_MODE_AC) {
2894 *output_int = 9;
2895 } else if (mode_bitmap & WIFI_MODE_N) {
2896 *output_int = 7;
2897 }
2898 }
2899 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002900
2901 return RETURN_OK;
2902}
2903
2904//Set the Modulation Coding Scheme index
2905INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2906{
developerf49437e2022-09-29 19:58:21 +08002907 // 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).
2908 char config_file[64] = {0};
2909 char set_value[16] = {0};
2910 char mcs_file[32] = {0};
2911 wifi_band band = band_invalid;
2912 struct params set_config = {0};
2913 FILE *f = NULL;
2914
2915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2916
2917 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2918
developer78a15382022-11-02 10:57:40 +08002919 // -1 means auto
2920 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08002921 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2922 return RETURN_ERR;
2923 }
2924
developer78a15382022-11-02 10:57:40 +08002925 if (MCS > 9 || MCS == -1)
2926 strcpy(set_value, "2");
2927 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08002928 strcpy(set_value, "1");
2929 else
developer78a15382022-11-02 10:57:40 +08002930 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08002931
2932 set_config.name = "he_basic_mcs_nss_set";
2933 set_config.value = set_value;
2934
2935 wifi_hostapdWrite(config_file, &set_config, 1);
2936 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2937
2938 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2939 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2940 f = fopen(mcs_file, "w");
2941 if (f == NULL) {
2942 fprintf(stderr, "%s: fopen failed\n", __func__);
2943 return RETURN_ERR;
2944 }
2945 fprintf(f, "%d", MCS);
2946 fclose(f);
2947
2948 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2949 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002950}
2951
2952//Get supported Transmit Power list, eg : "0,25,50,75,100"
2953//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.
2954INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2955{
2956 if (NULL == output_list)
2957 return RETURN_ERR;
2958 snprintf(output_list, 64,"0,25,50,75,100");
2959 return RETURN_OK;
2960}
2961
developera5005b62022-09-13 15:43:35 +08002962//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002963//The transmite power level is in units of full power for this radio.
2964INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2965{
developerd946fd62022-12-08 18:03:28 +08002966 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002967 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002968 char buf[16]={0};
2969 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002970
developera5005b62022-09-13 15:43:35 +08002971 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002972 return RETURN_ERR;
2973
developerac6f1142022-12-20 19:26:35 +08002974 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002975 return RETURN_ERR;
2976 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 +08002977 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002978
developera5005b62022-09-13 15:43:35 +08002979 *output_ulong = strtol(buf, NULL, 10);
2980
2981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002982 return RETURN_OK;
2983}
2984
2985//Set Transmit Power
2986//The transmite power level is in units of full power for this radio.
2987INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2988{
developerd946fd62022-12-08 18:03:28 +08002989 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08002990 char *support;
developer06a01d92022-09-07 16:32:39 +08002991 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002992 char buf[128]={0};
2993 char txpower_str[64] = {0};
2994 int txpower = 0;
2995 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08002996 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08002997
2998 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002999
developerac6f1142022-12-20 19:26:35 +08003000 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003001 return RETURN_ERR;
3002 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 +08003003 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003004 maximum_tx = strtol(buf, NULL, 10);
3005
3006 // Get the Tx power supported list and check that is the input in the list
3007 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3008 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3009 support = strtok(buf, ",");
3010 while(true)
3011 {
3012 if(support == NULL) { // input not in the list
3013 wifi_dbg_printf("Input value is invalid.\n");
3014 return RETURN_ERR;
3015 }
3016 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3017 break;
3018 }
3019 support = strtok(NULL, ",");
3020 }
3021 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003022 phyId = radio_index_to_phy(radioIndex);
3023 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003024 _syscmd(cmd, buf, sizeof(buf));
3025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003026
3027 return RETURN_OK;
3028}
3029
3030//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3031INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3032{
3033 if (NULL == Supported)
3034 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003035 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003036
3037 return RETURN_OK;
3038}
3039
3040//Get 80211h feature enable
3041INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3042{
developer3885fec2022-09-13 15:13:47 +08003043 char buf[64]={'\0'};
3044 char config_file[64] = {'\0'};
3045
3046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3047 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003048 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003049
3050 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3051 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003052
developer3885fec2022-09-13 15:13:47 +08003053 if (strncmp(buf, "1", 1) == 0)
3054 *enable = TRUE;
3055 else
3056 *enable = FALSE;
3057
3058 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003059 return RETURN_OK;
3060}
3061
3062//Set 80211h feature enable
3063INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3064{
developer3885fec2022-09-13 15:13:47 +08003065 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3066 struct params params={'\0'};
3067 char config_file[MAX_BUF_SIZE] = {0};
3068
3069 params.name = "ieee80211h";
3070
3071 if (enable) {
3072 params.value = "1";
3073 } else {
3074 params.value = "0";
3075 }
3076
3077 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3078 wifi_hostapdWrite(config_file, &params, 1);
3079
3080 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3081 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3082 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003083}
3084
3085//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.
3086INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3087{
3088 if (NULL == output)
3089 return RETURN_ERR;
3090 *output=100;
3091
3092 return RETURN_OK;
3093}
3094
3095//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.
3096INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3097{
3098 if (NULL == output)
3099 return RETURN_ERR;
3100 *output = -99;
3101
3102 return RETURN_OK;
3103}
3104
3105INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3106{
3107 return RETURN_ERR;
3108}
3109
3110
3111//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3112INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3113{
developerd946fd62022-12-08 18:03:28 +08003114 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003115 char cmd[MAX_BUF_SIZE]={'\0'};
3116 char buf[MAX_CMD_SIZE]={'\0'};
3117
3118 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3119 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003120 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003121
developerac6f1142022-12-20 19:26:35 +08003122 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003123 return RETURN_ERR;
3124 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 +08003125 _syscmd(cmd, buf, sizeof(buf));
3126 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003127
developer5f222492022-09-13 15:21:52 +08003128 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003129 return RETURN_OK;
3130}
3131
3132INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3133{
developer5f222492022-09-13 15:21:52 +08003134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3135 struct params params={'\0'};
3136 char buf[MAX_BUF_SIZE] = {'\0'};
3137 char config_file[MAX_BUF_SIZE] = {'\0'};
3138
developer5b398df2022-11-17 20:39:48 +08003139 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3140 return RETURN_ERR;
3141
developer5f222492022-09-13 15:21:52 +08003142 params.name = "beacon_int";
3143 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3144 params.value = buf;
3145
3146 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3147 wifi_hostapdWrite(config_file, &params, 1);
3148
3149 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3151 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003152}
3153
3154//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.
3155INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3156{
developer06a01d92022-09-07 16:32:39 +08003157 //TODO: need to revisit below implementation
3158 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003159 char temp_output[128] = {0};
3160 char temp_TransmitRates[64] = {0};
3161 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003162
3163 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3164 if (NULL == output)
3165 return RETURN_ERR;
3166 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003167 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3168
3169 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3170 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3171 } else {
3172 temp = strtok(temp_TransmitRates," ");
3173 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003174 {
developere9d0abd2022-09-13 15:40:57 +08003175 // Convert 100 kbps to Mbps
3176 temp[strlen(temp)-1]=0;
3177 if((temp[0]=='5') && (temp[1]=='\0'))
3178 {
3179 temp="5.5";
3180 }
3181 strcat(temp_output,temp);
3182 temp = strtok(NULL," ");
3183 if(temp!=NULL)
3184 {
3185 strcat(temp_output,",");
3186 }
developer06a01d92022-09-07 16:32:39 +08003187 }
developere9d0abd2022-09-13 15:40:57 +08003188 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003189 }
developer06a01d92022-09-07 16:32:39 +08003190 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003191 return RETURN_OK;
3192}
3193
3194INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3195{
3196 char *temp;
3197 char temp1[128];
3198 char temp_output[128];
3199 char temp_TransmitRates[128];
3200 char set[128];
3201 char sub_set[128];
3202 int set_count=0,subset_count=0;
3203 int set_index=0,subset_index=0;
3204 char *token;
3205 int flag=0, i=0;
3206 struct params params={'\0'};
3207 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003208 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003209
3210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3211 if(NULL == TransmitRates)
3212 return RETURN_ERR;
3213 strcpy(sub_set,TransmitRates);
3214
3215 //Allow only supported Data transmit rate to be set
3216 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3217 token = strtok(sub_set,",");
3218 while( token != NULL ) /* split the basic rate to be set, by comma */
3219 {
3220 sub_set[subset_count]=atoi(token);
3221 subset_count++;
3222 token=strtok(NULL,",");
3223 }
3224 token=strtok(set,",");
3225 while(token!=NULL) /* split the supported rate by comma */
3226 {
3227 set[set_count]=atoi(token);
3228 set_count++;
3229 token=strtok(NULL,",");
3230 }
3231 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3232 {
3233 for(set_index=0;set_index < set_count;set_index++)
3234 {
3235 flag=0;
3236 if(sub_set[subset_index]==set[set_index])
3237 break;
3238 else
3239 flag=1; /* No match found */
3240 }
3241 if(flag==1)
3242 return RETURN_ERR; //If value not found return Error
3243 }
3244 strcpy(temp_TransmitRates,TransmitRates);
3245
3246 for(i=0;i<strlen(temp_TransmitRates);i++)
3247 {
3248 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003249 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003250 {
3251 continue;
3252 }
3253 else
3254 {
3255 return RETURN_ERR;
3256 }
3257 }
3258 strcpy(temp_output,"");
3259 temp = strtok(temp_TransmitRates,",");
3260 while(temp!=NULL)
3261 {
3262 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003263 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003264 {
developeref938762022-10-19 17:21:01 +08003265 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003266 {
3267 return RETURN_ERR;
3268 }
3269 }
3270
3271 if(strcmp(temp,"5.5")==0)
3272 {
3273 strcpy(temp1,"55");
3274 }
3275 else
3276 {
3277 strcat(temp1,"0");
3278 }
3279 strcat(temp_output,temp1);
3280 temp = strtok(NULL,",");
3281 if(temp!=NULL)
3282 {
3283 strcat(temp_output," ");
3284 }
3285 }
3286 strcpy(TransmitRates,temp_output);
3287
3288 params.name= "basic_rates";
3289 params.value =TransmitRates;
3290
3291 wifi_dbg_printf("\n%s:",__func__);
3292 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3293 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3294 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3295 wifi_hostapdWrite(config_file,&params,1);
3296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3297 return RETURN_OK;
3298}
3299
3300//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003301INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003302{
3303 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3304 FILE *fp = NULL;
3305 char path[256] = {0}, output_string[256] = {0};
3306 int count = 0;
3307 char *interface = NULL;
3308
3309 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3310 if (fp == NULL)
3311 {
3312 printf("Failed to run command in Function %s\n", __FUNCTION__);
3313 return RETURN_ERR;
3314 }
3315 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3316 {
3317 interface = strchr(path, '=');
3318
3319 if (interface != NULL)
3320 {
3321 strcpy(output_string, interface + 1);
3322 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3323 interface_name[count] = output_string[count];
3324
3325 interface_name[count] = '\0';
3326 }
3327 }
3328 pclose(fp);
3329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3330 return RETURN_OK;
3331}
3332
3333INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3334{
3335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3336 output_struct->radio_BytesSent = 0;
3337 output_struct->radio_BytesReceived = 0;
3338 output_struct->radio_PacketsSent = 0;
3339 output_struct->radio_PacketsReceived = 0;
3340 output_struct->radio_ErrorsSent = 0;
3341 output_struct->radio_ErrorsReceived = 0;
3342 output_struct->radio_DiscardPacketsSent = 0;
3343 output_struct->radio_DiscardPacketsReceived = 0;
3344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3345 return RETURN_OK;
3346}
3347
3348
3349INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3350{
3351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3352 CHAR buf[MAX_CMD_SIZE] = {0};
3353 CHAR Value[MAX_BUF_SIZE] = {0};
3354 FILE *fp = NULL;
3355
3356 if (ifname == NULL || strlen(ifname) <= 1)
3357 return RETURN_OK;
3358
3359 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3360 system(buf);
3361
3362 fp = fopen("/tmp/Radio_Stats.txt", "r");
3363 if(fp == NULL)
3364 {
3365 printf("/tmp/Radio_Stats.txt not exists \n");
3366 return RETURN_ERR;
3367 }
3368 fclose(fp);
3369
3370 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3371 File_Reading(buf, Value);
3372 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3373
3374 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3375 File_Reading(buf, Value);
3376 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3377
3378 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3379 File_Reading(buf, Value);
3380 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3381
3382 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3383 File_Reading(buf, Value);
3384 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3385
3386 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3387 File_Reading(buf, Value);
3388 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3389
3390 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3391 File_Reading(buf, Value);
3392 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3393
3394 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3395 File_Reading(buf, Value);
3396 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3397
3398 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3399 File_Reading(buf, Value);
3400 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3401
3402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3403 return RETURN_OK;
3404}
3405
3406INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3407{
3408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3409 CHAR buf[MAX_CMD_SIZE] = {0};
3410 FILE *fp = NULL;
3411 INT count = 0;
3412
3413 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3414 {
3415 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3416 File_Reading(buf, status);
3417 }
3418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3419 return RETURN_OK;
3420}
3421
3422//Get detail radio traffic static info
3423INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3424{
3425
3426#if 0
3427 //ifconfig radio_x
3428 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3429 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3430 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3431 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3432
3433 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3434 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3435 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.
3436 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.
3437
3438 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3439 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].
3440 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3441 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.
3442 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
3443 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
3444 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
3445 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
3446 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
3447
3448 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
3449 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
3450 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
3451 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.
3452
3453 return RETURN_OK;
3454#endif
3455
developera91d99f2022-09-29 15:59:10 +08003456 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003457 BOOL iface_status = FALSE;
3458 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003459
3460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3461 if (NULL == output_struct)
3462 return RETURN_ERR;
3463
developerac6f1142022-12-20 19:26:35 +08003464 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08003465 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003466
developera91d99f2022-09-29 15:59:10 +08003467 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003468
developera91d99f2022-09-29 15:59:10 +08003469 if (iface_status == TRUE)
3470 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3471 else
3472 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003473
developera91d99f2022-09-29 15:59:10 +08003474 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3475 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3476 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3477 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3478 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3479 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3480 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3481 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003482
3483 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3484 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].
3485 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3486 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.
3487 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
3488 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
3489 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
3490 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
3491 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
3492
3493 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
3494 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
3495 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
3496 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.
3497
3498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3499
3500 return RETURN_OK;
3501}
3502
3503//Set radio traffic static Measureing rules
3504INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3505{
3506 //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
3507 // Else, save the MeasuringRate and MeasuringInterval for future usage
3508
3509 return RETURN_OK;
3510}
3511
3512//To start or stop RadioTrafficStats
3513INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3514{
3515 //zqiu: If the RadioTrafficStats process running
3516 // if(enable)
3517 // return RETURN_OK.
3518 // else
3519 // Stop RadioTrafficStats process
3520 // Else
3521 // if(enable)
3522 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3523 // else
3524 // return RETURN_OK.
3525
3526 return RETURN_OK;
3527}
3528
3529//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
3530INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3531{
3532 //zqiu: Please ignor signalIndex.
3533 if (NULL == SignalLevel)
3534 return RETURN_ERR;
3535 *SignalLevel=(radioIndex==0)?-19:-19;
3536
3537 return RETURN_OK;
3538}
3539
3540//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3541INT wifi_applyRadioSettings(INT radioIndex)
3542{
3543 return RETURN_OK;
3544}
3545
3546//Get the radio index assocated with this SSID entry
3547INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3548{
developer5b398df2022-11-17 20:39:48 +08003549 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003550 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003551 int max_radio_num = 0;
3552 wifi_getMaxRadioNumber(&max_radio_num);
3553 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003554 return RETURN_OK;
3555}
3556
3557//Device.WiFi.SSID.{i}.Enable
3558//Get SSID enable configuration parameters (not the SSID enable status)
3559INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3560{
3561 if (NULL == output_bool)
3562 return RETURN_ERR;
3563
developer06a01d92022-09-07 16:32:39 +08003564 return wifi_getApEnable(ssidIndex, output_bool);
3565}
3566
3567//Device.WiFi.SSID.{i}.Enable
3568//Set SSID enable configuration parameters
3569INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3570{
developer06a01d92022-09-07 16:32:39 +08003571 return wifi_setApEnable(ssidIndex, enable);
3572}
3573
3574//Device.WiFi.SSID.{i}.Status
3575//Get the SSID enable status
3576INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3577{
3578 char cmd[MAX_CMD_SIZE]={0};
3579 char buf[MAX_BUF_SIZE]={0};
3580 BOOL output_bool;
3581
3582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3583 if (NULL == output_string)
3584 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003585
developer06a01d92022-09-07 16:32:39 +08003586 wifi_getApEnable(ssidIndex,&output_bool);
3587 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3588
3589 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3590 return RETURN_OK;
3591}
3592
3593// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3594INT wifi_getSSIDName(INT apIndex, CHAR *output)
3595{
3596 char config_file[MAX_BUF_SIZE] = {0};
3597
3598 if (NULL == output)
3599 return RETURN_ERR;
3600
3601 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3602 wifi_hostapdRead(config_file,"ssid",output,32);
3603
3604 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3605 return RETURN_OK;
3606}
3607
3608// Set a max 32 byte string and sets an internal variable to the SSID name
3609INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3610{
3611 char str[MAX_BUF_SIZE]={'\0'};
3612 char cmd[MAX_CMD_SIZE]={'\0'};
3613 struct params params;
3614 char config_file[MAX_BUF_SIZE] = {0};
3615
3616 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3617 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3618 return RETURN_ERR;
3619
3620 params.name = "ssid";
3621 params.value = ssid_string;
3622 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3623 wifi_hostapdWrite(config_file, &params, 1);
3624 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3626
3627 return RETURN_OK;
3628}
3629
3630//Get the BSSID
3631INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3632{
3633 char cmd[MAX_CMD_SIZE]="";
3634
3635 if (NULL == output_string)
3636 return RETURN_ERR;
3637
3638 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3639 {
developer1d57d002022-10-12 18:03:15 +08003640 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 +08003641 _syscmd(cmd, output_string, 64);
3642 return RETURN_OK;
3643 }
3644 strncpy(output_string, "\0", 1);
3645
3646 return RETURN_ERR;
3647}
3648
3649//Get the MAC address associated with this Wifi SSID
3650INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3651{
3652 wifi_getBaseBSSID(ssidIndex,output_string);
3653 return RETURN_OK;
3654}
3655
3656//Get the basic SSID traffic static info
3657//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3658//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3659INT wifi_applySSIDSettings(INT ssidIndex)
3660{
developerd946fd62022-12-08 18:03:28 +08003661 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003662 BOOL status = false;
3663 char cmd[MAX_CMD_SIZE] = {0};
3664 char buf[MAX_CMD_SIZE] = {0};
3665 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003666 int max_radio_num = 0;
3667 int radioIndex = 0;
3668
3669 wifi_getMaxRadioNumber(&max_radio_num);
3670
3671 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003672
3673 wifi_getApEnable(ssidIndex,&status);
3674 // Do not apply when ssid index is disabled
3675 if (status == false)
3676 return RETURN_OK;
3677
3678 /* Doing full remove and add for ssid Index
3679 * Not all hostapd options are supported with reload
3680 * for example macaddr_acl
3681 */
3682 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3683 return RETURN_ERR;
3684
3685 ret = wifi_setApEnable(ssidIndex,true);
3686
3687 /* Workaround for hostapd issue with multiple bss definitions
3688 * when first created interface will be removed
3689 * then all vaps other vaps on same phy are removed
3690 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003691 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003692 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003693 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003694 return RETURN_ERR;
3695 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003696 _syscmd(cmd, buf, sizeof(buf));
3697 if(*buf == '1')
3698 wifi_setApEnable(apIndex, true);
3699 }
3700
3701 return ret;
3702}
3703
developera3c68b92022-09-13 15:27:29 +08003704struct channels_noise {
3705 int channel;
3706 int noise;
3707};
3708
3709// Return noise array for each channel
3710int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3711{
developerd946fd62022-12-08 18:03:28 +08003712 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003713 FILE *f = NULL;
3714 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003715 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003716 size_t len = 0;
3717 ssize_t read = 0;
3718 int tmp = 0, arr_index = -1;
3719
developerac6f1142022-12-20 19:26:35 +08003720 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003721 return RETURN_ERR;
3722 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003723
3724 if ((f = popen(cmd, "r")) == NULL) {
3725 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3726 return RETURN_ERR;
3727 }
developer5550e242022-09-30 09:59:32 +08003728
3729 while(fgets(line, sizeof(line), f) != NULL) {
3730 if(arr_index < channels_num){
3731 sscanf(line, "%d", &tmp);
3732 if (tmp > 0) { // channel frequency, the first line must be frequency
3733 arr_index++;
3734 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3735 } else { // noise
3736 channels_noise_arr[arr_index].noise = tmp;
3737 }
3738 }else{
3739 break;
developera3c68b92022-09-13 15:27:29 +08003740 }
3741 }
developera3c68b92022-09-13 15:27:29 +08003742 pclose(f);
3743 return RETURN_OK;
3744}
3745
developer06a01d92022-09-07 16:32:39 +08003746//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3747//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3748INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3749{
developera3c68b92022-09-13 15:27:29 +08003750 int index = -1;
3751 wifi_neighbor_ap2_t *scan_array = NULL;
3752 char cmd[256]={0};
3753 char buf[128]={0};
3754 char file_name[32] = {0};
3755 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003756 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003757 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003758 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003759 int freq=0;
3760 FILE *f = NULL;
3761 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003762 int channels_num = 0;
3763 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003764 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003765 bool filter_enable = false;
3766 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003767 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003768
developer615510b2022-09-27 10:14:35 +08003769 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003770
developerac6f1142022-12-20 19:26:35 +08003771 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003772 return RETURN_ERR;
3773
developera3c68b92022-09-13 15:27:29 +08003774 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3775 f = fopen(file_name, "r");
3776 if (f != NULL) {
3777 fgets(filter_SSID, sizeof(file_name), f);
3778 if (strlen(filter_SSID) != 0)
3779 filter_enable = true;
3780 fclose(f);
3781 }
3782
developer033b37b2022-10-18 11:27:46 +08003783 phyId = radio_index_to_phy(radioIndex);
3784 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003785 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003786 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003787
developer5550e242022-09-30 09:59:32 +08003788
developer06a01d92022-09-07 16:32:39 +08003789
developerd946fd62022-12-08 18:03:28 +08003790 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3791 // 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 +08003792 fprintf(stderr, "cmd: %s\n", cmd);
3793 if ((f = popen(cmd, "r")) == NULL) {
3794 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3795 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003796 }
developer5550e242022-09-30 09:59:32 +08003797
3798 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3799 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3800
developer615510b2022-09-27 10:14:35 +08003801 ret = fgets(line, sizeof(line), f);
3802 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003803 if(strstr(line, "BSS") != NULL) { // new neighbor info
3804 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3805 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3806 // 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 +08003807
developera3c68b92022-09-13 15:27:29 +08003808 if (!filter_BSS) {
3809 index++;
3810 wifi_neighbor_ap2_t *tmp;
3811 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3812 if (tmp == NULL) { // no more memory to use
3813 index--;
3814 wifi_dbg_printf("%s: realloc failed\n", __func__);
3815 break;
3816 }
3817 scan_array = tmp;
3818 }
3819 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3820
3821 filter_BSS = false;
3822 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3823 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3824 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3825 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3826 } else if (strstr(line, "freq") != NULL) {
3827 sscanf(line," freq: %d", &freq);
3828 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3829
3830 if (freq >= 2412 && freq <= 2484) {
3831 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3832 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3833 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3834 }
3835 else if (freq >= 5160 && freq <= 5805) {
3836 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3837 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3838 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3839 }
3840
3841 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003842 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003843 for (int i = 0; i < channels_num; i++) {
3844 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3845 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3846 break;
3847 }
3848 }
3849 }
3850 } else if (strstr(line, "beacon interval") != NULL) {
3851 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3852 } else if (strstr(line, "signal") != NULL) {
3853 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3854 } else if (strstr(line,"SSID") != NULL) {
3855 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3856 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3857 filter_BSS = true;
3858 }
3859 } else if (strstr(line, "Supported rates") != NULL) {
3860 char SRate[80] = {0}, *tmp = NULL;
3861 memset(buf, 0, sizeof(buf));
3862 strcpy(SRate, line);
3863 tmp = strtok(SRate, ":");
3864 tmp = strtok(NULL, ":");
3865 strcpy(buf, tmp);
3866 memset(SRate, 0, sizeof(SRate));
3867
3868 tmp = strtok(buf, " \n");
3869 while (tmp != NULL) {
3870 strcat(SRate, tmp);
3871 if (SRate[strlen(SRate) - 1] == '*') {
3872 SRate[strlen(SRate) - 1] = '\0';
3873 }
3874 strcat(SRate, ",");
3875
3876 tmp = strtok(NULL, " \n");
3877 }
3878 SRate[strlen(SRate) - 1] = '\0';
3879 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3880 } else if (strstr(line, "DTIM") != NULL) {
3881 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3882 } else if (strstr(line, "VHT capabilities") != NULL) {
3883 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3884 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3885 } else if (strstr(line, "HT capabilities") != NULL) {
3886 strcat(scan_array[index].ap_SupportedStandards, ",n");
3887 strcpy(scan_array[index].ap_OperatingStandards, "n");
3888 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003889 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003890 sscanf(line," * channel width: %d", &vht_channel_width);
3891 if(vht_channel_width == 1) {
3892 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3893 } else {
3894 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3895 }
3896 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3897 continue;
3898 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003899 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003900 sscanf(line," * secondary channel offset: %s", &buf);
3901 if (!strcmp(buf, "above")) {
3902 //40Mhz +
3903 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3904 }
3905 else if (!strcmp(buf, "below")) {
3906 //40Mhz -
3907 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3908 } else {
3909 //20Mhz
3910 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3911 }
3912 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3913 continue;
3914 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003915 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3916 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3917 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003918 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3919 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003920 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003921 else
developer615510b2022-09-27 10:14:35 +08003922 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003923 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003924 if (strstr(line, "HE80/5GHz") != NULL) {
3925 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3926 ret = fgets(line, sizeof(line), f);
3927 } else
3928 continue;
developera3c68b92022-09-13 15:27:29 +08003929 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003930 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003931 }
developer615510b2022-09-27 10:14:35 +08003932 continue;
developera3c68b92022-09-13 15:27:29 +08003933 } else if (strstr(line, "WPA") != NULL) {
3934 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3935 } else if (strstr(line, "RSN") != NULL) {
3936 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3937 } else if (strstr(line, "Group cipher") != NULL) {
3938 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3939 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3940 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3941 }
3942 }
developer615510b2022-09-27 10:14:35 +08003943 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003944 }
3945
3946 if (!filter_BSS) {
3947 *output_array_size = index + 1;
3948 } else {
3949 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3950 *output_array_size = index;
3951 }
3952 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003953 pclose(f);
developer5550e242022-09-30 09:59:32 +08003954 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003955 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003956 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003957}
3958
3959//>> Deprecated: used for old RDKB code.
3960INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3961{
3962 INT status = RETURN_ERR;
3963
3964 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3965 output_struct->wifi_PLCPErrorCount = 0;
3966 output_struct->wifi_FCSErrorCount = 0;
3967 output_struct->wifi_InvalidMACCount = 0;
3968 output_struct->wifi_PacketsOtherReceived = 0;
3969 output_struct->wifi_Noise = 0;
3970 status = RETURN_OK;
3971 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3972 return status;
3973}
3974
3975INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3976{
developerd946fd62022-12-08 18:03:28 +08003977 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08003978 char cmd[128] = {0};
3979 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08003980 char *pos = NULL;
3981
3982 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3983 if (NULL == output_struct)
3984 return RETURN_ERR;
3985
developerac6f1142022-12-20 19:26:35 +08003986 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003987 return RETURN_ERR;
3988
developer06a01d92022-09-07 16:32:39 +08003989 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3990
developerd946fd62022-12-08 18:03:28 +08003991 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08003992 _syscmd(cmd, buf, sizeof(buf));
3993
3994 pos = buf;
3995 if ((pos = strstr(pos, "RX packets:")) == NULL)
3996 return RETURN_ERR;
3997 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3998
3999 if ((pos = strstr(pos, "TX packets:")) == NULL)
4000 return RETURN_ERR;
4001 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4002
4003 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4004 return RETURN_ERR;
4005 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4006
4007 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4008 return RETURN_ERR;
4009 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4010
developerd946fd62022-12-08 18:03:28 +08004011 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004012 _syscmd(cmd, buf, sizeof(buf));
4013 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4014
4015#if 0
4016 //TODO: need to revisit below implementation
4017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4018 char interface_name[MAX_BUF_SIZE] = {0};
4019 char interface_status[MAX_BUF_SIZE] = {0};
4020 char Value[MAX_BUF_SIZE] = {0};
4021 char buf[MAX_CMD_SIZE] = {0};
4022 char cmd[MAX_CMD_SIZE] = {0};
4023 FILE *fp = NULL;
4024
4025 if (NULL == output_struct) {
4026 return RETURN_ERR;
4027 }
4028
4029 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4030
4031 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4032 {
4033 if(apIndex == 0) //private_wifi for 2.4G
4034 {
developerac6f1142022-12-20 19:26:35 +08004035 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004036 }
4037 else if(apIndex == 1) //private_wifi for 5G
4038 {
developerac6f1142022-12-20 19:26:35 +08004039 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004040 }
4041 else if(apIndex == 4) //public_wifi for 2.4G
4042 {
4043 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4044 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4045 {
4046 return RETURN_ERR;
4047 }
4048 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004049 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004050 else//tenda
developerac6f1142022-12-20 19:26:35 +08004051 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004052 }
4053 else if(apIndex == 5) //public_wifi for 5G
4054 {
developerac6f1142022-12-20 19:26:35 +08004055 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004056 }
4057
4058 GetIfacestatus(interface_name, interface_status);
4059
4060 if(0 != strcmp(interface_status, "1"))
4061 return RETURN_ERR;
4062
4063 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4064 system(cmd);
4065
4066 fp = fopen("/tmp/SSID_Stats.txt", "r");
4067 if(fp == NULL)
4068 {
4069 printf("/tmp/SSID_Stats.txt not exists \n");
4070 return RETURN_ERR;
4071 }
4072 fclose(fp);
4073
4074 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4075 File_Reading(buf, Value);
4076 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4077
4078 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4079 File_Reading(buf, Value);
4080 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4081
4082 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4083 File_Reading(buf, Value);
4084 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4085
4086 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4087 File_Reading(buf, Value);
4088 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4089
4090 /* There is no specific parameter from caller to associate the value wifi_Associations */
4091 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4092 //_syscmd(cmd, buf, sizeof(buf));
4093 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4094 }
4095#endif
4096 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4097 return RETURN_OK;
4098}
4099
4100INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4101{
4102 char interface_name[MAX_BUF_SIZE] = {0};
4103 char interface_status[MAX_BUF_SIZE] = {0};
4104 char Value[MAX_BUF_SIZE] = {0};
4105 char buf[MAX_CMD_SIZE] = {0};
4106 char cmd[MAX_CMD_SIZE] = {0};
4107 FILE *fp = NULL;
4108
4109 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4110 if (NULL == output_struct)
4111 return RETURN_ERR;
4112
4113 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4114
developerac6f1142022-12-20 19:26:35 +08004115 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004116 return RETURN_ERR;
4117 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004118
developerd946fd62022-12-08 18:03:28 +08004119 if(0 != strcmp(interface_status, "1"))
4120 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004121
developerd946fd62022-12-08 18:03:28 +08004122 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4123 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004124
developerd946fd62022-12-08 18:03:28 +08004125 fp = fopen("/tmp/SSID_Stats.txt", "r");
4126 if(fp == NULL)
4127 {
4128 printf("/tmp/SSID_Stats.txt not exists \n");
4129 return RETURN_ERR;
4130 }
4131 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004132
developerd946fd62022-12-08 18:03:28 +08004133 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4134 File_Reading(buf, Value);
4135 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004136
developerd946fd62022-12-08 18:03:28 +08004137 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4138 File_Reading(buf, Value);
4139 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004140
developerd946fd62022-12-08 18:03:28 +08004141 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4142 File_Reading(buf, Value);
4143 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004144
developerd946fd62022-12-08 18:03:28 +08004145 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4146 File_Reading(buf, Value);
4147 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004148
4149 output_struct->wifi_UnicastPacketsSent = 0;
4150 output_struct->wifi_UnicastPacketsReceived = 0;
4151 output_struct->wifi_MulticastPacketsSent = 0;
4152 output_struct->wifi_MulticastPacketsReceived = 0;
4153 output_struct->wifi_BroadcastPacketsSent = 0;
4154 output_struct->wifi_BroadcastPacketsRecevied = 0;
4155 output_struct->wifi_UnknownPacketsReceived = 0;
4156
4157 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4158 return RETURN_OK;
4159}
4160
4161INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4162{
4163 INT status = RETURN_ERR;
4164
4165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4166 //Below values should get updated from hal
4167 output_struct->wifi_RetransCount=0;
4168 output_struct->wifi_FailedRetransCount=0;
4169 output_struct->wifi_RetryCount=0;
4170 output_struct->wifi_MultipleRetryCount=0;
4171 output_struct->wifi_ACKFailureCount=0;
4172 output_struct->wifi_AggregatedPacketCount=0;
4173
4174 status = RETURN_OK;
4175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4176
4177 return status;
4178}
4179
4180INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4181{
4182 INT status = RETURN_ERR;
4183 UINT index;
4184 wifi_neighbor_ap_t *pt=NULL;
4185
4186 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4187 *output_array_size=2;
4188 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4189 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4190 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4191 strcpy(pt->ap_Radio,"");
4192 strcpy(pt->ap_SSID,"");
4193 strcpy(pt->ap_BSSID,"");
4194 strcpy(pt->ap_Mode,"");
4195 pt->ap_Channel=1;
4196 pt->ap_SignalStrength=0;
4197 strcpy(pt->ap_SecurityModeEnabled,"");
4198 strcpy(pt->ap_EncryptionMode,"");
4199 strcpy(pt->ap_OperatingFrequencyBand,"");
4200 strcpy(pt->ap_SupportedStandards,"");
4201 strcpy(pt->ap_OperatingStandards,"");
4202 strcpy(pt->ap_OperatingChannelBandwidth,"");
4203 pt->ap_BeaconPeriod=1;
4204 pt->ap_Noise=0;
4205 strcpy(pt->ap_BasicDataTransferRates,"");
4206 strcpy(pt->ap_SupportedDataTransferRates,"");
4207 pt->ap_DTIMPeriod=1;
4208 pt->ap_ChannelUtilization = 1;
4209 }
4210
4211 status = RETURN_OK;
4212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4213
4214 return status;
4215}
4216
4217//----------------- AP HAL -------------------------------
4218
4219//>> Deprecated: used for old RDKB code.
4220INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4221{
4222 if (NULL == output_ulong || NULL == output_struct)
4223 return RETURN_ERR;
4224 *output_ulong = 0;
4225 *output_struct = NULL;
4226 return RETURN_OK;
4227}
4228
4229#ifdef HAL_NETLINK_IMPL
4230static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4231 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4232 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4233 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4234 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4235 char mac_addr[20];
4236 static int count=0;
4237 int rate=0;
4238
4239 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4240
4241 nla_parse(tb,
4242 NL80211_ATTR_MAX,
4243 genlmsg_attrdata(gnlh, 0),
4244 genlmsg_attrlen(gnlh, 0),
4245 NULL);
4246
4247 if(!tb[NL80211_ATTR_STA_INFO]) {
4248 fprintf(stderr, "sta stats missing!\n");
4249 return NL_SKIP;
4250 }
4251
4252
4253 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4254 fprintf(stderr, "failed to parse nested attributes!\n");
4255 return NL_SKIP;
4256 }
4257
4258 //devIndex starts from 1
4259 if( ++count == out->wifi_devIndex )
4260 {
4261 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4262 //Getting the mac addrress
4263 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4264
4265 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4266 fprintf(stderr, "failed to parse nested rate attributes!");
4267 return NL_SKIP;
4268 }
4269
4270 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4271 if(rinfo[NL80211_RATE_INFO_BITRATE])
4272 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4273 out->wifi_devTxRate = rate/10;
4274 }
4275
4276 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4277 fprintf(stderr, "failed to parse nested rate attributes!");
4278 return NL_SKIP;
4279 }
4280
4281 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4282 if(rinfo[NL80211_RATE_INFO_BITRATE])
4283 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4284 out->wifi_devRxRate = rate/10;
4285 }
4286 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4287 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4288
4289 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4290 count = 0; //starts the count for next cycle
4291 return NL_STOP;
4292 }
4293
4294 return NL_SKIP;
4295
4296}
4297#endif
4298
4299INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4300{
4301#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004302 Netlink nl = {0};
4303 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004304 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004305
developer30423732022-12-01 16:17:49 +08004306 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004307 info.wifi_devIndex = devIndex;
4308
developerac6f1142022-12-20 19:26:35 +08004309 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004310 return RETURN_ERR;
4311
4312 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004313
4314 nl.id = initSock80211(&nl);
4315
4316 if (nl.id < 0) {
4317 fprintf(stderr, "Error initializing netlink \n");
4318 return -1;
4319 }
4320
4321 struct nl_msg* msg = nlmsg_alloc();
4322
4323 if (!msg) {
4324 fprintf(stderr, "Failed to allocate netlink message.\n");
4325 nlfree(&nl);
4326 return -2;
4327 }
4328
4329 genlmsg_put(msg,
4330 NL_AUTO_PORT,
4331 NL_AUTO_SEQ,
4332 nl.id,
4333 0,
4334 NLM_F_DUMP,
4335 NL80211_CMD_GET_STATION,
4336 0);
4337
4338 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4339 nl_send_auto(nl.socket, msg);
4340 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4341 nl_recvmsgs(nl.socket, nl.cb);
4342 nlmsg_free(msg);
4343 nlfree(&nl);
4344
4345 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4346 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4347 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4348 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4349 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4350 return RETURN_OK;
4351#else
4352 //iw utility to retrieve station information
4353#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4354#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4355#define MACFILE "/tmp/wifi_AssoMac.txt"
4356#define TXRATEFILE "/tmp/wifi_txrate.txt"
4357#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4358 FILE *file = NULL;
4359 char if_name[10] = {'\0'};
4360 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004361 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004362 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004363 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004364
developerac6f1142022-12-20 19:26:35 +08004365 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004366 return RETURN_ERR;
4367
4368 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004369
4370 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4371 file = popen(pipeCmd, "r");
4372
4373 if(file == NULL)
4374 return RETURN_ERR; //popen failed
4375
4376 fgets(line, sizeof line, file);
4377 device = atoi(line);
4378 pclose(file);
4379
4380 if(device == 0)
4381 return RETURN_ERR; //No devices are connected
4382
4383 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4384 system(pipeCmd);
4385
4386 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4387
4388 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4389
4390 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4391
4392 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4393
4394 //devIndex starts from 1, ++count
4395 if((file = fopen(SIGNALFILE, "r")) != NULL )
4396 {
4397 for(count =0;fgets(line, sizeof line, file) != NULL;)
4398 {
4399 if (++count == devIndex)
4400 {
4401 output_struct->wifi_devSignalStrength = atoi(line);
4402 break;
4403 }
4404 }
4405 fclose(file);
4406 }
4407 else
4408 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4409
4410 if((file = fopen(MACFILE, "r")) != NULL )
4411 {
4412 for(count =0;fgets(line, sizeof line, file) != NULL;)
4413 {
4414 if (++count == devIndex)
4415 {
4416 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]);
4417 break;
4418 }
4419 }
4420 fclose(file);
4421 }
4422 else
4423 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4424
4425 if((file = fopen(TXRATEFILE, "r")) != NULL )
4426 {
4427 for(count =0;fgets(line, sizeof line, file) != NULL;)
4428 {
4429 if (++count == devIndex)
4430 {
4431 output_struct->wifi_devTxRate = atoi(line);
4432 break;
4433 }
4434 }
4435 fclose(file);
4436 }
4437 else
4438 fprintf(stderr,"fopen wifi_txrate.txt failed");
4439
4440 if((file = fopen(RXRATEFILE, "r")) != NULL)
4441 {
4442 for(count =0;fgets(line, sizeof line, file) != NULL;)
4443 {
4444 if (++count == devIndex)
4445 {
4446 output_struct->wifi_devRxRate = atoi(line);
4447 break;
4448 }
4449 }
4450 fclose(file);
4451 }
4452 else
4453 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4454
4455 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4456
4457 return RETURN_OK;
4458#endif
4459}
4460
4461INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4462{
4463 if (NULL == device)
4464 return RETURN_ERR;
4465 return RETURN_OK;
4466}
4467//<<
4468
4469
4470//--------------wifi_ap_hal-----------------------------
4471//enables CTS protection for the radio used by this AP
4472INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4473{
4474 //save config and Apply instantly
4475 return RETURN_ERR;
4476}
4477
4478// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4479INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4480{
developer463d39a2022-09-13 15:32:51 +08004481 char config_file[64] = {'\0'};
4482 char buf[64] = {'\0'};
4483 struct params list;
4484
4485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4486 list.name = "ht_coex";
4487 snprintf(buf, sizeof(buf), "%d", enable);
4488 list.value = buf;
4489
4490 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4491 wifi_hostapdWrite(config_file, &list, 1);
4492 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4493
4494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4495
4496 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004497}
4498
4499//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4500INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4501{
developerea4bcce2022-09-13 15:26:13 +08004502 char config_file[MAX_BUF_SIZE] = {'\0'};
4503 char buf[MAX_BUF_SIZE] = {'\0'};
4504 struct params list;
4505
4506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4507 if (threshold < 256 || threshold > 2346 )
4508 return RETURN_ERR;
4509 list.name = "fragm_threshold";
4510 snprintf(buf, sizeof(buf), "%d", threshold);
4511 list.value = buf;
4512
4513 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4514 wifi_hostapdWrite(config_file, &list, 1);
4515 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004516
developerea4bcce2022-09-13 15:26:13 +08004517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004518
4519 return RETURN_OK;
4520}
4521
4522// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4523INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4524{
developer51a927d2022-09-13 15:42:22 +08004525 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004526 char cmd[512] = {'\0'};
4527 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004528 char stbc_config[16] = {'\0'};
4529 wifi_band band;
4530 int iterator = 0;
4531 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004532 int ant_count = 0;
4533 int ant_bitmap = 0;
4534 struct params list;
developer51a927d2022-09-13 15:42:22 +08004535
4536 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4537
4538 band = wifi_index_to_band(radioIndex);
4539 if (band == band_invalid)
4540 return RETURN_ERR;
4541
4542 if (band == band_2_4)
4543 iterator = 1;
4544 else if (band == band_5)
4545 iterator = 2;
4546 else
4547 return RETURN_OK;
4548
developer110b8a32022-12-26 15:56:44 +08004549 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4550 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4551 ant_count += ant_bitmap & 1;
4552
4553 if (ant_count == 1 && STBC_Enable == TRUE) {
4554 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4555 return RETURN_OK;
4556 }
4557
developer51a927d2022-09-13 15:42:22 +08004558 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4559
4560 // set ht and vht config
4561 for (int i = 0; i < iterator; i++) {
4562 memset(stbc_config, 0, sizeof(stbc_config));
4563 memset(cmd, 0, sizeof(cmd));
4564 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004565 list.name = (i == 0)?"ht_capab":"vht_capab";
4566 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004567 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4568 _syscmd(cmd, buf, sizeof(buf));
4569 if (strlen(buf) != 0)
4570 current_stbc = TRUE;
4571 if (current_stbc == STBC_Enable)
4572 continue;
4573
4574 if (STBC_Enable == TRUE) {
4575 // Append the STBC flags in capab config
4576 memset(cmd, 0, sizeof(cmd));
4577 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004578 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004579 else
developer6372c2b2022-10-27 17:39:51 +08004580 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 +08004581 _syscmd(cmd, buf, sizeof(buf));
4582 } else if (STBC_Enable == FALSE) {
4583 // Remove the STBC flags and remain other flags in capab
4584 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004585 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004586 _syscmd(cmd, buf, sizeof(buf));
4587 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004588 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004589 _syscmd(cmd, buf, sizeof(buf));
4590 }
developer110b8a32022-12-26 15:56:44 +08004591 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4592 list.value = buf;
4593 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004594 }
4595
4596 wifi_reloadAp(radioIndex);
4597
4598 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4599 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004600}
4601
4602// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4603INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4604{
developerfe7aefc2022-12-23 17:13:37 +08004605 char cmd[128] = {0};
4606 char buf[128] = {0};
4607 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004608
4609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4610
4611 if(output_bool == NULL)
4612 return RETURN_ERR;
4613
developerfe7aefc2022-12-23 17:13:37 +08004614 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4615 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004616
developerfe7aefc2022-12-23 17:13:37 +08004617 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4618 _syscmd(cmd, buf, sizeof(buf));
4619
4620 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004621 *output_bool = TRUE;
4622 else
4623 *output_bool = FALSE;
4624
4625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4626 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004627}
4628
4629// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4630INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4631{
developerfe7aefc2022-12-23 17:13:37 +08004632 char config_file[128] = {0};
4633 struct params list = {0};
4634 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004635
4636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4637
developerfe7aefc2022-12-23 17:13:37 +08004638 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004639 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004640
developerfe7aefc2022-12-23 17:13:37 +08004641 if (amsduEnable == enable)
4642 return RETURN_OK;
4643
4644 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4645 list.name = "amsdu";
4646 list.value = amsduEnable? "1":"0";
4647 wifi_hostapdWrite(config_file, &list, 1);
4648 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4649 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004650
4651 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4652 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004653}
4654
4655//P2 // outputs the number of Tx streams
4656INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4657{
developer2de97692022-09-26 14:00:03 +08004658 char buf[8] = {0};
4659 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004660 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004661
4662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4663
developer033b37b2022-10-18 11:27:46 +08004664 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004665 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004666 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004667
developer110b8a32022-12-26 15:56:44 +08004668 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004669
4670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4671
4672 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004673}
4674
developer110b8a32022-12-26 15:56:44 +08004675INT fitChainMask(INT radioIndex, int antcount)
4676{
4677 char buf[128] = {0};
4678 char cmd[128] = {0};
4679 char config_file[64] = {0};
4680 wifi_band band;
4681 struct params list[2] = {0};
4682
4683 band = wifi_index_to_band(radioIndex);
4684 if (band == band_invalid)
4685 return RETURN_ERR;
4686
4687 list[0].name = "he_mu_beamformer";
4688 list[1].name = "he_su_beamformer";
4689
4690 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4691 if (antcount == 1) {
4692 // remove config about multiple antennas
4693 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4694 _syscmd(cmd, buf, sizeof(buf));
4695
4696 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4697 _syscmd(cmd, buf, sizeof(buf));
4698
4699 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4700 _syscmd(cmd, buf, sizeof(buf));
4701
4702 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4703 _syscmd(cmd, buf, sizeof(buf));
4704
4705 list[0].value = "0";
4706 list[1].value = "0";
4707 } else {
4708 // 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.
4709 if (band == band_2_4 || band == band_5) {
4710 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4711 _syscmd(cmd, buf, sizeof(buf));
4712 if (strlen(buf) > 0) {
4713 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4714 _syscmd(cmd, buf, sizeof(buf));
4715 }
4716 }
4717 if (band == band_5) {
4718 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4719 _syscmd(cmd, buf, sizeof(buf));
4720 if (strlen(buf) > 0) {
4721 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4722 _syscmd(cmd, buf, sizeof(buf));
4723 }
4724 }
4725
4726 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4727 _syscmd(cmd, buf, sizeof(buf));
4728 if (strlen(buf) == 0) {
4729 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4730 _syscmd(cmd, buf, sizeof(buf));
4731 }
4732
4733 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4734 _syscmd(cmd, buf, sizeof(buf));
4735 if (strlen(buf) == 0) {
4736 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4737 _syscmd(cmd, buf, sizeof(buf));
4738 }
4739
4740 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4741 _syscmd(cmd, buf, sizeof(buf));
4742 if (strlen(buf) == 0) {
4743 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4744 } else {
4745 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4746 }
4747 _syscmd(cmd, buf, sizeof(buf));
4748
4749 list[0].value = "1";
4750 list[1].value = "1";
4751 }
4752 wifi_hostapdWrite(config_file, list, 2);
4753}
4754
developer06a01d92022-09-07 16:32:39 +08004755//P2 // sets the number of Tx streams to an enviornment variable
4756INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4757{
developer2de97692022-09-26 14:00:03 +08004758 char cmd[128] = {0};
4759 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004760 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08004761 int cur_mask = 0;
4762 int antcount = 0;
4763 wifi_band band;
developer2de97692022-09-26 14:00:03 +08004764
4765 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4766
developer110b8a32022-12-26 15:56:44 +08004767 if (numStreams <= 0) {
4768 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08004769 return RETURN_ERR;
4770 }
developer110b8a32022-12-26 15:56:44 +08004771
4772 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4773 if (cur_mask == numStreams)
4774 return RETURN_OK;
4775
developer2de97692022-09-26 14:00:03 +08004776 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004777
4778 phyId = radio_index_to_phy(radioIndex);
4779 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004780 _syscmd(cmd, buf, sizeof(buf));
4781
4782 if (strlen(buf) > 0) {
4783 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4784 return RETURN_ERR;
4785 }
developer2de97692022-09-26 14:00:03 +08004786
developer110b8a32022-12-26 15:56:44 +08004787 // if chain mask changed, we need to make the hostapd config valid.
4788 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
4789 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08004790 }
developer110b8a32022-12-26 15:56:44 +08004791 fitChainMask(radioIndex, antcount);
4792
4793 wifi_setRadioEnable(radioIndex, TRUE);
4794
developer2de97692022-09-26 14:00:03 +08004795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4796 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004797}
4798
4799//P2 // outputs the number of Rx streams
4800INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4801{
developer110b8a32022-12-26 15:56:44 +08004802 char buf[8] = {0};
4803 char cmd[128] = {0};
4804 int phyId = 0;
4805
developer2de97692022-09-26 14:00:03 +08004806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004807
4808 phyId = radio_index_to_phy(radioIndex);
4809 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
4810 _syscmd(cmd, buf, sizeof(buf));
4811
4812 *output_int = (INT)strtol(buf, NULL, 16);
4813
developer2de97692022-09-26 14:00:03 +08004814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004815
developer06a01d92022-09-07 16:32:39 +08004816 return RETURN_OK;
4817}
4818
4819//P2 // sets the number of Rx streams to an enviornment variable
4820INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4821{
developer2de97692022-09-26 14:00:03 +08004822 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4823 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4824 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4825 return RETURN_ERR;
4826 }
4827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004828 return RETURN_ERR;
4829}
4830
4831//Get radio RDG enable setting
4832INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4833{
4834 if (NULL == output_bool)
4835 return RETURN_ERR;
4836 *output_bool = TRUE;
4837 return RETURN_OK;
4838}
4839
4840//Get radio RDG enable setting
4841INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4842{
4843 if (NULL == output_bool)
4844 return RETURN_ERR;
4845 *output_bool = TRUE;
4846 return RETURN_OK;
4847}
4848
4849//Set radio RDG enable setting
4850INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4851{
4852 return RETURN_ERR;
4853}
4854
4855//Get radio ADDBA enable setting
4856INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4857{
4858 if (NULL == output_bool)
4859 return RETURN_ERR;
4860 *output_bool = TRUE;
4861 return RETURN_OK;
4862}
4863
4864//Set radio ADDBA enable setting
4865INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4866{
4867 return RETURN_ERR;
4868}
4869
4870//Get radio auto block ack enable setting
4871INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4872{
4873 if (NULL == output_bool)
4874 return RETURN_ERR;
4875 *output_bool = TRUE;
4876 return RETURN_OK;
4877}
4878
4879//Set radio auto block ack enable setting
4880INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4881{
4882 return RETURN_ERR;
4883}
4884
4885//Get radio 11n pure mode enable support
4886INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4887{
4888 if (NULL == output_bool)
4889 return RETURN_ERR;
4890 *output_bool = TRUE;
4891 return RETURN_OK;
4892}
4893
4894//Get radio 11n pure mode enable setting
4895INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4896{
4897 if (NULL == output_bool)
4898 return RETURN_ERR;
4899 *output_bool = TRUE;
4900 return RETURN_OK;
4901}
4902
4903//Set radio 11n pure mode enable setting
4904INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4905{
4906 return RETURN_ERR;
4907}
4908
4909//Get radio IGMP snooping enable setting
4910INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4911{
developerd946fd62022-12-08 18:03:28 +08004912 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004913 char cmd[128]={0};
4914 char buf[4]={0};
4915 bool bridge = FALSE, mac80211 = FALSE;
4916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4917
4918 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004919 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004920
4921 *output_bool = FALSE;
4922
4923 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4924 _syscmd(cmd, buf, sizeof(buf));
4925 if (strncmp(buf, "1", 1) == 0)
4926 bridge = TRUE;
4927
developerac6f1142022-12-20 19:26:35 +08004928 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004929 return RETURN_ERR;
4930 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 +08004931 _syscmd(cmd, buf, sizeof(buf));
4932 if (strncmp(buf, "1", 1) == 0)
4933 mac80211 = TRUE;
4934
4935 if (bridge && mac80211)
4936 *output_bool = TRUE;
4937
4938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004939 return RETURN_OK;
4940}
4941
4942//Set radio IGMP snooping enable setting
4943INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4944{
developerd946fd62022-12-08 18:03:28 +08004945 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004946 char cmd[128]={0};
4947 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004948 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004949 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4950
4951 // bridge
4952 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4953 _syscmd(cmd, buf, sizeof(buf));
4954
developer804c64f2022-10-19 13:54:40 +08004955 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004956 // mac80211
developer804c64f2022-10-19 13:54:40 +08004957 for (int i = 0; i < max_num_radios; i++) {
developerac6f1142022-12-20 19:26:35 +08004958 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004959 return RETURN_ERR;
4960 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 +08004961 _syscmd(cmd, buf, sizeof(buf));
4962 }
4963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4964 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004965}
4966
4967//Get the Reset count of radio
4968INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4969{
4970 if (NULL == output_int)
4971 return RETURN_ERR;
4972 *output_int = (radioIndex==0)? 1: 3;
4973
4974 return RETURN_OK;
4975}
4976
4977
4978//---------------------------------------------------------------------------------------------------
4979//
4980// Additional Wifi AP level APIs used for Access Point devices
4981//
4982//---------------------------------------------------------------------------------------------------
4983
4984// creates a new ap and pushes these parameters to the hardware
4985INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4986{
developer7930d352022-12-21 17:55:42 +08004987 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08004988 return RETURN_OK;
4989}
4990
4991// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4992INT wifi_deleteAp(INT apIndex)
4993{
developerd946fd62022-12-08 18:03:28 +08004994 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004995 char buf[1024];
4996 char cmd[128];
4997
developerac6f1142022-12-20 19:26:35 +08004998 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004999 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08005000 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005001 _syscmd(cmd, buf, sizeof(buf));
5002
5003 wifi_removeApSecVaribles(apIndex);
5004
5005 return RETURN_OK;
5006}
5007
5008// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5009INT wifi_getApName(INT apIndex, CHAR *output_string)
5010{
developerd946fd62022-12-08 18:03:28 +08005011 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005012 if(NULL == output_string)
5013 return RETURN_ERR;
5014
developerac6f1142022-12-20 19:26:35 +08005015 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005016 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005017 else
5018 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005019 return RETURN_OK;
5020}
5021
5022// Outputs the index number in that corresponds to the SSID string
5023INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5024{
developerd946fd62022-12-08 18:03:28 +08005025 char cmd [128] = {0};
5026 char buf[32] = {0};
5027 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005028 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005029
developerd946fd62022-12-08 18:03:28 +08005030 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5031 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005032
developerac6f1142022-12-20 19:26:35 +08005033 if (strlen(buf) != 0) {
5034 apIndex_str = strtok(buf, "\n");
5035 *output_int = strtoul(apIndex_str, NULL, 10);
5036 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005037 }
developer67b8ee92022-12-20 10:48:43 +08005038
5039 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5040 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5041 if (apIndex_str) {
5042 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5043 return RETURN_OK;
5044 }
developerd946fd62022-12-08 18:03:28 +08005045 *output_int = -1;
5046 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005047}
5048
5049INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5050{
5051 return wifi_getIndexFromName(inputSsidString, output_int);
5052}
5053
5054// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5055INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5056{
5057 char buf[MAX_BUF_SIZE] = {0};
5058 char cmd[MAX_CMD_SIZE] = {0};
5059 char config_file[MAX_BUF_SIZE] = {0};
5060
5061 if(NULL == output_string)
5062 return RETURN_ERR;
5063
5064 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5065 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5066 if((strcmp(buf,"3")==0))
5067 snprintf(output_string, 32, "WPAand11i");
5068 else if((strcmp(buf,"2")==0))
5069 snprintf(output_string, 32, "11i");
5070 else if((strcmp(buf,"1")==0))
5071 snprintf(output_string, 32, "WPA");
5072 else
5073 snprintf(output_string, 32, "None");
5074
5075 return RETURN_OK;
5076}
5077
5078// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5079INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5080{
5081 char config_file[MAX_BUF_SIZE] = {0};
5082 struct params list;
5083
5084 if (NULL == beaconTypeString)
5085 return RETURN_ERR;
5086 list.name = "wpa";
5087 list.value = "0";
5088
5089 if((strcmp(beaconTypeString,"WPAand11i")==0))
5090 list.value="3";
5091 else if((strcmp(beaconTypeString,"11i")==0))
5092 list.value="2";
5093 else if((strcmp(beaconTypeString,"WPA")==0))
5094 list.value="1";
5095
5096 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5097 wifi_hostapdWrite(config_file, &list, 1);
5098 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5099 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5100 return RETURN_OK;
5101}
5102
5103// sets the beacon interval on the hardware for this AP
5104INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5105{
developer5f222492022-09-13 15:21:52 +08005106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5107 struct params params={'\0'};
5108 char buf[MAX_BUF_SIZE] = {'\0'};
5109 char config_file[MAX_BUF_SIZE] = {'\0'};
5110
5111 params.name = "beacon_int";
5112 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5113 params.value = buf;
5114
5115 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5116 wifi_hostapdWrite(config_file, &params, 1);
5117
5118 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5120 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005121}
5122
5123INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5124{
developer5b398df2022-11-17 20:39:48 +08005125 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5126 return RETURN_ERR;
5127 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005128}
5129
5130// Get the packet size threshold supported.
5131INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5132{
5133 //save config and apply instantly
5134 if (NULL == output_bool)
5135 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005136 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005137 return RETURN_OK;
5138}
5139
5140// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5141INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5142{
developerd946fd62022-12-08 18:03:28 +08005143 char interface_name[16] = {0};
developer514406b2022-12-05 17:20:21 +08005144 char buf[16] = {0};
5145 char config_file[128] = {0};
5146 struct params param = {0};
5147
5148 if (threshold > 65535) {
5149 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5150 return RETURN_ERR;
5151 }
developer06a01d92022-09-07 16:32:39 +08005152
developerac6f1142022-12-20 19:26:35 +08005153 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005154 return RETURN_ERR;
5155 snprintf(config_file, sizeof(config_file), "%s.conf", interface_name);
developer514406b2022-12-05 17:20:21 +08005156 snprintf(buf, sizeof(buf), "%u", threshold);
5157 param.name = "rts_threshold";
5158 param.value = buf;
5159 wifi_hostapdWrite(config_file, &param, 1);
5160 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5161 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005162
5163 return RETURN_OK;
5164}
5165
5166// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5167INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5168{
5169 if (NULL == output_string)
5170 return RETURN_ERR;
5171 snprintf(output_string, 32, "TKIPandAESEncryption");
5172 return RETURN_OK;
5173
5174}
5175
5176// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5177INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5178{
5179 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005180 char *param_name = NULL;
5181 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005182
5183 if(NULL == output_string)
5184 return RETURN_ERR;
5185
5186 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5187 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5188
5189 if(strcmp(buf,"0")==0)
5190 {
5191 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5192 snprintf(output_string, 32, "None");
5193 return RETURN_OK;
5194 }
5195 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5196 param_name = "rsn_pairwise";
5197 else if((strcmp(buf,"1")==0))
5198 param_name = "wpa_pairwise";
5199 else
5200 return RETURN_ERR;
5201 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005202 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005203 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5204 param_name = "wpa_pairwise";
5205 memset(output_string, '\0', 32);
5206 wifi_hostapdRead(config_file, param_name, output_string, 32);
5207 }
developer06a01d92022-09-07 16:32:39 +08005208 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5209
5210 if(strcmp(output_string,"TKIP") == 0)
5211 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5212 else if(strcmp(output_string,"CCMP") == 0)
5213 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5214 else if(strcmp(output_string,"TKIP CCMP") == 0)
5215 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5216
5217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5218 return RETURN_OK;
5219}
5220
5221// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5222INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5223{
5224 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5225 struct params params={'\0'};
5226 char output_string[32];
5227 char config_file[MAX_BUF_SIZE] = {0};
5228
5229 memset(output_string,'\0',32);
5230 wifi_getApWpaEncryptionMode(apIndex,output_string);
5231
5232 if(strcmp(encMode, "TKIPEncryption") == 0)
5233 params.value = "TKIP";
5234 else if(strcmp(encMode,"AESEncryption") == 0)
5235 params.value = "CCMP";
5236 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5237 params.value = "TKIP CCMP";
5238
5239 if((strcmp(output_string,"WPAand11i")==0))
5240 {
5241 params.name = "wpa_pairwise";
5242 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5243 wifi_hostapdWrite(config_file, &params, 1);
5244 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5245
developer30423732022-12-01 16:17:49 +08005246 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005247 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5248 wifi_hostapdWrite(config_file, &params, 1);
5249 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5250
5251 return RETURN_OK;
5252 }
5253 else if((strcmp(output_string,"11i")==0))
5254 {
5255 params.name = "rsn_pairwise";
5256 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5257 wifi_hostapdWrite(config_file, &params, 1);
5258 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5259 return RETURN_OK;
5260 }
5261 else if((strcmp(output_string,"WPA")==0))
5262 {
5263 params.name = "wpa_pairwise";
5264 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5265 wifi_hostapdWrite(config_file, &params, 1);
5266 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5267 return RETURN_OK;
5268 }
5269
5270 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5271 return RETURN_OK;
5272}
5273
5274// deletes internal security varable settings for this ap
5275INT wifi_removeApSecVaribles(INT apIndex)
5276{
5277 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005278 //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 +08005279 //_syscmd(cmd, buf, sizeof(buf));
5280
developerd946fd62022-12-08 18:03:28 +08005281 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005282 //_syscmd(cmd, buf, sizeof(buf));
5283 return RETURN_ERR;
5284}
5285
5286// changes the hardware settings to disable encryption on this ap
5287INT wifi_disableApEncryption(INT apIndex)
5288{
5289 //Apply instantly
5290 return RETURN_ERR;
5291}
5292
5293// set the authorization mode on this ap
5294// mode mapping as: 1: open, 2: shared, 4:auto
5295INT wifi_setApAuthMode(INT apIndex, INT mode)
5296{
developeraf95c502022-09-13 16:18:22 +08005297 struct params params={0};
5298 char config_file[64] = {0};
5299 int ret;
5300
5301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5302
5303 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5304 params.name = "auth_algs";
5305
5306 if (mode & 1 && mode & 2)
5307 params.value = "3";
5308 else if (mode & 2)
5309 params.value = "2";
5310 else if (mode & 1)
5311 params.value = "1";
5312 else
5313 params.value = "0";
5314
5315 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5316 wifi_hostapdWrite(config_file, &params, 1);
5317 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5319
5320 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005321}
5322
5323// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5324INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5325{
5326 //save to wifi config, and wait for wifi restart to apply
5327 struct params params={'\0'};
5328 char config_file[MAX_BUF_SIZE] = {0};
5329 int ret;
5330
5331 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5332 if(authMode == NULL)
5333 return RETURN_ERR;
5334
5335 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5336 params.name = "wpa_key_mgmt";
5337
5338 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5339 params.value = "WPA-PSK";
5340 else if(strcmp(authMode,"EAPAuthentication") == 0)
5341 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005342 else if (strcmp(authMode, "SAEAuthentication") == 0)
5343 params.value = "SAE";
5344 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5345 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005346 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5347 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005348 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5349 return RETURN_OK; //This is taken careof in beaconType
5350
5351 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5352 ret=wifi_hostapdWrite(config_file,&params,1);
5353 if(!ret)
5354 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5355 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5356
5357 return ret;
5358}
5359
5360// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5361INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5362{
5363 //save to wifi config, and wait for wifi restart to apply
5364 char BeaconType[50] = {0};
5365 char config_file[MAX_BUF_SIZE] = {0};
5366
5367 *authMode = 0;
5368 wifi_getApBeaconType(apIndex,BeaconType);
5369 printf("%s____%s \n",__FUNCTION__,BeaconType);
5370
5371 if(strcmp(BeaconType,"None") == 0)
5372 strcpy(authMode,"None");
5373 else
5374 {
5375 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5376 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5377 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5378 if(strcmp(authMode,"WPA-PSK") == 0)
5379 strcpy(authMode,"SharedAuthentication");
5380 else if(strcmp(authMode,"WPA-EAP") == 0)
5381 strcpy(authMode,"EAPAuthentication");
5382 }
5383
5384 return RETURN_OK;
5385}
5386
5387// Outputs the number of stations associated per AP
5388INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5389{
developerd946fd62022-12-08 18:03:28 +08005390 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005391 char cmd[128]={0};
5392 char buf[128]={0};
5393 BOOL status = false;
5394
5395 if(apIndex > MAX_APS)
5396 return RETURN_ERR;
5397
5398 wifi_getApEnable(apIndex,&status);
5399 if (!status)
5400 return RETURN_OK;
5401
developerd946fd62022-12-08 18:03:28 +08005402 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005403 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005404 return RETURN_ERR;
5405 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005406 _syscmd(cmd, buf, sizeof(buf));
5407 sscanf(buf,"%lu", output_ulong);
5408
5409 return RETURN_OK;
5410}
5411
5412// manually removes any active wi-fi association with the device specified on this ap
5413INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5414{
developerd946fd62022-12-08 18:03:28 +08005415 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005416 char buf[126]={'\0'};
5417
developerac6f1142022-12-20 19:26:35 +08005418 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005419 return RETURN_ERR;
5420 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005421 system(buf);
5422
5423 return RETURN_OK;
5424}
5425
5426// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5427INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5428{
5429 if(NULL == output_int)
5430 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005431 int max_radio_num = 0;
5432 wifi_getMaxRadioNumber(&max_radio_num);
5433 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005434 return RETURN_OK;
5435}
5436
5437// sets the radio index for the specific ap
5438INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5439{
5440 //set to config only and wait for wifi reset to apply settings
5441 return RETURN_ERR;
5442}
5443
5444// Get the ACL MAC list per AP
5445INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5446{
developerd946fd62022-12-08 18:03:28 +08005447 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005448 char cmd[MAX_CMD_SIZE]={'\0'};
5449 int ret = 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(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005454 ret = _syscmd(cmd,macArray,buf_size);
5455 if (ret != 0)
5456 return RETURN_ERR;
5457
5458 return RETURN_OK;
5459}
5460
developere6aafda2022-09-13 14:59:28 +08005461INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5462{
developerd946fd62022-12-08 18:03:28 +08005463 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005464 char cmd[MAX_CMD_SIZE]={'\0'};
5465 int ret = 0;
5466
developerac6f1142022-12-20 19:26:35 +08005467 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005468 return RETURN_ERR;
5469 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005470 ret = _syscmd(cmd,macArray,buf_size);
5471 if (ret != 0)
5472 return RETURN_ERR;
5473
5474 return RETURN_OK;
5475}
5476
5477
developer06a01d92022-09-07 16:32:39 +08005478// Get the list of stations associated per AP
5479INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5480{
developerd946fd62022-12-08 18:03:28 +08005481 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005482 char cmd[128];
5483
5484 if(apIndex > 3) //Currently supporting apIndex upto 3
5485 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005486 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005487 return RETURN_ERR;
5488 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5489 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005490 _syscmd(cmd, macArray, buf_size);
5491
5492 return RETURN_OK;
5493}
5494
5495// adds the mac address to the filter list
5496//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5497INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5498{
5499 char cmd[MAX_CMD_SIZE]={'\0'};
5500 char buf[MAX_BUF_SIZE]={'\0'};
5501
5502#if 0
developerd946fd62022-12-08 18:03:28 +08005503 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005504 if(_syscmd(cmd,buf,sizeof(buf)))
5505 return RETURN_ERR;
5506#endif
5507 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5508 if(_syscmd(cmd,buf,sizeof(buf)))
5509 return RETURN_ERR;
5510
5511 return RETURN_OK;
5512}
5513
5514// deletes the mac address from the filter list
5515//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5516INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5517{
5518 char cmd[MAX_CMD_SIZE]={'\0'};
5519 char buf[MAX_BUF_SIZE]={'\0'};
5520
5521#if 0
developerd946fd62022-12-08 18:03:28 +08005522 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005523 if(_syscmd(cmd,buf,sizeof(buf)))
5524 return RETURN_ERR;
5525
5526#endif
5527 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5528 if(_syscmd(cmd,buf,sizeof(buf)))
5529 return RETURN_ERR;
5530
5531 return RETURN_OK;
5532}
5533
5534// outputs the number of devices in the filter list
5535INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5536{
developere6aafda2022-09-13 14:59:28 +08005537 char cmd[MAX_BUF_SIZE]={0};
5538 char buf[MAX_CMD_SIZE]={0};
5539
5540 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5541 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005542 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005543
5544 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5545 _syscmd(cmd, buf, sizeof(buf));
5546
5547 *output_uint = atoi(buf);
5548
5549 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5550 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005551}
5552
5553INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5554{
5555 char cmd[128]={'\0'};
5556 char buf[128]={'\0'};
5557
5558 if(strcmp(action,"DENY")==0)
5559 {
5560 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5561 system(buf);
5562 return RETURN_OK;
5563 }
5564
5565 if(strcmp(action,"ALLOW")==0)
5566 {
5567 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5568 system(buf);
5569 return RETURN_OK;
5570 }
5571
5572 return RETURN_ERR;
5573
5574}
5575
5576// enable kick for devices on acl black list
5577INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5578{
5579 char aclArray[512] = {0}, *acl = NULL;
5580 char assocArray[512] = {0}, *asso = NULL;
5581
developere6aafda2022-09-13 14:59:28 +08005582 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005583 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5584
5585 // if there are no devices connected there is nothing to do
5586 if (strlen(assocArray) < 17)
5587 return RETURN_OK;
5588
5589 if (enable == TRUE)
5590 {
5591 //kick off the MAC which is in ACL array (deny list)
5592 acl = strtok(aclArray, "\r\n");
5593 while (acl != NULL) {
5594 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5595 wifi_kickApAssociatedDevice(apIndex, acl);
5596
5597 acl = strtok(NULL, "\r\n");
5598 }
developere6aafda2022-09-13 14:59:28 +08005599 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005600 }
5601 else
5602 {
developere6aafda2022-09-13 14:59:28 +08005603 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005604 }
5605
5606#if 0
5607 //TODO: need to revisit below implementation
5608 char aclArray[512]={0}, *acl=NULL;
5609 char assocArray[512]={0}, *asso=NULL;
5610 char buf[256]={'\0'};
5611 char action[10]={'\0'};
5612 FILE *fr=NULL;
5613 char interface[10]={'\0'};
5614 char config_file[MAX_BUF_SIZE] = {0};
5615
5616 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5617 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5618 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5619 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5620
5621 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5622 system(buf);
5623 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5624 system(buf);
5625 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5626 system(buf);
5627 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5628 system(buf);
5629 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5630 system(buf);
5631
5632 if ( enable == TRUE )
5633 {
5634 int device_count=0;
5635 strcpy(action,"DENY");
5636 //kick off the MAC which is in ACL array (deny list)
5637 acl = strtok (aclArray,",");
5638 while (acl != NULL) {
5639 if(strlen(acl)>=17)
5640 {
5641 apply_rules(apIndex, acl,action,interface);
5642 device_count++;
5643 //Register mac to be blocked ,in syscfg.db persistent storage
5644 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5645 system(buf);
5646 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5647 system(buf);
5648 system("syscfg commit");
5649
5650 wifi_kickApAssociatedDevice(apIndex, acl);
5651 }
5652 acl = strtok (NULL, ",");
5653 }
5654 }
5655 else
5656 {
5657 int device_count=0;
5658 char cmdmac[20]={'\0'};
5659 strcpy(action,"ALLOW");
5660 //kick off the MAC which is not in ACL array (allow list)
5661 acl = strtok (aclArray,",");
5662 while (acl != NULL) {
5663 if(strlen(acl)>=17)
5664 {
5665 apply_rules(apIndex, acl,action,interface);
5666 device_count++;
5667 //Register mac to be Allowed ,in syscfg.db persistent storage
5668 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5669 system(buf);
5670 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5671 system(buf);
5672 sprintf(cmdmac,"%s",acl);
5673 }
5674 acl = strtok (NULL, ",");
5675 }
5676 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5677 system(buf);
5678
5679 //Disconnect the mac which is not in ACL
5680 asso = strtok (assocArray,",");
5681 while (asso != NULL) {
5682 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5683 wifi_kickApAssociatedDevice(apIndex, asso);
5684 asso = strtok (NULL, ",");
5685 }
5686 }
5687#endif
5688 return RETURN_OK;
5689}
5690
5691INT wifi_setPreferPrivateConnection(BOOL enable)
5692{
developer06a01d92022-09-07 16:32:39 +08005693 return RETURN_OK;
5694}
5695
5696// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5697INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5698{
developerd946fd62022-12-08 18:03:28 +08005699 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005700 int items = 1;
5701 struct params list[2];
5702 char buf[MAX_BUF_SIZE] = {0};
5703 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005704 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005705
5706 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005707
developer10adcc12022-09-13 14:39:17 +08005708 if (filterMode == 0) {
5709 sprintf(buf, "%d", 0);
5710 list[0].value = buf;
5711
5712 char cmd[128], rtn[128];
developerac6f1142022-12-20 19:26:35 +08005713 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005714 return RETURN_ERR;
5715 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
developer10adcc12022-09-13 14:39:17 +08005716 _syscmd(cmd, rtn, sizeof(rtn));
5717 memset(cmd,0,sizeof(cmd));
5718 // Delete deny_mac_file in hostapd configuration
5719 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5720 _syscmd(cmd, rtn, sizeof(rtn));
5721 }
5722 else if (filterMode == 1) {
5723 sprintf(buf, "%d", filterMode);
5724 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005725 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5726 list[1].name = "accept_mac_file";
5727 list[1].value = acl_file;
5728 items = 2;
developer10adcc12022-09-13 14:39:17 +08005729 } else if (filterMode == 2) {
5730 //TODO: deny_mac_file
5731 sprintf(buf, "%d", 0);
5732 list[0].value = buf;
5733 list[1].name = "deny_mac_file";
5734 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5735 list[1].value = deny_file;
5736 items = 2;
5737 } else {
5738 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005739 }
developer10adcc12022-09-13 14:39:17 +08005740
developer06a01d92022-09-07 16:32:39 +08005741 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5742 wifi_hostapdWrite(config_file, list, items);
5743
5744 return RETURN_OK;
5745
5746#if 0
5747 if(apIndex==0 || apIndex==1)
5748 {
5749 //set the filtermode
5750 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5751 system(buf);
5752 system("syscfg commit");
5753
5754 if(filterMode==0)
5755 {
5756 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5757 system(buf);
5758 return RETURN_OK;
5759 }
5760 }
5761 return RETURN_OK;
5762#endif
5763}
5764
5765// 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.
5766INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5767{
5768 return RETURN_ERR;
5769}
5770
5771// gets the vlan ID for this ap from an internal enviornment variable
5772INT wifi_getApVlanID(INT apIndex, INT *output_int)
5773{
developer30423732022-12-01 16:17:49 +08005774 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005775 {
5776 *output_int=100;
5777 return RETURN_OK;
5778 }
5779
5780 return RETURN_ERR;
5781}
5782
5783// sets the vlan ID for this ap to an internal enviornment variable
5784INT wifi_setApVlanID(INT apIndex, INT vlanId)
5785{
5786 //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)
5787 return RETURN_ERR;
5788}
5789
5790// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5791INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5792{
5793 snprintf(bridgeName, 32, "brlan0");
5794 snprintf(IP, 32, "10.0.0.1");
5795 snprintf(subnet, 32, "255.255.255.0");
5796
5797 return RETURN_OK;
5798}
5799
5800//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5801INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5802{
5803 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5804 return RETURN_ERR;
5805}
5806
5807// reset the vlan configuration for this ap
5808INT wifi_resetApVlanCfg(INT apIndex)
5809{
developerf5fef612022-09-20 19:38:26 +08005810 char original_config_file[64] = {0};
5811 char current_config_file[64] = {0};
5812 char buf[64] = {0};
5813 char cmd[64] = {0};
5814 char vlan_file[64] = {0};
5815 char vlan_tagged_interface[16] = {0};
5816 char vlan_bridge[16] = {0};
5817 char vlan_naming[16] = {0};
5818 struct params list[4] = {0};
5819 wifi_band band;
5820
5821 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5822
5823 band = wifi_index_to_band(apIndex);
5824 if (band == band_2_4)
5825 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08005826 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08005827 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08005828 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08005829 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5830
5831 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5832
5833 if (strlen(vlan_file) == 0)
5834 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005835
developerf5fef612022-09-20 19:38:26 +08005836 // The file should exist or this vap would not work.
5837 if (access(vlan_file, F_OK) != 0) {
5838 sprintf(cmd, "touch %s", vlan_file);
5839 _syscmd(cmd, buf, sizeof(buf));
5840 }
5841 list[0].name = "vlan_file";
5842 list[0].value = vlan_file;
5843
5844 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5845 list[1].name = "vlan_tagged_interface";
5846 list[1].value = vlan_tagged_interface;
5847
5848 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5849 list[2].name = "vlan_bridge";
5850 list[2].value = vlan_bridge;
5851
5852 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5853 list[3].name = "vlan_naming";
5854 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005855
developerf5fef612022-09-20 19:38:26 +08005856 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5857 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005858 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005859 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005860
developerf5fef612022-09-20 19:38:26 +08005861 // restart this ap
5862 wifi_setApEnable(apIndex, FALSE);
5863 wifi_setApEnable(apIndex, TRUE);
5864
5865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5866
5867 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005868}
5869
5870// 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.
5871INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5872{
5873 return RETURN_ERR;
5874}
5875
5876// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5877INT wifi_startHostApd()
5878{
5879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5880 system("systemctl start hostapd.service");
5881 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5882 return RETURN_OK;
5883 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5884}
5885
5886// stops hostapd
5887INT wifi_stopHostApd()
5888{
5889 char cmd[128] = {0};
5890 char buf[128] = {0};
5891
5892 sprintf(cmd,"systemctl stop hostapd");
5893 _syscmd(cmd, buf, sizeof(buf));
5894
5895 return RETURN_OK;
5896}
5897
5898// restart hostapd dummy function
5899INT wifi_restartHostApd()
5900{
5901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5902 system("systemctl restart hostapd-global");
5903 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5904
5905 return RETURN_OK;
5906}
5907
5908static int align_hostapd_config(int index)
5909{
5910 ULONG lval;
5911 wifi_getRadioChannel(index%2, &lval);
5912 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08005913 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005914}
5915
5916// sets the AP enable status variable for the specified ap.
5917INT wifi_setApEnable(INT apIndex, BOOL enable)
5918{
developerd946fd62022-12-08 18:03:28 +08005919 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005920 char config_file[MAX_BUF_SIZE] = {0};
5921 char cmd[MAX_CMD_SIZE] = {0};
5922 char buf[MAX_BUF_SIZE] = {0};
5923 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005924 int max_radio_num = 0;
5925 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005926
5927 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005928
5929 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005930 if (enable == status)
5931 return RETURN_OK;
5932
developerac6f1142022-12-20 19:26:35 +08005933 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005934 return RETURN_ERR;
5935
developer06a01d92022-09-07 16:32:39 +08005936 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005937 int radioIndex = apIndex % max_radio_num;
5938 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005939 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5940 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08005941 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005942 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005943 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005944 _syscmd(cmd, buf, sizeof(buf));
5945 }
5946 else {
developerd946fd62022-12-08 18:03:28 +08005947 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005948 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08005949 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08005950 _syscmd(cmd, buf, sizeof(buf));
5951 }
developer431128d2022-12-16 15:30:41 +08005952 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08005953 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08005954 _syscmd(cmd, buf, sizeof(buf));
5955 //Wait for wifi up/down to apply
5956 return RETURN_OK;
5957}
5958
5959// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5960INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5961{
developerd946fd62022-12-08 18:03:28 +08005962 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005963 char cmd[MAX_CMD_SIZE] = {'\0'};
5964 char buf[MAX_BUF_SIZE] = {'\0'};
5965
5966 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5967 return RETURN_ERR;
5968
5969 *output_bool = 0;
5970
5971 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5972 {
developerac6f1142022-12-20 19:26:35 +08005973 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08005974 *output_bool = FALSE;
5975 return RETURN_OK;
5976 }
5977 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08005978 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5979 }
5980
5981 return RETURN_OK;
5982}
5983
5984// Outputs the AP "Enabled" "Disabled" status from driver
5985INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5986{
5987 char cmd[128] = {0};
5988 char buf[128] = {0};
5989 BOOL output_bool;
5990
5991 if ( NULL == output_string)
5992 return RETURN_ERR;
5993 wifi_getApEnable(apIndex,&output_bool);
5994
5995 if(output_bool == 1)
5996 snprintf(output_string, 32, "Up");
5997 else
5998 snprintf(output_string, 32, "Disable");
5999
6000 return RETURN_OK;
6001}
6002
6003//Indicates whether or not beacons include the SSID name.
6004// outputs a 1 if SSID on the AP is enabled, else outputs 0
6005INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6006{
6007 //get the running status
6008 char config_file[MAX_BUF_SIZE] = {0};
6009 char buf[16] = {0};
6010
6011 if (!output)
6012 return RETURN_ERR;
6013
6014 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6015 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006016 // default is enable
6017 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6018 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006019
6020 return RETURN_OK;
6021}
6022
6023// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6024INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6025{
6026 //store the config, apply instantly
6027 char config_file[MAX_BUF_SIZE] = {0};
6028 struct params list;
6029
6030 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6031 list.name = "ignore_broadcast_ssid";
6032 list.value = enable?"0":"1";
6033
6034 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6035 wifi_hostapdWrite(config_file, &list, 1);
6036 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6037 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006038 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006039 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6040
6041 return RETURN_OK;
6042}
6043
6044//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6045INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6046{
6047 //get the running status
6048 if(!output_uint)
6049 return RETURN_ERR;
6050 *output_uint=16;
6051 return RETURN_OK;
6052}
6053
6054INT wifi_setApRetryLimit(INT apIndex, UINT number)
6055{
6056 //apply instantly
6057 return RETURN_ERR;
6058}
6059
6060//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6061INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6062{
6063 if(!output)
6064 return RETURN_ERR;
6065 *output=TRUE;
6066 return RETURN_OK;
6067}
6068
6069//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6070INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6071{
6072 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006073 char cmd[128] = {0};
6074 char buf[128] = {0};
6075 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006076 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006077
developer0b246d12022-09-30 15:24:20 +08006078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006079
developer0b246d12022-09-30 15:24:20 +08006080 wifi_getMaxRadioNumber(&max_radio_num);
6081 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006082 phyId = radio_index_to_phy(radioIndex);
6083 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006084 _syscmd(cmd,buf, sizeof(buf));
6085
6086 if (strlen(buf) > 0)
6087 *output = true;
6088
6089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006090
developer06a01d92022-09-07 16:32:39 +08006091 return RETURN_OK;
6092}
6093
6094//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6095INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6096{
6097 //get the running status from driver
6098 if(!output)
6099 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006100
6101 char config_file[MAX_BUF_SIZE] = {0};
6102 char buf[16] = {0};
6103
6104 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6105 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006106 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006107 *output = TRUE;
6108 else
6109 *output = FALSE;
6110
developer06a01d92022-09-07 16:32:39 +08006111 return RETURN_OK;
6112}
6113
6114// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6115INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6116{
6117 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006118 char config_file[MAX_BUF_SIZE] = {0};
6119 struct params list;
6120
6121 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6122 list.name = "wmm_enabled";
6123 list.value = enable?"1":"0";
6124
6125 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6126 wifi_hostapdWrite(config_file, &list, 1);
6127 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6128 wifi_reloadAp(apIndex);
6129 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6130
6131 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006132}
6133
6134//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.
6135INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6136{
6137 //get the running status from driver
6138 if(!output)
6139 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006140
6141 char config_file[128] = {0};
6142 char buf[16] = {0};
6143
6144 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6145 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6146 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6147 *output = TRUE;
6148 else
6149 *output = FALSE;
6150
developer06a01d92022-09-07 16:32:39 +08006151 return RETURN_OK;
6152}
6153
6154// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6155INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6156{
6157 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006158 char config_file[MAX_BUF_SIZE] = {0};
6159 struct params list;
6160
6161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6162 list.name = "uapsd_advertisement_enabled";
6163 list.value = enable?"1":"0";
6164
6165 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6166 wifi_hostapdWrite(config_file, &list, 1);
6167 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6168 wifi_reloadAp(apIndex);
6169 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6170
6171 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006172}
6173
developer6daeb3f2022-09-30 13:36:39 +08006174// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006175INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6176{
developerd946fd62022-12-08 18:03:28 +08006177 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006178 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6179 char cmd[128] = {0};
6180 char buf[128] = {0};
6181 char ack_filepath[128] = {0};
6182 uint16_t bitmap = 0;
6183 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6184 FILE *f = NULL;
6185
6186 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6187
6188 // Get current setting
6189 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6190 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6191 _syscmd(cmd, buf, sizeof(buf));
6192 if (strlen(buf) > 0)
6193 bitmap = strtoul(buf, NULL, 10);
6194
6195 bitmap = strtoul(buf, NULL, 10);
6196
6197 if (ackPolicy == TRUE) { // True, unset this class
6198 bitmap &= ~class_map[class];
6199 } else { // False, set this class
6200 bitmap |= class_map[class];
6201 }
6202
6203 f = fopen(ack_filepath, "w");
6204 if (f == NULL) {
6205 fprintf(stderr, "%s: fopen failed\n", __func__);
6206 return RETURN_ERR;
6207 }
6208 fprintf(f, "%hu", bitmap);
6209 fclose(f);
6210
developerac6f1142022-12-20 19:26:35 +08006211 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006212 return RETURN_ERR;
6213 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006214 _syscmd(cmd, buf, sizeof(buf));
6215
6216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6217 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006218}
6219
6220//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.
6221INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6222{
6223 //get the running status from driver
6224 if(!output_uint)
6225 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006226
6227 char output[16]={'\0'};
6228 char config_file[MAX_BUF_SIZE] = {0};
6229
6230 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6231 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6232 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6233 else {
6234 int device_num = atoi(output);
6235 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6236 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6237 return RETURN_ERR;
6238 }
6239 else {
6240 *output_uint = device_num;
6241 }
6242 }
6243
developer06a01d92022-09-07 16:32:39 +08006244 return RETURN_OK;
6245}
6246
6247INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6248{
6249 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006250 char str[MAX_BUF_SIZE]={'\0'};
6251 char cmd[MAX_CMD_SIZE]={'\0'};
6252 struct params params;
6253 char config_file[MAX_BUF_SIZE] = {0};
6254
6255 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006256 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006257 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6258 return RETURN_ERR;
6259 }
6260 sprintf(str, "%d", number);
6261 params.name = "max_num_sta";
6262 params.value = str;
6263
6264 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6265 int ret = wifi_hostapdWrite(config_file, &params, 1);
6266 if (ret) {
6267 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6268 ,__func__, ret);
6269 }
6270
6271 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6272 if (ret) {
6273 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6274 ,__func__, ret);
6275 }
6276 wifi_reloadAp(apIndex);
6277 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6278
6279 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006280}
6281
6282//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.
6283INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6284{
6285 //get the current threshold
6286 if(!output_uint)
6287 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006288 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6289 if (*output_uint == 0)
6290 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006291 return RETURN_OK;
6292}
6293
6294INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6295{
6296 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006297 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6298 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006299 return RETURN_ERR;
6300}
6301
6302//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.
6303INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6304{
6305 if(!output_uint)
6306 return RETURN_ERR;
6307 *output_uint = 3;
6308 return RETURN_OK;
6309}
6310
6311//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6312INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6313{
6314 if(!output_uint)
6315 return RETURN_ERR;
6316 *output_uint = 3;
6317 return RETURN_OK;
6318}
6319
6320//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.
6321INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6322{
6323 if(!output_in_seconds)
6324 return RETURN_ERR;
6325 *output_in_seconds = 0;
6326 return RETURN_OK;
6327}
6328
6329//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
6330INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6331{
6332 if(!output || apIndex>=MAX_APS)
6333 return RETURN_ERR;
6334 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006335 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006336 return RETURN_OK;
6337}
6338
6339//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6340INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6341{
developer587c1b62022-09-27 15:58:59 +08006342 char config_file[128] = {0};
6343 char wpa[16] = {0};
6344 char key_mgmt[64] = {0};
6345 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006346 if (!output)
6347 return RETURN_ERR;
6348
6349 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006350 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006351
developer587c1b62022-09-27 15:58:59 +08006352 strcpy(output, "None");//Copying "None" to output string for default case
6353 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006354 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006355 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006356 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006357 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006358 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006359 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006360 snprintf(output, 32, "WPA-WPA2-Personal");
6361
6362 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006363 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006364 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006365 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006366 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006367 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006368 snprintf(output, 32, "WPA-WPA2-Enterprise");
6369 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006370 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006371 snprintf(output, 32, "WPA3-Personal");
6372 else
developer4a359672022-10-13 15:30:46 +08006373 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006374 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6375 snprintf(output, 32, "WPA3-Enterprise");
6376 }
developer06a01d92022-09-07 16:32:39 +08006377
6378 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6379 return RETURN_OK;
6380#if 0
6381 //TODO: need to revisit below implementation
6382 char securityType[32], authMode[32];
6383 int enterpriseMode=0;
6384
6385 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6386 if(!output)
6387 return RETURN_ERR;
6388
6389 wifi_getApBeaconType(apIndex, securityType);
6390 strcpy(output,"None");//By default, copying "None" to output string
6391 if (strncmp(securityType,"None", strlen("None")) == 0)
6392 return RETURN_OK;
6393
6394 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6395 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6396
6397 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6398 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6399 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6400 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6401 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6402 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6403 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6404
6405 return RETURN_OK;
6406#endif
6407}
6408
6409INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6410{
6411 char securityType[32];
6412 char authMode[32];
6413
6414 //store settings and wait for wifi up to apply
6415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6416 if(!encMode)
6417 return RETURN_ERR;
6418
developer06a01d92022-09-07 16:32:39 +08006419 if (strcmp(encMode, "None")==0)
6420 {
6421 strcpy(securityType,"None");
6422 strcpy(authMode,"None");
6423 }
6424 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6425 {
6426 strcpy(securityType,"WPAand11i");
6427 strcpy(authMode,"PSKAuthentication");
6428 }
6429 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6430 {
6431 strcpy(securityType,"WPAand11i");
6432 strcpy(authMode,"EAPAuthentication");
6433 }
6434 else if (strcmp(encMode, "WPA-Personal")==0)
6435 {
6436 strcpy(securityType,"WPA");
6437 strcpy(authMode,"PSKAuthentication");
6438 }
6439 else if (strcmp(encMode, "WPA-Enterprise")==0)
6440 {
6441 strcpy(securityType,"WPA");
6442 strcpy(authMode,"EAPAuthentication");
6443 }
6444 else if (strcmp(encMode, "WPA2-Personal")==0)
6445 {
6446 strcpy(securityType,"11i");
6447 strcpy(authMode,"PSKAuthentication");
6448 }
6449 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6450 {
6451 strcpy(securityType,"11i");
6452 strcpy(authMode,"EAPAuthentication");
6453 }
developer587c1b62022-09-27 15:58:59 +08006454 else if (strcmp(encMode, "WPA3-Personal") == 0)
6455 {
6456 strcpy(securityType,"11i");
6457 strcpy(authMode,"SAEAuthentication");
6458 }
developer4a359672022-10-13 15:30:46 +08006459 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006460 {
6461 strcpy(securityType, "11i");
6462 strcpy(authMode, "PSK-SAEAuthentication");
6463 }
developer587c1b62022-09-27 15:58:59 +08006464 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6465 {
6466 strcpy(securityType,"11i");
6467 strcpy(authMode,"EAP_192-bit_Authentication");
6468 }
developer06a01d92022-09-07 16:32:39 +08006469 else
6470 {
6471 strcpy(securityType,"None");
6472 strcpy(authMode,"None");
6473 }
6474 wifi_setApBeaconType(apIndex, securityType);
6475 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6476 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6477
6478 return RETURN_OK;
6479}
6480
6481
6482//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6483// output_string must be pre-allocated as 64 character string by caller
6484// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6485INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6486{
developer30423732022-12-01 16:17:49 +08006487 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006488 char config_file[MAX_BUF_SIZE] = {0};
6489
6490 if(output_string==NULL)
6491 return RETURN_ERR;
6492
6493 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6494 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6495
6496 if(strcmp(buf,"0")==0)
6497 {
6498 printf("wpa_mode is %s ......... \n",buf);
6499 return RETURN_ERR;
6500 }
6501
6502 wifi_dbg_printf("\nFunc=%s\n",__func__);
6503 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6504 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6505 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6506
6507 return RETURN_OK;
6508}
6509
6510// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6511// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6512INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6513{
6514 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6515 struct params params={'\0'};
6516 int ret;
6517 char config_file[MAX_BUF_SIZE] = {0};
6518
6519 if(NULL == preSharedKey)
6520 return RETURN_ERR;
6521
6522 params.name = "wpa_passphrase";
6523
6524 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6525 {
6526 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6527 return RETURN_ERR;
6528 }
6529 params.value = preSharedKey;
6530 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6531 ret = wifi_hostapdWrite(config_file, &params, 1);
6532 if(!ret)
6533 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6534 return ret;
6535 //TODO: call hostapd_cli for dynamic_config_control
6536}
6537
6538//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6539// outputs the passphrase, maximum 63 characters
6540INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6541{
6542 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6543
6544 wifi_dbg_printf("\nFunc=%s\n",__func__);
6545 if (NULL == output_string)
6546 return RETURN_ERR;
6547
6548 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6549 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6550 if(strcmp(buf,"0")==0)
6551 {
6552 printf("wpa_mode is %s ......... \n",buf);
6553 return RETURN_ERR;
6554 }
6555
6556 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6557 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6558
6559 return RETURN_OK;
6560}
6561
6562// sets the passphrase enviornment variable, max 63 characters
6563INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6564{
6565 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6566 struct params params={'\0'};
6567 char config_file[MAX_BUF_SIZE] = {0};
6568 int ret;
6569
6570 if(NULL == passPhrase)
6571 return RETURN_ERR;
6572
6573 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6574 {
6575 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6576 return RETURN_ERR;
6577 }
6578 params.name = "wpa_passphrase";
6579 params.value = passPhrase;
6580 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6581 ret=wifi_hostapdWrite(config_file,&params,1);
6582 if(!ret)
6583 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6584
6585 return ret;
6586}
6587
6588//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.
6589INT wifi_setApSecurityReset(INT apIndex)
6590{
developer8d583982022-09-20 11:28:22 +08006591 char original_config_file[64] = {0};
6592 char current_config_file[64] = {0};
6593 char buf[64] = {0};
6594 char cmd[64] = {0};
6595 char wpa[4] = {0};
6596 char wpa_psk[64] = {0};
6597 char wpa_passphrase[64] = {0};
6598 char wpa_psk_file[128] = {0};
6599 char wpa_key_mgmt[64] = {0};
6600 char wpa_pairwise[32] = {0};
6601 wifi_band band;
6602 struct params list[6];
6603
6604 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6605
6606 band = wifi_index_to_band(apIndex);
6607 if (band == band_2_4)
6608 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006609 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006610 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006611 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006612 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6613 else
6614 return RETURN_ERR;
6615
6616 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6617 list[0].name = "wpa";
6618 list[0].value = wpa;
6619
6620 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6621 list[1].name = "wpa_psk";
6622 list[1].value = wpa_psk;
6623
6624 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6625 list[2].name = "wpa_passphrase";
6626 list[2].value = wpa_passphrase;
6627
6628 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6629
6630 if (strlen(wpa_psk_file) == 0)
6631 strcpy(wpa_psk_file, PSK_FILE);
6632
6633 if (access(wpa_psk_file, F_OK) != 0) {
6634 sprintf(cmd, "touch %s", wpa_psk_file);
6635 _syscmd(cmd, buf, sizeof(buf));
6636 }
6637 list[3].name = "wpa_psk_file";
6638 list[3].value = wpa_psk_file;
6639
6640 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6641 list[4].name = "wpa_key_mgmt";
6642 list[4].value = wpa_key_mgmt;
6643
6644 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6645 list[5].name = "wpa_pairwise";
6646 list[5].value = wpa_pairwise;
6647
6648 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6649 wifi_hostapdWrite(current_config_file, list, 6);
6650
6651 wifi_setApEnable(apIndex, FALSE);
6652 wifi_setApEnable(apIndex, TRUE);
6653
6654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6655 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006656}
6657
6658//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).
6659INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6660{
developer8f2ddd52022-09-13 15:39:24 +08006661 char config_file[64] = {0};
6662 char buf[64] = {0};
6663 char cmd[256] = {0};
6664
6665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6666
developer06a01d92022-09-07 16:32:39 +08006667 if(!IP_output || !Port_output || !RadiusSecret_output)
6668 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006669
developer8f2ddd52022-09-13 15:39:24 +08006670 // Read the first matched config
6671 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6672 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6673 _syscmd(cmd, buf, sizeof(buf));
6674 strncpy(IP_output, buf, 64);
6675
6676 memset(buf, 0, sizeof(buf));
6677 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6678 _syscmd(cmd, buf, sizeof(buf));
6679 *Port_output = atoi(buf);
6680
6681 memset(buf, 0, sizeof(buf));
6682 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6683 _syscmd(cmd, buf, sizeof(buf));
6684 strncpy(RadiusSecret_output, buf, 64);
6685
6686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006687 return RETURN_OK;
6688}
6689
6690INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6691{
developer8f2ddd52022-09-13 15:39:24 +08006692 char config_file[64] = {0};
6693 char port_str[8] = {0};
6694 char cmd[256] = {0};
6695 char buf[128] = {0};
6696
6697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6698
6699 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6700
6701 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6702 _syscmd(cmd, buf, sizeof(buf));
6703 memset(cmd, 0, sizeof(cmd));
6704
6705 snprintf(port_str, sizeof(port_str), "%d", port);
6706 if (strlen(buf) == 0)
6707 // Append
6708 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6709 "auth_server_addr=%s\\n"
6710 "auth_server_port=%s\\n"
6711 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6712 else {
6713 // Delete the three lines setting after the "# radius 1" comment
6714 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6715 _syscmd(cmd, buf, sizeof(buf));
6716 memset(cmd, 0, sizeof(cmd));
6717 // Use "# radius 1" comment to find the location to insert the radius setting
6718 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6719 "# radius 1\\n"
6720 "auth_server_addr=%s\\n"
6721 "auth_server_port=%s\\n"
6722 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6723 }
6724 if(_syscmd(cmd, buf, sizeof(buf))) {
6725 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6726 return RETURN_ERR;
6727 }
6728
6729 wifi_reloadAp(apIndex);
6730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6731 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006732}
6733
6734INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6735{
developer8f2ddd52022-09-13 15:39:24 +08006736 char config_file[64] = {0};
6737 char buf[64] = {0};
6738 char cmd[256] = {0};
6739
6740 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6741
developer06a01d92022-09-07 16:32:39 +08006742 if(!IP_output || !Port_output || !RadiusSecret_output)
6743 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006744
6745 // Read the second matched config
6746 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6747 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6748 _syscmd(cmd, buf, sizeof(buf));
6749 strncpy(IP_output, buf, 64);
6750
6751 memset(buf, 0, sizeof(buf));
6752 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6753 _syscmd(cmd, buf, sizeof(buf));
6754 *Port_output = atoi(buf);
6755
6756 memset(buf, 0, sizeof(buf));
6757 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6758 _syscmd(cmd, buf, sizeof(buf));
6759 strncpy(RadiusSecret_output, buf, 64);
6760
6761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006762 return RETURN_OK;
6763}
6764
6765INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6766{
developer8f2ddd52022-09-13 15:39:24 +08006767 char config_file[64] = {0};
6768 char port_str[8] = {0};
6769 char cmd[256] = {0};
6770 char buf[128] = {0};
6771
6772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6773
6774 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6775
6776 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6777 _syscmd(cmd, buf, sizeof(buf));
6778 memset(cmd, 0, sizeof(cmd));
6779
6780 snprintf(port_str, sizeof(port_str), "%d", port);
6781 if (strlen(buf) == 0)
6782 // Append
6783 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6784 "auth_server_addr=%s\\n"
6785 "auth_server_port=%s\\n"
6786 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6787 else {
6788 // Delete the three lines setting after the "# radius 2" comment
6789 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6790 _syscmd(cmd, buf, sizeof(buf));
6791 memset(cmd, 0, sizeof(cmd));
6792 // Use "# radius 2" comment to find the location to insert the radius setting
6793 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6794 "# radius 2\\n"
6795 "auth_server_addr=%s\\n"
6796 "auth_server_port=%s\\n"
6797 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6798 }
6799 if(_syscmd(cmd, buf, sizeof(buf))) {
6800 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6801 return RETURN_ERR;
6802 }
6803
6804 wifi_reloadAp(apIndex);
6805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6806 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006807}
6808
6809//RadiusSettings
6810INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6811{
6812 if(!output)
6813 return RETURN_ERR;
6814
6815 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6816 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6817 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6818 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6819 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6820 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.
6821 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6822 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6823 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6824 //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.
6825
6826 return RETURN_OK;
6827}
6828
6829INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6830{
6831 //store the paramters, and apply instantly
6832 return RETURN_ERR;
6833}
6834
6835//Device.WiFi.AccessPoint.{i}.WPS.Enable
6836//Enables or disables WPS functionality for this access point.
6837// outputs the WPS enable state of this ap in output_bool
6838INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6839{
developerd946fd62022-12-08 18:03:28 +08006840 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006841 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006842 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006843 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08006844 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006845 return RETURN_ERR;
6846 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006847 _syscmd(cmd, buf, sizeof(buf));
6848 if(strstr(buf, "configured"))
6849 *output_bool=TRUE;
6850 else
6851 *output_bool=FALSE;
6852
6853 return RETURN_OK;
6854}
6855
6856//Device.WiFi.AccessPoint.{i}.WPS.Enable
6857// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6858INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6859{
6860 char config_file[MAX_BUF_SIZE] = {0};
6861 struct params params;
6862
developer06a01d92022-09-07 16:32:39 +08006863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6864 //store the paramters, and wait for wifi up to apply
6865 params.name = "wps_state";
6866 params.value = enable ? "2":"0";
6867
6868 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6869 wifi_hostapdWrite(config_file, &params, 1);
6870 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6871 wifi_reloadAp(apIndex);
6872
6873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6874 return RETURN_OK;
6875}
6876
6877//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
6878INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6879{
6880 if(!output)
6881 return RETURN_ERR;
6882 snprintf(output, 128, "PushButton,PIN");
6883 return RETURN_OK;
6884}
6885
6886//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6887//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.
6888// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6889INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6890{
6891 if(!output)
6892 return RETURN_ERR;
6893 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6894
6895 return RETURN_OK;
6896}
6897
6898//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6899// 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
6900INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6901{
6902 //apply instantly. No setting need to be stored.
6903 char methods[MAX_BUF_SIZE], *token, *next_token;
6904 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6905 struct params params;
6906
developer5b398df2022-11-17 20:39:48 +08006907 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006908 return RETURN_ERR;
6909 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6910 //store the paramters, and wait for wifi up to apply
6911
6912 snprintf(methods, sizeof(methods), "%s", methodString);
6913 for(token=methods; *token; token=next_token)
6914 {
6915 strtok_r(token, ",", &next_token);
6916 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6917 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6918 else if(*token=='E')
6919 {
6920 if(!strcmp(methods, "Ethernet"))
6921 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6922 else if(!strcmp(methods, "ExternalNFCToken"))
6923 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6924 else
6925 printf("%s: Unknown WpsConfigMethod\n", __func__);
6926 }
6927 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6928 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6929 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6930 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6931 else if(*token=='P' )
6932 {
6933 if(!strcmp(token, "PushButton"))
6934 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6935 else if(!strcmp(token, "PIN"))
6936 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6937 else
6938 printf("%s: Unknown WpsConfigMethod\n", __func__);
6939 }
6940 else
6941 printf("%s: Unknown WpsConfigMethod\n", __func__);
6942 }
6943 params.name = "config_methods";
6944 params.value = config_methods;
6945 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6946 wifi_hostapdWrite(config_file, &params, 1);
6947 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6948 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6949
6950 return RETURN_OK;
6951}
6952
6953// outputs the pin value, ulong_pin must be allocated by the caller
6954INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6955{
6956 char buf[MAX_BUF_SIZE] = {0};
6957 char cmd[MAX_CMD_SIZE] = {0};
6958
developer5b398df2022-11-17 20:39:48 +08006959 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08006960 return RETURN_ERR;
6961 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6962 _syscmd(cmd, buf, sizeof(buf));
6963 if(strlen(buf) > 0)
6964 *output_ulong=strtoul(buf, NULL, 10);
6965
6966 return RETURN_OK;
6967}
6968
6969// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6970INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6971{
6972 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6973 char ap_pin[16] = {0};
6974 char buf[MAX_BUF_SIZE] = {0};
6975 char config_file[MAX_BUF_SIZE] = {0};
6976 ULONG prev_pin = 0;
6977 struct params params;
6978
developer06a01d92022-09-07 16:32:39 +08006979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6980 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6981 params.name = "ap_pin";
6982 params.value = ap_pin;
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// Output string is either Not configured or Configured, max 32 characters
6992INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6993{
developerd946fd62022-12-08 18:03:28 +08006994 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006995 char cmd[MAX_CMD_SIZE];
6996 char buf[MAX_BUF_SIZE]={0};
6997
developer5b398df2022-11-17 20:39:48 +08006998 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08006999 return RETURN_ERR;
7000 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7001 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007002 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007003 return RETURN_ERR;
7004 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007005 _syscmd(cmd, buf, sizeof(buf));
7006
developer348e3d92022-09-13 14:48:41 +08007007 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007008 snprintf(output_string, 32, "Configured");
7009 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7010
7011 return RETURN_OK;
7012}
7013
7014// sets the WPS pin for this AP
7015INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7016{
developerd946fd62022-12-08 18:03:28 +08007017 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007018 char cmd[MAX_CMD_SIZE];
7019 char buf[MAX_BUF_SIZE]={0};
7020 BOOL enable;
7021
developer06a01d92022-09-07 16:32:39 +08007022 wifi_getApEnable(apIndex, &enable);
7023 if (!enable)
7024 return RETURN_ERR;
7025 wifi_getApWpsEnable(apIndex, &enable);
7026 if (!enable)
7027 return RETURN_ERR;
7028
developerac6f1142022-12-20 19:26:35 +08007029 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007030 return RETURN_ERR;
7031 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007032 _syscmd(cmd, buf, sizeof(buf));
7033 if((strstr(buf, "OK"))!=NULL)
7034 return RETURN_OK;
7035
7036 return RETURN_ERR;
7037}
7038
7039// This function is called when the WPS push button has been pressed for this AP
7040INT wifi_setApWpsButtonPush(INT apIndex)
7041{
7042 char cmd[MAX_CMD_SIZE];
7043 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007044 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007045 BOOL enable=FALSE;
7046
developer06a01d92022-09-07 16:32:39 +08007047 wifi_getApEnable(apIndex, &enable);
7048 if (!enable)
7049 return RETURN_ERR;
7050
7051 wifi_getApWpsEnable(apIndex, &enable);
7052 if (!enable)
7053 return RETURN_ERR;
7054
developerac6f1142022-12-20 19:26:35 +08007055 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007056 return RETURN_ERR;
7057
7058 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 +08007059 _syscmd(cmd, buf, sizeof(buf));
7060
7061 if((strstr(buf, "OK"))!=NULL)
7062 return RETURN_OK;
7063 return RETURN_ERR;
7064}
7065
7066// cancels WPS mode for this AP
7067INT wifi_cancelApWPS(INT apIndex)
7068{
developerd946fd62022-12-08 18:03:28 +08007069 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007070 char cmd[MAX_CMD_SIZE];
7071 char buf[MAX_BUF_SIZE]={0};
7072
developerac6f1142022-12-20 19:26:35 +08007073 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007074 return RETURN_ERR;
7075 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007076 _syscmd(cmd,buf, sizeof(buf));
7077
7078 if((strstr(buf, "OK"))!=NULL)
7079 return RETURN_OK;
7080 return RETURN_ERR;
7081}
7082
7083//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7084//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7085INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7086{
developerd946fd62022-12-08 18:03:28 +08007087 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007088 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007089 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007090 char cmd[256] = {0}, buf[2048] = {0};
7091 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007092 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007093 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007094 wifi_associated_dev_t *dev=NULL;
7095
7096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7097 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007098 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007099 return RETURN_ERR;
7100 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007101 _syscmd(cmd,buf,sizeof(buf));
7102 *output_array_size = atoi(buf);
7103
7104 if (*output_array_size <= 0)
7105 return RETURN_OK;
7106
7107 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7108 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007109 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007110 _syscmd(cmd,buf,sizeof(buf));
7111 f = fopen("/tmp/connected_devices.txt", "r");
7112 if (f==NULL)
7113 {
7114 *output_array_size=0;
7115 return RETURN_ERR;
7116 }
developer30423732022-12-01 16:17:49 +08007117 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007118 {
7119 param = strtok(line,"=");
7120 value = strtok(NULL,"=");
7121
7122 if( strcmp("flags",param) == 0 )
7123 {
7124 value[strlen(value)-1]='\0';
7125 if(strstr (value,"AUTHORIZED") != NULL )
7126 {
7127 dev[auth_temp].cli_AuthenticationState = 1;
7128 dev[auth_temp].cli_Active = 1;
7129 auth_temp++;
7130 read_flag=1;
7131 }
7132 }
7133 if(read_flag==1)
7134 {
7135 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7136 {
7137 value[strlen(value)-1]='\0';
7138 sscanf(value, "%x:%x:%x:%x:%x:%x",
7139 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7140 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7141 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7142 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7143 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7144 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7145 mac_temp++;
7146 read_flag=0;
7147 }
7148 }
7149 }
7150 *output_array_size = auth_temp;
7151 auth_temp=0;
7152 mac_temp=0;
7153 free(line);
7154 fclose(f);
7155 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7156 return RETURN_OK;
7157}
7158
7159#define MACADDRESS_SIZE 6
7160
7161INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7162{
7163 FILE *fp = NULL;
7164 char str[MAX_BUF_SIZE] = {0};
7165 int wificlientindex = 0 ;
7166 int count = 0;
7167 int signalstrength = 0;
7168 int arr[MACADDRESS_SIZE] = {0};
7169 unsigned char mac[MACADDRESS_SIZE] = {0};
7170 UINT wifi_count = 0;
7171 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7172 char pipeCmd[MAX_CMD_SIZE] = {0};
7173
7174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7175 *output_array_size = 0;
7176 *associated_dev_array = NULL;
7177
7178 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7179 fp = popen(pipeCmd, "r");
7180 if (fp == NULL)
7181 {
7182 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7183 return RETURN_ERR;
7184 }
7185
7186 /* Read the output a line at a time - output it. */
7187 fgets(str, sizeof(str)-1, fp);
7188 wifi_count = (unsigned int) atoi ( str );
7189 *output_array_size = wifi_count;
7190 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7191 pclose(fp);
7192
7193 if(wifi_count == 0)
7194 {
7195 return RETURN_OK;
7196 }
7197 else
7198 {
7199 wifi_associated_dev3_t* temp = NULL;
7200 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7201 if(temp == NULL)
7202 {
7203 printf("Error Statement. Insufficient memory \n");
7204 return RETURN_ERR;
7205 }
7206
7207 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7208 system(pipeCmd);
7209 memset(pipeCmd,0,sizeof(pipeCmd));
7210 if(apIndex == 0)
7211 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7212 else if(apIndex == 1)
7213 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7214 system(pipeCmd);
7215
7216 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7217 if(fp == NULL)
7218 {
7219 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007220 free(temp);
developer06a01d92022-09-07 16:32:39 +08007221 return RETURN_ERR;
7222 }
7223 fclose(fp);
7224
developer30423732022-12-01 16:17:49 +08007225 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007226 fp = popen(pipeCmd, "r");
7227 if(fp)
7228 {
7229 for(count =0 ; count < wifi_count; count++)
7230 {
7231 fgets(str, MAX_BUF_SIZE, fp);
7232 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7233 {
7234 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7235 {
7236 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7237
7238 }
7239 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7240 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]);
7241 }
7242 temp[count].cli_AuthenticationState = 1; //TODO
7243 temp[count].cli_Active = 1; //TODO
7244 }
7245 pclose(fp);
7246 }
7247
developer30423732022-12-01 16:17:49 +08007248 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 +08007249 fp = popen(pipeCmd, "r");
7250 if(fp)
7251 {
7252 pclose(fp);
7253 }
7254 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7255 if(fp)
7256 {
7257 for(count =0 ; count < wifi_count ;count++)
7258 {
7259 fgets(str, MAX_BUF_SIZE, fp);
7260 signalstrength = atoi(str);
7261 temp[count].cli_SignalStrength = signalstrength;
7262 temp[count].cli_RSSI = signalstrength;
7263 temp[count].cli_SNR = signalstrength + 95;
7264 }
7265 pclose(fp);
7266 }
7267
7268
7269 if((apIndex == 0) || (apIndex == 4))
7270 {
7271 for(count =0 ; count < wifi_count ;count++)
7272 {
7273 strcpy(temp[count].cli_OperatingStandard,"g");
7274 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7275 }
7276
7277 //BytesSent
developer30423732022-12-01 16:17:49 +08007278 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 +08007279 fp = popen(pipeCmd, "r");
7280 if(fp)
7281 {
7282 pclose(fp);
7283 }
7284 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7285 if(fp)
7286 {
7287 for (count = 0; count < wifi_count; count++)
7288 {
7289 fgets(str, MAX_BUF_SIZE, fp);
7290 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7291 }
7292 pclose(fp);
7293 }
7294
7295 //BytesReceived
developer30423732022-12-01 16:17:49 +08007296 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 +08007297 fp = popen(pipeCmd, "r");
7298 if (fp)
7299 {
7300 pclose(fp);
7301 }
7302 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7303 if (fp)
7304 {
7305 for (count = 0; count < wifi_count; count++)
7306 {
7307 fgets(str, MAX_BUF_SIZE, fp);
7308 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7309 }
7310 pclose(fp);
7311 }
7312
7313 //PacketsSent
developer30423732022-12-01 16:17:49 +08007314 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 +08007315 fp = popen(pipeCmd, "r");
7316 if (fp)
7317 {
7318 pclose(fp);
7319 }
7320
7321 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7322 if (fp)
7323 {
7324 for (count = 0; count < wifi_count; count++)
7325 {
7326 fgets(str, MAX_BUF_SIZE, fp);
7327 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7328 }
7329 pclose(fp);
7330 }
7331
7332 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007333 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 +08007334 fp = popen(pipeCmd, "r");
7335 if (fp)
7336 {
7337 pclose(fp);
7338 }
7339 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7340 if (fp)
7341 {
7342 for (count = 0; count < wifi_count; count++)
7343 {
7344 fgets(str, MAX_BUF_SIZE, fp);
7345 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7346 }
7347 pclose(fp);
7348 }
7349
7350 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007351 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 +08007352 fp = popen(pipeCmd, "r");
7353 if (fp)
7354 {
7355 pclose(fp);
7356 }
7357 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7358 if (fp)
7359 {
7360 for (count = 0; count < wifi_count; count++)
7361 {
7362 fgets(str, MAX_BUF_SIZE, fp);
7363 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7364 }
7365 pclose(fp);
7366 }
7367
7368 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007369 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 +08007370 fp = popen(pipeCmd, "r");
7371 if (fp)
7372 {
7373 pclose(fp);
7374 }
7375 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7376 if (fp)
7377 {
7378 for (count = 0; count < wifi_count; count++)
7379 {
7380 fgets(str, MAX_BUF_SIZE, fp);
7381 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7382 }
7383 pclose(fp);
7384 }
7385
7386 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007387 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 +08007388 fp = popen(pipeCmd, "r");
7389 if (fp)
7390 {
7391 pclose(fp);
7392 }
7393 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7394 if (fp)
7395 {
7396 for (count = 0; count < wifi_count; count++)
7397 {
7398 fgets(str, MAX_BUF_SIZE, fp);
7399 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7400 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7401 }
7402 pclose(fp);
7403 }
7404
7405 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007406 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 +08007407 fp = popen(pipeCmd, "r");
7408 if (fp)
7409 {
7410 pclose(fp);
7411 }
7412 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7413 if (fp)
7414 {
7415 for (count = 0; count < wifi_count; count++)
7416 {
7417 fgets(str, MAX_BUF_SIZE, fp);
7418 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7419 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7420 }
7421 pclose(fp);
7422 }
7423
7424 }
7425 else if ((apIndex == 1) || (apIndex == 5))
7426 {
7427 for (count = 0; count < wifi_count; count++)
7428 {
7429 strcpy(temp[count].cli_OperatingStandard, "a");
7430 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7431 temp[count].cli_BytesSent = 0;
7432 temp[count].cli_BytesReceived = 0;
7433 temp[count].cli_LastDataUplinkRate = 0;
7434 temp[count].cli_LastDataDownlinkRate = 0;
7435 temp[count].cli_PacketsSent = 0;
7436 temp[count].cli_PacketsReceived = 0;
7437 temp[count].cli_ErrorsSent = 0;
7438 }
7439 }
7440
7441 for (count = 0; count < wifi_count; count++)
7442 {
7443 temp[count].cli_Retransmissions = 0;
7444 temp[count].cli_DataFramesSentAck = 0;
7445 temp[count].cli_DataFramesSentNoAck = 0;
7446 temp[count].cli_MinRSSI = 0;
7447 temp[count].cli_MaxRSSI = 0;
7448 strncpy(temp[count].cli_InterferenceSources, "", 64);
7449 memset(temp[count].cli_IPAddress, 0, 64);
7450 temp[count].cli_RetransCount = 0;
7451 temp[count].cli_FailedRetransCount = 0;
7452 temp[count].cli_RetryCount = 0;
7453 temp[count].cli_MultipleRetryCount = 0;
7454 }
7455 *associated_dev_array = temp;
7456 }
7457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7458 return RETURN_OK;
7459}
7460
7461int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7462{
7463 FILE *fp = NULL;
7464 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7465 char cmd[MAX_CMD_SIZE];
7466 int count = 0;
7467
7468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7469 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7470 fp = popen(cmd,"r");
7471 if(fp == NULL)
7472 {
7473 printf("Failed to run command in Function %s\n",__FUNCTION__);
7474 return 0;
7475 }
7476 if(fgets(path, sizeof(path)-1, fp) != NULL)
7477 {
7478 for(count=0;path[count]!='\n';count++)
7479 status[count]=path[count];
7480 status[count]='\0';
7481 }
7482 strcpy(wifi_status,status);
7483 pclose(fp);
7484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7485 return RETURN_OK;
7486}
7487
7488/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7489struct hostapd_sta_param {
7490 char key[50];
7491 char value[100];
7492}
7493
7494static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7495 int i = 0;
7496
7497 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7498 if (strncmp(params[i].key,key,50) == 0){
7499 return &params[i].value;
7500 }
7501 i++;
7502 }
7503 return NULL;
7504
7505} */
7506
7507static unsigned int count_occurences(const char *buf, const char *word)
7508{
7509 unsigned int n = 0;
7510 char *ptr = strstr(buf, word);
7511
7512 while (ptr++) {
7513 n++;
7514 ptr = strstr(ptr, word);
7515 }
7516
7517 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7518 return n;
7519}
7520
7521static const char *get_line_from_str_buf(const char *buf, char *line)
7522{
7523 int i;
7524 int n = strlen(buf);
7525
7526 for (i = 0; i < n; i++) {
7527 line[i] = buf[i];
7528 if (buf[i] == '\n') {
7529 line[i] = '\0';
7530 return &buf[i + 1];
7531 }
7532 }
7533
7534 return NULL;
7535}
7536
7537INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7538{
7539 unsigned int assoc_cnt = 0;
7540 char interface_name[50] = {0};
7541 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7542 char cmd[MAX_CMD_SIZE] = {'\0'};
7543 char line[256] = {'\0'};
7544 int i = 0;
7545 int ret = 0;
7546 const char *ptr = NULL;
7547 char *key = NULL;
7548 char *val = NULL;
7549 wifi_associated_dev3_t *temp = NULL;
7550 int rssi;
7551
7552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7553
7554 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7555 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7556 return RETURN_ERR;
7557 }
7558
7559 // Example filtered output of 'iw dev' command:
7560 // Station 0a:69:72:10:d2:fa (on wifi0)
7561 // signal avg:-67 [-71, -71] dBm
7562 // Station 28:c2:1f:25:5f:99 (on wifi0)
7563 // signal avg:-67 [-71, -70] dBm
7564 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7565 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7566 return RETURN_ERR;
7567 }
7568
7569 ret = _syscmd(cmd, buf, sizeof(buf));
7570 if (ret == RETURN_ERR) {
7571 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7572 return RETURN_ERR;
7573 }
7574
7575 *output_array_size = count_occurences(buf, "Station");
7576 if (*output_array_size == 0) return RETURN_OK;
7577
7578 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7579 if (temp == NULL) {
7580 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7581 return RETURN_ERR;
7582 }
7583 *associated_dev_array = temp;
7584
7585 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7586 ptr = get_line_from_str_buf(buf, line);
7587 i = -1;
7588 while (ptr) {
7589 if (strstr(line, "Station")) {
7590 i++;
7591 key = strtok(line, " ");
7592 val = strtok(NULL, " ");
7593 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7594 &temp[i].cli_MACAddress[0],
7595 &temp[i].cli_MACAddress[1],
7596 &temp[i].cli_MACAddress[2],
7597 &temp[i].cli_MACAddress[3],
7598 &temp[i].cli_MACAddress[4],
7599 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7600 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7601 free(*associated_dev_array);
7602 return RETURN_ERR;
7603 }
7604 }
7605 else if (i < 0) {
7606 ptr = get_line_from_str_buf(ptr, line);
7607 continue; // We didn't detect 'station' entry yet
7608 }
7609 else if (strstr(line, "signal avg")) {
7610 key = strtok(line, ":");
7611 val = strtok(NULL, " ");
7612 if (sscanf(val, "%d", &rssi) <= 0 ) {
7613 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7614 free(*associated_dev_array);
7615 return RETURN_ERR;
7616 }
7617 temp[i].cli_RSSI = rssi;
7618 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7619 }
7620 // Here other fields can be parsed if added to filter of 'iw dev' command
7621
7622 ptr = get_line_from_str_buf(ptr, line);
7623 };
7624
7625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7626
7627 return RETURN_OK;
7628}
7629
7630#if 0
7631//To-do
7632INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7633{
7634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7635
7636 //Using different approach to get required WiFi Parameters from system available commands
7637#if 0
7638 FILE *f;
7639 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7640 char cmd[256], buf[2048];
7641 char *param , *value, *line=NULL;
7642 size_t len = 0;
7643 ssize_t nread;
7644 wifi_associated_dev3_t *dev=NULL;
7645 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007646 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007647 _syscmd(cmd,buf,sizeof(buf));
7648 *output_array_size = atoi(buf);
7649
7650 if (*output_array_size <= 0)
7651 return RETURN_OK;
7652
7653 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7654 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007655 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007656 _syscmd(cmd,buf,sizeof(buf));
7657 f = fopen("/tmp/connected_devices.txt", "r");
7658 if (f==NULL)
7659 {
7660 *output_array_size=0;
7661 return RETURN_ERR;
7662 }
7663 while ((nread = getline(&line, &len, f)) != -1)
7664 {
7665 param = strtok(line,"=");
7666 value = strtok(NULL,"=");
7667
7668 if( strcmp("flags",param) == 0 )
7669 {
7670 value[strlen(value)-1]='\0';
7671 if(strstr (value,"AUTHORIZED") != NULL )
7672 {
7673 dev[auth_temp].cli_AuthenticationState = 1;
7674 dev[auth_temp].cli_Active = 1;
7675 auth_temp++;
7676 read_flag=1;
7677 }
7678 }
7679 if(read_flag==1)
7680 {
7681 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7682 {
7683 value[strlen(value)-1]='\0';
7684 sscanf(value, "%x:%x:%x:%x:%x:%x",
7685 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7686 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7687 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7688 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7689 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7690 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7691
7692 }
7693 else if( strcmp("rx_packets",param) == 0 )
7694 {
7695 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7696 }
7697
7698 else if( strcmp("tx_packets",param) == 0 )
7699 {
7700 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7701 }
7702
7703 else if( strcmp("rx_bytes",param) == 0 )
7704 {
7705 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7706 }
7707
7708 else if( strcmp("tx_bytes",param) == 0 )
7709 {
7710 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7711 mac_temp++;
7712 read_flag=0;
7713 }
7714 }
7715 }
7716
7717 *output_array_size = auth_temp;
7718 auth_temp=0;
7719 mac_temp=0;
7720 free(line);
7721 fclose(f);
7722#endif
7723 char interface_name[MAX_BUF_SIZE] = {0};
7724 char wifi_status[MAX_BUF_SIZE] = {0};
7725 char hostapdconf[MAX_BUF_SIZE] = {0};
7726
7727 wifi_associated_dev3_t *dev_array = NULL;
7728 ULONG wifi_count = 0;
7729
7730 *associated_dev_array = NULL;
7731 *output_array_size = 0;
7732
7733 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7734 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7735 {
7736 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7737
developerac6f1142022-12-20 19:26:35 +08007738 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08007739
7740 if(strlen(interface_name) > 1)
7741 {
7742 wifihal_interfacestatus(wifi_status,interface_name);
7743 if(strcmp(wifi_status,"RUNNING") == 0)
7744 {
7745 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7746
7747 *associated_dev_array = dev_array;
7748 *output_array_size = wifi_count;
7749 }
7750 else
7751 {
7752 *associated_dev_array = NULL;
7753 }
7754 }
7755 }
7756
7757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7758 return RETURN_OK;
7759}
7760#endif
7761
7762/* getIPAddress function */
7763/**
7764* @description Returning IpAddress of the Matched String
7765*
7766* @param
7767* @str Having MacAddress
7768* @ipaddr Having ipaddr
7769* @return The status of the operation
7770* @retval RETURN_OK if successful
7771* @retval RETURN_ERR if any error is detected
7772*
7773*/
7774
7775INT getIPAddress(char *str,char *ipaddr)
7776{
7777 FILE *fp = NULL;
7778 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7779 int LeaseTime = 0,ret = 0;
7780 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7781 {
7782 return RETURN_ERR;
7783 }
7784
7785 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7786 {
7787 /*
7788 Sample:sss
7789 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7790 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7791 */
7792 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08007793 &(LeaseTime),
7794 phyAddr,
7795 ipAddr,
7796 hostName
7797 );
developer06a01d92022-09-07 16:32:39 +08007798 if(ret != 4)
7799 continue;
7800 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08007801 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08007802 }
developerd946fd62022-12-08 18:03:28 +08007803 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08007804 return RETURN_OK;
7805}
7806
7807/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7808/**
7809* @description Returning Inactive wireless connected clients informations
7810*
7811* @param
7812* @filename Holding private_wifi 2g/5g content files
7813* @associated_dev_array Having inactiv wireless clients informations
7814* @output_array_size Returning Inactive wireless counts
7815* @return The status of the operation
7816* @retval RETURN_OK if successful
7817* @retval RETURN_ERR if any error is detected
7818*
7819*/
7820
7821INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7822{
7823 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7824 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7825 FILE *fp = NULL;
7826 int arr[MACADDRESS_SIZE] = {0};
7827 unsigned char mac[MACADDRESS_SIZE] = {0};
7828 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7829 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7830 fp = popen(buf,"r");
7831 if(fp == NULL)
7832 return RETURN_ERR;
7833 else
7834 {
7835 fgets(path,sizeof(path),fp);
7836 maccount = atoi(path);
7837 }
7838 pclose(fp);
7839 *output_array_size = maccount;
7840 wifi_associated_dev3_t* temp = NULL;
7841 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7842 *associated_dev_array = temp;
7843 if(temp == NULL)
7844 {
7845 printf("Error Statement. Insufficient memory \n");
7846 return RETURN_ERR;
7847 }
7848 memset(buf,0,sizeof(buf));
7849 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7850 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08007851 if (fp == NULL) {
7852 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7853 return RETURN_ERR;
7854 }
developer06a01d92022-09-07 16:32:39 +08007855 for(count = 0; count < maccount ; count++)
7856 {
7857 fgets(path,sizeof(path),fp);
7858 for(i = 0; path[i]!='\n';i++)
7859 str[i]=path[i];
7860 str[i]='\0';
7861 getIPAddress(str,ipaddr);
7862 memset(buf,0,sizeof(buf));
7863 if(strlen(ipaddr) > 0)
7864 {
7865 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7866 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7867 {
7868 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7869 {
7870 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7871 {
7872 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7873
7874 }
7875 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7876 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]);
7877 }
7878 temp[count].cli_AuthenticationState = 0; //TODO
7879 temp[count].cli_Active = 0; //TODO
7880 temp[count].cli_SignalStrength = 0;
7881 }
7882 else //Active wireless clients info
7883 {
7884 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7885 {
7886 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7887 {
7888 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7889
7890 }
7891 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7892 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]);
7893 }
7894 temp[count].cli_Active = 1;
7895 }
7896 }
7897 memset(ipaddr,0,sizeof(ipaddr));
7898 }
7899 pclose(fp);
7900 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7901 return RETURN_OK;
7902}
7903//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7904//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7905//To get Band Steering Capability
7906INT wifi_getBandSteeringCapability(BOOL *support)
7907{
7908 *support = FALSE;
7909 return RETURN_OK;
7910}
7911
7912
7913//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7914//To get Band Steering enable status
7915INT wifi_getBandSteeringEnable(BOOL *enable)
7916{
7917 *enable = FALSE;
7918 return RETURN_OK;
7919}
7920
7921//To turn on/off Band steering
7922INT wifi_setBandSteeringEnable(BOOL enable)
7923{
7924 return RETURN_OK;
7925}
7926
7927//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7928//To get Band Steering AP group
7929INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7930{
7931 if (NULL == output_ApGroup)
7932 return RETURN_ERR;
7933
7934 strcpy(output_ApGroup, "1,2");
7935 return RETURN_OK;
7936}
7937
7938//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7939//to set and read the band steering BandUtilizationThreshold parameters
7940INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7941{
7942 return RETURN_ERR;
7943}
7944
7945INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7946{
7947 return RETURN_ERR;
7948}
7949
7950//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7951//to set and read the band steering RSSIThreshold parameters
7952INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7953{
7954 return RETURN_ERR;
7955}
7956
7957INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7958{
7959 return RETURN_ERR;
7960}
7961
7962
7963//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7964//to set and read the band steering physical modulation rate threshold parameters
7965INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7966{
7967 //If chip is not support, return -1
7968 return RETURN_ERR;
7969}
7970
7971INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7972{
7973 //If chip is not support, return -1
7974 return RETURN_ERR;
7975}
7976
7977//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7978//to set and read the inactivity time (in seconds) for steering under overload condition
7979INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7980{
7981 return RETURN_ERR;
7982}
7983
7984INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7985{
7986 return RETURN_ERR;
7987}
7988
7989//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7990//to set and read the inactivity time (in seconds) for steering under Idle condition
7991INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7992{
7993 return RETURN_ERR;
7994}
7995
7996INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7997{
7998 return RETURN_ERR;
7999}
8000
8001//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8002//pClientMAC[64]
8003//pSourceSSIDIndex[64]
8004//pDestSSIDIndex[64]
8005//pSteeringReason[256]
8006INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8007{
8008 //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
8009 *pSteeringTime=time(NULL);
8010 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8011 return RETURN_OK;
8012}
8013
8014INT wifi_ifConfigDown(INT apIndex)
8015{
8016 INT status = RETURN_OK;
8017 char cmd[64];
8018
8019 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8020 printf("%s: %s\n", __func__, cmd);
8021 system(cmd);
8022
8023 return status;
8024}
8025
8026INT wifi_ifConfigUp(INT apIndex)
8027{
developerd946fd62022-12-08 18:03:28 +08008028 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008029 char cmd[128];
8030 char buf[1024];
8031
developerac6f1142022-12-20 19:26:35 +08008032 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008033 return RETURN_ERR;
8034 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008035 _syscmd(cmd, buf, sizeof(buf));
8036 return 0;
8037}
8038
8039//>> Deprecated. Replace with wifi_applyRadioSettings
8040INT wifi_pushBridgeInfo(INT apIndex)
8041{
developerd946fd62022-12-08 18:03:28 +08008042 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008043 char ip[32] = {0};
8044 char subnet[32] = {0};
8045 char bridge[32] = {0};
8046 int vlanId = 0;
8047 char cmd[128] = {0};
8048 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008049
8050 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8051 wifi_getApVlanID(apIndex,&vlanId);
8052
developerac6f1142022-12-20 19:26:35 +08008053 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008054 return RETURN_ERR;
8055 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008056 _syscmd(cmd,buf, sizeof(buf));
8057
8058 return 0;
8059}
8060
8061INT wifi_pushChannel(INT radioIndex, UINT channel)
8062{
developerd946fd62022-12-08 18:03:28 +08008063 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008064 char cmd[128];
8065 char buf[1024];
8066 int apIndex;
8067
8068 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008069 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008070 return RETURN_ERR;
8071 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008072 _syscmd(cmd,buf, sizeof(buf));
8073
8074 return 0;
8075}
8076
8077INT wifi_pushChannelMode(INT radioIndex)
8078{
8079 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8080 return RETURN_ERR;
8081}
8082
8083INT wifi_pushDefaultValues(INT radioIndex)
8084{
8085 //Apply Comcast specified default radio settings instantly
8086 //AMPDU=1
8087 //AMPDUFrames=32
8088 //AMPDULim=50000
8089 //txqueuelen=1000
8090
8091 return RETURN_ERR;
8092}
8093
8094INT wifi_pushTxChainMask(INT radioIndex)
8095{
8096 //Apply default TxChainMask instantly
8097 return RETURN_ERR;
8098}
8099
8100INT wifi_pushRxChainMask(INT radioIndex)
8101{
8102 //Apply default RxChainMask instantly
8103 return RETURN_ERR;
8104}
8105
8106INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8107{
8108 INT status;
8109
8110 status = wifi_setSSIDName(apIndex,ssid);
8111 wifi_setApEnable(apIndex,FALSE);
8112 wifi_setApEnable(apIndex,TRUE);
8113
8114 return status;
8115}
8116
8117INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8118{
8119 //Apply default Ssid Advertisement instantly
8120 return RETURN_ERR;
8121}
8122
8123INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8124{
8125 INT status = RETURN_ERR;
8126 *output = 0;
8127 return RETURN_ERR;
8128}
8129
8130INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8131{
8132 return RETURN_OK;
8133}
8134
8135INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8136{
8137 return RETURN_OK;
8138}
8139
8140//To-do
8141INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8142{
developereb199ae2022-09-13 14:04:27 +08008143 char output[16]={'\0'};
8144 char config_file[MAX_BUF_SIZE] = {0};
8145
8146 if (!output_string)
8147 return RETURN_ERR;
8148
8149 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8150 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8151
8152 if (strlen(output) == 0)
8153 snprintf(output_string, 64, "Disabled");
8154 else if (strncmp(output, "0", 1) == 0)
8155 snprintf(output_string, 64, "Disabled");
8156 else if (strncmp(output, "1", 1) == 0)
8157 snprintf(output_string, 64, "Optional");
8158 else if (strncmp(output, "2", 1) == 0)
8159 snprintf(output_string, 64, "Required");
8160 else {
8161 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8162 return RETURN_ERR;
8163 }
8164
8165 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008166 return RETURN_OK;
8167}
8168INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8169{
developereb199ae2022-09-13 14:04:27 +08008170 char str[MAX_BUF_SIZE]={'\0'};
8171 char cmd[MAX_CMD_SIZE]={'\0'};
8172 struct params params;
8173 char config_file[MAX_BUF_SIZE] = {0};
8174
8175 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8176 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8177 return RETURN_ERR;
8178
8179 params.name = "ieee80211w";
8180 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8181 params.value = "0";
8182 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8183 params.value = "1";
8184 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8185 params.value = "2";
8186 else{
8187 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8188 return RETURN_ERR;
8189 }
8190 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8191 wifi_hostapdWrite(config_file, &params, 1);
8192 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008193 return RETURN_OK;
8194}
8195INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8196{
8197 char output[16]={'\0'};
8198 char config_file[MAX_BUF_SIZE] = {0};
8199
8200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8201 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8202 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8203
8204 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8205 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8206
8207 return RETURN_OK;
8208}
8209
8210INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8211{
8212 return RETURN_OK;
8213}
8214
8215INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8216{
8217 return RETURN_OK;
8218}
8219
8220INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8221{
8222 return RETURN_OK;
8223}
8224
8225INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8226{
8227 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8228 char config_file[MAX_BUF_SIZE] = {0};
8229
8230 if (NULL == output)
8231 return RETURN_ERR;
8232 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8233 wifi_hostapdRead(config_file,"hw_mode",output,64);
8234
8235 if(strcmp(output,"b")==0)
8236 sprintf(output, "%s", "1,2,5.5,11");
8237 else if (strcmp(output,"a")==0)
8238 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8239 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8240 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8241
8242 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8243 return RETURN_OK;
8244}
8245
8246INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8247{
8248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8249 char *temp;
8250 char temp_output[128];
8251 char temp_TransmitRates[128];
8252 char config_file[MAX_BUF_SIZE] = {0};
8253
8254 if (NULL == output)
8255 return RETURN_ERR;
8256
8257 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8258 wifi_hostapdRead(config_file,"supported_rates",output,64);
8259
developer5b398df2022-11-17 20:39:48 +08008260 if (strlen(output) == 0) {
8261 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8262 return RETURN_OK;
8263 }
developer06a01d92022-09-07 16:32:39 +08008264 strcpy(temp_TransmitRates,output);
8265 strcpy(temp_output,"");
8266 temp = strtok(temp_TransmitRates," ");
8267 while(temp!=NULL)
8268 {
8269 temp[strlen(temp)-1]=0;
8270 if((temp[0]=='5') && (temp[1]=='\0'))
8271 {
8272 temp="5.5";
8273 }
8274 strcat(temp_output,temp);
8275 temp = strtok(NULL," ");
8276 if(temp!=NULL)
8277 {
8278 strcat(temp_output,",");
8279 }
8280 }
8281 strcpy(output,temp_output);
8282 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8283
8284 return RETURN_OK;
8285}
8286
8287INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8288{
8289 return RETURN_OK;
8290}
8291
8292
8293INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8294{
8295 int i=0;
8296 char *temp;
developeref938762022-10-19 17:21:01 +08008297 char temp1[128] = {0};
8298 char temp_output[128] = {0};
8299 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008300 struct params params={'\0'};
8301 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008302 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008303
8304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8305 if(NULL == output)
8306 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008307 strcpy(temp_TransmitRates,output);
8308
8309 for(i=0;i<strlen(temp_TransmitRates);i++)
8310 {
developeref938762022-10-19 17:21:01 +08008311 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008312 {
8313 continue;
8314 }
8315 else
8316 {
8317 return RETURN_ERR;
8318 }
8319 }
8320 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008321 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008322 while(temp!=NULL)
8323 {
8324 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008325 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008326 {
developeref938762022-10-19 17:21:01 +08008327 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008328 {
8329 return RETURN_ERR;
8330 }
8331 }
8332
8333 if(strcmp(temp,"5.5")==0)
8334 {
8335 strcpy(temp1,"55");
8336 }
8337 else
8338 {
8339 strcat(temp1,"0");
8340 }
8341 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008342 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008343 if(temp!=NULL)
8344 {
8345 strcat(temp_output," ");
8346 }
8347 }
8348 strcpy(output,temp_output);
8349
developer06a01d92022-09-07 16:32:39 +08008350 params.name = "supported_rates";
8351 params.value = output;
8352
8353 wifi_dbg_printf("\n%s:",__func__);
8354 wifi_dbg_printf("params.value=%s\n",params.value);
8355 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8356 wifi_hostapdWrite(config_file,&params,1);
8357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8358
8359 return RETURN_OK;
8360}
8361
8362
8363static char *sncopy(char *dst, int dst_sz, const char *src)
8364{
8365 if (src && dst && dst_sz > 0) {
8366 strncpy(dst, src, dst_sz);
8367 dst[dst_sz - 1] = '\0';
8368 }
8369 return dst;
8370}
8371
8372static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8373{
8374 if (0 == strcmp(ht_mode, "HT40") ||
8375 0 == strcmp(ht_mode, "HT80") ||
8376 0 == strcmp(ht_mode, "HT160")) {
8377 switch (channel) {
8378 case 1 ... 7:
8379 case 36:
8380 case 44:
8381 case 52:
8382 case 60:
8383 case 100:
8384 case 108:
8385 case 116:
8386 case 124:
8387 case 132:
8388 case 140:
8389 case 149:
8390 case 157:
8391 return 1;
8392 case 8 ... 13:
8393 case 40:
8394 case 48:
8395 case 56:
8396 case 64:
8397 case 104:
8398 case 112:
8399 case 120:
8400 case 128:
8401 case 136:
8402 case 144:
8403 case 153:
8404 case 161:
8405 return -1;
8406 default:
8407 return -EINVAL;
8408 }
8409 }
8410
8411 return -EINVAL;
8412}
8413
developerb7593de2022-10-18 09:51:57 +08008414static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8415{
8416 int idx = channel%8;
8417 if (0 == strcmp(ht_mode, "HT40") ||
8418 0 == strcmp(ht_mode, "HT80") ||
8419 0 == strcmp(ht_mode, "HT160")) {
8420 switch (idx) {
8421 case 1:
8422 return 1;
8423 case 5:
8424 return -1;
8425 default:
8426 return -EINVAL;
8427 }
8428 }
8429
8430 return -EINVAL;
8431}
developer06a01d92022-09-07 16:32:39 +08008432static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8433{
8434 if (NULL == hw_mode) return;
8435
8436 if (0 == strcmp(hw_mode, "ac"))
8437 sncopy(bw_mode, bw_mode_len, "ht vht");
8438
8439 if (0 == strcmp(hw_mode, "n"))
8440 sncopy(bw_mode, bw_mode_len, "ht");
8441
8442 return;
8443}
8444
8445static int util_chan_to_freq(int chan)
8446{
8447 if (chan == 14)
8448 return 2484;
8449 else if (chan < 14)
8450 return 2407 + chan * 5;
8451 else if (chan >= 182 && chan <= 196)
8452 return 4000 + chan * 5;
8453 else
8454 return 5000 + chan * 5;
8455 return 0;
8456}
8457
developerb7593de2022-10-18 09:51:57 +08008458static int util_6G_chan_to_freq(int chan)
8459{
8460 if (chan)
8461 return 5950 + chan * 5;
8462 else
8463 return 0;
8464
8465}
developer06a01d92022-09-07 16:32:39 +08008466const int *util_unii_5g_chan2list(int chan, int width)
8467{
8468 static const int lists[] = {
8469 // <width>, <chan1>, <chan2>..., 0,
8470 20, 36, 0,
8471 20, 40, 0,
8472 20, 44, 0,
8473 20, 48, 0,
8474 20, 52, 0,
8475 20, 56, 0,
8476 20, 60, 0,
8477 20, 64, 0,
8478 20, 100, 0,
8479 20, 104, 0,
8480 20, 108, 0,
8481 20, 112, 0,
8482 20, 116, 0,
8483 20, 120, 0,
8484 20, 124, 0,
8485 20, 128, 0,
8486 20, 132, 0,
8487 20, 136, 0,
8488 20, 140, 0,
8489 20, 144, 0,
8490 20, 149, 0,
8491 20, 153, 0,
8492 20, 157, 0,
8493 20, 161, 0,
8494 20, 165, 0,
8495 40, 36, 40, 0,
8496 40, 44, 48, 0,
8497 40, 52, 56, 0,
8498 40, 60, 64, 0,
8499 40, 100, 104, 0,
8500 40, 108, 112, 0,
8501 40, 116, 120, 0,
8502 40, 124, 128, 0,
8503 40, 132, 136, 0,
8504 40, 140, 144, 0,
8505 40, 149, 153, 0,
8506 40, 157, 161, 0,
8507 80, 36, 40, 44, 48, 0,
8508 80, 52, 56, 60, 64, 0,
8509 80, 100, 104, 108, 112, 0,
8510 80, 116, 120, 124, 128, 0,
8511 80, 132, 136, 140, 144, 0,
8512 80, 149, 153, 157, 161, 0,
8513 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8514 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8515 -1 // final delimiter
8516 };
8517 const int *start;
8518 const int *p;
8519
8520 for (p = lists; *p != -1; p++) {
8521 if (*p == width) {
8522 for (start = ++p; *p != 0; p++) {
8523 if (*p == chan)
8524 return start;
8525 }
8526 }
8527 // move to the end of channel list of given width
8528 while (*p != 0) {
8529 p++;
8530 }
8531 }
8532
8533 return NULL;
8534}
8535
8536static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8537{
8538 if (NULL == ht_mode)
8539 return 0;
8540
8541 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8542 const int *chans = util_unii_5g_chan2list(channel, width);
8543 int sum = 0;
8544 int cnt = 0;
8545
8546 if (NULL == chans)
8547 return 0;
8548
8549 while (*chans) {
8550 sum += *chans;
8551 cnt++;
8552 chans++;
8553 }
developer30423732022-12-01 16:17:49 +08008554 if (cnt == 0)
8555 return 0;
developer06a01d92022-09-07 16:32:39 +08008556 return sum / cnt;
8557}
8558
developerb7593de2022-10-18 09:51:57 +08008559static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8560{
8561 if (NULL == ht_mode)
8562 return 0;
8563
8564 int width = strtol((ht_mode + 2), NULL, 10);
8565
8566 int idx = 0 ;
8567 int centerchan = 0;
8568 int chan_ofs = 1;
8569
8570 if (width == 40){
8571 idx = ((channel/4) + chan_ofs)%2;
8572 switch (idx) {
8573 case 0:
8574 centerchan = (channel - 2);
8575 break;
8576 case 1:
8577 centerchan = (channel + 2);
8578 break;
8579 default:
8580 return -EINVAL;
8581 }
8582 }else if (width == 80){
8583 idx = ((channel/4) + chan_ofs)%4;
8584 switch (idx) {
8585 case 0:
8586 centerchan = (channel - 6);
8587 break;
8588 case 1:
8589 centerchan = (channel + 6);
8590 break;
8591 case 2:
8592 centerchan = (channel + 2);
8593 break;
8594 case 3:
8595 centerchan = (channel - 2);
8596 break;
8597 default:
8598 return -EINVAL;
8599 }
8600 }else if (width == 160){
8601 switch (channel) {
8602 case 1 ... 29:
8603 centerchan = 15;
8604 break;
8605 case 33 ... 61:
8606 centerchan = 47;
8607 break;
8608 case 65 ... 93:
8609 centerchan = 79;
8610 break;
8611 case 97 ... 125:
8612 centerchan = 111;
8613 break;
8614 case 129 ... 157:
8615 centerchan = 143;
8616 break;
8617 case 161 ... 189:
8618 centerchan = 175;
8619 break;
8620 case 193 ... 221:
8621 centerchan = 207;
8622 break;
8623 default:
8624 return -EINVAL;
8625 }
8626 }
8627 return centerchan;
8628}
developer06a01d92022-09-07 16:32:39 +08008629static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8630{
8631 BOOL onlyG, onlyN, onlyA;
8632 CHAR tmp[64];
8633 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8634 if (ret == RETURN_OK) {
8635 sncopy(hw_mode, hw_mode_size, tmp);
8636 }
8637 return ret;
8638}
8639
8640INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8641{
8642 // Sample commands:
8643 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8644 // hostapd_cli -i wifi0 chan_switch 30 2437
8645 char cmd[MAX_CMD_SIZE] = {0};
8646 char buf[MAX_BUF_SIZE] = {0};
8647 int freq = 0, ret = 0;
8648 char center_freq1_str[32] = ""; // center_freq1=%d
8649 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8650 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8651 char hw_mode[16] = ""; // n|ac
8652 char bw_mode[16] = ""; // ht|ht vht
8653 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008654 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008655 int sec_chan_offset;
8656 int width;
developer4fb0b922022-09-30 14:29:09 +08008657 char config_file[64] = {0};
8658 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008659 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008660 wifi_band band = band_invalid;
8661 int center_chan = 0;
8662 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008663
developer4fb0b922022-09-30 14:29:09 +08008664 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008665
developerac6f1142022-12-20 19:26:35 +08008666 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008667 return RETURN_ERR;
8668
developer06a01d92022-09-07 16:32:39 +08008669 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8670
developerb7593de2022-10-18 09:51:57 +08008671 band = wifi_index_to_band(radioIndex);
8672
developer5884e982022-10-06 10:52:50 +08008673 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008674
8675 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008676 if (channel){
developerb7593de2022-10-18 09:51:57 +08008677 if (band == band_6){
8678 freq = util_6G_chan_to_freq(channel);
8679 }else{
8680 freq = util_chan_to_freq(channel);
8681 }
developer5884e982022-10-06 10:52:50 +08008682 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008683
developer5884e982022-10-06 10:52:50 +08008684 // Provide bandwith if specified
8685 if (channel_width_MHz > 20) {
8686 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8687 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8688 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008689
developer5884e982022-10-06 10:52:50 +08008690 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8691 }else if (channel_width_MHz == 20){
8692 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8693 }
developer06a01d92022-09-07 16:32:39 +08008694
developerb7593de2022-10-18 09:51:57 +08008695
developer5884e982022-10-06 10:52:50 +08008696 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008697 if (band == band_6){
8698 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8699 if(center_chan){
8700 center_freq1 = util_6G_chan_to_freq(center_chan);
8701 }
8702 }else{
8703 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8704 if(center_chan){
8705 center_freq1 = util_chan_to_freq(center_chan);
8706 }
developer5884e982022-10-06 10:52:50 +08008707 }
developerb7593de2022-10-18 09:51:57 +08008708
8709 if (center_freq1)
8710 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8711
8712 }
8713
8714 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8715 if (band == band_6){
8716 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8717 }else{
8718 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008719 }
developerb7593de2022-10-18 09:51:57 +08008720 if (sec_chan_offset != -EINVAL)
8721 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008722
developer5884e982022-10-06 10:52:50 +08008723 // Only the first AP, other are hanging on the same radio
8724 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08008725 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8726 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08008727 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8728 wifi_dbg_printf("execute: '%s'\n", cmd);
8729 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008730
developer5884e982022-10-06 10:52:50 +08008731 ret = wifi_setRadioChannel(radioIndex, channel);
8732 if (ret != RETURN_OK) {
8733 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8734 return RETURN_ERR;
8735 }
8736
8737 if (sec_chan_offset == 1) ext_str = "Above";
8738 else if (sec_chan_offset == -1) ext_str = "Below";
8739
8740 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008741
developer5884e982022-10-06 10:52:50 +08008742 } else {
8743 if (channel_width_MHz > 20)
8744 ext_str = "Above";
8745 }
developer4fb0b922022-09-30 14:29:09 +08008746 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8747 _syscmd(cmd, buf, sizeof(buf));
8748 if (strlen(buf) != 0)
8749 stbcEnable = TRUE;
8750
developer06a01d92022-09-07 16:32:39 +08008751 wifi_setRadioExtChannel(radioIndex, ext_str);
8752
developer4fb0b922022-09-30 14:29:09 +08008753 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8754
developer06a01d92022-09-07 16:32:39 +08008755 char mhz_str[16];
8756 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8757 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8758
8759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8760
8761 return RETURN_OK;
8762}
8763
8764INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8765{
developer615510b2022-09-27 10:14:35 +08008766 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008767 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008768 char cmd[256]={0};
8769 char buf[128]={0};
8770 char file_name[32] = {0};
8771 char filter_SSID[32] = {0};
8772 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08008773 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08008774 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008775 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008776 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008777 size_t len=0;
8778 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008779 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008780 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008781 bool filter_enable = false;
8782 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008783 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008784
developer615510b2022-09-27 10:14:35 +08008785 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008786
developer615510b2022-09-27 10:14:35 +08008787 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8788 f = fopen(file_name, "r");
8789 if (f != NULL) {
8790 fgets(filter_SSID, sizeof(file_name), f);
8791 if (strlen(filter_SSID) != 0)
8792 filter_enable = true;
8793 fclose(f);
8794 }
8795
developerac6f1142022-12-20 19:26:35 +08008796 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008797 return RETURN_ERR;
8798
developer033b37b2022-10-18 11:27:46 +08008799 phyId = radio_index_to_phy(radio_index);
8800
8801 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008802 _syscmd(cmd, buf, sizeof(buf));
8803 channels_num = strtol(buf, NULL, 10);
8804
developerd946fd62022-12-08 18:03:28 +08008805 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8806 // 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 +08008807 fprintf(stderr, "cmd: %s\n", cmd);
8808 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008809 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8810 return RETURN_ERR;
8811 }
developer5550e242022-09-30 09:59:32 +08008812
8813 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8814 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8815
developer615510b2022-09-27 10:14:35 +08008816 ret = fgets(line, sizeof(line), f);
8817 while (ret != NULL) {
8818 if(strstr(line, "BSS") != NULL) { // new neighbor info
8819 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8820 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8821 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8822
8823 if (!filter_BSS) {
8824 index++;
8825 wifi_neighbor_ap2_t *tmp;
8826 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8827 if (tmp == NULL) { // no more memory to use
8828 index--;
8829 wifi_dbg_printf("%s: realloc failed\n", __func__);
8830 break;
8831 }
8832 scan_array = tmp;
8833 }
8834 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008835
developer615510b2022-09-27 10:14:35 +08008836 filter_BSS = false;
8837 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8838 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8839 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8840 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8841 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008842 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008843 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008844
developer615510b2022-09-27 10:14:35 +08008845 if (freq >= 2412 && freq <= 2484) {
8846 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8847 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8848 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8849 }
8850 else if (freq >= 5160 && freq <= 5805) {
8851 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8852 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8853 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8854 }
developer06a01d92022-09-07 16:32:39 +08008855
developer615510b2022-09-27 10:14:35 +08008856 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008857 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008858 for (int i = 0; i < channels_num; i++) {
8859 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8860 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8861 break;
8862 }
8863 }
developer06a01d92022-09-07 16:32:39 +08008864 }
developer615510b2022-09-27 10:14:35 +08008865 } else if (strstr(line, "beacon interval") != NULL) {
8866 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8867 } else if (strstr(line, "signal") != NULL) {
8868 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8869 } else if (strstr(line,"SSID") != NULL) {
8870 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8871 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8872 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008873 }
developer615510b2022-09-27 10:14:35 +08008874 } else if (strstr(line, "Supported rates") != NULL) {
8875 char SRate[80] = {0}, *tmp = NULL;
8876 memset(buf, 0, sizeof(buf));
8877 strcpy(SRate, line);
8878 tmp = strtok(SRate, ":");
8879 tmp = strtok(NULL, ":");
8880 strcpy(buf, tmp);
8881 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008882
developer615510b2022-09-27 10:14:35 +08008883 tmp = strtok(buf, " \n");
8884 while (tmp != NULL) {
8885 strcat(SRate, tmp);
8886 if (SRate[strlen(SRate) - 1] == '*') {
8887 SRate[strlen(SRate) - 1] = '\0';
8888 }
8889 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008890
developer615510b2022-09-27 10:14:35 +08008891 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008892 }
developer615510b2022-09-27 10:14:35 +08008893 SRate[strlen(SRate) - 1] = '\0';
8894 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8895 } else if (strstr(line, "DTIM") != NULL) {
8896 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8897 } else if (strstr(line, "VHT capabilities") != NULL) {
8898 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8899 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8900 } else if (strstr(line, "HT capabilities") != NULL) {
8901 strcat(scan_array[index].ap_SupportedStandards, ",n");
8902 strcpy(scan_array[index].ap_OperatingStandards, "n");
8903 } else if (strstr(line, "VHT operation") != NULL) {
8904 ret = fgets(line, sizeof(line), f);
8905 sscanf(line," * channel width: %d", &vht_channel_width);
8906 if(vht_channel_width == 1) {
8907 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8908 } else {
8909 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8910 }
8911 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8912 continue;
8913 } else if (strstr(line, "HT operation") != NULL) {
8914 ret = fgets(line, sizeof(line), f);
8915 sscanf(line," * secondary channel offset: %s", &buf);
8916 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008917 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008918 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 +08008919 }
developer615510b2022-09-27 10:14:35 +08008920 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008921 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008922 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8923 } else {
8924 //20Mhz
8925 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 +08008926 }
developer615510b2022-09-27 10:14:35 +08008927 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008928 continue;
developer615510b2022-09-27 10:14:35 +08008929 } else if (strstr(line, "HE capabilities") != NULL) {
8930 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8931 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8932 ret = fgets(line, sizeof(line), f);
8933 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8934 if (strstr(line, "HE40/2.4GHz") != NULL)
8935 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8936 else
8937 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8938 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8939 if (strstr(line, "HE80/5GHz") != NULL) {
8940 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8941 ret = fgets(line, sizeof(line), f);
8942 } else
8943 continue;
8944 if (strstr(line, "HE160/5GHz") != NULL)
8945 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008946 }
developer615510b2022-09-27 10:14:35 +08008947 continue;
8948 } else if (strstr(line, "WPA") != NULL) {
8949 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8950 } else if (strstr(line, "RSN") != NULL) {
8951 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8952 } else if (strstr(line, "Group cipher") != NULL) {
8953 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8954 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8955 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008956 }
developer06a01d92022-09-07 16:32:39 +08008957 }
developer615510b2022-09-27 10:14:35 +08008958 ret = fgets(line, sizeof(line), f);
8959 }
8960
8961 if (!filter_BSS) {
8962 *output_array_size = index + 1;
8963 } else {
8964 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8965 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008966 }
developer06a01d92022-09-07 16:32:39 +08008967 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008968 pclose(f);
developer5550e242022-09-30 09:59:32 +08008969 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008970 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008971 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008972}
developer615510b2022-09-27 10:14:35 +08008973
developer06a01d92022-09-07 16:32:39 +08008974INT wifi_getApAssociatedDeviceStats(
8975 INT apIndex,
8976 mac_address_t *clientMacAddress,
8977 wifi_associated_dev_stats_t *associated_dev_stats,
8978 u64 *handle)
8979{
8980 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8981 char interface_name[50] = {0};
8982 char cmd[1024] = {0};
8983 char mac_str[18] = {0};
8984 char *key = NULL;
8985 char *val = NULL;
8986 FILE *f = NULL;
8987 char *line = NULL;
8988 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08008989
8990 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8991 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8992 return RETURN_ERR;
8993 }
8994
8995 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8996 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8997 if((f = popen(cmd, "r")) == NULL) {
8998 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8999 return RETURN_ERR;
9000 }
9001
developer30423732022-12-01 16:17:49 +08009002 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009003 key = strtok(line,":");
9004 val = strtok(NULL,":");
9005
9006 if(!strncmp(key,"rx bytes",8))
9007 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9008 if(!strncmp(key,"tx bytes",8))
9009 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9010 if(!strncmp(key,"rx packets",10))
9011 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9012 if(!strncmp(key,"tx packets",10))
9013 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9014 if(!strncmp(key,"tx retries",10))
9015 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9016 if(!strncmp(key,"tx failed",9))
9017 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9018 if(!strncmp(key,"rx drop misc",13))
9019 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9020 if(!strncmp(key,"rx bitrate",10)) {
9021 val = strtok(val, " ");
9022 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9023 }
9024 if(!strncmp(key,"tx bitrate",10)) {
9025 val = strtok(val, " ");
9026 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9027 }
9028 }
9029 free(line);
9030 pclose(f);
9031 return RETURN_OK;
9032}
9033
9034INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9035{
developerd946fd62022-12-08 18:03:28 +08009036 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009037 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9038
9039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9040 if (NULL == output_string)
9041 return RETURN_ERR;
9042
developerac6f1142022-12-20 19:26:35 +08009043 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009044 return RETURN_ERR;
9045 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 +08009046 _syscmd(cmd, buf, sizeof(buf));
9047
9048 //size of SSID name restricted to value less than 32 bytes
9049 snprintf(output_string, 32, "%s", buf);
9050 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9051
9052 return RETURN_OK;
9053}
9054
9055INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9056{
9057 //char cmd[MAX_CMD_SIZE] = {0};
9058 char config_file[MAX_BUF_SIZE] = {0};
9059 char buf[32] = {0};
9060
9061 if (!output_filterMode)
9062 return RETURN_ERR;
9063
9064 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9065 //_syscmd(cmd, buf, sizeof(buf));
9066 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9067 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009068 if(strlen(buf) == 0) {
9069 *output_filterMode = 0;
9070 }
9071 else {
9072 int macaddr_acl_mode = strtol(buf, NULL, 10);
9073 if (macaddr_acl_mode == 1) {
9074 *output_filterMode = 1;
9075 } else if (macaddr_acl_mode == 0) {
9076 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9077 if (strlen(buf) == 0) {
9078 *output_filterMode = 0;
9079 } else {
9080 *output_filterMode = 2;
9081 }
9082 } else {
9083 return RETURN_ERR;
9084 }
9085 }
developer06a01d92022-09-07 16:32:39 +08009086
9087 return RETURN_OK;
9088}
9089
9090INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9091{
9092 FILE *fp = NULL;
9093 char str[MAX_BUF_SIZE] = {0};
9094 int wificlientindex = 0 ;
9095 int count = 0;
9096 int signalstrength = 0;
9097 int arr[MACADDRESS_SIZE] = {0};
9098 unsigned char mac[MACADDRESS_SIZE] = {0};
9099 UINT wifi_count = 0;
9100 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9101 char pipeCmd[MAX_CMD_SIZE] = {0};
9102
9103 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9104 *output_array_size = 0;
9105 *associated_dev_array = NULL;
9106 char interface_name[50] = {0};
9107
9108 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9109 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9110 return RETURN_ERR;
9111 }
9112
9113 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9114 fp = popen(pipeCmd, "r");
9115 if (fp == NULL)
9116 {
9117 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9118 return RETURN_ERR;
9119 }
9120
9121 /* Read the output a line at a time - output it. */
9122 fgets(str, sizeof(str)-1, fp);
9123 wifi_count = (unsigned int) atoi ( str );
9124 *output_array_size = wifi_count;
9125 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9126 pclose(fp);
9127
9128 if(wifi_count == 0)
9129 {
9130 return RETURN_OK;
9131 }
9132 else
9133 {
9134 wifi_associated_dev2_t* temp = NULL;
9135 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9136 *associated_dev_array = temp;
9137 if(temp == NULL)
9138 {
9139 printf("Error Statement. Insufficient memory \n");
9140 return RETURN_ERR;
9141 }
9142
9143 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9144 system(pipeCmd);
9145
9146 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9147 if(fp == NULL)
9148 {
9149 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9150 return RETURN_ERR;
9151 }
9152 fclose(fp);
9153
developer30423732022-12-01 16:17:49 +08009154 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009155 fp = popen(pipeCmd, "r");
9156 if(fp)
9157 {
9158 for(count =0 ; count < wifi_count; count++)
9159 {
9160 fgets(str, MAX_BUF_SIZE, fp);
9161 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9162 {
9163 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9164 {
9165 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9166
9167 }
9168 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9169 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]);
9170 }
9171 temp[count].cli_AuthenticationState = 1; //TODO
9172 temp[count].cli_Active = 1; //TODO
9173 }
9174 pclose(fp);
9175 }
9176
9177 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009178 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 +08009179 fp = popen(pipeCmd, "r");
9180 if(fp)
9181 {
9182 pclose(fp);
9183 }
9184 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9185 if(fp)
9186 {
9187 for(count =0 ; count < wifi_count ;count++)
9188 {
9189 fgets(str, MAX_BUF_SIZE, fp);
9190 signalstrength = atoi(str);
9191 temp[count].cli_RSSI = signalstrength;
9192 }
9193 pclose(fp);
9194 }
9195
9196
9197 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009198 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 +08009199 fp = popen(pipeCmd, "r");
9200 if (fp)
9201 {
9202 pclose(fp);
9203 }
9204 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9205 if (fp)
9206 {
9207 for (count = 0; count < wifi_count; count++)
9208 {
9209 fgets(str, MAX_BUF_SIZE, fp);
9210 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9211 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9212 }
9213 pclose(fp);
9214 }
9215
9216 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009217 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 +08009218 fp = popen(pipeCmd, "r");
9219 if (fp)
9220 {
9221 pclose(fp);
9222 }
9223 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9224 if (fp)
9225 {
9226 for (count = 0; count < wifi_count; count++)
9227 {
9228 fgets(str, MAX_BUF_SIZE, fp);
9229 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9230 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9231 }
9232 pclose(fp);
9233 }
9234 }
9235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9236 return RETURN_OK;
9237
9238}
9239
9240INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9241{
9242#if 0
9243 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009244 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009245 _syscmd(cmd, buf, sizeof(buf));*/
9246
9247 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9248 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9249 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9250 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9251
9252 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.
9253 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].
9254 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].
9255 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].
9256 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9257 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9258
9259 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9260 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9261 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9262 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.
9263 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.
9264 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.
9265 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.
9266 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.
9267 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.
9268 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.
9269 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9270#endif
9271
9272 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009273 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009274 char pipeCmd[128] = {0};
9275 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009276 wifi_ssidTrafficStats2_t *out = output_struct;
9277
developerce736392022-09-13 15:24:34 +08009278 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009279 if (!output_struct)
9280 return RETURN_ERR;
9281
developerce736392022-09-13 15:24:34 +08009282 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009283 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009284 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009285 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009286
developer06a01d92022-09-07 16:32:39 +08009287 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009288 if (fp == NULL) {
9289 fprintf(stderr, "%s: popen failed\n", __func__);
9290 return RETURN_ERR;
9291 }
9292 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009293 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009294
developerce736392022-09-13 15:24:34 +08009295 if (strlen(str) == 0) // interface not exist
9296 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009297
developerce736392022-09-13 15:24:34 +08009298 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9299 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009300
developerce736392022-09-13 15:24:34 +08009301 memset(str, 0, sizeof(str));
9302 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009303 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009304 if (fp == NULL) {
9305 fprintf(stderr, "%s: popen failed\n", __func__);
9306 return RETURN_ERR;
9307 }
9308 fgets(str, sizeof(str), fp);
9309
9310 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9311 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009312 pclose(fp);
developerce736392022-09-13 15:24:34 +08009313
9314 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9315 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9316
9317 // Not supported
9318 output_struct->ssid_RetransCount = 0;
9319 output_struct->ssid_FailedRetransCount = 0;
9320 output_struct->ssid_RetryCount = 0;
9321 output_struct->ssid_MultipleRetryCount = 0;
9322 output_struct->ssid_ACKFailureCount = 0;
9323 output_struct->ssid_AggregatedPacketCount = 0;
9324
developer06a01d92022-09-07 16:32:39 +08009325 return RETURN_OK;
9326}
9327
9328//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).
9329INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9330{
9331 char output_val[16]={'\0'};
9332 char config_file[MAX_BUF_SIZE] = {0};
9333
9334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9335 if (!output)
9336 return RETURN_ERR;
9337 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9338 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9339
9340 if( strcmp(output_val,"1") == 0 )
9341 *output = TRUE;
9342 else
9343 *output = FALSE;
9344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9345
9346 return RETURN_OK;
9347}
9348
9349INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9350{
9351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9352 char str[MAX_BUF_SIZE]={'\0'};
9353 char string[MAX_BUF_SIZE]={'\0'};
9354 char cmd[MAX_CMD_SIZE]={'\0'};
9355 char *ch;
9356 char config_file[MAX_BUF_SIZE] = {0};
9357 struct params params;
9358
9359 if(enable == TRUE)
9360 strcpy(string,"1");
9361 else
9362 strcpy(string,"0");
9363
9364 params.name = "ap_isolate";
9365 params.value = string;
9366
9367 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9368 wifi_hostapdWrite(config_file,&params,1);
9369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9370
9371 return RETURN_OK;
9372}
9373
9374INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9375{
9376 if (NULL == output_dBm)
9377 return RETURN_ERR;
9378
9379 *output_dBm = 0;
9380 return RETURN_OK;
9381}
9382
9383INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9384{
9385 return RETURN_OK;
9386}
9387INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9388{
9389 return RETURN_OK;
9390}
9391INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9392{
9393 return RETURN_OK;
9394}
9395INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9396{
9397 return RETURN_OK;
9398}
9399INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9400{
9401 return RETURN_OK;
9402}
9403INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9404{
9405 char config_file[MAX_BUF_SIZE] = {0};
9406 struct params list;
9407
9408 list.name = "bss_transition";
9409 list.value = activate?"1":"0";
9410 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9411 wifi_hostapdWrite(config_file, &list, 1);
9412
9413 return RETURN_OK;
9414}
9415wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9416
9417void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9418{
9419 return;
9420}
9421
9422INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9423{
9424 // TODO Implement me!
9425 return RETURN_OK;
9426}
9427
9428INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9429{
developera3c68b92022-09-13 15:27:29 +08009430 char file_name[128] = {0};
9431 char buf[128] = {0};
9432 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009433 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009434
9435 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9436
developer804c64f2022-10-19 13:54:40 +08009437 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009438 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009439 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009440 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9441 f = fopen(file_name, "w");
9442 if (f == NULL)
9443 return RETURN_ERR;
9444 // For mode == 0 is to disable filter, just don't write to the file.
9445 if (mode)
9446 fprintf(f, "%s", essid);
9447
9448 fclose(f);
9449 }
9450 } else { // special case, need to set AP's SSID as filter for each radio.
9451 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9452 f = fopen(file_name, "w");
9453 if (f == NULL)
9454 return RETURN_ERR;
9455
9456 // For mode == 0 is to disable filter, just don't write to the file.
9457 if (mode)
9458 fprintf(f, "%s", essid);
9459
9460 fclose(f);
9461 }
9462
9463 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009464 return RETURN_OK;
9465}
9466
9467INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9468{
9469 // TODO Implement me!
9470 //Apply wifi_pushRadioChannel() instantly
9471 return RETURN_ERR;
9472}
9473
9474INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9475{
9476 // TODO Implement me!
9477 return RETURN_OK;
9478}
9479
9480#ifdef HAL_NETLINK_IMPL
9481static int tidStats_callback(struct nl_msg *msg, void *arg) {
9482 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9483 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9484 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9485 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9486 int rem , tid_index = 0;
9487
9488 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9489 wifi_associated_dev_tid_entry_t *stats_entry;
9490
9491 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9492 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9493 };
9494 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9495 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9496 };
9497
9498 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9499 genlmsg_attrlen(gnlh, 0), NULL);
9500
9501
9502 if (!tb[NL80211_ATTR_STA_INFO]) {
9503 fprintf(stderr, "station stats missing!\n");
9504 return NL_SKIP;
9505 }
9506
9507 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9508 tb[NL80211_ATTR_STA_INFO],
9509 stats_policy)) {
9510 fprintf(stderr, "failed to parse nested attributes!\n");
9511 return NL_SKIP;
9512 }
9513
9514 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9515 {
9516 stats_entry = &out->tid_array[tid_index];
9517
9518 stats_entry->tid = tid_index;
9519 stats_entry->ac = _tid_ac_index_get[tid_index];
9520
9521 if(sinfo[NL80211_STA_INFO_TID_STATS])
9522 {
9523 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9524 printf("failed to parse nested stats attributes!");
9525 return NL_SKIP;
9526 }
9527 }
9528 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9529 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9530
9531 if(tid_index < (PS_MAX_TID - 1))
9532 tid_index++;
9533 }
9534 //ToDo: sum_time_ms, ewma_time_ms
9535 return NL_SKIP;
9536}
9537#endif
9538
9539INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9540{
9541#ifdef HAL_NETLINK_IMPL
9542 Netlink nl;
9543 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009544 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009545
developerac6f1142022-12-20 19:26:35 +08009546 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009547 return RETURN_ERR;
9548
9549 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009550
9551 nl.id = initSock80211(&nl);
9552
9553 if (nl.id < 0) {
9554 fprintf(stderr, "Error initializing netlink \n");
9555 return -1;
9556 }
9557
9558 struct nl_msg* msg = nlmsg_alloc();
9559
9560 if (!msg) {
9561 fprintf(stderr, "Failed to allocate netlink message.\n");
9562 nlfree(&nl);
9563 return -2;
9564 }
9565
9566 genlmsg_put(msg,
9567 NL_AUTO_PORT,
9568 NL_AUTO_SEQ,
9569 nl.id,
9570 0,
9571 0,
9572 NL80211_CMD_GET_STATION,
9573 0);
9574
9575 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9576 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9577 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9578 nl_send_auto(nl.socket, msg);
9579 nl_recvmsgs(nl.socket, nl.cb);
9580 nlmsg_free(msg);
9581 nlfree(&nl);
9582 return RETURN_OK;
9583#else
9584//iw implementation
9585#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9586#define TOTAL_MAX_LINES 50
9587
9588 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009589 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009590 FILE *fp=NULL;
9591 char pipeCmd[1024]= {'\0'};
9592 int lines,tid_index=0;
9593 char mac_addr[20] = {'\0'};
9594
developerac6f1142022-12-20 19:26:35 +08009595 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009596 return RETURN_ERR;
9597
developer06a01d92022-09-07 16:32:39 +08009598 wifi_associated_dev_tid_entry_t *stats_entry;
9599
developer06a01d92022-09-07 16:32:39 +08009600 strcpy(mac_addr,clientMacAddress);
9601
9602 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9603 fp= popen(pipeCmd,"r");
9604 if(fp == NULL)
9605 {
9606 perror("popen for station dump failed\n");
9607 return RETURN_ERR;
9608 }
9609 pclose(fp);
9610
9611 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9612 fp=popen(pipeCmd,"r");
9613 if(fp == NULL)
9614 {
9615 perror("popen for grep station failed\n");
9616 return RETURN_ERR;
9617 }
9618 else if(fgets(buf,sizeof(buf),fp) != NULL)
9619 lines=atoi(buf);
9620 else
9621 {
9622 pclose(fp);
9623 fprintf(stderr,"No devices are connected \n");
9624 return RETURN_ERR;
9625 }
9626 pclose(fp);
9627
9628 if(lines == 1)
9629 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9630
9631 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9632 {
9633 stats_entry = &tid_stats->tid_array[tid_index];
9634 stats_entry->tid = tid_index;
9635
9636 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);
9637
9638 fp=popen(pipeCmd,"r");
9639 if(fp ==NULL)
9640 {
9641 perror("Failed to read from tid file \n");
9642 return RETURN_ERR;
9643 }
9644 else if(fgets(buf,sizeof(buf),fp) != NULL)
9645 stats_entry->num_msdus = atol(buf);
9646
9647 pclose(fp);
9648 stats_entry->ac = _tid_ac_index_get[tid_index];
9649// TODO:
9650// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9651// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9652 }
9653 return RETURN_OK;
9654#endif
9655}
9656
9657
9658INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9659{
developerd946fd62022-12-08 18:03:28 +08009660 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009661 char cmd[128]={0};
9662 char buf[128]={0};
9663 int freq = 0;
9664
9665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9666
9667 // full mode is used to scan all channels.
9668 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9669 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9670 ieee80211_channel_to_frequency(chan_list[0], &freq);
9671
developerac6f1142022-12-20 19:26:35 +08009672 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009673 return RETURN_ERR;
9674
developer615510b2022-09-27 10:14:35 +08009675 if (freq)
developerd946fd62022-12-08 18:03:28 +08009676 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009677 else
developerd946fd62022-12-08 18:03:28 +08009678 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009679
9680 _syscmd(cmd, buf, sizeof(buf));
9681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9682
developer06a01d92022-09-07 16:32:39 +08009683 return RETURN_OK;
9684}
9685
9686
9687INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9688{
9689 // TODO Implement me!
9690 return RETURN_ERR;
9691}
9692
9693INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9694{
9695 // TODO Implement me!
9696 return RETURN_ERR;
9697}
9698
9699INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9700{
9701 // TODO Implement me!
9702 return RETURN_ERR;
9703}
9704
9705INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9706{
9707 // TODO Implement me!
9708 return RETURN_ERR;
9709}
9710
9711INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9712{
9713 // TODO Implement me!
9714 return RETURN_ERR;
9715}
9716
9717INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9718{
9719 // TODO Implement me!
9720 return RETURN_ERR;
9721}
9722
9723INT wifi_steering_eventUnregister(void)
9724{
9725 // TODO Implement me!
9726 return RETURN_ERR;
9727}
9728
9729INT wifi_delApAclDevices(INT apIndex)
9730{
9731#if 0
9732 char cmd[MAX_BUF_SIZE] = {0};
9733 char buf[MAX_BUF_SIZE] = {0};
9734
9735 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +08009736 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +08009737 if(_syscmd(cmd,buf,sizeof(buf)))
9738 return RETURN_ERR;
9739#endif
developere6aafda2022-09-13 14:59:28 +08009740 char cmd[MAX_CMD_SIZE]={0};
9741 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009742
developere6aafda2022-09-13 14:59:28 +08009743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9744 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9745 if(_syscmd(cmd, buf, sizeof(buf)))
9746 return RETURN_ERR;
9747 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009748
9749 return RETURN_OK;
9750}
9751
9752#ifdef HAL_NETLINK_IMPL
9753static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9754 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9755 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9756 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9757 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9758 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9759 char mac_addr[20],dev[20];
9760
9761 nla_parse(tb,
9762 NL80211_ATTR_MAX,
9763 genlmsg_attrdata(gnlh, 0),
9764 genlmsg_attrlen(gnlh, 0),
9765 NULL);
9766
9767 if(!tb[NL80211_ATTR_STA_INFO]) {
9768 fprintf(stderr, "sta stats missing!\n");
9769 return NL_SKIP;
9770 }
9771
9772 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9773 fprintf(stderr, "failed to parse nested attributes!\n");
9774 return NL_SKIP;
9775 }
9776 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9777
9778 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9779
9780 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9781 fprintf(stderr, "failed to parse nested rate attributes!");
9782 return NL_SKIP;
9783 }
9784
9785 if(sinfo[NL80211_STA_INFO_TID_STATS])
9786 {
9787 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9788 printf("failed to parse nested stats attributes!");
9789 return NL_SKIP;
9790 }
9791 }
9792
9793 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9794 {
9795 printf("Type is VHT\n");
9796 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9797 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9798
9799 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9800 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9801 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9802 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9803 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9804 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9805 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9806 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9807 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9808 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9809 }
9810 else
9811 {
9812 printf(" OFDM or CCK \n");
9813 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9814 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9815 }
9816
9817 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9818 if(rinfo[NL80211_RATE_INFO_MCS])
9819 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9820 }
9821 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9822 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9823 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9824 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9825
9826 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9827 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9828
9829 if (sinfo[NL80211_STA_INFO_SIGNAL])
9830 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9831 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9832 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9833 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9834 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9835 //rssi_array need to be filled
9836 return NL_SKIP;
9837}
9838#endif
9839
9840INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9841{
9842#ifdef HAL_NETLINK_IMPL
9843 Netlink nl;
developerd946fd62022-12-08 18:03:28 +08009844 char if_name[32];
developerac6f1142022-12-20 19:26:35 +08009845 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009846 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009847
9848 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9849
9850 if (*output_array_size <= 0)
9851 return RETURN_OK;
9852
developer06a01d92022-09-07 16:32:39 +08009853 nl.id = initSock80211(&nl);
9854
9855 if (nl.id < 0) {
9856 fprintf(stderr, "Error initializing netlink \n");
9857 return 0;
9858 }
9859
9860 struct nl_msg* msg = nlmsg_alloc();
9861
9862 if (!msg) {
9863 fprintf(stderr, "Failed to allocate netlink message.\n");
9864 nlfree(&nl);
9865 return 0;
9866 }
9867
9868 genlmsg_put(msg,
9869 NL_AUTO_PORT,
9870 NL_AUTO_SEQ,
9871 nl.id,
9872 0,
9873 0,
9874 NL80211_CMD_GET_STATION,
9875 0);
9876
9877 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9878 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9879 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9880 nl_send_auto(nl.socket, msg);
9881 nl_recvmsgs(nl.socket, nl.cb);
9882 nlmsg_free(msg);
9883 nlfree(&nl);
9884 return RETURN_OK;
9885#else
9886 //TODO Implement me
9887 return RETURN_OK;
9888#endif
9889}
9890
9891#ifdef HAL_NETLINK_IMPL
9892static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9893 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9894 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9895 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9896 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9897 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9898 char mac_addr[20],dev[20];
9899
9900 nla_parse(tb,
9901 NL80211_ATTR_MAX,
9902 genlmsg_attrdata(gnlh, 0),
9903 genlmsg_attrlen(gnlh, 0),
9904 NULL);
9905
9906 if(!tb[NL80211_ATTR_STA_INFO]) {
9907 fprintf(stderr, "sta stats missing!\n");
9908 return NL_SKIP;
9909 }
9910
9911 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9912 fprintf(stderr, "failed to parse nested attributes!\n");
9913 return NL_SKIP;
9914 }
9915
9916 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9917
9918 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9919
9920 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9921 fprintf(stderr, "failed to parse nested rate attributes!");
9922 return NL_SKIP;
9923 }
9924
9925 if(sinfo[NL80211_STA_INFO_TID_STATS])
9926 {
9927 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9928 printf("failed to parse nested stats attributes!");
9929 return NL_SKIP;
9930 }
9931 }
9932 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9933 {
9934 printf("Type is VHT\n");
9935 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9936 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9937
9938 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9939 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9940 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9941 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9942 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9943 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9944 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9945 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9946 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9947 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9948 }
9949 else
9950 {
9951 printf(" OFDM or CCK \n");
9952 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9953 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9954 }
9955
9956 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9957 if(rinfo[NL80211_RATE_INFO_MCS])
9958 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9959 }
9960
9961 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9962 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9963 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9964 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9965
9966 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9967 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9968 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9969
9970 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9971 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9972
9973 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9974 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9975
9976 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9977 ((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]);
9978
9979 return NL_SKIP;
9980}
9981#endif
9982
9983INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9984{
9985#ifdef HAL_NETLINK_IMPL
9986 Netlink nl;
9987 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009988 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +08009989 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009990 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009991
9992 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9993
9994 if (*output_array_size <= 0)
9995 return RETURN_OK;
9996
developerd946fd62022-12-08 18:03:28 +08009997 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009998
9999 nl.id = initSock80211(&nl);
10000
10001 if(nl.id < 0) {
10002 fprintf(stderr, "Error initializing netlink \n");
10003 return 0;
10004 }
10005
10006 struct nl_msg* msg = nlmsg_alloc();
10007
10008 if(!msg) {
10009 fprintf(stderr, "Failed to allocate netlink message.\n");
10010 nlfree(&nl);
10011 return 0;
10012 }
10013
10014 genlmsg_put(msg,
10015 NL_AUTO_PORT,
10016 NL_AUTO_SEQ,
10017 nl.id,
10018 0,
10019 0,
10020 NL80211_CMD_GET_STATION,
10021 0);
10022
10023 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10024 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10025 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10026 nl_send_auto(nl.socket, msg);
10027 nl_recvmsgs(nl.socket, nl.cb);
10028 nlmsg_free(msg);
10029 nlfree(&nl);
10030 return RETURN_OK;
10031#else
10032 //TODO Implement me
10033 return RETURN_OK;
10034#endif
10035}
10036
10037INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10038{
10039 // TODO Implement me!
10040 char buf[MAX_BUF_SIZE] = {0};
10041 char config_file[MAX_BUF_SIZE] = {0};
10042
10043 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10044 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10045 *activate = (strncmp("1",buf,1) == 0);
10046
10047 return RETURN_OK;
10048}
10049
10050INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10051{
10052 char config_file[MAX_BUF_SIZE] = {0};
10053 struct params list;
10054
10055 list.name = "rrm_neighbor_report";
10056 list.value = activate?"1":"0";
10057 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10058 wifi_hostapdWrite(config_file, &list, 1);
10059
10060 return RETURN_OK;
10061}
10062
10063INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10064{
10065 char buf[32] = {0};
10066 char config_file[MAX_BUF_SIZE] = {0};
10067
10068 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10069 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10070 *activate = (strncmp("1",buf,1) == 0);
10071
10072 return RETURN_OK;
10073}
10074#undef HAL_NETLINK_IMPL
10075#ifdef HAL_NETLINK_IMPL
10076static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10077 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10078 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10079 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10080 char dev[20];
10081 int freq =0 ;
10082 static int i=0;
10083
10084 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10085
10086 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10087 };
10088
10089 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10090
10091 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10092
10093 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10094 fprintf(stderr, "survey data missing!\n");
10095 return NL_SKIP;
10096 }
10097
10098 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10099 {
10100 fprintf(stderr, "failed to parse nested attributes!\n");
10101 return NL_SKIP;
10102 }
10103
10104
10105 if(out[0].array_size == 1 )
10106 {
10107 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10108 {
10109 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10110 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10111 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10112
10113 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10114 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10115 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10116 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10117 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10118 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10119 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10120 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10121 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10122 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10123 if (sinfo[NL80211_SURVEY_INFO_TIME])
10124 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10125 return NL_STOP;
10126 }
10127 }
10128 else
10129 {
10130 if ( i <= out[0].array_size )
10131 {
10132 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10133 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10134 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10135
10136 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10137 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10138 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10139 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10140 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10141 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10142 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10143 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10144 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10145 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10146 if (sinfo[NL80211_SURVEY_INFO_TIME])
10147 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10148 }
10149 }
10150
10151 i++;
10152 return NL_SKIP;
10153}
10154#endif
10155
10156static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10157{
10158 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10159 FILE *fp;
10160
10161 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10162 {
10163 printf("Creating Frequency-Channel Map\n");
10164 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10165 }
10166 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10167 if((fp = popen(command, "r")))
10168 {
10169 fgets(output, sizeof(output), fp);
10170 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010171 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010172 }
10173
10174 return 0;
10175}
10176
10177static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10178{
10179 int freqMHz = -1;
10180 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010181 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010182
10183 ieee80211_channel_to_frequency(channel, &freqMHz);
10184 if (freqMHz == -1) {
10185 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10186 return -1;
10187 }
10188
developer7930d352022-12-21 17:55:42 +080010189 wifi_GetInterfaceName(radioIndex, interface_name);
10190 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010191 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10192 radioIndex, freqMHz);
10193 return -1;
10194 }
10195
10196 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10197 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10198 return -1;
10199 }
10200
10201 return 0;
10202}
10203
10204static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10205{
10206 const char *ptr = buf;
10207 char *key = NULL;
10208 char *val = NULL;
10209 char line[256] = { '\0' };
10210
10211 while (ptr = get_line_from_str_buf(ptr, line)) {
10212 if (strstr(line, "Frequency")) continue;
10213
10214 key = strtok(line, ":");
10215 val = strtok(NULL, " ");
10216 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10217
10218 if (!strcmp(key, "noise")) {
10219 sscanf(val, "%d", &stats->ch_noise);
10220 if (stats->ch_noise == 0) {
10221 // Workaround for missing noise information.
10222 // Assume -95 for 2.4G and -103 for 5G
10223 if (radioIndex == 0) stats->ch_noise = -95;
10224 if (radioIndex == 1) stats->ch_noise = -103;
10225 }
10226 }
10227 else if (!strcmp(key, "channel active time")) {
10228 sscanf(val, "%llu", &stats->ch_utilization_total);
10229 }
10230 else if (!strcmp(key, "channel busy time")) {
10231 sscanf(val, "%llu", &stats->ch_utilization_busy);
10232 }
10233 else if (!strcmp(key, "channel receive time")) {
10234 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10235 }
10236 else if (!strcmp(key, "channel transmit time")) {
10237 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10238 }
10239 };
10240
10241 return 0;
10242}
10243
10244INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10245{
10246 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10247#ifdef HAL_NETLINK_IMPL
10248 Netlink nl;
10249 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010250 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010251
10252 local[0].array_size = array_size;
10253
developerac6f1142022-12-20 19:26:35 +080010254 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010255 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010256
10257 nl.id = initSock80211(&nl);
10258
10259 if (nl.id < 0) {
10260 fprintf(stderr, "Error initializing netlink \n");
10261 return -1;
10262 }
10263
10264 struct nl_msg* msg = nlmsg_alloc();
10265
10266 if (!msg) {
10267 fprintf(stderr, "Failed to allocate netlink message.\n");
10268 nlfree(&nl);
10269 return -2;
10270 }
10271
10272 genlmsg_put(msg,
10273 NL_AUTO_PORT,
10274 NL_AUTO_SEQ,
10275 nl.id,
10276 0,
10277 NLM_F_DUMP,
10278 NL80211_CMD_GET_SURVEY,
10279 0);
10280
10281 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10282 nl_send_auto(nl.socket, msg);
10283 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10284 nl_recvmsgs(nl.socket, nl.cb);
10285 nlmsg_free(msg);
10286 nlfree(&nl);
10287 //Copying the Values
10288 for(int i=0;i<array_size;i++)
10289 {
10290 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10291 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10292 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10293 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10294 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10295 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10296 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10297 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10298 }
10299#else
10300 ULONG channel = 0;
10301 int i;
10302 int number_of_channels = array_size;
10303 char buf[512];
10304 INT ret;
10305 wifi_channelStats_t tmp_stats;
10306
10307 if (number_of_channels == 0) {
10308 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10309 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10310 return RETURN_ERR;
10311 }
10312 number_of_channels = 1;
10313 input_output_channelStats_array[0].ch_number = channel;
10314 }
10315
10316 for (i = 0; i < number_of_channels; i++) {
10317
10318 input_output_channelStats_array[i].ch_noise = 0;
10319 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10320 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10321 input_output_channelStats_array[i].ch_utilization_busy = 0;
10322 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10323 input_output_channelStats_array[i].ch_utilization_total = 0;
10324
10325 memset(buf, 0, sizeof(buf));
10326 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10327 return RETURN_ERR;
10328 }
10329 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10330 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10331 return RETURN_ERR;
10332 }
10333
10334 // XXX: fake missing 'self' counter which is not available in iw survey output
10335 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10336 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10337
10338 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10339 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10340 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10341 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10342 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10343
10344 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",
10345 __func__,
10346 input_output_channelStats_array[i].ch_number,
10347 input_output_channelStats_array[i].ch_noise,
10348 input_output_channelStats_array[i].ch_utilization_total,
10349 input_output_channelStats_array[i].ch_utilization_busy,
10350 input_output_channelStats_array[i].ch_utilization_busy_rx,
10351 input_output_channelStats_array[i].ch_utilization_busy_tx,
10352 input_output_channelStats_array[i].ch_utilization_busy_self,
10353 input_output_channelStats_array[i].ch_utilization_busy_ext);
10354 }
10355#endif
10356 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10357 return RETURN_OK;
10358}
10359#define HAL_NETLINK_IMPL
10360
10361/* Hostapd events */
10362
10363#ifndef container_of
10364#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10365#define container_of(ptr, type, member) \
10366 ((type *)((char *)ptr - offset_of(type, member)))
10367#endif /* container_of */
10368
10369struct ctrl {
10370 char sockpath[128];
10371 char sockdir[128];
10372 char bss[IFNAMSIZ];
10373 char reply[4096];
10374 int ssid_index;
10375 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10376 void (*overrun)(struct ctrl *ctrl);
10377 struct wpa_ctrl *wpa;
10378 unsigned int ovfl;
10379 size_t reply_len;
10380 int initialized;
10381 ev_timer retry;
10382 ev_timer watchdog;
10383 ev_stat stat;
10384 ev_io io;
10385};
10386static wifi_newApAssociatedDevice_callback clients_connect_cb;
10387static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10388static struct ctrl wpa_ctrl[MAX_APS];
10389static int initialized;
10390
10391static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10392{
10393 char cbuf[256] = {};
10394 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10395 struct cmsghdr *cmsg;
10396 unsigned int ovfl = ctrl->ovfl;
10397 unsigned int drop;
10398
10399 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10400 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10401 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10402 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10403
10404 drop = ovfl - ctrl->ovfl;
10405 ctrl->ovfl = ovfl;
10406
10407 return drop;
10408}
10409
10410static void ctrl_close(struct ctrl *ctrl)
10411{
10412 if (ctrl->io.cb)
10413 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10414 if (ctrl->retry.cb)
10415 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10416 if (!ctrl->wpa)
10417 return;
10418
10419 wpa_ctrl_detach(ctrl->wpa);
10420 wpa_ctrl_close(ctrl->wpa);
10421 ctrl->wpa = NULL;
10422 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10423}
10424
10425static void ctrl_process(struct ctrl *ctrl)
10426{
10427 const char *str;
10428 int drops;
10429 int level;
10430 int err;
10431
10432 /* Example events:
10433 *
10434 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10435 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10436 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10437 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10438 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10439 */
10440 if (!(str = index(ctrl->reply, '>')))
10441 return;
10442 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10443 return;
10444
10445 str++;
10446
10447 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10448 if (!(str = index(ctrl->reply, ' ')))
10449 return;
10450 wifi_associated_dev_t sta;
10451 memset(&sta, 0, sizeof(sta));
10452
10453 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10454 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10455 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10456
10457 sta.cli_Active=true;
10458
10459 (clients_connect_cb)(ctrl->ssid_index, &sta);
10460 goto handled;
10461 }
10462
10463 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10464 if (!(str = index(ctrl->reply, ' ')))
10465 return;
10466
10467 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10468 goto handled;
10469 }
10470
10471 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10472 printf("CTRL_WPA: handle TERMINATING event\n");
10473 goto retry;
10474 }
10475
10476 if (strncmp("AP-DISABLED", str, 11) == 0) {
10477 printf("CTRL_WPA: handle AP-DISABLED\n");
10478 goto retry;
10479 }
10480
10481 printf("Event not supported!!\n");
10482
10483handled:
10484
10485 if ((drops = ctrl_get_drops(ctrl))) {
10486 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10487 if (ctrl->overrun)
10488 ctrl->overrun(ctrl);
10489 }
10490
10491 return;
10492
10493retry:
10494 printf("WPA_CTRL: closing\n");
10495 ctrl_close(ctrl);
10496 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10497 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10498}
10499
10500static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10501{
10502 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10503 int err;
10504
10505 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10506 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10507 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10508 ctrl->reply[ctrl->reply_len] = 0;
10509 if (err < 0) {
10510 if (errno == EAGAIN || errno == EWOULDBLOCK)
10511 return;
10512 ctrl_close(ctrl);
10513 ev_timer_again(EV_A_ &ctrl->retry);
10514 return;
10515 }
10516
10517 ctrl_process(ctrl);
10518}
10519
10520static int ctrl_open(struct ctrl *ctrl)
10521{
10522 int fd;
10523
10524 if (ctrl->wpa)
10525 return 0;
10526
10527 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10528 if (!ctrl->wpa)
10529 goto err;
10530
10531 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10532 goto err_close;
10533
10534 fd = wpa_ctrl_get_fd(ctrl->wpa);
10535 if (fd < 0)
10536 goto err_detach;
10537
10538 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10539 goto err_detach;
10540
10541 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10542 ev_io_start(EV_DEFAULT_ &ctrl->io);
10543
10544 return 0;
10545
10546err_detach:
10547 wpa_ctrl_detach(ctrl->wpa);
10548err_close:
10549 wpa_ctrl_close(ctrl->wpa);
10550err:
10551 ctrl->wpa = NULL;
10552 return -1;
10553}
10554
10555static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10556{
10557 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10558
10559 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10560 ctrl_open(ctrl);
10561}
10562
10563static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10564{
10565 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10566
10567 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10568 if (ctrl_open(ctrl) == 0) {
10569 printf("WPA_CTRL: retry successful\n");
10570 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10571 }
10572}
10573
10574int ctrl_enable(struct ctrl *ctrl)
10575{
10576 if (ctrl->wpa)
10577 return 0;
10578
10579 if (!ctrl->stat.cb) {
10580 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10581 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10582 }
10583
10584 if (!ctrl->retry.cb) {
10585 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10586 }
10587
10588 return ctrl_open(ctrl);
10589}
10590
10591static void
10592ctrl_msg_cb(char *buf, size_t len)
10593{
10594 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10595
10596 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10597 ctrl_process(ctrl);
10598}
10599
10600static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10601{
10602 int err;
10603
10604 if (!ctrl->wpa)
10605 return -1;
10606 if (*reply_len < 2)
10607 return -1;
10608
10609 (*reply_len)--;
10610 ctrl->reply_len = sizeof(ctrl->reply);
10611 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10612 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10613 if (err < 0)
10614 return err;
10615
10616 if (ctrl->reply_len > *reply_len)
10617 ctrl->reply_len = *reply_len;
10618
10619 *reply_len = ctrl->reply_len;
10620 memcpy(reply, ctrl->reply, *reply_len);
10621 reply[*reply_len - 1] = 0;
10622 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10623 return 0;
10624}
10625
10626static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10627{
10628 const char *pong = "PONG";
10629 const char *ping = "PING";
10630 char reply[1024];
10631 size_t len = sizeof(reply);
10632 int err;
10633 ULONG s, snum;
10634 INT ret;
10635 BOOL status;
10636
10637 printf("WPA_CTRL: watchdog cb\n");
10638
10639 ret = wifi_getSSIDNumberOfEntries(&snum);
10640 if (ret != RETURN_OK) {
10641 printf("%s: failed to get SSID count", __func__);
10642 return;
10643 }
10644
10645 if (snum > MAX_APS) {
10646 printf("more ssid than supported! %lu\n", snum);
10647 return;
10648 }
10649
10650 for (s = 0; s < snum; s++) {
10651 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010652 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010653 continue;
10654 }
10655 if (status == false) continue;
10656
10657 memset(reply, 0, sizeof(reply));
10658 len = sizeof(reply);
10659 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10660 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10661 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10662 continue;
10663
10664 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10665 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010666 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010667 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10668 }
10669}
10670
10671static int init_wpa()
10672{
10673 int ret = 0, i = 0;
10674 ULONG s, snum;
10675
10676 ret = wifi_getSSIDNumberOfEntries(&snum);
10677 if (ret != RETURN_OK) {
10678 printf("%s: failed to get SSID count", __func__);
10679 return RETURN_ERR;
10680 }
10681
10682 if (snum > MAX_APS) {
10683 printf("more ssid than supported! %lu\n", snum);
10684 return RETURN_ERR;
10685 }
10686
10687 for (s = 0; s < snum; s++) {
10688 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10689 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10690 wpa_ctrl[s].ssid_index = s;
10691 ctrl_enable(&wpa_ctrl[s]);
10692 }
10693
10694 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10695 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10696
10697 initialized = 1;
10698 printf("WPA_CTRL: initialized\n");
10699
10700 return RETURN_OK;
10701}
10702
10703void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10704{
10705 clients_connect_cb = callback_proc;
10706 if (!initialized)
10707 init_wpa();
10708}
10709
10710void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10711{
10712 clients_disconnect_cb = callback_proc;
10713 if (!initialized)
10714 init_wpa();
10715}
10716
10717INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10718{
10719 // TODO Implement me!
10720 return RETURN_ERR;
10721}
10722
10723INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10724{
10725 // TODO Implement me!
10726 return RETURN_ERR;
10727}
10728
10729INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10730{
10731 int i;
10732 char cmd[256];
10733 char channel_numbers_buf[256];
10734 char dfs_state_buf[256];
10735 char line[256];
10736 const char *ptr;
10737
10738 memset(cmd, 0, sizeof(cmd));
10739 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10740 memset(line, 0, sizeof(line));
10741 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10742 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10743
10744 if (radioIndex == 0) { // 2.4G - all allowed
10745 if (outputMapSize < 11) {
10746 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10747 return RETURN_ERR;
10748 }
10749
10750 for (i = 0; i < 11; i++) {
10751 outputMap[i].ch_number = i + 1;
10752 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10753 }
10754
10755 return RETURN_OK;
10756 }
10757
10758 if (radioIndex == 1) { // 5G
10759// Example output of iw list:
10760//
10761// Frequencies:
10762// * 5180 MHz [36] (17.0 dBm)
10763// * 5200 MHz [40] (17.0 dBm)
10764// * 5220 MHz [44] (17.0 dBm)
10765// * 5240 MHz [48] (17.0 dBm)
10766// * 5260 MHz [52] (23.0 dBm) (radar detection)
10767// DFS state: usable (for 78930 sec)
10768// DFS CAC time: 60000 ms
10769// * 5280 MHz [56] (23.0 dBm) (radar detection)
10770// DFS state: usable (for 78930 sec)
10771// DFS CAC time: 60000 ms
10772// * 5300 MHz [60] (23.0 dBm) (radar detection)
10773// DFS state: usable (for 78930 sec)
10774// DFS CAC time: 60000 ms
10775// * 5320 MHz [64] (23.0 dBm) (radar detection)
10776// DFS state: usable (for 78930 sec)
10777// DFS CAC time: 60000 ms
10778// * 5500 MHz [100] (disabled)
10779// * 5520 MHz [104] (disabled)
10780// * 5540 MHz [108] (disabled)
10781// * 5560 MHz [112] (disabled)
10782//
10783// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10784 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10785 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10786 return RETURN_ERR;
10787 }
10788
10789 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10790 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10791 return RETURN_ERR;
10792 }
10793
10794 ptr = channel_numbers_buf;
10795 i = 0;
10796 while (ptr = get_line_from_str_buf(ptr, line)) {
10797 if (i >= outputMapSize) {
10798 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10799 return RETURN_ERR;
10800 }
10801 sscanf(line, "%d", &outputMap[i].ch_number);
10802
10803 memset(cmd, 0, sizeof(cmd));
10804 // Below command should fetch string for DFS state (usable, available or unavailable)
10805 // Example line: "DFS state: usable (for 78930 sec)"
10806 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) {
10807 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10808 return RETURN_ERR;
10809 }
10810
10811 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10812 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10813 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10814 return RETURN_ERR;
10815 }
10816
10817 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10818
10819 if (!strcmp(dfs_state_buf, "usable")) {
10820 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10821 } else if (!strcmp(dfs_state_buf, "available")) {
10822 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10823 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10824 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10825 } else {
10826 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10827 }
10828 i++;
10829 }
10830
10831 return RETURN_OK;
10832 }
10833
10834 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10835 return RETURN_ERR;
10836}
10837
10838INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10839{
10840 // TODO Implement me!
10841 return RETURN_ERR;
10842}
10843
10844INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10845{
10846 return RETURN_OK;
10847}
10848
10849INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10850{
10851 // TODO Implement me!
10852 return RETURN_ERR;
10853}
10854
10855INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10856{
10857 // TODO API refrence Implementaion is present on RPI hal
10858 return RETURN_ERR;
10859}
10860
10861INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10862{
developerd946fd62022-12-08 18:03:28 +080010863 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080010864 char cmd[128]={'\0'};
10865 char buf[128]={'\0'};
10866 char *support;
10867 int maximum_tx = 0, current_tx = 0;
10868
10869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10870 if(txpwr_pcntg == NULL)
10871 return RETURN_ERR;
10872
developerac6f1142022-12-20 19:26:35 +080010873 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010874 return RETURN_ERR;
10875
developera5005b62022-09-13 15:43:35 +080010876 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080010877 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 +080010878 _syscmd(cmd, buf, sizeof(buf));
10879 maximum_tx = strtol(buf, NULL, 10);
10880
10881 // Get the current tx power
10882 memset(cmd, 0, sizeof(cmd));
10883 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080010884 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 +080010885 _syscmd(cmd, buf, sizeof(buf));
10886 current_tx = strtol(buf, NULL, 10);
10887
10888 // Get the power supported list and find the current power percentage in supported list
10889 memset(buf, 0, sizeof(buf));
10890 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10891 support = strtok(buf, ",");
10892 while(true)
10893 {
10894 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 +080010895 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010896 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010897 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010898 }
10899 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10900 if (tmp == current_tx) {
10901 *txpwr_pcntg = strtol(support, NULL, 10);
10902 break;
10903 }
10904 support = strtok(NULL, ",");
10905 }
10906 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010907 return RETURN_OK;
10908}
10909
10910INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10911{
developer58599c22022-09-13 16:40:34 +080010912 // TODO precac feature.
10913 struct params params = {0};
10914 char config_file[128] = {0};
10915
10916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10917
10918 params.name = "enable_background_radar";
10919 params.value = enable?"1":"0";
10920 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10921 wifi_hostapdWrite(config_file, &params, 1);
10922 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10923
10924 /* TODO precac feature */
10925
10926 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10927 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010928}
10929
10930INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10931{
developer58599c22022-09-13 16:40:34 +080010932 char config_file[128] = {0};
10933 char buf[64] = {0};
10934
10935 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10936 if (NULL == enable || NULL == precac)
10937 return RETURN_ERR;
10938
10939 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10940 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10941 if (strncmp(enable, "1", 1) == 0)
10942 *enable = true;
10943 else
10944 *enable = false;
10945
10946 /* TODO precac feature */
10947
10948 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10949 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010950}
10951
10952INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10953{
developer58599c22022-09-13 16:40:34 +080010954 *supported = TRUE;
10955 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010956}
10957
developer3e6b1692022-09-30 18:04:05 +080010958INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10959{
10960 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10961 struct params params = {0};
10962 char config_file[64] = {0};
10963 char buf[64] = {0};
10964 unsigned int set_mu_type = 0;
10965 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10966
10967 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10968 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10969
10970 if (strlen(buf) > 0)
10971 set_mu_type = strtol(buf, NULL, 10);
10972
10973 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10974 set_mu_type &= ~0x05; // unset bit 0, 2
10975 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10976 set_mu_type |= 0x01;
10977 set_mu_type &= ~0x04;
10978 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10979 set_mu_type &= ~0x01;
10980 set_mu_type |= 0x04;
10981 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10982 set_mu_type |= 0x05; // set bit 0, 2
10983 }
10984
10985 params.name = "hemu_onoff";
10986 sprintf(buf, "%u", set_mu_type);
10987 params.value = buf;
10988 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10989 wifi_hostapdWrite(config_file, &params, 1);
10990 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10991
10992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10993 return RETURN_OK;
10994}
10995
10996INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10997{
10998 struct params params={0};
10999 char config_file[64] = {0};
11000 char buf[64] = {0};
11001 unsigned int get_mu_type = 0;
11002
11003 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11004
11005 if (mu_type == NULL)
11006 return RETURN_ERR;
11007
11008 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11009 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11010 get_mu_type = strtol(buf, NULL, 10);
11011
11012 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11013 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11014 else if (get_mu_type & 0x04)
11015 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11016 else if (get_mu_type & 0x01)
11017 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11018 else
11019 *mu_type = WIFI_DL_MU_TYPE_NONE;
11020
11021 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11022 return RETURN_OK;
11023}
11024
11025INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11026{
11027 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11028 struct params params={0};
11029 char config_file[64] = {0};
11030 char buf[64] = {0};
11031 unsigned int set_mu_type = 0;
11032 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11033
11034 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11035 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11036
11037 if (strlen(buf) > 0)
11038 set_mu_type = strtol(buf, NULL, 10);
11039
11040 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11041 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11042 set_mu_type &= ~0x0a;
11043 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11044 set_mu_type |= 0x02;
11045 set_mu_type &= ~0x08;
11046 }
11047
11048 params.name = "hemu_onoff";
11049 sprintf(buf, "%u", set_mu_type);
11050 params.value = buf;
11051 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11052 wifi_hostapdWrite(config_file, &params, 1);
11053 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11054
11055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11056 return RETURN_OK;
11057}
11058
11059INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11060{
11061 struct params params={0};
11062 char config_file[64] = {0};
11063 char buf[64] = {0};
11064 unsigned int get_mu_type = 0;
11065
11066 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11067
11068 if (mu_type == NULL)
11069 return RETURN_ERR;
11070
11071 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11072 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11073
11074 get_mu_type = strtol(buf, NULL, 10);
11075 if (get_mu_type & 0x02)
11076 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11077 else
11078 *mu_type = WIFI_DL_MU_TYPE_NONE;
11079
11080 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11081 return RETURN_OK;
11082}
11083
11084
developer454b9462022-09-13 15:29:16 +080011085INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11086{
11087 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011088 char buf[256] = {0};
11089 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011090 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011091 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011092 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011093 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011094
11095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11096
developer254882b2022-09-30 17:12:31 +080011097 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011098 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11099 return RETURN_ERR;
11100 }
developer454b9462022-09-13 15:29:16 +080011101
developer254882b2022-09-30 17:12:31 +080011102 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011103 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011104
developer254882b2022-09-30 17:12:31 +080011105 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11106 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011107 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011108 _syscmd(cmd, buf, sizeof(buf));
11109 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11110 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11111 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011112 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 +080011113 _syscmd(cmd, buf, sizeof(buf));
11114 }
11115 if (band == band_5) {
11116 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11117 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011118 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 +080011119 _syscmd(cmd, buf, sizeof(buf));
11120 }
11121 }
11122 }
11123 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011124
developer254882b2022-09-30 17:12:31 +080011125 if (guard_interval == wifi_guard_interval_400)
11126 strcpy(GI, "0.4");
11127 else if (guard_interval == wifi_guard_interval_800)
11128 strcpy(GI, "0.8");
11129 else if (guard_interval == wifi_guard_interval_1600)
11130 strcpy(GI, "1.6");
11131 else if (guard_interval == wifi_guard_interval_3200)
11132 strcpy(GI, "3.2");
11133 else if (guard_interval == wifi_guard_interval_auto)
11134 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011135 // Record GI for get GI function
11136 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11137 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011138 if (f == NULL)
11139 return RETURN_ERR;
11140 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011141 fclose(f);
11142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11143 return RETURN_OK;
11144}
11145
11146INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11147{
11148 char buf[32] = {0};
11149 char cmd[64] = {0};
11150
11151 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11152
11153 if (guard_interval == NULL)
11154 return RETURN_ERR;
11155
11156 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11157 _syscmd(cmd, buf, sizeof(buf));
11158
11159 if (strncmp(buf, "0.4", 3) == 0)
11160 *guard_interval = wifi_guard_interval_400;
11161 else if (strncmp(buf, "0.8", 3) == 0)
11162 *guard_interval = wifi_guard_interval_800;
11163 else if (strncmp(buf, "1.6", 3) == 0)
11164 *guard_interval = wifi_guard_interval_1600;
11165 else if (strncmp(buf, "3.2", 3) == 0)
11166 *guard_interval = wifi_guard_interval_3200;
11167 else
11168 *guard_interval = wifi_guard_interval_auto;
11169
11170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11171 return RETURN_OK;
11172}
11173
developer3cc61d12022-09-13 16:36:05 +080011174INT wifi_setBSSColor(INT radio_index, UCHAR color)
11175{
11176 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11177 struct params params = {0};
11178 char config_file[128] = {0};
11179 char bss_color[4] ={0};
11180
11181 params.name = "he_bss_color";
11182 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11183 params.value = bss_color;
11184 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11185 wifi_hostapdWrite(config_file, &params, 1);
11186 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11187
11188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11189 return RETURN_OK;
11190}
11191
11192INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11193{
11194 char config_file[128] = {0};
11195 char buf[64] = {0};
11196 char temp_output[128] = {'\0'};
11197
11198 wifi_dbg_printf("\nFunc=%s\n", __func__);
11199 if (NULL == color)
11200 return RETURN_ERR;
11201
11202 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11203 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11204
11205 if(strlen(buf) > 0) {
11206 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11207 } else {
11208 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11209 }
11210
11211 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11212 wifi_dbg_printf("\noutput_string=%s\n", color);
11213
11214 return RETURN_OK;
11215}
11216
developer06a01d92022-09-07 16:32:39 +080011217/* multi-psk support */
11218INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11219{
11220 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011221 char interface_name[16] = {0};
11222
developerac6f1142022-12-20 19:26:35 +080011223 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011224 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011225
developerd946fd62022-12-08 18:03:28 +080011226 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11227 interface_name,
developer06a01d92022-09-07 16:32:39 +080011228 mac[0],
11229 mac[1],
11230 mac[2],
11231 mac[3],
11232 mac[4],
11233 mac[5]
11234 );
11235 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11236 _syscmd(cmd, key->wifi_keyId, 64);
11237
11238
11239 return RETURN_OK;
11240}
11241
11242INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11243{
developerd946fd62022-12-08 18:03:28 +080011244 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011245 FILE *fd = NULL;
11246 char fname[100];
11247 char cmd[128] = {0};
11248 char out[64] = {0};
11249 wifi_key_multi_psk_t * key = NULL;
11250 if(keysNumber < 0)
11251 return RETURN_ERR;
11252
developer431128d2022-12-16 15:30:41 +080011253 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011254 fd = fopen(fname, "w");
11255 if (!fd) {
11256 return RETURN_ERR;
11257 }
11258 key= (wifi_key_multi_psk_t *) keys;
11259 for(int i=0; i<keysNumber; ++i, key++) {
11260 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11261 }
11262 fclose(fd);
11263
11264 //reload file
developerac6f1142022-12-20 19:26:35 +080011265 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011266 return RETURN_ERR;
11267 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011268 _syscmd(cmd, out, 64);
11269 return RETURN_OK;
11270}
11271
11272INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11273{
11274 FILE *fd = NULL;
11275 char fname[100];
11276 char * line = NULL;
11277 char * pos = NULL;
11278 size_t len = 0;
11279 ssize_t read = 0;
11280 INT ret = RETURN_OK;
11281 wifi_key_multi_psk_t *keys_it = NULL;
11282
11283 if (keysNumber < 1) {
11284 return RETURN_ERR;
11285 }
11286
developer431128d2022-12-16 15:30:41 +080011287 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011288 fd = fopen(fname, "r");
11289 if (!fd) {
11290 return RETURN_ERR;
11291 }
11292
11293 if (keys == NULL) {
11294 ret = RETURN_ERR;
11295 goto close;
11296 }
11297
11298 keys_it = keys;
11299 while ((read = getline(&line, &len, fd)) != -1) {
11300 //Strip trailing new line if present
11301 if (read > 0 && line[read-1] == '\n') {
11302 line[read-1] = '\0';
11303 }
11304
11305 if(strcmp(line,"keyid=")) {
11306 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11307 if (!(pos = index(line, ' '))) {
11308 ret = RETURN_ERR;
11309 goto close;
11310 }
11311 pos++;
11312 //Here should be 00:00:00:00:00:00
11313 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11314 printf("Not supported MAC: %s\n", pos);
11315 }
11316 if (!(pos = index(pos, ' '))) {
11317 ret = RETURN_ERR;
11318 goto close;
11319 }
11320 pos++;
11321
11322 //The rest is PSK
11323 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11324 keys_it++;
11325
11326 if(--keysNumber <= 0)
11327 break;
11328 }
11329 }
11330
11331close:
11332 free(line);
11333 fclose(fd);
11334 return ret;
11335}
11336/* end of multi-psk support */
11337
11338INT wifi_setNeighborReports(UINT apIndex,
11339 UINT numNeighborReports,
11340 wifi_NeighborReport_t *neighborReports)
11341{
11342 char cmd[256] = { 0 };
11343 char hex_bssid[13] = { 0 };
11344 char bssid[18] = { 0 };
11345 char nr[256] = { 0 };
11346 char ssid[256];
11347 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011348 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011349 INT ret;
11350
11351 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011352 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011353 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011354 return RETURN_ERR;
11355 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 +080011356 system(cmd);
11357
11358 for(unsigned int i = 0; i < numNeighborReports; i++)
11359 {
11360 memset(ssid, 0, sizeof(ssid));
11361 ret = wifi_getSSIDName(apIndex, ssid);
11362 if (ret != RETURN_OK)
11363 return RETURN_ERR;
11364
11365 memset(hex_ssid, 0, sizeof(hex_ssid));
11366 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11367 sprintf(hex_ssid + k,"%02x", ssid[j]);
11368
11369 snprintf(hex_bssid, sizeof(hex_bssid),
11370 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11371 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11372 snprintf(bssid, sizeof(bssid),
11373 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11374 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11375
11376 snprintf(nr, sizeof(nr),
11377 "%s" // bssid
11378 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11379 "%02hhx" // operclass
11380 "%02hhx" // channel
11381 "%02hhx", // phy_mode
11382 hex_bssid,
11383 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11384 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11385 neighborReports[i].opClass,
11386 neighborReports[i].channel,
11387 neighborReports[i].phyTable);
11388
11389 snprintf(cmd, sizeof(cmd),
11390 "hostapd_cli set_neighbor "
11391 "%s " // bssid
11392 "ssid=%s " // ssid
11393 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011394 "-i %s",
11395 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011396
11397 if (WEXITSTATUS(system(cmd)) != 0)
11398 {
11399 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11400 }
11401 }
11402
11403 return RETURN_OK;
11404}
11405
11406INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11407{
11408 return RETURN_OK;
11409}
11410
11411#ifdef _WIFI_HAL_TEST_
11412int main(int argc,char **argv)
11413{
11414 int index;
11415 INT ret=0;
11416 char buf[1024]="";
11417
11418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11419 if(argc<3)
11420 {
11421 if(argc==2)
11422 {
11423 if(!strcmp(argv[1], "init"))
11424 return wifi_init();
11425 if(!strcmp(argv[1], "reset"))
11426 return wifi_reset();
11427 if(!strcmp(argv[1], "wifi_getHalVersion"))
11428 {
11429 char buffer[64];
11430 if(wifi_getHalVersion(buffer)==RETURN_OK)
11431 printf("Version: %s\n", buffer);
11432 else
11433 printf("Error in wifi_getHalVersion\n");
11434 return RETURN_OK;
11435 }
11436 }
11437 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11438 exit(-1);
11439 }
11440
11441 index = atoi(argv[2]);
11442 if(strstr(argv[1], "wifi_getApName")!=NULL)
11443 {
11444 wifi_getApName(index,buf);
11445 printf("Ap name is %s \n",buf);
11446 return 0;
11447 }
11448 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11449 {
11450 BOOL b = FALSE;
11451 BOOL *output_bool = &b;
11452 wifi_getRadioAutoChannelEnable(index,output_bool);
11453 printf("Channel enabled = %d \n",b);
11454 return 0;
11455 }
11456 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11457 {
11458 wifi_getApWpaEncryptionMode(index,buf);
11459 printf("encryption enabled = %s\n",buf);
11460 return 0;
11461 }
11462 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11463 {
11464 BOOL b = FALSE;
11465 BOOL *output_bool = &b;
11466 wifi_getApSsidAdvertisementEnable(index,output_bool);
11467 printf("advertisment enabled = %d\n",b);
11468 return 0;
11469 }
11470 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11471 {
11472 if(argc <= 3 )
11473 {
11474 printf("Insufficient arguments \n");
11475 exit(-1);
11476 }
11477
11478 char sta[20] = {'\0'};
11479 ULLONG handle= 0;
11480 strcpy(sta,argv[3]);
11481 mac_address_t st;
11482 mac_addr_aton(st,sta);
11483
11484 wifi_associated_dev_tid_stats_t tid_stats;
11485 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11486 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11487 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);
11488 }
11489
11490 if(strstr(argv[1], "getApEnable")!=NULL) {
11491 BOOL enable;
11492 ret=wifi_getApEnable(index, &enable);
11493 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11494 }
11495 else if(strstr(argv[1], "setApEnable")!=NULL) {
11496 BOOL enable = atoi(argv[3]);
11497 ret=wifi_setApEnable(index, enable);
11498 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11499 }
11500 else if(strstr(argv[1], "getApStatus")!=NULL) {
11501 char status[64];
11502 ret=wifi_getApStatus(index, status);
11503 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11504 }
11505 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11506 {
11507 wifi_getSSIDNameStatus(index,buf);
11508 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11509 return 0;
11510 }
11511 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11512 wifi_ssidTrafficStats2_t stats={0};
11513 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11514 printf("%s %d: returns %d\n", argv[1], index, ret);
11515 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11516 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11517 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11518 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11519 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11520 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11521 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11522 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11523 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11524 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11525 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11526 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11527 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11528 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11529 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11530 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11531 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11532 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11533 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11534 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11535 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11536 }
11537 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11538 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11539 UINT array_size=0;
11540 UINT i=0;
11541 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11542 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11543 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11544 printf(" neighbor %d:\n", i);
11545 printf(" ap_SSID =%s\n", pt->ap_SSID);
11546 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11547 printf(" ap_Mode =%s\n", pt->ap_Mode);
11548 printf(" ap_Channel =%d\n", pt->ap_Channel);
11549 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11550 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11551 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11552 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11553 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11554 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11555 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11556 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11557 printf(" ap_Noise =%d\n", pt->ap_Noise);
11558 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11559 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11560 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11561 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11562 }
11563 if(neighbor_ap_array)
11564 free(neighbor_ap_array); //make sure to free the list
11565 }
11566 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11567 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11568 UINT array_size=0;
11569 UINT i=0;
11570 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11571 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11572 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11573 printf(" associated_dev %d:\n", i);
11574 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11575 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11576 printf(" cli_SNR =%d\n", pt->cli_SNR);
11577 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11578 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11579 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11580 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11581 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11582 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11583 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11584 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11585 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11586 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11587 }
11588 if(associated_dev_array)
11589 free(associated_dev_array); //make sure to free the list
11590 }
11591
11592 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11593 {
11594#define MAX_ARRAY_SIZE 64
11595 int i, array_size;
11596 char *p, *ch_str;
11597 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11598
11599 if(argc != 5)
11600 {
11601 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11602 exit(-1);
11603 }
11604 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11605
11606 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11607 {
11608 strtok_r(ch_str, ",", &p);
11609 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11610 }
11611 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11612 if(!array_size)
11613 array_size=1;//Need to print current channel statistics
11614 for(i=0; i<array_size; i++)
11615 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11616 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11617 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11618 input_output_channelStats_array[i].ch_number,\
11619 input_output_channelStats_array[i].ch_noise,\
11620 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11621 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11622 input_output_channelStats_array[i].ch_utilization_busy,\
11623 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11624 input_output_channelStats_array[i].ch_utilization_total);
11625 }
11626
11627 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11628 {
11629 if(argc <= 3 )
11630 {
11631 printf("Insufficient arguments \n");
11632 exit(-1);
11633 }
11634 char mac_addr[20] = {'\0'};
11635 wifi_device_t output_struct;
11636 int dev_index = atoi(argv[3]);
11637
11638 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11639 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11640 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);
11641 }
11642
11643 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11644 {
11645 if (argc <= 3)
11646 {
11647 printf("Insufficient arguments\n");
11648 exit(-1);
11649 }
11650 char args[256];
11651 wifi_NeighborReport_t *neighborReports;
11652
11653 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11654 if (!neighborReports)
11655 {
11656 printf("Failed to allocate memory");
11657 exit(-1);
11658 }
11659
11660 for (int i = 3; i < argc; ++i)
11661 {
11662 char *val;
11663 int j = 0;
11664 memset(args, 0, sizeof(args));
11665 strncpy(args, argv[i], sizeof(args));
11666 val = strtok(args, ";");
11667 while (val != NULL)
11668 {
11669 if (j == 0)
11670 {
11671 mac_addr_aton(neighborReports[i - 3].bssid, val);
11672 } else if (j == 1)
11673 {
11674 neighborReports[i - 3].info = strtol(val, NULL, 16);
11675 } else if (j == 2)
11676 {
11677 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11678 } else if (j == 3)
11679 {
11680 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11681 } else if (j == 4)
11682 {
11683 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11684 } else {
11685 printf("Insufficient arguments]n\n");
11686 exit(-1);
11687 }
11688 val = strtok(NULL, ";");
11689 j++;
11690 }
11691 }
11692
11693 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11694 if (ret != RETURN_OK)
11695 {
11696 printf("wifi_setNeighborReports ret = %d", ret);
11697 exit(-1);
11698 }
11699 }
11700 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11701 {
11702 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11703 printf("%s.\n", buf);
11704 else
11705 printf("Error returned\n");
11706 }
11707 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11708 {
11709 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11710 printf("%s.\n", buf);
11711 else
11712 printf("Error returned\n");
11713 }
11714 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11715 {
11716 if (argc <= 2)
11717 {
11718 printf("Insufficient arguments\n");
11719 exit(-1);
11720 }
11721 char buf[64]= {'\0'};
11722 wifi_getRadioOperatingChannelBandwidth(index,buf);
11723 printf("Current bandwidth is %s \n",buf);
11724 return 0;
11725 }
11726 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11727 {
11728 if (argc <= 5)
11729 {
11730 printf("Insufficient arguments\n");
11731 exit(-1);
11732 }
11733 UINT channel = atoi(argv[3]);
11734 UINT width = atoi(argv[4]);
11735 UINT beacon = atoi(argv[5]);
11736 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11737 printf("Result = %d", ret);
11738 }
11739
11740 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11741 return 0;
11742}
11743
11744#endif
11745
11746#ifdef WIFI_HAL_VERSION_3
11747
developer1e5aa162022-09-13 16:06:24 +080011748INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11749{
11750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11751 if (bitMap & WIFI_BITRATE_1MBPS)
11752 strcat(BasicRate, "1,");
11753 if (bitMap & WIFI_BITRATE_2MBPS)
11754 strcat(BasicRate, "2,");
11755 if (bitMap & WIFI_BITRATE_5_5MBPS)
11756 strcat(BasicRate, "5.5,");
11757 if (bitMap & WIFI_BITRATE_6MBPS)
11758 strcat(BasicRate, "6,");
11759 if (bitMap & WIFI_BITRATE_9MBPS)
11760 strcat(BasicRate, "9,");
11761 if (bitMap & WIFI_BITRATE_11MBPS)
11762 strcat(BasicRate, "11,");
11763 if (bitMap & WIFI_BITRATE_12MBPS)
11764 strcat(BasicRate, "12,");
11765 if (bitMap & WIFI_BITRATE_18MBPS)
11766 strcat(BasicRate, "18,");
11767 if (bitMap & WIFI_BITRATE_24MBPS)
11768 strcat(BasicRate, "24,");
11769 if (bitMap & WIFI_BITRATE_36MBPS)
11770 strcat(BasicRate, "36,");
11771 if (bitMap & WIFI_BITRATE_48MBPS)
11772 strcat(BasicRate, "48,");
11773 if (bitMap & WIFI_BITRATE_54MBPS)
11774 strcat(BasicRate, "54,");
11775 if (strlen(BasicRate) != 0) // remove last comma
11776 BasicRate[strlen(BasicRate) - 1] = '\0';
11777 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11778 return RETURN_OK;
11779}
11780
11781INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11782{
11783 UINT BitMap = 0;
11784 char *rate;
11785
11786 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11787 rate = strtok(BasicRatesList, ",");
11788 while(rate != NULL)
11789 {
11790 if (strcmp(rate, "1") == 0)
11791 BitMap |= WIFI_BITRATE_1MBPS;
11792 else if (strcmp(rate, "2") == 0)
11793 BitMap |= WIFI_BITRATE_2MBPS;
11794 else if (strcmp(rate, "5.5") == 0)
11795 BitMap |= WIFI_BITRATE_5_5MBPS;
11796 else if (strcmp(rate, "6") == 0)
11797 BitMap |= WIFI_BITRATE_6MBPS;
11798 else if (strcmp(rate, "9") == 0)
11799 BitMap |= WIFI_BITRATE_9MBPS;
11800 else if (strcmp(rate, "11") == 0)
11801 BitMap |= WIFI_BITRATE_11MBPS;
11802 else if (strcmp(rate, "12") == 0)
11803 BitMap |= WIFI_BITRATE_12MBPS;
11804 else if (strcmp(rate, "18") == 0)
11805 BitMap |= WIFI_BITRATE_18MBPS;
11806 else if (strcmp(rate, "24") == 0)
11807 BitMap |= WIFI_BITRATE_24MBPS;
11808 else if (strcmp(rate, "36") == 0)
11809 BitMap |= WIFI_BITRATE_36MBPS;
11810 else if (strcmp(rate, "48") == 0)
11811 BitMap |= WIFI_BITRATE_48MBPS;
11812 else if (strcmp(rate, "54") == 0)
11813 BitMap |= WIFI_BITRATE_54MBPS;
11814 rate = strtok(NULL, ",");
11815 }
11816 *basicRateBitMap = BitMap;
11817 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11818 return RETURN_OK;
11819}
11820
11821// 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 +080011822INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11823{
developer1e5aa162022-09-13 16:06:24 +080011824 char buf[128] = {0};
11825 char cmd[128] = {0};
11826 char config_file[64] = {0};
11827 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011828 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011829 wifi_radio_operationParam_t current_param;
11830
11831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11832
11833 multiple_set = TRUE;
11834 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11835 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11836 return RETURN_ERR;
11837 }
11838 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11839 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11840 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11841 return RETURN_ERR;
11842 }
11843 }
developer5884e982022-10-06 10:52:50 +080011844
11845 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11846 bandwidth = 20;
11847 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11848 bandwidth = 40;
11849 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11850 bandwidth = 80;
11851 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11852 bandwidth = 160;
11853 if (operationParam->autoChannelEnabled){
11854 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11855 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11856 return RETURN_ERR;
11857 }
11858 }else{
developer1e5aa162022-09-13 16:06:24 +080011859 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11860 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11861 return RETURN_ERR;
11862 }
11863 }
developer5884e982022-10-06 10:52:50 +080011864
developer1e5aa162022-09-13 16:06:24 +080011865 if (current_param.variant != operationParam->variant) {
11866 // Two different definition bit map, so need to check every bit.
11867 if (operationParam->variant & WIFI_80211_VARIANT_A)
11868 set_mode |= WIFI_MODE_A;
11869 if (operationParam->variant & WIFI_80211_VARIANT_B)
11870 set_mode |= WIFI_MODE_B;
11871 if (operationParam->variant & WIFI_80211_VARIANT_G)
11872 set_mode |= WIFI_MODE_G;
11873 if (operationParam->variant & WIFI_80211_VARIANT_N)
11874 set_mode |= WIFI_MODE_N;
11875 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11876 set_mode |= WIFI_MODE_AC;
11877 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11878 set_mode |= WIFI_MODE_AX;
11879 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11880 memset(buf, 0, sizeof(buf));
11881 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11882 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11883 return RETURN_ERR;
11884 }
11885 }
11886 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11887 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11888 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11889 return RETURN_ERR;
11890 }
11891 }
11892 if (current_param.beaconInterval != operationParam->beaconInterval) {
11893 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11894 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11895 return RETURN_ERR;
11896 }
11897 }
11898 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11899 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11900 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11901 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11902 return RETURN_ERR;
11903 }
11904 }
11905 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11906 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11907 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11908 return RETURN_ERR;
11909 }
11910 }
11911 if (current_param.guardInterval != operationParam->guardInterval) {
11912 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11913 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11914 return RETURN_ERR;
11915 }
11916 }
11917 if (current_param.transmitPower != operationParam->transmitPower) {
11918 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11919 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11920 return RETURN_ERR;
11921 }
11922 }
11923 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11924 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11925 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11926 return RETURN_ERR;
11927 }
11928 }
11929 if (current_param.obssCoex != operationParam->obssCoex) {
11930 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11931 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11932 return RETURN_ERR;
11933 }
11934 }
11935 if (current_param.stbcEnable != operationParam->stbcEnable) {
11936 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11937 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11938 return RETURN_ERR;
11939 }
11940 }
11941 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11942 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11943 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11944 return RETURN_ERR;
11945 }
11946 }
11947
11948 // if enable is true, then restart the radio
11949 wifi_setRadioEnable(index, FALSE);
11950 if (operationParam->enable == TRUE)
11951 wifi_setRadioEnable(index, TRUE);
11952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11953
developer06a01d92022-09-07 16:32:39 +080011954 return RETURN_OK;
11955}
11956
11957INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11958{
developer1e5aa162022-09-13 16:06:24 +080011959 char band[64] = {0};
11960 char buf[256] = {0};
11961 char config_file[64] = {0};
11962 char cmd[128] = {0};
11963 int ret = RETURN_ERR;
11964 int mode = 0;
11965 ULONG channel = 0;
11966 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011967
11968 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11969 printf("Entering %s index = %d\n", __func__, (int)index);
11970
developer1e5aa162022-09-13 16:06:24 +080011971 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11972 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11973 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011974 {
developer1e5aa162022-09-13 16:06:24 +080011975 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011976 return RETURN_ERR;
11977 }
11978 operationParam->enable = enabled;
11979
11980 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011981 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011982 {
developer1e5aa162022-09-13 16:06:24 +080011983 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011984 return RETURN_ERR;
11985 }
11986
11987 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011988 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011989 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011990 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011991 else if (!strcmp(band, "6GHz"))
11992 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011993 else
11994 {
developer1e5aa162022-09-13 16:06:24 +080011995 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011996 band);
11997 }
11998
developer1e5aa162022-09-13 16:06:24 +080011999 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12000 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12001 operationParam->channel = 0;
12002 operationParam->autoChannelEnabled = TRUE;
12003 } else {
12004 operationParam->channel = strtol(buf, NULL, 10);
12005 operationParam->autoChannelEnabled = FALSE;
12006 }
12007
developer06a01d92022-09-07 16:32:39 +080012008 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012009 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12010 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12011 return RETURN_ERR;
12012 }
developer06a01d92022-09-07 16:32:39 +080012013 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12014 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12015 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012016 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
12017 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080012018 else
12019 {
developer1e5aa162022-09-13 16:06:24 +080012020 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12021 return false;
developer06a01d92022-09-07 16:32:39 +080012022 }
12023
developer1e5aa162022-09-13 16:06:24 +080012024 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12025 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12026 return RETURN_ERR;
12027 }
12028 // Two different definition bit map, so need to check every bit.
12029 if (mode & WIFI_MODE_A)
12030 operationParam->variant |= WIFI_80211_VARIANT_A;
12031 if (mode & WIFI_MODE_B)
12032 operationParam->variant |= WIFI_80211_VARIANT_B;
12033 if (mode & WIFI_MODE_G)
12034 operationParam->variant |= WIFI_80211_VARIANT_G;
12035 if (mode & WIFI_MODE_N)
12036 operationParam->variant |= WIFI_80211_VARIANT_N;
12037 if (mode & WIFI_MODE_AC)
12038 operationParam->variant |= WIFI_80211_VARIANT_AC;
12039 if (mode & WIFI_MODE_AX)
12040 operationParam->variant |= WIFI_80211_VARIANT_AX;
12041 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12042 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12043 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012044 }
developer1e5aa162022-09-13 16:06:24 +080012045 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12046 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12047 return RETURN_ERR;
12048 }
12049 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12050 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12051 return RETURN_ERR;
12052 }
developer06a01d92022-09-07 16:32:39 +080012053
developer1e5aa162022-09-13 16:06:24 +080012054 memset(buf, 0, sizeof(buf));
12055 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12056 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12057 return RETURN_ERR;
12058 }
12059 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12060
12061 memset(buf, 0, sizeof(buf));
12062 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12063 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12064 return RETURN_ERR;
12065 }
12066 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12067
12068 memset(buf, 0, sizeof(buf));
12069 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12070 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12071
12072 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12073 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12074 return RETURN_ERR;
12075 }
12076 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12077 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12078 return RETURN_ERR;
12079 }
12080
12081 memset(buf, 0, sizeof(buf));
12082 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12083 if (strcmp(buf, "-1") == 0) {
12084 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12085 operationParam->ctsProtection = FALSE;
12086 } else {
12087 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12088 operationParam->ctsProtection = TRUE;
12089 }
12090
12091 memset(buf, 0, sizeof(buf));
12092 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12093 if (strcmp(buf, "0") == 0)
12094 operationParam->obssCoex = FALSE;
12095 else
12096 operationParam->obssCoex = TRUE;
12097
12098 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12099 _syscmd(cmd, buf, sizeof(buf));
12100 if (strlen(buf) != 0)
12101 operationParam->stbcEnable = TRUE;
12102 else
12103 operationParam->stbcEnable = FALSE;
12104
12105 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12106 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12107 return RETURN_ERR;
12108 }
12109
12110 // Below value is hardcoded
12111
12112 operationParam->numSecondaryChannels = 0;
12113 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12114 operationParam->channelSecondary[i] = 0;
12115 }
12116 operationParam->csa_beacon_count = 15;
12117 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012118
12119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12120 return RETURN_OK;
12121}
12122
12123static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12124{
developerc086fb72022-10-04 10:18:22 +080012125 int max_radio_num = 0;
12126
12127 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012128 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012129 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12130 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012131 }
12132
developerc086fb72022-10-04 10:18:22 +080012133 return (arrayIndex * max_radio_num) + radioIndex;
12134}
developer06a01d92022-09-07 16:32:39 +080012135
developerc086fb72022-10-04 10:18:22 +080012136wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12137 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12138 return WIFI_BITRATE_1MBPS;
12139 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12140 return WIFI_BITRATE_2MBPS;
12141 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12142 return WIFI_BITRATE_5_5MBPS;
12143 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12144 return WIFI_BITRATE_6MBPS;
12145 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12146 return WIFI_BITRATE_9MBPS;
12147 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12148 return WIFI_BITRATE_11MBPS;
12149 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12150 return WIFI_BITRATE_12MBPS;
12151 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12152 return WIFI_BITRATE_18MBPS;
12153 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12154 return WIFI_BITRATE_24MBPS;
12155 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12156 return WIFI_BITRATE_36MBPS;
12157 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12158 return WIFI_BITRATE_48MBPS;
12159 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12160 return WIFI_BITRATE_54MBPS;
12161 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012162}
12163
developer1d57d002022-10-12 18:03:15 +080012164INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12165{
12166 if (beacon == WIFI_BITRATE_1MBPS)
12167 strcpy(beacon_str, "1Mbps");
12168 else if (beacon == WIFI_BITRATE_2MBPS)
12169 strcpy(beacon_str, "2Mbps");
12170 else if (beacon == WIFI_BITRATE_5_5MBPS)
12171 strcpy(beacon_str, "5.5Mbps");
12172 else if (beacon == WIFI_BITRATE_6MBPS)
12173 strcpy(beacon_str, "6Mbps");
12174 else if (beacon == WIFI_BITRATE_9MBPS)
12175 strcpy(beacon_str, "9Mbps");
12176 else if (beacon == WIFI_BITRATE_11MBPS)
12177 strcpy(beacon_str, "11Mbps");
12178 else if (beacon == WIFI_BITRATE_12MBPS)
12179 strcpy(beacon_str, "12Mbps");
12180 else if (beacon == WIFI_BITRATE_18MBPS)
12181 strcpy(beacon_str, "18Mbps");
12182 else if (beacon == WIFI_BITRATE_24MBPS)
12183 strcpy(beacon_str, "24Mbps");
12184 else if (beacon == WIFI_BITRATE_36MBPS)
12185 strcpy(beacon_str, "36Mbps");
12186 else if (beacon == WIFI_BITRATE_48MBPS)
12187 strcpy(beacon_str, "48Mbps");
12188 else if (beacon == WIFI_BITRATE_54MBPS)
12189 strcpy(beacon_str, "54Mbps");
12190 return RETURN_OK;
12191}
12192
developer06a01d92022-09-07 16:32:39 +080012193INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12194{
developerc086fb72022-10-04 10:18:22 +080012195 INT mode = 0;
12196 INT ret = -1;
12197 INT output = 0;
12198 int i = 0;
12199 int vap_index = 0;
12200 BOOL enabled = FALSE;
12201 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012202 wifi_vap_security_t security = {0};
developerc086fb72022-10-04 10:18:22 +080012203 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080012204
12205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12206 printf("Entering %s index = %d\n", __func__, (int)index);
12207
developer06a01d92022-09-07 16:32:39 +080012208 for (i = 0; i < 5; i++)
12209 {
developerc086fb72022-10-04 10:18:22 +080012210 map->vap_array[i].radio_index = index;
12211
developer06a01d92022-09-07 16:32:39 +080012212 vap_index = array_index_to_vap_index(index, i);
12213 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012214 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012215
developerc086fb72022-10-04 10:18:22 +080012216 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012217
12218 map->vap_array[i].vap_index = vap_index;
12219
12220 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012221 ret = wifi_getApName(vap_index, buf);
12222 if (ret != RETURN_OK) {
12223 printf("%s: wifi_getApName return error\n", __func__);
12224 return RETURN_ERR;
12225 }
12226 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12227
12228 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012229 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012230 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012231 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012232 return RETURN_ERR;
12233 }
12234 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 +080012235
12236 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012237 if (ret != RETURN_OK) {
12238 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012239 return RETURN_ERR;
12240 }
12241 map->vap_array[i].u.bss_info.enabled = enabled;
12242
developerc086fb72022-10-04 10:18:22 +080012243 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12244 if (ret != RETURN_OK) {
12245 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12246 return RETURN_ERR;
12247 }
developer06a01d92022-09-07 16:32:39 +080012248 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012249
12250 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12251 if (ret != RETURN_OK) {
12252 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12253 return RETURN_ERR;
12254 }
12255 map->vap_array[i].u.bss_info.isolation = enabled;
12256
12257 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12258 if (ret != RETURN_OK) {
12259 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12260 return RETURN_ERR;
12261 }
12262 map->vap_array[i].u.bss_info.bssMaxSta = output;
12263
12264 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12265 if (ret != RETURN_OK) {
12266 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12267 return RETURN_ERR;
12268 }
12269 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012270
developerc086fb72022-10-04 10:18:22 +080012271 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12272 if (ret != RETURN_OK) {
12273 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12274 return RETURN_ERR;
12275 }
12276 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012277
developerc086fb72022-10-04 10:18:22 +080012278 ret = wifi_getApSecurity(vap_index, &security);
12279 if (ret != RETURN_OK) {
12280 printf("%s: wifi_getApSecurity return error\n", __func__);
12281 return RETURN_ERR;
12282 }
12283 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012284
developerc086fb72022-10-04 10:18:22 +080012285 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12286 if (ret != RETURN_OK) {
12287 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12288 return RETURN_ERR;
12289 }
12290 if (mode == 0)
12291 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12292 else
12293 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12294 if (mode == 1)
12295 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12296 else if (mode == 2)
12297 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012298
developerc086fb72022-10-04 10:18:22 +080012299 ret = wifi_getApWmmEnable(vap_index, &enabled);
12300 if (ret != RETURN_OK) {
12301 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12302 return RETURN_ERR;
12303 }
12304 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012305
developerc086fb72022-10-04 10:18:22 +080012306 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12307 if (ret != RETURN_OK) {
12308 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012309 return RETURN_ERR;
12310 }
developerc086fb72022-10-04 10:18:22 +080012311 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012312
12313 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012314 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012315 if (ret != RETURN_OK) {
12316 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12317 return RETURN_ERR;
12318 }
12319 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012320
developerc086fb72022-10-04 10:18:22 +080012321 memset(buf, 0, sizeof(buf));
12322 ret = wifi_getBaseBSSID(vap_index, buf);
12323 if (ret != RETURN_OK) {
12324 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12325 return RETURN_ERR;
12326 }
12327 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12328 &map->vap_array[i].u.bss_info.bssid[0],
12329 &map->vap_array[i].u.bss_info.bssid[1],
12330 &map->vap_array[i].u.bss_info.bssid[2],
12331 &map->vap_array[i].u.bss_info.bssid[3],
12332 &map->vap_array[i].u.bss_info.bssid[4],
12333 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012334 // 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]);
12335
12336 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12337 if (ret != RETURN_OK) {
12338 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12339 return RETURN_ERR;
12340 }
12341 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012342
developerc086fb72022-10-04 10:18:22 +080012343 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012344 }
12345 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12346 return RETURN_OK;
12347}
12348
developer431128d2022-12-16 15:30:41 +080012349void checkVapStatus(int apIndex, bool *enable)
12350{
12351 char if_name[16] = {0};
12352 char cmd[128] = {0};
12353 char buf[128] = {0};
12354
12355 *enable = FALSE;
developerac6f1142022-12-20 19:26:35 +080012356 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
developer431128d2022-12-16 15:30:41 +080012357 return;
12358
12359 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12360 _syscmd(cmd, buf, sizeof(buf));
12361 if (strlen(buf) > 0)
12362 *enable = TRUE;
12363 return;
12364}
12365
developerd946fd62022-12-08 18:03:28 +080012366static int prepareInterface(UINT apIndex, char *new_interface)
12367{
12368 char cur_interface[16] = {0};
12369 char config_file[128] = {0};
12370 char cmd[128] = {0};
12371 char buf[16] = {0};
12372 int max_radio_num = 0;
12373 int radioIndex = -1;
12374 int phyIndex = -1;
12375
12376 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12377 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12378
12379 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12380 wifi_getMaxRadioNumber(&max_radio_num);
12381 radioIndex = apIndex % max_radio_num;
12382 phyIndex = radio_index_to_phy(radioIndex);
12383 // disable and del old interface, then add new interface
12384 wifi_setApEnable(apIndex, FALSE);
developer431128d2022-12-16 15:30:41 +080012385 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 +080012386 _syscmd(cmd, buf, sizeof(buf));
12387 }
developer431128d2022-12-16 15:30:41 +080012388 // update the vap status file
12389 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12390 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012391 return RETURN_OK;
12392}
12393
developer06a01d92022-09-07 16:32:39 +080012394INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12395{
developerd946fd62022-12-08 18:03:28 +080012396 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012397 unsigned int i;
12398 wifi_vap_info_t *vap_info = NULL;
12399 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012400 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012401 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012402 char buf[256] = {0};
12403 char cmd[128] = {0};
12404 char config_file[64] = {0};
12405 char bssid[32] = {0};
12406 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012407 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012408
12409 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12410 printf("Entering %s index = %d\n", __func__, (int)index);
12411 for (i = 0; i < map->num_vaps; i++)
12412 {
developer1d57d002022-10-12 18:03:15 +080012413 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012414 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012415
12416 // Check vap status file to enable multiple ap if the system boot.
12417 checkVapStatus(vap_info->vap_index, &enable);
12418 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012419 continue;
developer06a01d92022-09-07 16:32:39 +080012420
developer1d57d002022-10-12 18:03:15 +080012421 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12422
developer431128d2022-12-16 15:30:41 +080012423 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12424 enable = FALSE;
12425
12426 // multi-ap first up need to copy current radio config
12427 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012428 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12429 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012430 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12431 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12432 } else {
12433 // Check whether the interface name is valid or this ap change it.
12434 int apIndex = -1;
12435 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12436 if (apIndex != -1 && apIndex != vap_info->vap_index)
12437 continue;
12438 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012439 }
developer06a01d92022-09-07 16:32:39 +080012440
developer1d57d002022-10-12 18:03:15 +080012441 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012442 params[0].name = "interface";
12443 params[0].value = vap_info->vap_name;
12444 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12445 params[1].name = "bssid";
12446 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012447 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012448 params[2].name = "wpa_psk_file";
12449 params[2].value = psk_file;
12450
12451 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12452 wifi_hostapdWrite(config_file, params, 3);
12453
12454 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12455 _syscmd(cmd, buf, sizeof(buf));
12456
12457 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12458 if (ret != RETURN_OK) {
12459 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12460 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012461 }
developer1d57d002022-10-12 18:03:15 +080012462
12463 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12464 if (ret != RETURN_OK) {
12465 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12466 return RETURN_ERR;
12467 }
12468
12469 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12470 if (ret != RETURN_OK) {
12471 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12472 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012473 }
12474
developer1d57d002022-10-12 18:03:15 +080012475 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12476 if (ret != RETURN_OK) {
12477 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12478 return RETURN_ERR;
12479 }
developer06a01d92022-09-07 16:32:39 +080012480
developer1d57d002022-10-12 18:03:15 +080012481 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12482 if (ret != RETURN_OK) {
12483 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12484 return RETURN_ERR;
12485 }
developer06a01d92022-09-07 16:32:39 +080012486
developer1d57d002022-10-12 18:03:15 +080012487 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12488 if (ret != RETURN_OK) {
12489 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12490 return RETURN_ERR;
12491 }
12492
developer804c64f2022-10-19 13:54:40 +080012493 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012494 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012495 }else {
12496 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012497 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012498 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12499 _syscmd(cmd, buf, sizeof(buf));
12500 }else{
developer1d57d002022-10-12 18:03:15 +080012501 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012502 }
developer1d57d002022-10-12 18:03:15 +080012503 }
12504
12505 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12506 if (ret != RETURN_OK) {
12507 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12508 return RETURN_ERR;
12509 }
12510
12511 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12512 if (ret != RETURN_OK) {
12513 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12514 return RETURN_ERR;
12515 }
12516
12517 memset(buf, 0, sizeof(buf));
12518 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12519 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12520 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12521 if (ret != RETURN_OK) {
12522 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12523 return RETURN_ERR;
12524 }
12525
12526 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12527 if (ret != RETURN_OK) {
12528 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12529 return RETURN_ERR;
12530 }
12531
12532 wifi_setApEnable(vap_info->vap_index, TRUE);
12533 multiple_set = FALSE;
12534
12535 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12536 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12537 if (ret != RETURN_OK) {
12538 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12539 return RETURN_ERR;
12540 }
12541
12542 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12543 if (ret != RETURN_OK) {
12544 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12545 return RETURN_ERR;
12546 }
developer06a01d92022-09-07 16:32:39 +080012547
developer1d57d002022-10-12 18:03:15 +080012548 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012549 }
12550 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12551 return RETURN_OK;
12552}
12553
12554int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12555{
12556 char *token, *next;
12557 const char s[2] = ",";
12558 int count =0;
12559
12560 /* get the first token */
12561 token = strtok_r(pchannels, s, &next);
12562
12563 /* walk through other tokens */
12564 while( token != NULL && count < MAX_CHANNELS) {
12565 chlistptr->channels_list[count++] = atoi(token);
12566 token = strtok_r(NULL, s, &next);
12567 }
12568
12569 return count;
12570}
12571
12572static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12573{
12574 INT status;
12575 wifi_channels_list_t *chlistp;
12576 CHAR output_string[64];
12577 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080012578 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080012579 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080012580
12581 if(rcap == NULL)
12582 {
12583 return RETURN_ERR;
12584 }
12585
12586 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012587 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012588
developer1e5aa162022-09-13 16:06:24 +080012589 if (band == band_2_4)
12590 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12591 else if (band == band_5)
12592 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12593 else if (band == band_6)
12594 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012595
12596 chlistp = &(rcap->channel_list[0]);
12597 memset(pchannels, 0, sizeof(pchannels));
12598
12599 /* possible number of radio channels */
12600 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12601 {
12602 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12603 }
12604 /* Number of channels and list*/
12605 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12606
12607 /* autoChannelSupported */
12608 /* always ON with wifi_getRadioAutoChannelSupported */
12609 rcap->autoChannelSupported = TRUE;
12610
12611 /* DCSSupported */
12612 /* always ON with wifi_getRadioDCSSupported */
12613 rcap->DCSSupported = TRUE;
12614
12615 /* zeroDFSSupported - TBD */
12616 rcap->zeroDFSSupported = FALSE;
12617
12618 /* Supported Country List*/
12619 memset(output_string, 0, sizeof(output_string));
12620 status = wifi_getRadioCountryCode(radioIndex, output_string);
12621 if( status != 0 ) {
12622 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12623 return RETURN_ERR;
12624 } else {
12625 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12626 }
12627 if(!strcmp(output_string,"US")){
12628 rcap->countrySupported[0] = wifi_countrycode_US;
12629 rcap->countrySupported[1] = wifi_countrycode_CA;
12630 } else if (!strcmp(output_string,"CA")) {
12631 rcap->countrySupported[0] = wifi_countrycode_CA;
12632 rcap->countrySupported[1] = wifi_countrycode_US;
12633 } else {
12634 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12635 }
12636
12637 rcap->numcountrySupported = 2;
12638
12639 /* csi */
12640 rcap->csi.maxDevices = 8;
12641 rcap->csi.soudingFrameSupported = TRUE;
12642
developer7930d352022-12-21 17:55:42 +080012643 wifi_GetInterfaceName(radioIndex, interface_name);
12644 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080012645
12646 /* channelWidth - all supported bandwidths */
12647 int i=0;
12648 rcap->channelWidth[i] = 0;
12649 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12650 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12651 WIFI_CHANNELBANDWIDTH_40MHZ);
12652
12653 }
developer1e5aa162022-09-13 16:06:24 +080012654 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012655 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12656 WIFI_CHANNELBANDWIDTH_40MHZ |
12657 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12658 }
12659
12660
12661 /* mode - all supported variants */
12662 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12663 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012664 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 +080012665 }
12666 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012667 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12668 }
12669 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12670 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012671 }
12672 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12673 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12674
12675 /* supportedBitRate - all supported bitrates */
12676 rcap->supportedBitRate[i] = 0;
12677 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12678 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12679 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12680 }
developer1e5aa162022-09-13 16:06:24 +080012681 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012682 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12683 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12684 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12685 }
12686
12687
12688 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12689 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12690 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12691 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12692 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12693 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12694 rcap->cipherSupported = 0;
12695 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12696 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12697
12698 return RETURN_OK;
12699}
12700
12701INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12702{
developer30423732022-12-01 16:17:49 +080012703 INT status = 0, radioIndex = 0;
12704 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080012705 int iter = 0;
developer30423732022-12-01 16:17:49 +080012706 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080012707 int max_num_radios;
developer30423732022-12-01 16:17:49 +080012708 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080012709
12710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12711
12712 memset(cap, 0, sizeof(wifi_hal_capability_t));
12713
12714 /* version */
12715 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12716 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12717
12718 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080012719 wifi_getMaxRadioNumber(&max_num_radios);
12720 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080012721
12722 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12723 {
12724 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12725 if (status != 0) {
12726 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12727 return RETURN_ERR;
12728 }
12729
12730 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12731 {
developer804c64f2022-10-19 13:54:40 +080012732 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012733 {
12734 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12735 return RETURN_ERR;
12736 }
12737 iface_info = &cap->wifi_prop.interface_map[iter];
12738 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12739 iface_info->rdk_radio_index = radioIndex;
12740 memset(output, 0, sizeof(output));
12741 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12742 {
12743 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12744 }
12745 // TODO: bridge name
12746 // TODO: vlan id
12747 // TODO: primary
12748 iface_info->index = array_index_to_vap_index(radioIndex, j);
12749 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080012750 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012751 {
12752 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12753 }
12754 iter++;
12755 }
12756 }
12757
12758 cap->BandSteeringSupported = FALSE;
12759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12760 return RETURN_OK;
12761}
12762
developer9df4e652022-10-11 11:27:38 +080012763INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12764{
12765 struct params h_config={0};
12766 char config_file[64] = {0};
12767
12768 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12769
12770 h_config.name = "okc";
12771 h_config.value = okc_enable?"1":"0";
12772
12773 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12774 wifi_hostapdWrite(config_file, &h_config, 1);
12775 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12776
12777 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12778 return RETURN_OK;
12779}
12780
12781INT wifi_setSAEMFP(int ap_index, BOOL enable)
12782{
12783 struct params h_config={0};
12784 char config_file[64] = {0};
12785 char buf[128] = {0};
12786
12787 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12788
12789 h_config.name = "sae_require_mfp";
12790 h_config.value = enable?"1":"0";
12791
12792 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12793 wifi_hostapdWrite(config_file, &h_config, 1);
12794 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12795
12796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12797 return RETURN_OK;
12798}
12799
12800INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12801{
12802 struct params h_config={0};
12803 char config_file[64] = {0};
12804 char buf[128] = {0};
12805
12806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12807
12808 h_config.name = "sae_pwe";
12809 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12810 h_config.value = buf;
12811
12812 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12813 wifi_hostapdWrite(config_file, &h_config, 1);
12814 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12815
12816 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12817 return RETURN_OK;
12818}
12819
12820INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12821{
12822 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12823 struct params h_config={0};
12824 char config_file[64] = {0};
12825
12826 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12827
12828 h_config.name = "wpa_disable_eapol_key_retries";
12829 h_config.value = disable_EAPOL_retries?"1":"0";
12830
12831 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12832 wifi_hostapdWrite(config_file, &h_config, 1);
12833 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12834
12835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12836 return RETURN_OK;
12837}
12838
developer06a01d92022-09-07 16:32:39 +080012839INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12840{
developer587c1b62022-09-27 15:58:59 +080012841 char buf[128] = {0};
12842 char config_file[128] = {0};
12843 char password[64] = {0};
12844 char mfp[32] = {0};
12845 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012846 BOOL okc_enable = FALSE;
12847 BOOL sae_MFP = FALSE;
12848 BOOL disable_EAPOL_retries = TRUE;
12849 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012850 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012851 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012852
12853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12854
12855 multiple_set = TRUE;
12856 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12857 if (security->mode == wifi_security_mode_none) {
12858 strcpy(wpa_mode, "None");
12859 } else if (security->mode == wifi_security_mode_wpa_personal)
12860 strcpy(wpa_mode, "WPA-Personal");
12861 else if (security->mode == wifi_security_mode_wpa2_personal)
12862 strcpy(wpa_mode, "WPA2-Personal");
12863 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12864 strcpy(wpa_mode, "WPA-WPA2-Personal");
12865 else if (security->mode == wifi_security_mode_wpa_enterprise)
12866 strcpy(wpa_mode, "WPA-Enterprise");
12867 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12868 strcpy(wpa_mode, "WPA2-Enterprise");
12869 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12870 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012871 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012872 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012873 okc_enable = TRUE;
12874 sae_MFP = TRUE;
12875 sae_pwe = 2;
12876 disable_EAPOL_retries = FALSE;
12877 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012878 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012879 okc_enable = TRUE;
12880 sae_MFP = TRUE;
12881 sae_pwe = 2;
12882 disable_EAPOL_retries = FALSE;
12883 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012884 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012885 sae_MFP = TRUE;
12886 sae_pwe = 2;
12887 disable_EAPOL_retries = FALSE;
12888 }
12889
12890 band = wifi_index_to_band(ap_index);
12891 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12892 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12893 return RETURN_ERR;
12894 }
developer587c1b62022-09-27 15:58:59 +080012895
12896 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012897 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012898 wifi_setSAEMFP(ap_index, sae_MFP);
12899 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012900 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012901
developer9df4e652022-10-11 11:27:38 +080012902 if (security->mode != wifi_security_mode_none) {
12903 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12904 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12905 password[63] = '\0';
12906 wifi_setApSecurityKeyPassphrase(ap_index, password);
12907 }
12908 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12909 params.name = "sae_password";
12910 params.value = security->u.key.key;
12911 wifi_hostapdWrite(config_file, &params, 1);
12912 }
12913 }
developer587c1b62022-09-27 15:58:59 +080012914
12915 if (security->mode != wifi_security_mode_none) {
12916 memset(&params, 0, sizeof(params));
12917 params.name = "wpa_pairwise";
12918 if (security->encr == wifi_encryption_tkip)
12919 params.value = "TKIP";
12920 else if (security->encr == wifi_encryption_aes)
12921 params.value = "CCMP";
12922 else if (security->encr == wifi_encryption_aes_tkip)
12923 params.value = "TKIP CCMP";
12924 wifi_hostapdWrite(config_file, &params, 1);
12925 }
12926
12927 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012928 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012929 else if (security->mfp == wifi_mfp_cfg_optional)
12930 strcpy(mfp, "Optional");
12931 else if (security->mfp == wifi_mfp_cfg_required)
12932 strcpy(mfp, "Required");
12933 wifi_setApSecurityMFPConfig(ap_index, mfp);
12934
12935 memset(&params, 0, sizeof(params));
12936 params.name = "transition_disable";
12937 if (security->wpa3_transition_disable == TRUE)
12938 params.value = "0x01";
12939 else
12940 params.value = "0x00";
12941 wifi_hostapdWrite(config_file, &params, 1);
12942
12943 memset(&params, 0, sizeof(params));
12944 params.name = "wpa_group_rekey";
12945 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12946 params.value = buf;
12947 wifi_hostapdWrite(config_file, &params, 1);
12948
12949 memset(&params, 0, sizeof(params));
12950 params.name = "wpa_strict_rekey";
12951 params.value = security->strict_rekey?"1":"0";
12952 wifi_hostapdWrite(config_file, &params, 1);
12953
12954 memset(&params, 0, sizeof(params));
12955 params.name = "wpa_pairwise_update_count";
12956 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12957 params.value = buf;
12958 wifi_hostapdWrite(config_file, &params, 1);
12959
12960 memset(&params, 0, sizeof(params));
12961 params.name = "disable_pmksa_caching";
12962 params.value = security->disable_pmksa_caching?"1":"0";
12963 wifi_hostapdWrite(config_file, &params, 1);
12964
12965 wifi_setApEnable(ap_index, FALSE);
12966 wifi_setApEnable(ap_index, TRUE);
12967
12968 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12969
developer06a01d92022-09-07 16:32:39 +080012970 return RETURN_OK;
12971}
12972
12973INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12974{
developer9df4e652022-10-11 11:27:38 +080012975 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012976 char config_file[128] = {0};
12977 int disable = 0;
12978 // struct params params = {0};
12979
12980 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12981 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12982 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12983 security->mode = wifi_security_mode_none;
12984 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012985 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012986 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012987 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012988 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012989 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012990 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012991 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012992 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012993 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012994 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012995 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012996 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012997 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012998 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012999 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013000 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013001 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013002 security->mode = wifi_security_mode_wpa3_enterprise;
13003 }
13004
13005 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13006 if (security->mode == wifi_security_mode_none)
13007 security->encr = wifi_encryption_none;
13008 else {
13009 if (strcmp(buf, "TKIP") == 0)
13010 security->encr = wifi_encryption_tkip;
13011 else if (strcmp(buf, "CCMP") == 0)
13012 security->encr = wifi_encryption_aes;
13013 else
13014 security->encr = wifi_encryption_aes_tkip;
13015 }
13016
developer9df4e652022-10-11 11:27:38 +080013017 if (security->mode != wifi_encryption_none) {
13018 memset(buf, 0, sizeof(buf));
13019 // wpa3 can use one or both configs as password, so we check sae_password first.
13020 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13021 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13022 security->u.key.type = wifi_security_key_type_sae;
13023 } else {
13024 security->u.key.type = wifi_security_key_type_psk;
13025 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13026 }
13027 strncpy(security->u.key.key, buf, sizeof(buf));
13028 security->u.key.key[255] = '\0';
13029 }
13030
developer587c1b62022-09-27 15:58:59 +080013031 memset(buf, 0, sizeof(buf));
13032 wifi_getApSecurityMFPConfig(ap_index, buf);
13033 if (strcmp(buf, "Disabled") == 0)
13034 security->mfp = wifi_mfp_cfg_disabled;
13035 else if (strcmp(buf, "Optional") == 0)
13036 security->mfp = wifi_mfp_cfg_optional;
13037 else if (strcmp(buf, "Required") == 0)
13038 security->mfp = wifi_mfp_cfg_required;
13039
13040 memset(buf, 0, sizeof(buf));
13041 security->wpa3_transition_disable = FALSE;
13042 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13043 disable = strtol(buf, NULL, 16);
13044 if (disable != 0)
13045 security->wpa3_transition_disable = TRUE;
13046
13047 memset(buf, 0, sizeof(buf));
13048 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13049 if (strlen(buf) == 0)
13050 security->rekey_interval = 86400;
13051 else
13052 security->rekey_interval = strtol(buf, NULL, 10);
13053
13054 memset(buf, 0, sizeof(buf));
13055 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13056 if (strlen(buf) == 0)
13057 security->strict_rekey = 1;
13058 else
13059 security->strict_rekey = strtol(buf, NULL, 10);
13060
13061 memset(buf, 0, sizeof(buf));
13062 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13063 if (strlen(buf) == 0)
13064 security->eapol_key_retries = 4;
13065 else
13066 security->eapol_key_retries = strtol(buf, NULL, 10);
13067
13068 memset(buf, 0, sizeof(buf));
13069 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13070 if (strlen(buf) == 0)
13071 security->disable_pmksa_caching = FALSE;
13072 else
13073 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13074
13075 /* TODO
13076 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13077 */
13078 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13079 security->eap_identity_req_timeout = 0;
13080 security->eap_identity_req_retries = 0;
13081 security->eap_req_timeout = 0;
13082 security->eap_req_retries = 0;
13083 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013084 return RETURN_OK;
13085}
13086
13087#endif /* WIFI_HAL_VERSION_3 */
13088
13089#ifdef WIFI_HAL_VERSION_3_PHASE2
13090INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13091{
developerd946fd62022-12-08 18:03:28 +080013092 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013093 char cmd[128] = {0};
13094 char buf[128] = {0};
13095 char *mac_addr = NULL;
13096 BOOL status = FALSE;
13097 size_t len = 0;
13098
13099 if(ap_index > MAX_APS)
13100 return RETURN_ERR;
13101
13102 *output_numDevices = 0;
13103 wifi_getApEnable(ap_index, &status);
13104 if (status == FALSE)
13105 return RETURN_OK;
13106
developerac6f1142022-12-20 19:26:35 +080013107 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013108 return RETURN_ERR;
13109 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013110 _syscmd(cmd, buf, sizeof(buf));
13111
13112 mac_addr = strtok(buf, "\n");
13113 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13114 *output_numDevices = i + 1;
13115 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13116 addr_ptr = output_deviceMacAddressArray[i];
13117 mac_addr_aton(addr_ptr, mac_addr);
13118 mac_addr = strtok(NULL, "\n");
13119 }
13120
13121 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013122}
13123#else
13124INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13125{
developerd946fd62022-12-08 18:03:28 +080013126 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013127 char cmd[128];
13128 BOOL status = false;
13129
13130 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13131 return RETURN_ERR;
13132
13133 output_buf[0] = '\0';
13134
13135 wifi_getApEnable(ap_index,&status);
13136 if (!status)
13137 return RETURN_OK;
13138
developerac6f1142022-12-20 19:26:35 +080013139 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013140 return RETURN_ERR;
13141 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013142 _syscmd(cmd, output_buf, output_buf_size);
13143
13144 return RETURN_OK;
13145}
13146#endif
developer2f513ab2022-09-13 14:26:06 +080013147
13148INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13149{
13150 char output[16]={'\0'};
13151 char config_file[MAX_BUF_SIZE] = {0};
13152
13153 if (!enable)
13154 return RETURN_ERR;
13155
13156 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13157 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13158
13159 if (strlen(output) == 0)
13160 *enable = FALSE;
13161 else if (strncmp(output, "1", 1) == 0)
13162 *enable = TRUE;
13163 else
13164 *enable = FALSE;
13165
13166 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13167 return RETURN_OK;
13168}
developer2d9c30f2022-09-13 15:06:14 +080013169
13170INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13171{
developer804c64f2022-10-19 13:54:40 +080013172 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013173 return RETURN_ERR;
13174 *output_enable=TRUE;
13175 return RETURN_OK;
13176}
developerfd7d2892022-09-13 16:44:53 +080013177
13178INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13179{
13180 char cmd[128] = {0};
13181 char buf[128] = {0};
13182 char line[128] = {0};
13183 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013184 FILE *f = NULL;
13185 int index = 0;
13186 int exp = 0;
13187 int mantissa = 0;
13188 int duration = 0;
13189 int radio_index = 0;
13190 int max_radio_num = 0;
13191 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013192 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013193 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13194
13195 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013196
developerfd7d2892022-09-13 16:44:53 +080013197 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013198
13199 phyId = radio_index_to_phy(radio_index);
13200 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013201 _syscmd(cmd, buf, sizeof(buf));
13202 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13203 if (*numSessionReturned > maxNumberSessions)
13204 *numSessionReturned = maxNumberSessions;
13205 else if (*numSessionReturned < 1) {
13206 *numSessionReturned = 0;
13207 return RETURN_OK;
13208 }
13209
developer033b37b2022-10-18 11:27:46 +080013210 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 +080013211 if ((f = popen(cmd, "r")) == NULL) {
13212 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13213 return RETURN_ERR;
13214 }
13215
13216 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013217 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013218 char *tmp = NULL;
13219 strcpy(buf, line);
13220 tmp = strtok(buf, " ");
13221 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13222 tmp = strtok(NULL, " ");
13223 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13224 tmp = strtok(NULL, " ");
13225 if (strstr(tmp, "t")) {
13226 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13227 }
13228 if (strstr(tmp, "a")) {
13229 twtSessions[index].twtParameters.operation.announced = TRUE;
13230 }
13231 tmp = strtok(NULL, " ");
13232 exp = strtol(tmp, NULL, 10);
13233 tmp = strtok(NULL, " ");
13234 mantissa = strtol(tmp, NULL, 10);
13235 tmp = strtok(NULL, " ");
13236 duration = strtol(tmp, NULL, 10);
13237
13238 // only implicit supported
13239 twtSessions[index].twtParameters.operation.implicit = TRUE;
13240 // only individual agreement supported
13241 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13242
13243 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13244 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013245 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013246 // Overflow handling
13247 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13248 } else {
13249 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13250 }
13251 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13252 index++;
13253 }
13254
13255 pclose(f);
13256 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13257 return RETURN_OK;
13258}