blob: 606aff6920ae5c074c7d2a680e7a68b92e0e9067 [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
66#define MAX_BUF_SIZE 128
67#define MAX_CMD_SIZE 1024
68#define MAX_POSSIBLE_CHANNEL_STRING_BUF 512
69#define IF_NAME_SIZE 50
70#define CONFIG_PREFIX "/nvram/hostapd"
71#define ACL_PREFIX "/tmp/hostapd-acl"
developer10adcc12022-09-13 14:39:17 +080072#define DENY_PREFIX "/tmp/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080073//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
75#define VAP_STATUS_FILE "/tmp/vap-status"
developera3c68b92022-09-13 15:27:29 +080076#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080077#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
100#define MAX_APS 10
101#define NUMBER_OF_RADIOS 2
102
103#ifndef AP_PREFIX
104#define AP_PREFIX "wifi"
105#endif
106
107#ifndef RADIO_PREFIX
108#define RADIO_PREFIX "wlan"
109#endif
110
111#define MAX_BUF_SIZE 128
112#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800113#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800114
115//Uncomment to enable debug logs
116//#define WIFI_DEBUG
117
118#ifdef WIFI_DEBUG
119#define wifi_dbg_printf printf
120#define WIFI_ENTRY_EXIT_DEBUG printf
121#else
122#define wifi_dbg_printf(format, args...) printf("")
123#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
124#endif
125
126#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
127#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
128#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
129#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
130#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
131#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
132#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
133#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
134#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
135#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
136
developer4fb0b922022-09-30 14:29:09 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800138
139#define BW_FNAME "/nvram/bw_file.txt"
140
141#define PS_MAX_TID 16
142
143static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
145 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
148 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
150 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
153 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
156 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
158 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
160};
161
162typedef unsigned long long u64;
163
164/* Enum to define WiFi Bands */
165typedef enum
166{
167 band_invalid = -1,
168 band_2_4 = 0,
169 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800170 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800171} wifi_band;
172
developerdb744382022-09-13 15:34:54 +0800173typedef enum {
174 WIFI_MODE_A = 0x01,
175 WIFI_MODE_B = 0x02,
176 WIFI_MODE_G = 0x04,
177 WIFI_MODE_N = 0x08,
178 WIFI_MODE_AC = 0x10,
179 WIFI_MODE_AX = 0x20,
180} wifi_ieee80211_Mode;
181
developer06a01d92022-09-07 16:32:39 +0800182#ifdef WIFI_HAL_VERSION_3
183
184// Return number of elements in array
185#ifndef ARRAY_SIZE
186#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187#endif /* ARRAY_SIZE */
188
189#ifndef ARRAY_AND_SIZE
190#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
191#endif /* ARRAY_AND_SIZE */
192
193#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
194
195typedef struct {
196 int32_t value;
197 int32_t param;
198 intptr_t key;
199 intptr_t data;
200} wifi_secur_list;
201
202wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
203wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
204char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800205static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800206
207static wifi_secur_list map_security[] =
208{
209 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
270 sscanf(arg, "%x:%x:%x:%x:%x:%x", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
289 snprintf(mac_addr, 20, "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
developerf5745ee2022-10-05 16:09:53 +0800295 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800296 if (freq == 2484)
297 return 14;
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
299 else if (freq == 5935)
300 return 2;
developer06a01d92022-09-07 16:32:39 +0800301 else if (freq < 2484)
302 return (freq - 2407) / 5;
303 else if (freq >= 4910 && freq <= 4980)
304 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800305 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800306 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800307 else if (freq <= 45000) /* DMG band lower limit */
308 /* see 802.11ax D6.1 27.3.23.2 */
309 return (freq - 5950) / 5;
310 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800311 return (freq - 56160) / 2160;
312 else
313 return 0;
314}
315
316static int initSock80211(Netlink* nl) {
317 nl->socket = nl_socket_alloc();
318 if (!nl->socket) {
319 fprintf(stderr, "Failing to allocate the sock\n");
320 return -ENOMEM;
321 }
322
323 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
324
325 if (genl_connect(nl->socket)) {
326 fprintf(stderr, "Failed to connect\n");
327 nl_close(nl->socket);
328 nl_socket_free(nl->socket);
329 return -ENOLINK;
330 }
331
332 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
333 if (nl->id< 0) {
334 fprintf(stderr, "interface not found.\n");
335 nl_close(nl->socket);
336 nl_socket_free(nl->socket);
337 return -ENOENT;
338 }
339
340 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
341 if ((!nl->cb)) {
342 fprintf(stderr, "Failed to allocate netlink callback.\n");
343 nl_close(nl->socket);
344 nl_socket_free(nl->socket);
345 return ENOMEM;
346 }
347
348 return nl->id;
349}
350
351static int nlfree(Netlink *nl)
352{
353 nl_cb_put(nl->cb);
354 nl_close(nl->socket);
355 nl_socket_free(nl->socket);
356 return 0;
357}
358
359static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
360 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
361 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
362 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
363};
364
365static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
366};
367
368static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
369};
370
371typedef struct _wifi_channelStats_loc {
372 INT array_size;
373 INT ch_number;
374 BOOL ch_in_pool;
375 INT ch_noise;
376 BOOL ch_radar_noise;
377 INT ch_max_80211_rssi;
378 INT ch_non_80211_noise;
379 INT ch_utilization;
380 ULLONG ch_utilization_total;
381 ULLONG ch_utilization_busy;
382 ULLONG ch_utilization_busy_tx;
383 ULLONG ch_utilization_busy_rx;
384 ULLONG ch_utilization_busy_self;
385 ULLONG ch_utilization_busy_ext;
386} wifi_channelStats_t_loc;
387
388typedef struct wifi_device_info {
389 INT wifi_devIndex;
390 UCHAR wifi_devMacAddress[6];
391 CHAR wifi_devIPAddress[64];
392 BOOL wifi_devAssociatedDeviceAuthentiationState;
393 INT wifi_devSignalStrength;
394 INT wifi_devTxRate;
395 INT wifi_devRxRate;
396} wifi_device_info_t;
397
398#endif
399
400//For 5g Alias Interfaces
401static BOOL priv_flag = TRUE;
402static BOOL pub_flag = TRUE;
403static BOOL Radio_flag = TRUE;
404//wifi_setApBeaconRate(1, beaconRate);
405
developer1e5aa162022-09-13 16:06:24 +0800406BOOL multiple_set = FALSE;
407
developer06a01d92022-09-07 16:32:39 +0800408struct params
409{
410 char * name;
411 char * value;
412};
413
414static int _syscmd(char *cmd, char *retBuf, int retBufSize)
415{
416 FILE *f;
417 char *ptr = retBuf;
418 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
419
420 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
421 if((f = popen(cmd, "r")) == NULL) {
422 fprintf(stderr,"\npopen %s error\n", cmd);
423 return RETURN_ERR;
424 }
425
426 while(!feof(f))
427 {
428 *ptr = 0;
429 if(bufSize>=128) {
430 bufbytes=128;
431 } else {
432 bufbytes=bufSize-1;
433 }
434
435 fgets(ptr,bufbytes,f);
436 readbytes=strlen(ptr);
437
438 if(!readbytes)
439 break;
440
441 bufSize-=readbytes;
442 ptr += readbytes;
443 }
444 cmd_ret = pclose(f);
445 retBuf[retBufSize-1]=0;
446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
447
448 return cmd_ret >> 8;
449}
450
developerc707e972022-09-13 15:38:02 +0800451wifi_band wifi_index_to_band(int apIndex)
452{
453 char cmd[128] = {0};
454 char buf[64] = {0};
455 int freq = 0;
developer5884e982022-10-06 10:52:50 +0800456 int i = 0;
developerc707e972022-09-13 15:38:02 +0800457 wifi_band band = band_invalid;
458
459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5884e982022-10-06 10:52:50 +0800460 while(i < 10){
461 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
462 _syscmd(cmd, buf, sizeof(buf));
463 freq = strtol(buf, NULL, 10);
464 if (freq > 2401 && freq < 2495)
465 band = band_2_4;
466 else if (freq > 5160 && freq < 5915)
467 band = band_5;
468 else if (freq > 5955 && freq < 7125)
469 band = band_6;
470
471 if(band != band_invalid)
472 break;
473
474 i++;
475 sleep(1);
476 }
developerc707e972022-09-13 15:38:02 +0800477
478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
479 return band;
480}
481
developer06a01d92022-09-07 16:32:39 +0800482static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
483{
484 char cmd[MAX_CMD_SIZE]={'\0'};
485 char buf[MAX_BUF_SIZE]={'\0'};
486 int ret = 0;
487
488 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
489 ret = _syscmd(cmd, buf, sizeof(buf));
490 if ((ret != 0) && (strlen(buf) == 0))
491 return -1;
492 snprintf(output, output_size, "%s", buf);
493
494 return 0;
495}
496
497static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
498{
499 char cmd[MAX_CMD_SIZE]={'\0'};
500 char buf[MAX_BUF_SIZE]={'\0'};
501
502 for(int i=0;i<item_count;i++)
503 {
504 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
505 if (strlen(buf) == 0) //Insert
506 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
507 else //Update
508 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 +0800509
developer06a01d92022-09-07 16:32:39 +0800510 if(_syscmd(cmd, buf, sizeof(buf)))
511 return -1;
512 }
513
514 return 0;
515}
516
517static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
518{
developer1e5aa162022-09-13 16:06:24 +0800519 if (multiple_set == TRUE)
520 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800521 char cmd[MAX_CMD_SIZE]="", output[32]="";
522 FILE *fp;
523 int i;
524 //NOTE RELOAD should be done in ApplySSIDSettings
525
526 for(i=0; i<item_count; i++, list++)
527 {
528 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
529 if((fp = popen(cmd, "r"))==NULL)
530 {
531 perror("popen failed");
532 return -1;
533 }
534 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
535 {
536 pclose(fp);
537 perror("fgets failed");
538 return -1;
539 }
540 pclose(fp);
541 }
542 return 0;
543}
544
545static int wifi_reloadAp(int apIndex)
546{
developer1e5aa162022-09-13 16:06:24 +0800547 if (multiple_set == TRUE)
548 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800549 char cmd[MAX_CMD_SIZE]="";
550 char buf[MAX_BUF_SIZE]="";
551
552 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
553 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
554 return RETURN_ERR;
555
556 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
557 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
558 return RETURN_ERR;
559
560 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
561 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
562 return RETURN_ERR;
563
564 return RETURN_OK;
565}
566
567
568//For Getting Current Interface Name from corresponding hostapd configuration
569void GetInterfaceName(char *interface_name, char *conf_file)
570{
571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
572 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
574}
575
576INT File_Reading(CHAR *file, char *Value)
577{
578 FILE *fp = NULL;
579 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
580 int count = 0;
581
582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
583 fp = popen(file,"r");
584 if(fp == NULL)
585 return RETURN_ERR;
586
587 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
588 {
589 for(count=0;buf[count]!='\n';count++)
590 copy_buf[count]=buf[count];
591 copy_buf[count]='\0';
592 }
593 strcpy(Value,copy_buf);
594 pclose(fp);
595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
596
597 return RETURN_OK;
598}
599
600void wifi_RestartHostapd_2G()
601{
602 int Public2GApIndex = 4;
603
604 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
605 wifi_setApEnable(Public2GApIndex, FALSE);
606 wifi_setApEnable(Public2GApIndex, TRUE);
607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
608}
609
610void wifi_RestartHostapd_5G()
611{
612 int Public5GApIndex = 5;
613
614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
615 wifi_setApEnable(Public5GApIndex, FALSE);
616 wifi_setApEnable(Public5GApIndex, TRUE);
617 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
618}
619
620void wifi_RestartPrivateWifi_2G()
621{
622 int PrivateApIndex = 0;
623
624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
625 wifi_setApEnable(PrivateApIndex, FALSE);
626 wifi_setApEnable(PrivateApIndex, TRUE);
627 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
628}
629
630void wifi_RestartPrivateWifi_5G()
631{
632 int Private5GApIndex = 1;
633
634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
635 wifi_setApEnable(Private5GApIndex, FALSE);
636 wifi_setApEnable(Private5GApIndex, TRUE);
637 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
638}
639
640static int writeBandWidth(int radioIndex,char *bw_value)
641{
642 char buf[MAX_BUF_SIZE];
643 char cmd[MAX_CMD_SIZE];
644
645 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
646 if(_syscmd(cmd, buf, sizeof(buf)))
647 {
648 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
649 _syscmd(cmd, buf, sizeof(buf));
650 return RETURN_OK;
651 }
652
653 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
654 _syscmd(cmd,buf,sizeof(buf));
655 return RETURN_OK;
656}
657
658static int readBandWidth(int radioIndex,char *bw_value)
659{
660 char buf[MAX_BUF_SIZE];
661 char cmd[MAX_CMD_SIZE];
662 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
663 _syscmd(cmd,buf,sizeof(buf));
664 if(NULL!=strstr(buf,"20MHz"))
665 {
666 strcpy(bw_value,"20MHz");
667 }
668 else if(NULL!=strstr(buf,"40MHz"))
669 {
670 strcpy(bw_value,"40MHz");
671 }
672 else if(NULL!=strstr(buf,"80MHz"))
673 {
674 strcpy(bw_value,"80MHz");
675 }
676 else
677 {
678 return RETURN_ERR;
679 }
680 return RETURN_OK;
681}
682
developer39a5efb2022-09-13 16:09:06 +0800683INT wifi_getMaxRadioNumber(INT *max_radio_num)
684{
685 char cmd[64] = {0};
686 char buf[4] = {0};
687
688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
689
690 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
691 _syscmd(cmd, buf, sizeof(buf));
692 *max_radio_num = strtoul(buf, NULL, 10);
693
694 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
695
696 return RETURN_OK;
697}
698
developer5f222492022-09-13 15:21:52 +0800699// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800700INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
701{
developer5f222492022-09-13 15:21:52 +0800702 struct params params={'\0'};
703 char config_file[MAX_BUF_SIZE] = {0};
704 char buf[MAX_BUF_SIZE] = {'\0'};
705
706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
707 if (strlen (beaconRate) < 5)
708 return RETURN_ERR;
709 // Copy the numeric value
710 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
711 buf[strlen(beaconRate) - 4] = '\0';
712
713 params.name = "beacon_rate";
714 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
715 if (strncmp(buf, "5.5", 3) == 0) {
716 snprintf(buf, sizeof(buf), "55");
717 params.value = buf;
718 } else {
719 strcat(buf, "0");
720 params.value = buf;
721 }
722
723 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
724 wifi_hostapdWrite(config_file, &params, 1);
725 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
727
728 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800729}
730
731INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
732{
developer5f222492022-09-13 15:21:52 +0800733 char config_file[MAX_BUF_SIZE] = {'\0'};
734 char temp_output[MAX_BUF_SIZE] = {'\0'};
735 char buf[MAX_BUF_SIZE] = {'\0'};
736 float rate = 0;
737
738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
739 if (NULL == beaconRate)
740 return RETURN_ERR;
741
742 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
743 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
744 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
745 if(strlen(buf) > 0) {
746 rate = atof(buf)/10;
747 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
748 } else {
749 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
750 }
751 strncpy(beaconRate, temp_output, sizeof(temp_output));
752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
753
754 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800755}
756
757INT wifi_setLED(INT radioIndex, BOOL enable)
758{
759 return 0;
760}
761INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
762{
763 return RETURN_OK;
764}
765/**********************************************************************************
766 *
767 * Wifi Subsystem level function prototypes
768 *
769**********************************************************************************/
770//---------------------------------------------------------------------------------------------------
771//Wifi system api
772//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
773INT wifi_getHalVersion(CHAR *output_string) //RDKB
774{
775 if(!output_string)
776 return RETURN_ERR;
777 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
778
779 return RETURN_OK;
780}
781
782
783/* wifi_factoryReset() function */
784/**
785* @description Clears internal variables to implement a factory reset of the Wi-Fi
786* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
787*
788* @param None
789*
790* @return The status of the operation.
791* @retval RETURN_OK if successful.
792* @retval RETURN_ERR if any error is detected
793*
794* @execution Synchronous
795* @sideeffect None
796*
797* @note This function must not suspend and must not invoke any blocking system
798* calls. It should probably just send a message to a driver event handler task.
799*
800*/
801INT wifi_factoryReset()
802{
803 char cmd[128];
804
805 /*delete running hostapd conf files*/
806 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
807 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
808 system(cmd);
809 system("systemctl restart hostapd.service");
810
811 return RETURN_OK;
812}
813
814/* wifi_factoryResetRadios() function */
815/**
816* @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.
817*
818* @param None
819* @return The status of the operation
820* @retval RETURN_OK if successful
821* @retval RETURN_ERR if any error is detected
822*
823* @execution Synchronous
824*
825* @sideeffect None
826*
827* @note This function must not suspend and must not invoke any blocking system
828* calls. It should probably just send a message to a driver event handler task.
829*
830*/
831INT wifi_factoryResetRadios()
832{
833 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
834 return RETURN_OK;
835
836 return RETURN_ERR;
837}
838
839
840/* wifi_factoryResetRadio() function */
841/**
842* @description Restore selected radio parameters without touching access point parameters
843*
844* @param radioIndex - Index of Wi-Fi Radio channel
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_factoryResetRadio(int radioIndex) //RDKB
858{
developer5ff7f5f2022-09-13 15:12:16 +0800859 system("systemctl stop hostapd.service");
860
developer06a01d92022-09-07 16:32:39 +0800861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
862 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800863 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800864 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800865 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800866 else
867 return RETURN_ERR;
868
developer5ff7f5f2022-09-13 15:12:16 +0800869 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
871 return RETURN_OK;
872}
873
874/* wifi_initRadio() function */
875/**
876* Description: This function call initializes the specified radio.
877* Implementation specifics may dictate the functionality since
878* different hardware implementations may have different initilization requirements.
879* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
880*
881* @return The status of the operation.
882* @retval RETURN_OK if successful.
883* @retval RETURN_ERR if any error is detected
884*
885* @execution Synchronous.
886* @sideeffect None.
887*
888* @note This function must not suspend and must not invoke any blocking system
889* calls. It should probably just send a message to a driver event handler task.
890*
891*/
892INT wifi_initRadio(INT radioIndex)
893{
894 //TODO: Initializes the wifi subsystem (for specified radio)
895 return RETURN_OK;
896}
897void macfilter_init()
898{
899 char count[4]={'\0'};
900 char buf[253]={'\0'};
901 char tmp[19]={'\0'};
902 int dev_count,block,mac_entry=0;
903 char res[4]={'\0'};
904 char acl_file_path[64] = {'\0'};
905 FILE *fp = NULL;
906 int index=0;
907 char iface[10]={'\0'};
908 char config_file[MAX_BUF_SIZE] = {0};
909
910
911 sprintf(acl_file_path,"/tmp/mac_filter.sh");
912
913 fp=fopen(acl_file_path,"w+");
914 sprintf(buf,"#!/bin/sh \n");
915 fprintf(fp,"%s\n",buf);
916
917 system("chmod 0777 /tmp/mac_filter.sh");
918
919 for(index=0;index<=1;index++)
920 {
921 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
922 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
923 sprintf(buf,"syscfg get %dcountfilter",index);
924 _syscmd(buf,count,sizeof(count));
925 mac_entry=atoi(count);
926
927 sprintf(buf,"syscfg get %dblockall",index);
928 _syscmd(buf,res,sizeof(res));
929 block = atoi(res);
930
931 //Allow only those macs mentioned in ACL
932 if(block==1)
933 {
934 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
935 fprintf(fp,"%s\n",buf);
936 for(dev_count=1;dev_count<=mac_entry;dev_count++)
937 {
938 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
939 _syscmd(buf,tmp,sizeof(tmp));
940 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
941 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
942 fprintf(fp,"%s\n",buf);
943 }
944 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
945 fprintf(fp,"%s\n",buf);
946 }
947
948 //Block all the macs mentioned in ACL
949 else if(block==2)
950 {
951 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
952 fprintf(fp,"%s\n",buf);
953
954 for(dev_count=1;dev_count<=mac_entry;dev_count++)
955 {
956 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
957 _syscmd(buf,tmp,sizeof(tmp));
958 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
959 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
960 fprintf(fp,"%s\n",buf);
961 }
962 }
963 }
964 fclose(fp);
965}
966
967// Initializes the wifi subsystem (all radios)
968INT wifi_init() //RDKB
969{
970 char interface[MAX_BUF_SIZE]={'\0'};
971 char bridge_name[MAX_BUF_SIZE]={'\0'};
972 INT len=0;
973
974 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
975 //Not intitializing macfilter for Turris-Omnia Platform for now
976 //macfilter_init();
977
978 system("/usr/sbin/iw reg set US");
979 system("systemctl start hostapd.service");
980 sleep(2);//sleep to wait for hostapd to start
981
982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
983
984 return RETURN_OK;
985}
986
987/* wifi_reset() function */
988/**
989* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
990* Implementation specifics may dictate what is actualy reset since
991* different hardware implementations may have different requirements.
992* Parameters : None
993*
994* @return The status of the operation.
995* @retval RETURN_OK if successful.
996* @retval RETURN_ERR if any error is detected
997*
998* @execution Synchronous.
999* @sideeffect None.
1000*
1001* @note This function must not suspend and must not invoke any blocking system
1002* calls. It should probably just send a message to a driver event handler task.
1003*
1004*/
1005INT wifi_reset()
1006{
1007 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001008 system("systemctl stop hostapd.service");
1009 sleep(2);
1010 system("systemctl start hostapd.service");
1011 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001012 return RETURN_OK;
1013}
1014
1015/* wifi_down() function */
1016/**
1017* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1018* Implementation specifics may dictate some functionality since
1019* different hardware implementations may have different requirements.
1020*
1021* @param None
1022*
1023* @return The status of the operation
1024* @retval RETURN_OK if successful
1025* @retval RETURN_ERR if any error is detected
1026*
1027* @execution Synchronous
1028* @sideeffect None
1029*
1030* @note This function must not suspend and must not invoke any blocking system
1031* calls. It should probably just send a message to a driver event handler task.
1032*
1033*/
1034INT wifi_down()
1035{
1036 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001037 system("systemctl stop hostapd.service");
1038 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001039 return RETURN_OK;
1040}
1041
1042
1043/* wifi_createInitialConfigFiles() function */
1044/**
1045* @description This function creates wifi configuration files. The format
1046* and content of these files are implementation dependent. This function call is
1047* used to trigger this task if necessary. Some implementations may not need this
1048* function. If an implementation does not need to create config files the function call can
1049* do nothing and return RETURN_OK.
1050*
1051* @param None
1052*
1053* @return The status of the operation
1054* @retval RETURN_OK if successful
1055* @retval RETURN_ERR if any error is detected
1056*
1057* @execution Synchronous
1058* @sideeffect None
1059*
1060* @note This function must not suspend and must not invoke any blocking system
1061* calls. It should probably just send a message to a driver event handler task.
1062*
1063*/
1064INT wifi_createInitialConfigFiles()
1065{
1066 //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)
1067 return RETURN_OK;
1068}
1069
1070// outputs the country code to a max 64 character string
1071INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1072{
developer7543b3b2022-09-13 13:47:17 +08001073 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1074 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001075 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001076
1077 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1078 _syscmd(cmd, buf, sizeof(buf));
1079 if(strlen(buf) > 0)
1080 snprintf(output_string, 64, "%s", buf);
1081 else
1082 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001083
1084 return RETURN_OK;
1085}
1086
1087INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1088{
1089 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001090 char str[MAX_BUF_SIZE]={'\0'};
1091 char cmd[MAX_CMD_SIZE]={'\0'};
1092 struct params params;
1093 char config_file[MAX_BUF_SIZE] = {0};
1094
1095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1096 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1097 return RETURN_ERR;
1098
developerb86c6f32022-10-07 14:34:58 +08001099 if (strlen(CountryCode) == 0)
1100 strcpy(CountryCode, "US");
1101
developer7543b3b2022-09-13 13:47:17 +08001102 params.name = "country_code";
1103 params.value = CountryCode;
1104 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1105 int ret = wifi_hostapdWrite(config_file, &params, 1);
1106 if (ret) {
1107 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1108 ,__func__, ret);
1109 }
1110
1111 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1112 if (ret) {
1113 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1114 ,__func__, ret);
1115 }
1116 wifi_reloadAp(radioIndex);
1117 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1118
developer06a01d92022-09-07 16:32:39 +08001119 return RETURN_OK;
1120}
1121
developera748dcf2022-09-13 15:56:48 +08001122INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1123{
1124 char channel_util_file[64] = {0};
1125 char cmd[128] = {0};
1126 char buf[128] = {0};
1127 char line[128] = {0};
1128 char *param = NULL, *value = NULL;
1129 int read = 0;
1130 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1131 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1132 size_t len = 0;
1133 FILE *f = NULL;
1134
1135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1136
1137 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1138 _syscmd(cmd, buf, sizeof(buf));
1139 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1140
1141 memset(cmd, 0, sizeof(cmd));
1142 memset(buf, 0, sizeof(buf));
1143 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1144 if ((f = popen(cmd, "r")) == NULL) {
1145 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1146 return RETURN_ERR;
1147 }
1148
1149 read = getline(&line, &len, f);
1150 while (read != -1) {
1151 param = strtok(line, ":\t");
1152 value = strtok(NULL, " ");
1153 if(strstr(param, "frequency") != NULL) {
1154 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1155 }
1156 if(strstr(param, "noise") != NULL) {
1157 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1158 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1159 }
1160 if(strstr(param, "channel active time") != NULL) {
1161 ActiveTime = strtol(value, NULL, 10);
1162 }
1163 if(strstr(param, "channel busy time") != NULL) {
1164 BusyTime = strtol(value, NULL, 10);
1165 }
1166 if(strstr(param, "channel transmit time") != NULL) {
1167 TransmitTime = strtol(value, NULL, 10);
1168 }
1169 read = getline(&line, &len, f);
1170 }
1171 pclose(f);
1172
1173 // The file should store the last active, busy and transmit time
1174 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1175 f = fopen(channel_util_file, "r");
1176 if (f != NULL) {
1177 read = getline(&line, &len, f);
1178 preActiveTime = strtol(line, NULL, 10);
1179 read = getline(&line, &len, f);
1180 preBusyTime = strtol(line, NULL, 10);
1181 read = getline(&line, &len, f);
1182 preTransmitTime = strtol(line, NULL, 10);
1183 fclose(f);
1184 }
1185
1186 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1187 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1188
1189 f = fopen(channel_util_file, "w");
1190 if (f != NULL) {
1191 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1192 fclose(f);
1193 }
1194 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1195 return RETURN_OK;
1196}
1197
developer06a01d92022-09-07 16:32:39 +08001198/**********************************************************************************
1199 *
1200 * Wifi radio level function prototypes
1201 *
1202**********************************************************************************/
1203
1204//Get the total number of radios in this wifi subsystem
1205INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1206{
1207 if (NULL == output)
1208 return RETURN_ERR;
1209 *output = 2;
1210
1211 return RETURN_OK;
1212}
1213
1214//Get the total number of SSID entries in this wifi subsystem
1215INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1216{
1217 if (NULL == output)
1218 return RETURN_ERR;
1219 *output = MAX_APS;
1220
1221 return RETURN_OK;
1222}
1223
1224//Get the Radio enable config parameter
1225INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1226{
1227 char interface_path[MAX_CMD_SIZE] = {0};
1228 FILE *fp = NULL;
1229
1230 if (NULL == output_bool)
1231 return RETURN_ERR;
1232
1233 *output_bool = FALSE;
1234 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1235 return RETURN_ERR;
1236
1237 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1238 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001239 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001240 {
developercf48e482022-09-13 14:49:50 +08001241 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001242 }
1243 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001244 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1245 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1246 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001247
developercf48e482022-09-13 14:49:50 +08001248 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1249 *output_bool = TRUE;
1250 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001251 return RETURN_OK;
1252}
1253
1254INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1255{
1256 char cmd[MAX_CMD_SIZE] = {0};
1257 char buf[MAX_CMD_SIZE] = {0};
1258 int apIndex, ret;
1259 FILE *fp = NULL;
1260
1261 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1262 if(enable==FALSE)
1263 {
1264 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1265 {
1266 //Detaching %s%d from hostapd daemon
1267 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1268 _syscmd(cmd, buf, sizeof(buf));
1269 if(strncmp(buf, "OK", 2))
1270 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1271 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1272 _syscmd(cmd, buf, sizeof(buf));
1273 }
developer456aa3e2022-09-13 14:27:36 +08001274 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001275 _syscmd(cmd, buf, sizeof(buf));
1276 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001277 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001278 }
1279 else
1280 {
developer456aa3e2022-09-13 14:27:36 +08001281 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001282 _syscmd(cmd, buf, sizeof(buf));
1283 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001284 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001285 sleep(1);
1286 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1287 {
1288 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1289 fp = fopen(cmd, "r");
1290 if(!fp)
1291 {
1292 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1293 _syscmd(cmd, buf, sizeof(buf));
1294 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1295 _syscmd(cmd, buf, sizeof(buf));
1296 }
1297 if(fp)
1298 fclose(fp);
1299 }
1300 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1301 {
1302 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1303 ret = _syscmd(cmd, buf, sizeof(buf));
1304 if ( ret == RETURN_ERR)
1305 {
1306 fprintf(stderr, "VAP interface creation failed\n");
1307 continue;
1308 }
1309 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1310 _syscmd(cmd, buf, sizeof(buf));
1311 if(*buf == '1')
1312 {
1313 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1314 radioIndex, apIndex);
1315 _syscmd(cmd, buf, sizeof(buf));
1316 if(strncmp(buf, "OK", 2))
1317 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1318 }
1319 }
1320 }
1321
1322 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1323 return RETURN_OK;
1324}
1325
1326//Get the Radio enable status
1327INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1328{
1329 if (NULL == output_bool)
1330 return RETURN_ERR;
1331
1332 return wifi_getRadioEnable(radioIndex, output_bool);
1333}
1334
1335//Get the Radio Interface name from platform, eg "wlan0"
1336INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1337{
1338 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1339 return RETURN_ERR;
1340 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1341
1342 return RETURN_OK;
1343}
1344
1345//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1346//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.
1347INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1348{
developerbcc556a2022-09-22 20:02:45 +08001349 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1350 // For max bit rate, we should always choose the best MCS
1351 char mode[64] = {0};
1352 char channel_bandwidth_str[16] = {0};
1353 char *tmp = NULL;
1354 UINT mode_map = 0;
1355 UINT num_subcarrier = 0;
1356 UINT code_bits = 0;
1357 float code_rate = 0; // use max code rate
1358 int NSS = 0;
1359 UINT Symbol_duration = 0;
1360 UINT GI_duration = 0;
1361 wifi_band band = band_invalid;
1362 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1363 BOOL enable = FALSE;
1364 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001365
1366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1367 if (NULL == output_string)
1368 return RETURN_ERR;
1369
developerbcc556a2022-09-22 20:02:45 +08001370 wifi_getRadioEnable(radioIndex, &enable);
1371 if (enable == FALSE) {
1372 snprintf(output_string, 64, "0 Mb/s");
1373 return RETURN_OK;
1374 }
1375
1376 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1377 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1378 return RETURN_ERR;
1379 }
1380
1381 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1382 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1383 return RETURN_ERR;
1384 }
1385
1386 if (gi == wifi_guard_interval_3200)
1387 GI_duration = 32;
1388 else if (gi == wifi_guard_interval_1600)
1389 GI_duration = 16;
1390 else if (gi == wifi_guard_interval_800)
1391 GI_duration = 8;
1392 else // auto, 400
1393 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001394
developerbcc556a2022-09-22 20:02:45 +08001395 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1396 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1397 return RETURN_ERR;
1398 }
1399
1400 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1401 strcpy(channel_bandwidth_str, "160");
1402
1403 if (mode_map & WIFI_MODE_AX) {
1404 if (strstr(channel_bandwidth_str, "160") != NULL)
1405 num_subcarrier = 1960;
1406 else if (strstr(channel_bandwidth_str, "80") != NULL)
1407 num_subcarrier = 980;
1408 else if (strstr(channel_bandwidth_str, "40") != NULL)
1409 num_subcarrier = 468;
1410 else if (strstr(channel_bandwidth_str, "20") != NULL)
1411 num_subcarrier = 234;
1412 code_bits = 10;
1413 code_rate = (float)5/6;
1414 Symbol_duration = 128;
1415 } else if (mode_map & WIFI_MODE_AC) {
1416 if (strstr(channel_bandwidth_str, "160") != NULL)
1417 num_subcarrier = 468;
1418 else if (strstr(channel_bandwidth_str, "80") != NULL)
1419 num_subcarrier = 234;
1420 else if (strstr(channel_bandwidth_str, "40") != NULL)
1421 num_subcarrier = 108;
1422 else if (strstr(channel_bandwidth_str, "20") != NULL)
1423 num_subcarrier = 52;
1424 code_bits = 8;
1425 code_rate = (float)5/6;
1426 Symbol_duration = 32;
1427 } else if (mode_map & WIFI_MODE_N) {
1428 if (strstr(channel_bandwidth_str, "160") != NULL)
1429 num_subcarrier = 468;
1430 else if (strstr(channel_bandwidth_str, "80") != NULL)
1431 num_subcarrier = 234;
1432 else if (strstr(channel_bandwidth_str, "40") != NULL)
1433 num_subcarrier = 108;
1434 else if (strstr(channel_bandwidth_str, "20") != NULL)
1435 num_subcarrier = 52;
1436 code_bits = 6;
1437 code_rate = (float)3/4;
1438 Symbol_duration = 32;
1439 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1440 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1441 snprintf(output_string, 64, "65 Mb/s");
1442 return RETURN_OK;
1443 } else {
1444 snprintf(output_string, 64, "0 Mb/s");
1445 return RETURN_OK;
1446 }
developer06a01d92022-09-07 16:32:39 +08001447
developerbcc556a2022-09-22 20:02:45 +08001448 // Spatial streams
1449 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1450 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1451 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001452 }
developerbcc556a2022-09-22 20:02:45 +08001453
1454 // multiple 10 is to align duration unit (0.1 us)
1455 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1456 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1457
developer06a01d92022-09-07 16:32:39 +08001458 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1459
1460 return RETURN_OK;
1461}
1462#if 0
1463INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1464{
1465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1466 char cmd[64];
1467 char buf[1024];
1468 int apIndex;
1469
1470 if (NULL == output_string)
1471 return RETURN_ERR;
1472
1473 apIndex=(radioIndex==0)?0:1;
1474
1475 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1476 _syscmd(cmd,buf, sizeof(buf));
1477
1478 snprintf(output_string, 64, "%s", buf);
1479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1480 return RETURN_OK;
1481}
1482#endif
1483
1484
1485//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1486//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.
1487INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1488{
developer963da0c2022-09-13 15:58:27 +08001489 wifi_band band = band_invalid;
1490
developer06a01d92022-09-07 16:32:39 +08001491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1492 if (NULL == output_string)
1493 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001494
1495 band = wifi_index_to_band(radioIndex);
1496
1497 memset(output_string, 0, 10);
1498 if (band == band_2_4)
1499 strcpy(output_string, "2.4GHz");
1500 else if (band == band_5)
1501 strcpy(output_string, "5GHz");
1502 else if (band == band_6)
1503 strcpy(output_string, "6GHz");
1504 else
1505 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1507
1508 return RETURN_OK;
1509#if 0
1510 char buf[MAX_BUF_SIZE]={'\0'};
1511 char str[MAX_BUF_SIZE]={'\0'};
1512 char cmd[MAX_CMD_SIZE]={'\0'};
1513 char *ch=NULL;
1514 char *ch2=NULL;
1515
1516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1517 if (NULL == output_string)
1518 return RETURN_ERR;
1519
1520
1521 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1522
1523 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1524 {
1525 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1526 return RETURN_ERR;
1527 }
1528 ch=strchr(buf,'\n');
1529 *ch='\0';
1530 ch=strchr(buf,'=');
1531 if(ch==NULL)
1532 return RETURN_ERR;
1533
1534
1535 ch++;
1536
1537 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1538 strcpy(buf,"0");
1539 if(strlen(ch) == 1)
1540 ch=strcat(buf,ch);
1541
1542
1543 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1544
1545 if(_syscmd(cmd,str,64) == RETURN_ERR)
1546 {
1547 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1548 return RETURN_ERR;
1549 }
1550
1551
1552 ch2=strchr(str,'\n');
1553 //replace \n with \0
1554 *ch2='\0';
1555 ch2=strchr(str,'=');
1556 if(ch2==NULL)
1557 {
1558 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1559 return RETURN_ERR;
1560 }
1561 else
1562 wifi_dbg_printf("%s",ch2+1);
1563
1564
1565 ch2++;
1566
1567
1568 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1569
1570 memset(buf,'\0',sizeof(buf));
1571 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1572 {
1573 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1574 return RETURN_ERR;
1575 }
1576 if (strstr(buf,"2.4") != NULL )
1577 strcpy(output_string,"2.4GHz");
1578 else if(strstr(buf,"5.") != NULL )
1579 strcpy(output_string,"5GHz");
1580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1581
1582 return RETURN_OK;
1583#endif
1584}
1585
1586//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1587//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.
1588INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1589{
1590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1591 if (NULL == output_string)
1592 return RETURN_ERR;
1593 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1594 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1595
1596 return RETURN_OK;
1597#if 0
1598 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1599 char buf[MAX_BUF_SIZE]={'\0'};
1600 char str[MAX_BUF_SIZE]={'\0'};
1601 char cmd[MAX_CMD_SIZE]={'\0'};
1602 char *ch=NULL;
1603 char *ch2=NULL;
1604 char ch1[5]="0";
1605
1606 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1607
1608 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1609 {
1610 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1611 return RETURN_ERR;
1612 }
1613
1614 ch=strchr(buf,'\n');
1615 *ch='\0';
1616 ch=strchr(buf,'=');
1617 if(ch==NULL)
1618 return RETURN_ERR;
1619 ch++;
1620
1621 if(strlen(ch)==1)
1622 {
1623 strcat(ch1,ch);
1624
1625 }
1626 else
1627 {
1628 strcpy(ch1,ch);
1629 }
1630
1631
1632
1633 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1634 if(_syscmd(cmd,str,64) == RETURN_ERR)
1635 {
1636 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1637 return RETURN_ERR;
1638 }
1639
1640
1641 ch2=strchr(str,'\n');
1642 //replace \n with \0
1643 *ch2='\0';
1644 ch2=strchr(str,'=');
1645 if(ch2==NULL)
1646 {
1647 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1648 return RETURN_ERR;
1649 }
1650 else
1651 wifi_dbg_printf("%s",ch2+1);
1652 ch2++;
1653
1654
1655 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1656 memset(buf,'\0',sizeof(buf));
1657 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1658 {
1659 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1660 return RETURN_ERR;
1661 }
1662
1663
1664 if(strstr(buf,"2.4")!=NULL)
1665 {
1666 strcpy(output_string,"2.4GHz");
1667 }
1668 if(strstr(buf,"5.")!=NULL)
1669 {
1670 strcpy(output_string,"5GHz");
1671 }
1672 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1673 return RETURN_OK;
1674#endif
1675}
1676
1677//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1678//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.
1679INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1680{
developer963da0c2022-09-13 15:58:27 +08001681 char cmd[128]={0};
1682 char buf[128]={0};
1683 char temp_output[128] = {0};
1684 wifi_band band;
1685
1686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001687 if (NULL == output_string)
1688 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001689
1690 band = wifi_index_to_band(radioIndex);
1691 if (band == band_2_4) {
1692 strcat(temp_output, "b,g,");
1693 } else if (band == band_5) {
1694 strcat(temp_output, "a,");
1695 }
1696
1697 // ht capabilities
1698 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
1699 _syscmd(cmd, buf, sizeof(buf));
1700 if (strncmp(buf, "0x00", 4) != 0) {
1701 strcat(temp_output, "n,");
1702 }
developer06a01d92022-09-07 16:32:39 +08001703
developer963da0c2022-09-13 15:58:27 +08001704 // vht capabilities
1705 if (band == band_5) {
1706 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1707 _syscmd(cmd, buf, sizeof(buf));
1708 if (strncmp(buf, "0x00000000", 10) != 0) {
1709 strcat(temp_output, "ac,");
1710 }
1711 }
1712
1713 // he capabilities
1714 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'", radioIndex);
1715 _syscmd(cmd, buf, sizeof(buf));
1716 if (strncmp (buf, "0x0000", 6) != 0) {
1717 strcat(temp_output, "ax,");
1718 }
1719
1720 // Remove the last comma
1721 if (strlen(temp_output) != 0)
1722 temp_output[strlen(temp_output)-1] = '\0';
1723 strncpy(output_string, temp_output, strlen(temp_output));
1724 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001725 return RETURN_OK;
1726}
1727
1728//Get the radio operating mode, and pure mode flag. eg: "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_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1731{
1732 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1733 if (NULL == output_string)
1734 return RETURN_ERR;
1735
1736 if (radioIndex == 0) {
1737 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1738 *gOnly = FALSE;
1739 *nOnly = TRUE;
1740 *acOnly = FALSE;
1741 } else {
1742 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1743 *gOnly = FALSE;
1744 *nOnly = FALSE;
1745 *acOnly = FALSE;
1746 }
1747 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1748
1749 return RETURN_OK;
1750#if 0
1751 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1752 char buf[64] = {0};
1753 char config_file[MAX_BUF_SIZE] = {0};
1754
1755 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1756 return RETURN_ERR;
1757
1758 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1759 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1760
1761 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1762 if (strlen(buf) == 0)
1763 {
1764 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1765 return RETURN_ERR;
1766 }
1767 if(strcmp(buf,"g")==0)
1768 {
1769 wifi_dbg_printf("\nG\n");
1770 *gOnly=TRUE;
1771 *nOnly=FALSE;
1772 *acOnly=FALSE;
1773 }
1774 else if(strcmp(buf,"n")==0)
1775 {
1776 wifi_dbg_printf("\nN\n");
1777 *gOnly=FALSE;
1778 *nOnly=TRUE;
1779 *acOnly=FALSE;
1780 }
1781 else if(strcmp(buf,"ac")==0)
1782 {
1783 wifi_dbg_printf("\nac\n");
1784 *gOnly=FALSE;
1785 *nOnly=FALSE;
1786 *acOnly=TRUE;
1787 }
1788 /* hostapd-5G.conf has "a" as hw_mode */
1789 else if(strcmp(buf,"a")==0)
1790 {
1791 wifi_dbg_printf("\na\n");
1792 *gOnly=FALSE;
1793 *nOnly=FALSE;
1794 *acOnly=FALSE;
1795 }
1796 else
1797 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1798
1799 //for a,n mode
1800 if(radioIndex == 1)
1801 {
1802 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1803 if(strcmp(buf,"1")==0)
1804 {
1805 strncpy(output_string, "n", 1);
1806 *nOnly=FALSE;
1807 }
1808 }
1809
1810 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1812 return RETURN_OK;
1813#endif
1814}
1815
developerdb744382022-09-13 15:34:54 +08001816INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1817{
1818 char cmd[128] = {0};
1819 char buf[64] = {0};
1820 char config_file[64] = {0};
1821 wifi_band band;
1822
1823 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1824 if(NULL == output_string || NULL == pureMode)
1825 return RETURN_ERR;
1826
1827 // grep all of the ieee80211 protocol config set to 1
1828 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1829 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1830 _syscmd(cmd, buf, sizeof(buf));
1831
1832 band = wifi_index_to_band(radioIndex);
1833 // puremode is a bit map
1834 *pureMode = 0;
1835 if (band == band_2_4) {
1836 strcat(output_string, "b,g");
1837 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1838 if (strstr(buf, "n") != NULL) {
1839 strcat(output_string, ",n");
1840 *pureMode |= WIFI_MODE_N;
1841 }
1842 if (strstr(buf, "ax") != NULL) {
1843 strcat(output_string, ",ax");
1844 *pureMode |= WIFI_MODE_AX;
1845 }
1846 } else if (band == band_5) {
1847 strcat(output_string, "a");
1848 *pureMode |= WIFI_MODE_A;
1849 if (strstr(buf, "n") != NULL) {
1850 strcat(output_string, ",n");
1851 *pureMode |= WIFI_MODE_N;
1852 }
1853 if (strstr(buf, "ac") != NULL) {
1854 strcat(output_string, ",ac");
1855 *pureMode |= WIFI_MODE_AC;
1856 }
1857 if (strstr(buf, "ax") != NULL) {
1858 strcat(output_string, ",ax");
1859 *pureMode |= WIFI_MODE_AX;
1860 }
1861 } else if (band == band_6) {
1862 if (strstr(buf, "ax") != NULL) {
1863 strcat(output_string, "ax");
1864 *pureMode |= WIFI_MODE_AX;
1865 }
1866 }
1867
1868 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1869 return RETURN_OK;
1870}
1871
1872// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001873INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1874{
1875 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1876 if (strcmp (channelMode,"11A") == 0)
1877 {
1878 writeBandWidth(radioIndex,"20MHz");
1879 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1880 printf("\nChannel Mode is 802.11a (5GHz)\n");
1881 }
1882 else if (strcmp (channelMode,"11NAHT20") == 0)
1883 {
1884 writeBandWidth(radioIndex,"20MHz");
1885 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1886 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1887 }
1888 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1889 {
1890 writeBandWidth(radioIndex,"40MHz");
1891 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1892 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1893 }
1894 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1895 {
1896 writeBandWidth(radioIndex,"40MHz");
1897 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1898 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1899 }
1900 else if (strcmp (channelMode,"11ACVHT20") == 0)
1901 {
1902 writeBandWidth(radioIndex,"20MHz");
1903 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1904 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1905 }
1906 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1907 {
1908 writeBandWidth(radioIndex,"40MHz");
1909 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1910 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1911 }
1912 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1913 {
1914 writeBandWidth(radioIndex,"40MHz");
1915 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1916 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1917 }
1918 else if (strcmp (channelMode,"11ACVHT80") == 0)
1919 {
1920 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1921 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1922 }
1923 else if (strcmp (channelMode,"11ACVHT160") == 0)
1924 {
1925 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1926 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1927 }
1928 else if (strcmp (channelMode,"11B") == 0)
1929 {
1930 writeBandWidth(radioIndex,"20MHz");
1931 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1932 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1933 }
1934 else if (strcmp (channelMode,"11G") == 0)
1935 {
1936 writeBandWidth(radioIndex,"20MHz");
1937 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1938 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1939 }
1940 else if (strcmp (channelMode,"11NGHT20") == 0)
1941 {
1942 writeBandWidth(radioIndex,"20MHz");
1943 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1944 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1945 }
1946 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1947 {
1948 writeBandWidth(radioIndex,"40MHz");
1949 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1950 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1951 }
1952 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1953 {
1954 writeBandWidth(radioIndex,"40MHz");
1955 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1956 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1957 }
1958 else
1959 {
1960 return RETURN_ERR;
1961 }
1962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1963
1964 return RETURN_OK;
1965}
1966
developerdb744382022-09-13 15:34:54 +08001967// Set the radio operating mode, and pure mode flag.
1968INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1969{
1970 int num_hostapd_support_mode = 3; // n, ac, ax
1971 struct params list[num_hostapd_support_mode];
1972 char config_file[64] = {0};
1973 char bandwidth[16] = {0};
1974 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08001975
developerdb744382022-09-13 15:34:54 +08001976
1977 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1978 // Set radio mode
1979 list[0].name = "ieee80211n";
1980 list[1].name = "ieee80211ac";
1981 list[2].name = "ieee80211ax";
1982 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1983
1984 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08001985 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08001986 list[0].value = "1";
1987 else
1988 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08001989 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08001990 list[1].value = "1";
1991 else
1992 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08001993 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08001994 list[2].value = "1";
1995 else
1996 list[2].value = "0";
1997 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1998
1999 if (channelMode == NULL || strlen(channelMode) == 0)
2000 return RETURN_OK;
2001 // Set bandwidth
2002 if (strstr(channelMode, "40") != NULL)
2003 strcpy(bandwidth, "40MHz");
2004 else if (strstr(channelMode, "80") != NULL)
2005 strcpy(bandwidth, "80MHz");
2006 else if (strstr(channelMode, "160") != NULL)
2007 strcpy(bandwidth, "160MHz");
2008 else // 11A, 11B, 11G....
2009 strcpy(bandwidth, "20MHz");
2010
2011 writeBandWidth(radioIndex, bandwidth);
2012 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2013
2014 wifi_reloadAp(radioIndex);
2015 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2016
2017 return RETURN_OK;
2018}
2019
developer1d12ebf2022-10-04 15:13:38 +08002020INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2021
2022 char config_file[64] = {0};
2023 struct params params = {0};
2024 wifi_band band = band_invalid;
2025
2026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2027
2028 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002029
2030 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002031 return RETURN_ERR;
2032 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2033 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002034 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2035 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002036
2037 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2038 params.name = "hw_mode";
2039 params.value = hw_mode;
2040 wifi_hostapdWrite(config_file, &params, 1);
2041 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2042
2043 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2044 return RETURN_OK;
2045}
2046
developer06a01d92022-09-07 16:32:39 +08002047//Get the list of supported channel. eg: "1-11"
2048//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.
2049INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2050{
developer6318ed52022-09-13 15:17:58 +08002051 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002052 if (NULL == output_string)
2053 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002054 char cmd[256] = {0};
2055 char buf[128] = {0};
2056 BOOL dfs_enable = false;
2057 // Parse possible channel number and separate them with commas.
2058 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer76989232022-10-04 14:13:19 +08002059 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002060 if (dfs_enable)
developer76989232022-10-04 14:13:19 +08002061 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/.$//'", radioIndex);
developer6318ed52022-09-13 15:17:58 +08002062 else
developer76989232022-10-04 14:13:19 +08002063 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/.$//'", radioIndex);
developer6318ed52022-09-13 15:17:58 +08002064
2065 _syscmd(cmd,buf,sizeof(buf));
2066 strncpy(output_string, buf, sizeof(buf));
2067
2068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2069 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002070}
2071
2072//Get the list for used channel. eg: "1,6,9,11"
2073//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.
2074INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2075{
developerf5745ee2022-10-05 16:09:53 +08002076 char cmd[128] = {0};
2077 char buf[128] = {0};
2078 char config_file[64] = {0};
2079 int channel = 0;
2080 int freq = 0;
2081 int bandwidth = 0;
2082 int center_freq = 0;
2083 int center_channel = 0;
2084 int channel_delta = 0;
2085 wifi_band band = band_invalid;
2086
2087 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2088
developer06a01d92022-09-07 16:32:39 +08002089 if (NULL == output_string)
2090 return RETURN_ERR;
2091
developerf5745ee2022-10-05 16:09:53 +08002092 sprintf(cmd, "iw %s%d info | grep channel | sed -e 's/[^0-9 ]//g'", AP_PREFIX, radioIndex);
2093 _syscmd(cmd, buf, sizeof(buf));
2094 if (strlen(buf) == 0) {
2095 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2096 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002097 }
developerf5745ee2022-10-05 16:09:53 +08002098 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2099
2100 if (bandwidth == 20) {
2101 snprintf(output_string, 256, "%d", channel);
2102 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002103 }
developerf5745ee2022-10-05 16:09:53 +08002104
2105 center_channel = ieee80211_frequency_to_channel(center_freq);
2106
2107 band = wifi_index_to_band(radioIndex);
2108 if (band == band_2_4 && bandwidth == 40) {
2109 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2110 memset(buf, 0, sizeof(buf));
2111 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2112
2113 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2114 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2115 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2116 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2117 } else {
2118 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2119 return RETURN_ERR;
2120 }
2121 } else if (band == band_5 || band == band_6){
2122 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2123 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2124 channel_delta = (bandwidth-20)/10;
2125 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2126 } else
2127 return RETURN_ERR;
2128
2129 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002130 return RETURN_OK;
2131}
2132
2133//Get the running channel number
2134INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2135{
developerda1ed692022-09-13 13:59:20 +08002136#ifdef MTK_IMPL
2137 if(!wifi_getApChannel(radioIndex, output_ulong))
2138 return RETURN_OK;
2139 else
2140 return RETURN_ERR;
2141#else
developer06a01d92022-09-07 16:32:39 +08002142 char cmd[1024] = {0}, buf[5] = {0};
2143
2144 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2145 if (NULL == output_ulong)
2146 return RETURN_ERR;
2147
2148 snprintf(cmd, sizeof(cmd),
2149 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2150 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2151 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2152 _syscmd(cmd, buf, sizeof(buf));
2153
2154 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2155 if (*output_ulong <= 0) {
2156 *output_ulong = 0;
2157 return RETURN_ERR;
2158 }
2159
2160 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2161 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002162#endif
developer06a01d92022-09-07 16:32:39 +08002163}
2164
2165
2166INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2167{
2168 char cmd[1024] = {0}, buf[5] = {0};
2169 char interface_name[50] = {0};
2170
2171 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2172 if (NULL == output_ulong)
2173 return RETURN_ERR;
2174
2175 wifi_getApName(apIndex,interface_name);
2176 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2177 _syscmd(cmd,buf,sizeof(buf));
2178 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2179 if (*output_ulong == 0) {
2180 return RETURN_ERR;
2181 }
2182
2183 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2184 return RETURN_OK;
2185}
2186
2187//Storing the previous channel value
2188INT wifi_storeprevchanval(INT radioIndex)
2189{
2190 char buf[256] = {0};
2191 char output[4]={'\0'};
2192 char config_file[MAX_BUF_SIZE] = {0};
2193 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2194 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2195 if(radioIndex == 0)
2196 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2197 else if(radioIndex == 1)
2198 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2199 system(buf);
2200 Radio_flag = FALSE;
2201 return RETURN_OK;
2202}
2203
2204//Set the running channel number
2205INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2206{
developer76989232022-10-04 14:13:19 +08002207 // We only write hostapd config here
2208 char str_channel[8]={0};
2209 char *list_channel;
2210 char config_file[128] = {0};
2211 char possible_channels[256] = {0};
2212 int max_radio_num = 0;
2213 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002214
developer76989232022-10-04 14:13:19 +08002215 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002216
developer76989232022-10-04 14:13:19 +08002217 // Check valid
2218 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002219
developer76989232022-10-04 14:13:19 +08002220 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2221 list_channel = strtok(possible_channels, ",");
2222 while(true)
developer06a01d92022-09-07 16:32:39 +08002223 {
developer76989232022-10-04 14:13:19 +08002224 if(list_channel == NULL) { // input not in the list
2225 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2226 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002227 }
developer76989232022-10-04 14:13:19 +08002228 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2229 break;
2230 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002231 }
2232
developer76989232022-10-04 14:13:19 +08002233 list.name = "channel";
2234 list.value = str_channel;
2235 wifi_getMaxRadioNumber(&max_radio_num);
2236 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002237 {
developer76989232022-10-04 14:13:19 +08002238 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2239 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002240 }
2241
developer76989232022-10-04 14:13:19 +08002242 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002243 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002244}
developer06a01d92022-09-07 16:32:39 +08002245
2246INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2247{
developer76989232022-10-04 14:13:19 +08002248 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002249 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002250 char config_file[64];
2251 int max_num_radios = 0;
2252 wifi_band band = band_invalid;
2253
2254 band = wifi_index_to_band(radioIndex);
2255 if (band == band_2_4)
2256 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002257
developer06a01d92022-09-07 16:32:39 +08002258 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002259 list[0].name = "vht_oper_centr_freq_seg0_idx";
2260 list[0].value = str_idx;
2261 list[1].name = "he_oper_centr_freq_seg0_idx";
2262 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002263
developer76989232022-10-04 14:13:19 +08002264 wifi_getMaxRadioNumber(&max_num_radios);
2265 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002266 {
developer76989232022-10-04 14:13:19 +08002267 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2268 if (band == band_6)
2269 wifi_hostapdWrite(config_file, &list[1], 1);
2270 else
2271 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002272 }
2273
2274 return RETURN_OK;
2275}
2276
2277//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2278//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2279INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2280{
2281 //Set to wifi config only. Wait for wifi reset to apply.
2282 char buf[256] = {0};
2283 char str_channel[256] = {0};
2284 int count = 0;
2285 ULONG Value = 0;
2286 FILE *fp = NULL;
2287 if(enable == TRUE)
2288 {
developer06a01d92022-09-07 16:32:39 +08002289 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002290 }
developer5884e982022-10-06 10:52:50 +08002291 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002292}
2293
developer0b246d12022-09-30 15:24:20 +08002294INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2295{
2296 if (output_bool == NULL)
2297 return RETURN_ERR;
2298
2299 *output_bool = TRUE;
2300
2301 return RETURN_OK;
2302}
2303
developer06a01d92022-09-07 16:32:39 +08002304INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2305{
2306 if (NULL == output_bool)
2307 return RETURN_ERR;
2308 *output_bool=FALSE;
2309 return RETURN_OK;
2310}
2311
2312INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2313{
2314 if (NULL == output_bool)
2315 return RETURN_ERR;
2316 *output_bool=FALSE;
2317 return RETURN_OK;
2318}
2319
2320INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2321{
2322 //Set to wifi config only. Wait for wifi reset to apply.
2323 return RETURN_OK;
2324}
2325
2326INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2327{
2328 return RETURN_OK;
2329}
2330
2331INT wifi_factoryResetAP(int apIndex)
2332{
developer838cca92022-10-03 13:19:57 +08002333 char ap_config_file[64] = {0};
2334 char cmd[128] = {0};
2335
developer06a01d92022-09-07 16:32:39 +08002336 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002337
2338 wifi_setApEnable(apIndex, FALSE);
2339 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2340 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2341 wifi_setApEnable(apIndex, TRUE);
2342
developer06a01d92022-09-07 16:32:39 +08002343 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002344
developer06a01d92022-09-07 16:32:39 +08002345 return RETURN_OK;
2346}
2347
2348//To set Band Steering AP group
2349//To-do
2350INT wifi_setBandSteeringApGroup(char *ApGroup)
2351{
2352 return RETURN_OK;
2353}
2354
developer1e5aa162022-09-13 16:06:24 +08002355INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2356{
2357 char config_file[128] = {'\0'};
2358 char buf[128] = {'\0'};
2359
2360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2361 if (dtimInterval == NULL)
2362 return RETURN_ERR;
2363
2364 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2365 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2366
2367 if (strlen(buf) == 0) {
2368 *dtimInterval = 2;
2369 } else {
2370 *dtimInterval = strtoul(buf, NULL, 10);
2371 }
2372
2373 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2374 return RETURN_OK;
2375}
2376
developer06a01d92022-09-07 16:32:39 +08002377INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2378{
developer5f222492022-09-13 15:21:52 +08002379 struct params params={0};
2380 char config_file[MAX_BUF_SIZE] = {'\0'};
2381 char buf[MAX_BUF_SIZE] = {'\0'};
2382
2383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2384 if (dtimInterval < 1 || dtimInterval > 255) {
2385 return RETURN_ERR;
2386 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2387 }
2388
2389 params.name = "dtim_period";
2390 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2391 params.value = buf;
2392
2393 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2394 wifi_hostapdWrite(config_file, &params, 1);
2395 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2396
2397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2398 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002399}
2400
2401//Check if the driver support the Dfs
2402INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2403{
2404 if (NULL == output_bool)
2405 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002406 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002407 return RETURN_OK;
2408}
2409
2410//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.
2411//The value of this parameter is a comma seperated list of channel number
2412INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2413{
2414 if (NULL == output_pool)
2415 return RETURN_ERR;
2416 if (radioIndex==1)
2417 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2418 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2419
2420 return RETURN_OK;
2421}
2422
2423INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2424{
2425 //Set to wifi config. And apply instantly.
2426 return RETURN_OK;
2427}
2428
2429INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2430{
2431 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2432 return RETURN_ERR;
2433 *output_interval_seconds=1800;
2434 *output_dwell_milliseconds=40;
2435
2436 return RETURN_OK;
2437}
2438
2439INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2440{
2441 //Set to wifi config. And apply instantly.
2442 return RETURN_OK;
2443}
2444
developerbfc18512022-10-05 17:54:28 +08002445INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2446{
2447 if (output_bool == NULL)
2448 return RETURN_ERR;
2449 *output_bool = true;
2450 return RETURN_OK;
2451}
2452
2453INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2454{
2455 return RETURN_OK;
2456}
2457
developer06a01d92022-09-07 16:32:39 +08002458//Get the Dfs enable status
2459INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2460{
developer9964b5b2022-09-13 15:59:34 +08002461 char buf[16] = {0};
2462 FILE *f = NULL;
2463 wifi_band band;
2464
2465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2466
2467 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002468 if (NULL == output_bool)
2469 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002470
2471 band = wifi_index_to_band(radioIndex);
2472 if (band != band_5)
2473 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002474
developer9964b5b2022-09-13 15:59:34 +08002475 f = fopen(DFS_ENABLE_FILE, "r");
2476 if (f != NULL) {
2477 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002478 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002479 *output_bool = FALSE;
2480 fclose(f);
2481 }
2482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002483 return RETURN_OK;
2484}
2485
2486//Set the Dfs enable status
2487INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2488{
developer9964b5b2022-09-13 15:59:34 +08002489 char config_file[128] = {0};
2490 FILE *f = NULL;
2491 struct params params={0};
2492 wifi_band band;
2493
2494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2495
2496 band = wifi_index_to_band(radioIndex);
2497 if (band != band_5)
2498 return RETURN_OK;
2499
2500 f = fopen(DFS_ENABLE_FILE, "w");
2501 if (f == NULL)
2502 return RETURN_ERR;
2503 fprintf(f, "%d", enable);
2504 fclose(f);
2505
2506 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002507 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002508 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2509 wifi_hostapdWrite(config_file, &params, 1);
2510 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2511
2512 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2513
developer9964b5b2022-09-13 15:59:34 +08002514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002515 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002516}
2517
2518//Check if the driver support the AutoChannelRefreshPeriod
2519INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2520{
2521 if (NULL == output_bool)
2522 return RETURN_ERR;
2523 *output_bool=FALSE; //not support
2524
2525 return RETURN_OK;
2526}
2527
2528//Get the ACS refresh period in seconds
2529INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2530{
2531 if (NULL == output_ulong)
2532 return RETURN_ERR;
2533 *output_ulong=300;
2534
2535 return RETURN_OK;
2536}
2537
2538//Set the ACS refresh period in seconds
2539INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2540{
2541 return RETURN_ERR;
2542}
2543
2544//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2545//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.
2546INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2547{
developer70490032022-09-13 15:45:20 +08002548 char cmd[128] = {0}, buf[64] = {0};
2549 char interface_name[64] = {0};
2550 int ret = 0, len=0;
2551 BOOL radio_enable = FALSE;
2552
2553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2554
developer06a01d92022-09-07 16:32:39 +08002555 if (NULL == output_string)
2556 return RETURN_ERR;
2557
developer70490032022-09-13 15:45:20 +08002558 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2559 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002560
developer70490032022-09-13 15:45:20 +08002561 if (radio_enable != TRUE)
2562 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002563
developer70490032022-09-13 15:45:20 +08002564 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002565 ret = _syscmd(cmd, buf, sizeof(buf));
2566 len = strlen(buf);
2567 if((ret != 0) || (len == 0))
2568 {
2569 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2570 return RETURN_ERR;
2571 }
2572
2573 buf[len-1] = '\0';
2574 snprintf(output_string, 64, "%sMHz", buf);
2575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2576
2577#if 0
2578 //TODO: revisit below implementation
2579 char output_buf[8]={0};
2580 char bw_value[10];
2581 char config_file[MAX_BUF_SIZE] = {0};
2582
2583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2584 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2585 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2586 readBandWidth(radioIndex,bw_value);
2587
2588 if(strstr (output_buf,"0") != NULL )
2589 {
2590 strcpy(output_string,bw_value);
2591 }
2592 else if (strstr (output_buf,"1") != NULL)
2593 {
2594 strcpy(output_string,"80MHz");
2595 }
2596 else if (strstr (output_buf,"2") != NULL)
2597 {
2598 strcpy(output_string,"160MHz");
2599 }
2600 else if (strstr (output_buf,"3") != NULL)
2601 {
2602 strcpy(output_string,"80+80");
2603 }
2604 else
2605 {
2606 strcpy(output_string,"Auto");
2607 }
2608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2609#endif
2610
2611 return RETURN_OK;
2612}
2613
2614//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002615INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002616{
developerf7a466e2022-09-29 11:55:56 +08002617 char config_file[128];
2618 char set_value[16];
2619 struct params params[2];
2620 int max_radio_num = 0;
2621
developer06a01d92022-09-07 16:32:39 +08002622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002623
developerf7a466e2022-09-29 11:55:56 +08002624 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002625 return RETURN_ERR;
2626
developerf7a466e2022-09-29 11:55:56 +08002627 if(strstr(bandwidth,"80+80") != NULL)
2628 strcpy(set_value, "3");
2629 else if(strstr(bandwidth,"160") != NULL)
2630 strcpy(set_value, "2");
2631 else if(strstr(bandwidth,"80") != NULL)
2632 strcpy(set_value, "1");
2633 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2634 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002635 else
2636 {
developerf7a466e2022-09-29 11:55:56 +08002637 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002638 return RETURN_ERR;
2639 }
2640
developerf7a466e2022-09-29 11:55:56 +08002641 params[0].name = "vht_oper_chwidth";
2642 params[0].value = set_value;
2643 params[1].name = "he_oper_chwidth";
2644 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002645
developerf7a466e2022-09-29 11:55:56 +08002646 wifi_getMaxRadioNumber(&max_radio_num);
2647 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002648 {
developerf7a466e2022-09-29 11:55:56 +08002649 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2650 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002651 }
2652
2653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2654 return RETURN_OK;
2655}
2656
2657//Getting current radio extension channel
2658INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2659{
2660 CHAR buf[150] = {0};
2661 CHAR cmd[150] = {0};
2662 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2663 _syscmd(cmd, buf, sizeof(buf));
2664 if(NULL != strstr(buf,"HT40+"))
2665 strcpy(Value,"AboveControlChannel");
2666 else if(NULL != strstr(buf,"HT40-"))
2667 strcpy(Value,"BelowControlChannel");
2668 return RETURN_OK;
2669}
2670
2671//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2672//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2673INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2674{
2675 if (NULL == output_string)
2676 return RETURN_ERR;
2677
2678 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2679#if 0
2680 CHAR Value[100] = {0};
2681 if (NULL == output_string)
2682 return RETURN_ERR;
2683 if(radioIndex == 0)
2684 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2685 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2686 {
2687 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2688 if(strcmp(Value,"40MHz") == 0)
2689 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2690 else
2691 strcpy(Value,"Auto");
2692 }
2693 strcpy(output_string,Value);
2694#endif
2695
2696 return RETURN_OK;
2697}
2698
2699//Set the extension channel.
2700INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2701{
2702 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2703 struct params params={'\0'};
2704 char config_file[MAX_BUF_SIZE] = {0};
2705 char ext_channel[127]={'\0'};
2706
2707 params.name = "ht_capab";
2708
2709 if(radioIndex == 0)
2710 {
2711 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002712 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002713 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002714 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002715 else
developer3cc0f2e2022-09-15 18:25:39 +08002716 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002717 }
2718 else if(radioIndex == 1)
2719 {
2720 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002721 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002722 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002723 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002724 else
developer3cc0f2e2022-09-15 18:25:39 +08002725 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002726 }
2727
2728 params.value = ext_channel;
2729 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2730 {
2731 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2732 wifi_hostapdWrite(config_file, &params, 1);
2733 }
2734
2735 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2737 return RETURN_OK;
2738}
2739
2740//Get the guard interval value. eg "400nsec" or "800nsec"
2741//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.
2742INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2743{
developer454b9462022-09-13 15:29:16 +08002744 wifi_guard_interval_t GI;
2745
2746 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2747
2748 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002749 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002750
2751 if (GI == wifi_guard_interval_400)
2752 strcpy(output_string, "400nsec");
2753 else if (GI == wifi_guard_interval_800)
2754 strcpy(output_string, "800nsec");
2755 else if (GI == wifi_guard_interval_1600)
2756 strcpy(output_string, "1600nsec");
2757 else if (GI == wifi_guard_interval_3200)
2758 strcpy(output_string, "3200nsec");
2759 else
2760 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002761
developer454b9462022-09-13 15:29:16 +08002762 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002763 return RETURN_OK;
2764}
2765
2766//Set the guard interval value.
2767INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2768{
developer454b9462022-09-13 15:29:16 +08002769 wifi_guard_interval_t GI;
2770 int ret = 0;
2771
2772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2773
2774 if (strcmp(string, "400nsec") == 0)
2775 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002776 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002777 GI = wifi_guard_interval_800;
2778 else if (strcmp(string , "1600nsec") == 0)
2779 GI = wifi_guard_interval_1600;
2780 else if (strcmp(string , "3200nsec") == 0)
2781 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002782 else
2783 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002784
2785 ret = wifi_setGuardInterval(radioIndex, GI);
2786
2787 if (ret == RETURN_ERR) {
2788 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2789 return RETURN_ERR;
2790 }
2791
2792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2793 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002794}
2795
2796//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2797INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2798{
developerf49437e2022-09-29 19:58:21 +08002799 char buf[32]={0};
2800 char mcs_file[64] = {0};
2801 char cmd[64] = {0};
2802 int mode_bitmap = 0;
2803
2804 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2805 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002806 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002807 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2808
2809 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2810 _syscmd(cmd, buf, sizeof(buf));
2811 if (strlen(buf) > 0)
2812 *output_int = strtol(buf, NULL, 10);
2813 else {
2814 // output the max MCS for the current radio mode
2815 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2816 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2817 return RETURN_ERR;
2818 }
2819 if (mode_bitmap & WIFI_MODE_AX) {
2820 *output_int = 11;
2821 } else if (mode_bitmap & WIFI_MODE_AC) {
2822 *output_int = 9;
2823 } else if (mode_bitmap & WIFI_MODE_N) {
2824 *output_int = 7;
2825 }
2826 }
2827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002828
2829 return RETURN_OK;
2830}
2831
2832//Set the Modulation Coding Scheme index
2833INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2834{
developerf49437e2022-09-29 19:58:21 +08002835 // 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).
2836 char config_file[64] = {0};
2837 char set_value[16] = {0};
2838 char mcs_file[32] = {0};
2839 wifi_band band = band_invalid;
2840 struct params set_config = {0};
2841 FILE *f = NULL;
2842
2843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2844
2845 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2846
2847 if (MCS > 11 || MCS < 0) {
2848 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2849 return RETURN_ERR;
2850 }
2851
2852 if (MCS <= 7)
2853 strcpy(set_value, "0");
2854 else if (MCS <= 9)
2855 strcpy(set_value, "1");
2856 else
2857 strcpy(set_value, "2");
2858
2859 set_config.name = "he_basic_mcs_nss_set";
2860 set_config.value = set_value;
2861
2862 wifi_hostapdWrite(config_file, &set_config, 1);
2863 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2864
2865 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2866 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2867 f = fopen(mcs_file, "w");
2868 if (f == NULL) {
2869 fprintf(stderr, "%s: fopen failed\n", __func__);
2870 return RETURN_ERR;
2871 }
2872 fprintf(f, "%d", MCS);
2873 fclose(f);
2874
2875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2876 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002877}
2878
2879//Get supported Transmit Power list, eg : "0,25,50,75,100"
2880//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.
2881INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2882{
2883 if (NULL == output_list)
2884 return RETURN_ERR;
2885 snprintf(output_list, 64,"0,25,50,75,100");
2886 return RETURN_OK;
2887}
2888
developera5005b62022-09-13 15:43:35 +08002889//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002890//The transmite power level is in units of full power for this radio.
2891INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2892{
2893 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002894 char buf[16]={0};
2895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002896
developera5005b62022-09-13 15:43:35 +08002897 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002898 return RETURN_ERR;
2899
developera5005b62022-09-13 15:43:35 +08002900 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002901 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002902
developera5005b62022-09-13 15:43:35 +08002903 *output_ulong = strtol(buf, NULL, 10);
2904
2905 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002906 return RETURN_OK;
2907}
2908
2909//Set Transmit Power
2910//The transmite power level is in units of full power for this radio.
2911INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2912{
developera5005b62022-09-13 15:43:35 +08002913 char *support;
developer06a01d92022-09-07 16:32:39 +08002914 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002915 char buf[128]={0};
2916 char txpower_str[64] = {0};
2917 int txpower = 0;
2918 int maximum_tx = 0;
2919
2920 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002921
developera5005b62022-09-13 15:43:35 +08002922 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002923 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002924 maximum_tx = strtol(buf, NULL, 10);
2925
2926 // Get the Tx power supported list and check that is the input in the list
2927 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2928 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2929 support = strtok(buf, ",");
2930 while(true)
2931 {
2932 if(support == NULL) { // input not in the list
2933 wifi_dbg_printf("Input value is invalid.\n");
2934 return RETURN_ERR;
2935 }
2936 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2937 break;
2938 }
2939 support = strtok(NULL, ",");
2940 }
2941 txpower = TransmitPower*maximum_tx/100;
2942 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2943 _syscmd(cmd, buf, sizeof(buf));
2944 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002945
2946 return RETURN_OK;
2947}
2948
2949//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2950INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2951{
2952 if (NULL == Supported)
2953 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002954 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002955
2956 return RETURN_OK;
2957}
2958
2959//Get 80211h feature enable
2960INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2961{
developer3885fec2022-09-13 15:13:47 +08002962 char buf[64]={'\0'};
2963 char config_file[64] = {'\0'};
2964
2965 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2966 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002967 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002968
2969 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2970 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002971
developer3885fec2022-09-13 15:13:47 +08002972 if (strncmp(buf, "1", 1) == 0)
2973 *enable = TRUE;
2974 else
2975 *enable = FALSE;
2976
2977 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002978 return RETURN_OK;
2979}
2980
2981//Set 80211h feature enable
2982INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2983{
developer3885fec2022-09-13 15:13:47 +08002984 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2985 struct params params={'\0'};
2986 char config_file[MAX_BUF_SIZE] = {0};
2987
2988 params.name = "ieee80211h";
2989
2990 if (enable) {
2991 params.value = "1";
2992 } else {
2993 params.value = "0";
2994 }
2995
2996 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2997 wifi_hostapdWrite(config_file, &params, 1);
2998
2999 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3000 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3001 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003002}
3003
3004//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.
3005INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3006{
3007 if (NULL == output)
3008 return RETURN_ERR;
3009 *output=100;
3010
3011 return RETURN_OK;
3012}
3013
3014//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.
3015INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3016{
3017 if (NULL == output)
3018 return RETURN_ERR;
3019 *output = -99;
3020
3021 return RETURN_OK;
3022}
3023
3024INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3025{
3026 return RETURN_ERR;
3027}
3028
3029
3030//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3031INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3032{
developer5f222492022-09-13 15:21:52 +08003033 char cmd[MAX_BUF_SIZE]={'\0'};
3034 char buf[MAX_CMD_SIZE]={'\0'};
3035
3036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3037 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003038 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003039
3040 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3041 _syscmd(cmd, buf, sizeof(buf));
3042 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003043
developer5f222492022-09-13 15:21:52 +08003044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003045 return RETURN_OK;
3046}
3047
3048INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3049{
developer5f222492022-09-13 15:21:52 +08003050 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3051 struct params params={'\0'};
3052 char buf[MAX_BUF_SIZE] = {'\0'};
3053 char config_file[MAX_BUF_SIZE] = {'\0'};
3054
3055 params.name = "beacon_int";
3056 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3057 params.value = buf;
3058
3059 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3060 wifi_hostapdWrite(config_file, &params, 1);
3061
3062 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3064 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003065}
3066
3067//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.
3068INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3069{
developer06a01d92022-09-07 16:32:39 +08003070 //TODO: need to revisit below implementation
3071 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003072 char temp_output[128] = {0};
3073 char temp_TransmitRates[64] = {0};
3074 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003075
3076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3077 if (NULL == output)
3078 return RETURN_ERR;
3079 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003080 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3081
3082 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3083 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3084 } else {
3085 temp = strtok(temp_TransmitRates," ");
3086 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003087 {
developere9d0abd2022-09-13 15:40:57 +08003088 // Convert 100 kbps to Mbps
3089 temp[strlen(temp)-1]=0;
3090 if((temp[0]=='5') && (temp[1]=='\0'))
3091 {
3092 temp="5.5";
3093 }
3094 strcat(temp_output,temp);
3095 temp = strtok(NULL," ");
3096 if(temp!=NULL)
3097 {
3098 strcat(temp_output,",");
3099 }
developer06a01d92022-09-07 16:32:39 +08003100 }
developere9d0abd2022-09-13 15:40:57 +08003101 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003102 }
developer06a01d92022-09-07 16:32:39 +08003103 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003104 return RETURN_OK;
3105}
3106
3107INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3108{
3109 char *temp;
3110 char temp1[128];
3111 char temp_output[128];
3112 char temp_TransmitRates[128];
3113 char set[128];
3114 char sub_set[128];
3115 int set_count=0,subset_count=0;
3116 int set_index=0,subset_index=0;
3117 char *token;
3118 int flag=0, i=0;
3119 struct params params={'\0'};
3120 char config_file[MAX_BUF_SIZE] = {0};
3121
3122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3123 if(NULL == TransmitRates)
3124 return RETURN_ERR;
3125 strcpy(sub_set,TransmitRates);
3126
3127 //Allow only supported Data transmit rate to be set
3128 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3129 token = strtok(sub_set,",");
3130 while( token != NULL ) /* split the basic rate to be set, by comma */
3131 {
3132 sub_set[subset_count]=atoi(token);
3133 subset_count++;
3134 token=strtok(NULL,",");
3135 }
3136 token=strtok(set,",");
3137 while(token!=NULL) /* split the supported rate by comma */
3138 {
3139 set[set_count]=atoi(token);
3140 set_count++;
3141 token=strtok(NULL,",");
3142 }
3143 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3144 {
3145 for(set_index=0;set_index < set_count;set_index++)
3146 {
3147 flag=0;
3148 if(sub_set[subset_index]==set[set_index])
3149 break;
3150 else
3151 flag=1; /* No match found */
3152 }
3153 if(flag==1)
3154 return RETURN_ERR; //If value not found return Error
3155 }
3156 strcpy(temp_TransmitRates,TransmitRates);
3157
3158 for(i=0;i<strlen(temp_TransmitRates);i++)
3159 {
3160 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3161 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3162 {
3163 continue;
3164 }
3165 else
3166 {
3167 return RETURN_ERR;
3168 }
3169 }
3170 strcpy(temp_output,"");
3171 temp = strtok(temp_TransmitRates,",");
3172 while(temp!=NULL)
3173 {
3174 strcpy(temp1,temp);
3175 if(radioIndex==1)
3176 {
3177 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3178 {
3179 return RETURN_ERR;
3180 }
3181 }
3182
3183 if(strcmp(temp,"5.5")==0)
3184 {
3185 strcpy(temp1,"55");
3186 }
3187 else
3188 {
3189 strcat(temp1,"0");
3190 }
3191 strcat(temp_output,temp1);
3192 temp = strtok(NULL,",");
3193 if(temp!=NULL)
3194 {
3195 strcat(temp_output," ");
3196 }
3197 }
3198 strcpy(TransmitRates,temp_output);
3199
3200 params.name= "basic_rates";
3201 params.value =TransmitRates;
3202
3203 wifi_dbg_printf("\n%s:",__func__);
3204 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3205 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3206 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3207 wifi_hostapdWrite(config_file,&params,1);
3208 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3209 return RETURN_OK;
3210}
3211
3212//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3213INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3214{
3215 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3216 FILE *fp = NULL;
3217 char path[256] = {0}, output_string[256] = {0};
3218 int count = 0;
3219 char *interface = NULL;
3220
3221 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3222 if (fp == NULL)
3223 {
3224 printf("Failed to run command in Function %s\n", __FUNCTION__);
3225 return RETURN_ERR;
3226 }
3227 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3228 {
3229 interface = strchr(path, '=');
3230
3231 if (interface != NULL)
3232 {
3233 strcpy(output_string, interface + 1);
3234 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3235 interface_name[count] = output_string[count];
3236
3237 interface_name[count] = '\0';
3238 }
3239 }
3240 pclose(fp);
3241 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3242 return RETURN_OK;
3243}
3244
3245INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3246{
3247 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3248 output_struct->radio_BytesSent = 0;
3249 output_struct->radio_BytesReceived = 0;
3250 output_struct->radio_PacketsSent = 0;
3251 output_struct->radio_PacketsReceived = 0;
3252 output_struct->radio_ErrorsSent = 0;
3253 output_struct->radio_ErrorsReceived = 0;
3254 output_struct->radio_DiscardPacketsSent = 0;
3255 output_struct->radio_DiscardPacketsReceived = 0;
3256 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3257 return RETURN_OK;
3258}
3259
3260
3261INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3262{
3263 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3264 CHAR buf[MAX_CMD_SIZE] = {0};
3265 CHAR Value[MAX_BUF_SIZE] = {0};
3266 FILE *fp = NULL;
3267
3268 if (ifname == NULL || strlen(ifname) <= 1)
3269 return RETURN_OK;
3270
3271 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3272 system(buf);
3273
3274 fp = fopen("/tmp/Radio_Stats.txt", "r");
3275 if(fp == NULL)
3276 {
3277 printf("/tmp/Radio_Stats.txt not exists \n");
3278 return RETURN_ERR;
3279 }
3280 fclose(fp);
3281
3282 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3283 File_Reading(buf, Value);
3284 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3285
3286 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3287 File_Reading(buf, Value);
3288 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3289
3290 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3291 File_Reading(buf, Value);
3292 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3293
3294 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3295 File_Reading(buf, Value);
3296 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3297
3298 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3299 File_Reading(buf, Value);
3300 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3301
3302 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3303 File_Reading(buf, Value);
3304 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3305
3306 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3307 File_Reading(buf, Value);
3308 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3309
3310 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3311 File_Reading(buf, Value);
3312 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3313
3314 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3315 return RETURN_OK;
3316}
3317
3318INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3319{
3320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3321 CHAR buf[MAX_CMD_SIZE] = {0};
3322 FILE *fp = NULL;
3323 INT count = 0;
3324
3325 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3326 {
3327 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3328 File_Reading(buf, status);
3329 }
3330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3331 return RETURN_OK;
3332}
3333
3334//Get detail radio traffic static info
3335INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3336{
3337
3338#if 0
3339 //ifconfig radio_x
3340 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3341 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3342 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3343 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3344
3345 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3346 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3347 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.
3348 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.
3349
3350 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3351 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].
3352 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3353 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.
3354 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
3355 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
3356 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
3357 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
3358 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
3359
3360 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
3361 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
3362 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
3363 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.
3364
3365 return RETURN_OK;
3366#endif
3367
developera91d99f2022-09-29 15:59:10 +08003368 CHAR interface_name[64] = {0};
3369 CHAR config_path[64] = {0};
3370 BOOL iface_status = FALSE;
3371 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003372
3373 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3374 if (NULL == output_struct)
3375 return RETURN_ERR;
3376
developera91d99f2022-09-29 15:59:10 +08003377 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3378 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003379
developera91d99f2022-09-29 15:59:10 +08003380 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003381
developera91d99f2022-09-29 15:59:10 +08003382 if (iface_status == TRUE)
3383 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3384 else
3385 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003386
developera91d99f2022-09-29 15:59:10 +08003387 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3388 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3389 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3390 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3391 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3392 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3393 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3394 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003395
3396 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3397 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].
3398 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3399 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.
3400 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
3401 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
3402 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
3403 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
3404 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
3405
3406 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
3407 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
3408 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
3409 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.
3410
3411 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3412
3413 return RETURN_OK;
3414}
3415
3416//Set radio traffic static Measureing rules
3417INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3418{
3419 //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
3420 // Else, save the MeasuringRate and MeasuringInterval for future usage
3421
3422 return RETURN_OK;
3423}
3424
3425//To start or stop RadioTrafficStats
3426INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3427{
3428 //zqiu: If the RadioTrafficStats process running
3429 // if(enable)
3430 // return RETURN_OK.
3431 // else
3432 // Stop RadioTrafficStats process
3433 // Else
3434 // if(enable)
3435 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3436 // else
3437 // return RETURN_OK.
3438
3439 return RETURN_OK;
3440}
3441
3442//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
3443INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3444{
3445 //zqiu: Please ignor signalIndex.
3446 if (NULL == SignalLevel)
3447 return RETURN_ERR;
3448 *SignalLevel=(radioIndex==0)?-19:-19;
3449
3450 return RETURN_OK;
3451}
3452
3453//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3454INT wifi_applyRadioSettings(INT radioIndex)
3455{
3456 return RETURN_OK;
3457}
3458
3459//Get the radio index assocated with this SSID entry
3460INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3461{
3462 if (NULL == radioIndex)
3463 return RETURN_ERR;
3464 *radioIndex=ssidIndex%2;
3465
3466 return RETURN_OK;
3467}
3468
3469//Device.WiFi.SSID.{i}.Enable
3470//Get SSID enable configuration parameters (not the SSID enable status)
3471INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3472{
3473 if (NULL == output_bool)
3474 return RETURN_ERR;
3475
3476 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3477 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3478 return wifi_getApEnable(ssidIndex, output_bool);
3479}
3480
3481//Device.WiFi.SSID.{i}.Enable
3482//Set SSID enable configuration parameters
3483INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3484{
3485 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3486 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3487 return wifi_setApEnable(ssidIndex, enable);
3488}
3489
3490//Device.WiFi.SSID.{i}.Status
3491//Get the SSID enable status
3492INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3493{
3494 char cmd[MAX_CMD_SIZE]={0};
3495 char buf[MAX_BUF_SIZE]={0};
3496 BOOL output_bool;
3497
3498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3499 if (NULL == output_string)
3500 return RETURN_ERR;
3501 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3502 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3503
3504 wifi_getApEnable(ssidIndex,&output_bool);
3505 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3506
3507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3508 return RETURN_OK;
3509}
3510
3511// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3512INT wifi_getSSIDName(INT apIndex, CHAR *output)
3513{
3514 char config_file[MAX_BUF_SIZE] = {0};
3515
3516 if (NULL == output)
3517 return RETURN_ERR;
3518
3519 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3520 wifi_hostapdRead(config_file,"ssid",output,32);
3521
3522 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3523 return RETURN_OK;
3524}
3525
3526// Set a max 32 byte string and sets an internal variable to the SSID name
3527INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3528{
3529 char str[MAX_BUF_SIZE]={'\0'};
3530 char cmd[MAX_CMD_SIZE]={'\0'};
3531 struct params params;
3532 char config_file[MAX_BUF_SIZE] = {0};
3533
3534 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3535 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3536 return RETURN_ERR;
3537
3538 params.name = "ssid";
3539 params.value = ssid_string;
3540 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3541 wifi_hostapdWrite(config_file, &params, 1);
3542 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3544
3545 return RETURN_OK;
3546}
3547
3548//Get the BSSID
3549INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3550{
3551 char cmd[MAX_CMD_SIZE]="";
3552
3553 if (NULL == output_string)
3554 return RETURN_ERR;
3555
3556 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3557 {
3558 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3559 _syscmd(cmd, output_string, 64);
3560 return RETURN_OK;
3561 }
3562 strncpy(output_string, "\0", 1);
3563
3564 return RETURN_ERR;
3565}
3566
3567//Get the MAC address associated with this Wifi SSID
3568INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3569{
3570 wifi_getBaseBSSID(ssidIndex,output_string);
3571 return RETURN_OK;
3572}
3573
3574//Get the basic SSID traffic static info
3575//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3576//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3577INT wifi_applySSIDSettings(INT ssidIndex)
3578{
3579 BOOL status = false;
3580 char cmd[MAX_CMD_SIZE] = {0};
3581 char buf[MAX_CMD_SIZE] = {0};
3582 int apIndex, ret;
3583 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3584
3585 wifi_getApEnable(ssidIndex,&status);
3586 // Do not apply when ssid index is disabled
3587 if (status == false)
3588 return RETURN_OK;
3589
3590 /* Doing full remove and add for ssid Index
3591 * Not all hostapd options are supported with reload
3592 * for example macaddr_acl
3593 */
3594 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3595 return RETURN_ERR;
3596
3597 ret = wifi_setApEnable(ssidIndex,true);
3598
3599 /* Workaround for hostapd issue with multiple bss definitions
3600 * when first created interface will be removed
3601 * then all vaps other vaps on same phy are removed
3602 * after calling setApEnable to false readd all enabled vaps */
3603 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3604 apIndex = 2*i+radioIndex;
3605 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3606 _syscmd(cmd, buf, sizeof(buf));
3607 if(*buf == '1')
3608 wifi_setApEnable(apIndex, true);
3609 }
3610
3611 return ret;
3612}
3613
developera3c68b92022-09-13 15:27:29 +08003614struct channels_noise {
3615 int channel;
3616 int noise;
3617};
3618
3619// Return noise array for each channel
3620int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3621{
3622 FILE *f = NULL;
3623 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003624 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003625 size_t len = 0;
3626 ssize_t read = 0;
3627 int tmp = 0, arr_index = -1;
3628
3629 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3630
3631 if ((f = popen(cmd, "r")) == NULL) {
3632 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3633 return RETURN_ERR;
3634 }
developer5550e242022-09-30 09:59:32 +08003635
3636 while(fgets(line, sizeof(line), f) != NULL) {
3637 if(arr_index < channels_num){
3638 sscanf(line, "%d", &tmp);
3639 if (tmp > 0) { // channel frequency, the first line must be frequency
3640 arr_index++;
3641 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3642 } else { // noise
3643 channels_noise_arr[arr_index].noise = tmp;
3644 }
3645 }else{
3646 break;
developera3c68b92022-09-13 15:27:29 +08003647 }
3648 }
developera3c68b92022-09-13 15:27:29 +08003649 pclose(f);
3650 return RETURN_OK;
3651}
3652
developer06a01d92022-09-07 16:32:39 +08003653//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3654//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3655INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3656{
developera3c68b92022-09-13 15:27:29 +08003657 int index = -1;
3658 wifi_neighbor_ap2_t *scan_array = NULL;
3659 char cmd[256]={0};
3660 char buf[128]={0};
3661 char file_name[32] = {0};
3662 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003663 char line[256] = {0};
3664 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003665 int freq=0;
3666 FILE *f = NULL;
3667 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003668 int channels_num = 0;
3669 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003670 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003671 bool filter_enable = false;
3672 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003673
developer615510b2022-09-27 10:14:35 +08003674 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003675
3676 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3677 f = fopen(file_name, "r");
3678 if (f != NULL) {
3679 fgets(filter_SSID, sizeof(file_name), f);
3680 if (strlen(filter_SSID) != 0)
3681 filter_enable = true;
3682 fclose(f);
3683 }
3684
3685 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003686 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003687 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003688
developer5550e242022-09-30 09:59:32 +08003689
developer06a01d92022-09-07 16:32:39 +08003690
developera3c68b92022-09-13 15:27:29 +08003691 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
developer615510b2022-09-27 10:14:35 +08003692 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
developera3c68b92022-09-13 15:27:29 +08003693 fprintf(stderr, "cmd: %s\n", cmd);
3694 if ((f = popen(cmd, "r")) == NULL) {
3695 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3696 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003697 }
developer5550e242022-09-30 09:59:32 +08003698
3699 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3700 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3701
developer615510b2022-09-27 10:14:35 +08003702 ret = fgets(line, sizeof(line), f);
3703 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003704 if(strstr(line, "BSS") != NULL) { // new neighbor info
3705 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3706 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3707 // 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 +08003708
developera3c68b92022-09-13 15:27:29 +08003709 if (!filter_BSS) {
3710 index++;
3711 wifi_neighbor_ap2_t *tmp;
3712 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3713 if (tmp == NULL) { // no more memory to use
3714 index--;
3715 wifi_dbg_printf("%s: realloc failed\n", __func__);
3716 break;
3717 }
3718 scan_array = tmp;
3719 }
3720 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3721
3722 filter_BSS = false;
3723 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3724 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3725 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3726 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3727 } else if (strstr(line, "freq") != NULL) {
3728 sscanf(line," freq: %d", &freq);
3729 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3730
3731 if (freq >= 2412 && freq <= 2484) {
3732 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3733 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3734 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3735 }
3736 else if (freq >= 5160 && freq <= 5805) {
3737 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3738 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3739 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3740 }
3741
3742 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003743 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003744 for (int i = 0; i < channels_num; i++) {
3745 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3746 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3747 break;
3748 }
3749 }
3750 }
3751 } else if (strstr(line, "beacon interval") != NULL) {
3752 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3753 } else if (strstr(line, "signal") != NULL) {
3754 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3755 } else if (strstr(line,"SSID") != NULL) {
3756 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3757 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3758 filter_BSS = true;
3759 }
3760 } else if (strstr(line, "Supported rates") != NULL) {
3761 char SRate[80] = {0}, *tmp = NULL;
3762 memset(buf, 0, sizeof(buf));
3763 strcpy(SRate, line);
3764 tmp = strtok(SRate, ":");
3765 tmp = strtok(NULL, ":");
3766 strcpy(buf, tmp);
3767 memset(SRate, 0, sizeof(SRate));
3768
3769 tmp = strtok(buf, " \n");
3770 while (tmp != NULL) {
3771 strcat(SRate, tmp);
3772 if (SRate[strlen(SRate) - 1] == '*') {
3773 SRate[strlen(SRate) - 1] = '\0';
3774 }
3775 strcat(SRate, ",");
3776
3777 tmp = strtok(NULL, " \n");
3778 }
3779 SRate[strlen(SRate) - 1] = '\0';
3780 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3781 } else if (strstr(line, "DTIM") != NULL) {
3782 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3783 } else if (strstr(line, "VHT capabilities") != NULL) {
3784 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3785 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3786 } else if (strstr(line, "HT capabilities") != NULL) {
3787 strcat(scan_array[index].ap_SupportedStandards, ",n");
3788 strcpy(scan_array[index].ap_OperatingStandards, "n");
3789 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003790 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003791 sscanf(line," * channel width: %d", &vht_channel_width);
3792 if(vht_channel_width == 1) {
3793 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3794 } else {
3795 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3796 }
3797 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3798 continue;
3799 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003800 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003801 sscanf(line," * secondary channel offset: %s", &buf);
3802 if (!strcmp(buf, "above")) {
3803 //40Mhz +
3804 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3805 }
3806 else if (!strcmp(buf, "below")) {
3807 //40Mhz -
3808 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3809 } else {
3810 //20Mhz
3811 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3812 }
3813 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3814 continue;
3815 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003816 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3817 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3818 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003819 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3820 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003821 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003822 else
developer615510b2022-09-27 10:14:35 +08003823 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003824 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003825 if (strstr(line, "HE80/5GHz") != NULL) {
3826 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3827 ret = fgets(line, sizeof(line), f);
3828 } else
3829 continue;
developera3c68b92022-09-13 15:27:29 +08003830 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003831 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003832 }
developer615510b2022-09-27 10:14:35 +08003833 continue;
developera3c68b92022-09-13 15:27:29 +08003834 } else if (strstr(line, "WPA") != NULL) {
3835 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3836 } else if (strstr(line, "RSN") != NULL) {
3837 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3838 } else if (strstr(line, "Group cipher") != NULL) {
3839 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3840 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3841 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3842 }
3843 }
developer615510b2022-09-27 10:14:35 +08003844 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003845 }
3846
3847 if (!filter_BSS) {
3848 *output_array_size = index + 1;
3849 } else {
3850 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3851 *output_array_size = index;
3852 }
3853 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003854 pclose(f);
developer5550e242022-09-30 09:59:32 +08003855 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003856 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003857 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003858}
3859
3860//>> Deprecated: used for old RDKB code.
3861INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3862{
3863 INT status = RETURN_ERR;
3864
3865 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3866 output_struct->wifi_PLCPErrorCount = 0;
3867 output_struct->wifi_FCSErrorCount = 0;
3868 output_struct->wifi_InvalidMACCount = 0;
3869 output_struct->wifi_PacketsOtherReceived = 0;
3870 output_struct->wifi_Noise = 0;
3871 status = RETURN_OK;
3872 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3873 return status;
3874}
3875
3876INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3877{
3878 char cmd[128];
3879 char buf[1280];
3880 char *pos = NULL;
3881
3882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3883 if (NULL == output_struct)
3884 return RETURN_ERR;
3885
3886 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3887
3888 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3889 _syscmd(cmd, buf, sizeof(buf));
3890
3891 pos = buf;
3892 if ((pos = strstr(pos, "RX packets:")) == NULL)
3893 return RETURN_ERR;
3894 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3895
3896 if ((pos = strstr(pos, "TX packets:")) == NULL)
3897 return RETURN_ERR;
3898 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3899
3900 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3901 return RETURN_ERR;
3902 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3903
3904 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3905 return RETURN_ERR;
3906 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3907
3908 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3909 _syscmd(cmd, buf, sizeof(buf));
3910 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3911
3912#if 0
3913 //TODO: need to revisit below implementation
3914 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3915 char interface_name[MAX_BUF_SIZE] = {0};
3916 char interface_status[MAX_BUF_SIZE] = {0};
3917 char Value[MAX_BUF_SIZE] = {0};
3918 char buf[MAX_CMD_SIZE] = {0};
3919 char cmd[MAX_CMD_SIZE] = {0};
3920 FILE *fp = NULL;
3921
3922 if (NULL == output_struct) {
3923 return RETURN_ERR;
3924 }
3925
3926 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3927
3928 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3929 {
3930 if(apIndex == 0) //private_wifi for 2.4G
3931 {
3932 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3933 }
3934 else if(apIndex == 1) //private_wifi for 5G
3935 {
3936 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3937 }
3938 else if(apIndex == 4) //public_wifi for 2.4G
3939 {
3940 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3941 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3942 {
3943 return RETURN_ERR;
3944 }
3945 if(buf[0] == '#')//tp-link
3946 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3947 else//tenda
3948 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3949 }
3950 else if(apIndex == 5) //public_wifi for 5G
3951 {
3952 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3953 }
3954
3955 GetIfacestatus(interface_name, interface_status);
3956
3957 if(0 != strcmp(interface_status, "1"))
3958 return RETURN_ERR;
3959
3960 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3961 system(cmd);
3962
3963 fp = fopen("/tmp/SSID_Stats.txt", "r");
3964 if(fp == NULL)
3965 {
3966 printf("/tmp/SSID_Stats.txt not exists \n");
3967 return RETURN_ERR;
3968 }
3969 fclose(fp);
3970
3971 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3972 File_Reading(buf, Value);
3973 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3974
3975 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3976 File_Reading(buf, Value);
3977 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3978
3979 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3980 File_Reading(buf, Value);
3981 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3982
3983 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3984 File_Reading(buf, Value);
3985 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3986
3987 /* There is no specific parameter from caller to associate the value wifi_Associations */
3988 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3989 //_syscmd(cmd, buf, sizeof(buf));
3990 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3991 }
3992#endif
3993 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3994 return RETURN_OK;
3995}
3996
3997INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3998{
3999 char interface_name[MAX_BUF_SIZE] = {0};
4000 char interface_status[MAX_BUF_SIZE] = {0};
4001 char Value[MAX_BUF_SIZE] = {0};
4002 char buf[MAX_CMD_SIZE] = {0};
4003 char cmd[MAX_CMD_SIZE] = {0};
4004 FILE *fp = NULL;
4005
4006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4007 if (NULL == output_struct)
4008 return RETURN_ERR;
4009
4010 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4011
4012 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4013 {
4014 if(apIndex == 0) //private_wifi for 2.4G
4015 {
4016 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4017 }
4018 else if(apIndex == 1) //private_wifi for 5G
4019 {
4020 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4021 }
4022 else if(apIndex == 4) //public_wifi for 2.4G
4023 {
4024 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4025 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4026 {
4027 return RETURN_ERR;
4028 }
4029 if(buf[0] == '#')
4030 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4031 else
4032 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4033 }
4034 else if(apIndex == 5) //public_wifi for 5G
4035 {
4036 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4037 }
4038
4039 GetIfacestatus(interface_name, interface_status);
4040
4041 if(0 != strcmp(interface_status, "1"))
4042 return RETURN_ERR;
4043
4044 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4045 system(cmd);
4046
4047 fp = fopen("/tmp/SSID_Stats.txt", "r");
4048 if(fp == NULL)
4049 {
4050 printf("/tmp/SSID_Stats.txt not exists \n");
4051 return RETURN_ERR;
4052 }
4053 fclose(fp);
4054
4055 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4056 File_Reading(buf, Value);
4057 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4058
4059 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4060 File_Reading(buf, Value);
4061 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4062
4063 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4064 File_Reading(buf, Value);
4065 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4066
4067 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4068 File_Reading(buf, Value);
4069 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4070 }
4071
4072 output_struct->wifi_UnicastPacketsSent = 0;
4073 output_struct->wifi_UnicastPacketsReceived = 0;
4074 output_struct->wifi_MulticastPacketsSent = 0;
4075 output_struct->wifi_MulticastPacketsReceived = 0;
4076 output_struct->wifi_BroadcastPacketsSent = 0;
4077 output_struct->wifi_BroadcastPacketsRecevied = 0;
4078 output_struct->wifi_UnknownPacketsReceived = 0;
4079
4080 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4081 return RETURN_OK;
4082}
4083
4084INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4085{
4086 INT status = RETURN_ERR;
4087
4088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4089 //Below values should get updated from hal
4090 output_struct->wifi_RetransCount=0;
4091 output_struct->wifi_FailedRetransCount=0;
4092 output_struct->wifi_RetryCount=0;
4093 output_struct->wifi_MultipleRetryCount=0;
4094 output_struct->wifi_ACKFailureCount=0;
4095 output_struct->wifi_AggregatedPacketCount=0;
4096
4097 status = RETURN_OK;
4098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4099
4100 return status;
4101}
4102
4103INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4104{
4105 INT status = RETURN_ERR;
4106 UINT index;
4107 wifi_neighbor_ap_t *pt=NULL;
4108
4109 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4110 *output_array_size=2;
4111 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4112 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4113 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4114 strcpy(pt->ap_Radio,"");
4115 strcpy(pt->ap_SSID,"");
4116 strcpy(pt->ap_BSSID,"");
4117 strcpy(pt->ap_Mode,"");
4118 pt->ap_Channel=1;
4119 pt->ap_SignalStrength=0;
4120 strcpy(pt->ap_SecurityModeEnabled,"");
4121 strcpy(pt->ap_EncryptionMode,"");
4122 strcpy(pt->ap_OperatingFrequencyBand,"");
4123 strcpy(pt->ap_SupportedStandards,"");
4124 strcpy(pt->ap_OperatingStandards,"");
4125 strcpy(pt->ap_OperatingChannelBandwidth,"");
4126 pt->ap_BeaconPeriod=1;
4127 pt->ap_Noise=0;
4128 strcpy(pt->ap_BasicDataTransferRates,"");
4129 strcpy(pt->ap_SupportedDataTransferRates,"");
4130 pt->ap_DTIMPeriod=1;
4131 pt->ap_ChannelUtilization = 1;
4132 }
4133
4134 status = RETURN_OK;
4135 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4136
4137 return status;
4138}
4139
4140//----------------- AP HAL -------------------------------
4141
4142//>> Deprecated: used for old RDKB code.
4143INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4144{
4145 if (NULL == output_ulong || NULL == output_struct)
4146 return RETURN_ERR;
4147 *output_ulong = 0;
4148 *output_struct = NULL;
4149 return RETURN_OK;
4150}
4151
4152#ifdef HAL_NETLINK_IMPL
4153static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4154 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4155 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4156 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4157 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4158 char mac_addr[20];
4159 static int count=0;
4160 int rate=0;
4161
4162 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4163
4164 nla_parse(tb,
4165 NL80211_ATTR_MAX,
4166 genlmsg_attrdata(gnlh, 0),
4167 genlmsg_attrlen(gnlh, 0),
4168 NULL);
4169
4170 if(!tb[NL80211_ATTR_STA_INFO]) {
4171 fprintf(stderr, "sta stats missing!\n");
4172 return NL_SKIP;
4173 }
4174
4175
4176 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4177 fprintf(stderr, "failed to parse nested attributes!\n");
4178 return NL_SKIP;
4179 }
4180
4181 //devIndex starts from 1
4182 if( ++count == out->wifi_devIndex )
4183 {
4184 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4185 //Getting the mac addrress
4186 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4187
4188 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4189 fprintf(stderr, "failed to parse nested rate attributes!");
4190 return NL_SKIP;
4191 }
4192
4193 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4194 if(rinfo[NL80211_RATE_INFO_BITRATE])
4195 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4196 out->wifi_devTxRate = rate/10;
4197 }
4198
4199 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4200 fprintf(stderr, "failed to parse nested rate attributes!");
4201 return NL_SKIP;
4202 }
4203
4204 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4205 if(rinfo[NL80211_RATE_INFO_BITRATE])
4206 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4207 out->wifi_devRxRate = rate/10;
4208 }
4209 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4210 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4211
4212 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4213 count = 0; //starts the count for next cycle
4214 return NL_STOP;
4215 }
4216
4217 return NL_SKIP;
4218
4219}
4220#endif
4221
4222INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4223{
4224#ifdef HAL_NETLINK_IMPL
4225 Netlink nl;
4226 char if_name[10];
4227
4228 wifi_device_info_t info;
4229 info.wifi_devIndex = devIndex;
4230
4231 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4232
4233 nl.id = initSock80211(&nl);
4234
4235 if (nl.id < 0) {
4236 fprintf(stderr, "Error initializing netlink \n");
4237 return -1;
4238 }
4239
4240 struct nl_msg* msg = nlmsg_alloc();
4241
4242 if (!msg) {
4243 fprintf(stderr, "Failed to allocate netlink message.\n");
4244 nlfree(&nl);
4245 return -2;
4246 }
4247
4248 genlmsg_put(msg,
4249 NL_AUTO_PORT,
4250 NL_AUTO_SEQ,
4251 nl.id,
4252 0,
4253 NLM_F_DUMP,
4254 NL80211_CMD_GET_STATION,
4255 0);
4256
4257 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4258 nl_send_auto(nl.socket, msg);
4259 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4260 nl_recvmsgs(nl.socket, nl.cb);
4261 nlmsg_free(msg);
4262 nlfree(&nl);
4263
4264 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4265 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4266 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4267 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4268 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4269 return RETURN_OK;
4270#else
4271 //iw utility to retrieve station information
4272#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4273#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4274#define MACFILE "/tmp/wifi_AssoMac.txt"
4275#define TXRATEFILE "/tmp/wifi_txrate.txt"
4276#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4277 FILE *file = NULL;
4278 char if_name[10] = {'\0'};
4279 char pipeCmd[256] = {'\0'};
4280 char line[256];
4281 int count,device = 0;
4282
4283 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4284
4285 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4286 file = popen(pipeCmd, "r");
4287
4288 if(file == NULL)
4289 return RETURN_ERR; //popen failed
4290
4291 fgets(line, sizeof line, file);
4292 device = atoi(line);
4293 pclose(file);
4294
4295 if(device == 0)
4296 return RETURN_ERR; //No devices are connected
4297
4298 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4299 system(pipeCmd);
4300
4301 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4302
4303 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4304
4305 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4306
4307 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4308
4309 //devIndex starts from 1, ++count
4310 if((file = fopen(SIGNALFILE, "r")) != NULL )
4311 {
4312 for(count =0;fgets(line, sizeof line, file) != NULL;)
4313 {
4314 if (++count == devIndex)
4315 {
4316 output_struct->wifi_devSignalStrength = atoi(line);
4317 break;
4318 }
4319 }
4320 fclose(file);
4321 }
4322 else
4323 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4324
4325 if((file = fopen(MACFILE, "r")) != NULL )
4326 {
4327 for(count =0;fgets(line, sizeof line, file) != NULL;)
4328 {
4329 if (++count == devIndex)
4330 {
4331 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]);
4332 break;
4333 }
4334 }
4335 fclose(file);
4336 }
4337 else
4338 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4339
4340 if((file = fopen(TXRATEFILE, "r")) != NULL )
4341 {
4342 for(count =0;fgets(line, sizeof line, file) != NULL;)
4343 {
4344 if (++count == devIndex)
4345 {
4346 output_struct->wifi_devTxRate = atoi(line);
4347 break;
4348 }
4349 }
4350 fclose(file);
4351 }
4352 else
4353 fprintf(stderr,"fopen wifi_txrate.txt failed");
4354
4355 if((file = fopen(RXRATEFILE, "r")) != NULL)
4356 {
4357 for(count =0;fgets(line, sizeof line, file) != NULL;)
4358 {
4359 if (++count == devIndex)
4360 {
4361 output_struct->wifi_devRxRate = atoi(line);
4362 break;
4363 }
4364 }
4365 fclose(file);
4366 }
4367 else
4368 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4369
4370 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4371
4372 return RETURN_OK;
4373#endif
4374}
4375
4376INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4377{
4378 if (NULL == device)
4379 return RETURN_ERR;
4380 return RETURN_OK;
4381}
4382//<<
4383
4384
4385//--------------wifi_ap_hal-----------------------------
4386//enables CTS protection for the radio used by this AP
4387INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4388{
4389 //save config and Apply instantly
4390 return RETURN_ERR;
4391}
4392
4393// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4394INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4395{
developer463d39a2022-09-13 15:32:51 +08004396 char config_file[64] = {'\0'};
4397 char buf[64] = {'\0'};
4398 struct params list;
4399
4400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4401 list.name = "ht_coex";
4402 snprintf(buf, sizeof(buf), "%d", enable);
4403 list.value = buf;
4404
4405 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4406 wifi_hostapdWrite(config_file, &list, 1);
4407 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4408
4409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4410
4411 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004412}
4413
4414//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4415INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4416{
developerea4bcce2022-09-13 15:26:13 +08004417 char config_file[MAX_BUF_SIZE] = {'\0'};
4418 char buf[MAX_BUF_SIZE] = {'\0'};
4419 struct params list;
4420
4421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4422 if (threshold < 256 || threshold > 2346 )
4423 return RETURN_ERR;
4424 list.name = "fragm_threshold";
4425 snprintf(buf, sizeof(buf), "%d", threshold);
4426 list.value = buf;
4427
4428 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4429 wifi_hostapdWrite(config_file, &list, 1);
4430 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004431
developerea4bcce2022-09-13 15:26:13 +08004432 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004433
4434 return RETURN_OK;
4435}
4436
4437// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4438INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4439{
developer51a927d2022-09-13 15:42:22 +08004440 char config_file[64] = {'\0'};
4441 char cmd[128] = {'\0'};
4442 char buf[64] = {'\0'};
4443 char stbc_config[16] = {'\0'};
4444 wifi_band band;
4445 int iterator = 0;
4446 BOOL current_stbc = FALSE;
4447
4448 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4449
4450 band = wifi_index_to_band(radioIndex);
4451 if (band == band_invalid)
4452 return RETURN_ERR;
4453
4454 if (band == band_2_4)
4455 iterator = 1;
4456 else if (band == band_5)
4457 iterator = 2;
4458 else
4459 return RETURN_OK;
4460
4461 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4462
4463 // set ht and vht config
4464 for (int i = 0; i < iterator; i++) {
4465 memset(stbc_config, 0, sizeof(stbc_config));
4466 memset(cmd, 0, sizeof(cmd));
4467 memset(buf, 0, sizeof(buf));
4468 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4469 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4470 _syscmd(cmd, buf, sizeof(buf));
4471 if (strlen(buf) != 0)
4472 current_stbc = TRUE;
4473 if (current_stbc == STBC_Enable)
4474 continue;
4475
4476 if (STBC_Enable == TRUE) {
4477 // Append the STBC flags in capab config
4478 memset(cmd, 0, sizeof(cmd));
4479 if (i == 0)
4480 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4481 else
4482 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4483 _syscmd(cmd, buf, sizeof(buf));
4484 } else if (STBC_Enable == FALSE) {
4485 // Remove the STBC flags and remain other flags in capab
4486 memset(cmd, 0, sizeof(cmd));
4487 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4488 _syscmd(cmd, buf, sizeof(buf));
4489 memset(cmd, 0, sizeof(cmd));
4490 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4491 _syscmd(cmd, buf, sizeof(buf));
4492 }
4493 }
4494
4495 wifi_reloadAp(radioIndex);
4496
4497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4498 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004499}
4500
4501// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4502INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4503{
developer54e6b9f2022-09-28 14:41:20 +08004504 char AMSDU_file_path[64] = {0};
4505
4506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4507
4508 if(output_bool == NULL)
4509 return RETURN_ERR;
4510
4511 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4512
4513 if (access(AMSDU_file_path, F_OK) == 0)
4514 *output_bool = TRUE;
4515 else
4516 *output_bool = FALSE;
4517
4518 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4519 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004520}
4521
4522// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4523INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4524{
developer54e6b9f2022-09-28 14:41:20 +08004525 char cmd[64]={0};
4526 char buf[64]={0};
4527 char AMSDU_file_path[64] = {0};
4528
4529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4530
4531 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4532 _syscmd(cmd, buf, sizeof(buf));
4533
4534 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4535 memset(cmd, 0, sizeof(cmd));
4536 if (amsduEnable == TRUE)
4537 sprintf(cmd, "touch %s", AMSDU_file_path);
4538 else
4539 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4540 _syscmd(cmd, buf, sizeof(buf));
4541
4542 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4543 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004544}
4545
4546//P2 // outputs the number of Tx streams
4547INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4548{
developer2de97692022-09-26 14:00:03 +08004549 char buf[8] = {0};
4550 char cmd[128] = {0};
4551
4552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4553
4554 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4555 _syscmd(cmd, buf, sizeof(buf));
4556
4557 // if there is no record, output the max number of spatial streams
4558 if (strlen(buf) == 0) {
4559 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4560 _syscmd(cmd, buf, sizeof(buf));
4561 }
4562
4563 *output_int = (INT)strtol(buf, NULL, 10);
4564
4565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4566
4567 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004568}
4569
4570//P2 // sets the number of Tx streams to an enviornment variable
4571INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4572{
developer2de97692022-09-26 14:00:03 +08004573 char cmd[128] = {0};
4574 char buf[128] = {0};
4575 char chain_mask_file[128] = {0};
4576 FILE *f = NULL;
4577
4578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4579
4580 if (numStreams == 0) {
4581 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4582 return RETURN_ERR;
4583 }
4584 wifi_setRadioEnable(radioIndex, FALSE);
4585 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4586 _syscmd(cmd, buf, sizeof(buf));
4587
4588 if (strlen(buf) > 0) {
4589 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4590 return RETURN_ERR;
4591 }
4592 wifi_setRadioEnable(radioIndex, TRUE);
4593
4594 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4595 f = fopen(chain_mask_file, "w");
4596 if (f == NULL) {
4597 fprintf(stderr, "%s: fopen failed.\n", __func__);
4598 return RETURN_ERR;
4599 }
4600 fprintf(f, "%d", numStreams);
4601 fclose(f);
4602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4603 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004604}
4605
4606//P2 // outputs the number of Rx streams
4607INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4608{
developer2de97692022-09-26 14:00:03 +08004609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4610 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4611 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004612 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004613 }
4614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004615 return RETURN_OK;
4616}
4617
4618//P2 // sets the number of Rx streams to an enviornment variable
4619INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4620{
developer2de97692022-09-26 14:00:03 +08004621 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4622 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4623 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4624 return RETURN_ERR;
4625 }
4626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004627 return RETURN_ERR;
4628}
4629
4630//Get radio RDG enable setting
4631INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4632{
4633 if (NULL == output_bool)
4634 return RETURN_ERR;
4635 *output_bool = TRUE;
4636 return RETURN_OK;
4637}
4638
4639//Get radio RDG enable setting
4640INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4641{
4642 if (NULL == output_bool)
4643 return RETURN_ERR;
4644 *output_bool = TRUE;
4645 return RETURN_OK;
4646}
4647
4648//Set radio RDG enable setting
4649INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4650{
4651 return RETURN_ERR;
4652}
4653
4654//Get radio ADDBA enable setting
4655INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4656{
4657 if (NULL == output_bool)
4658 return RETURN_ERR;
4659 *output_bool = TRUE;
4660 return RETURN_OK;
4661}
4662
4663//Set radio ADDBA enable setting
4664INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4665{
4666 return RETURN_ERR;
4667}
4668
4669//Get radio auto block ack enable setting
4670INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4671{
4672 if (NULL == output_bool)
4673 return RETURN_ERR;
4674 *output_bool = TRUE;
4675 return RETURN_OK;
4676}
4677
4678//Set radio auto block ack enable setting
4679INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4680{
4681 return RETURN_ERR;
4682}
4683
4684//Get radio 11n pure mode enable support
4685INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4686{
4687 if (NULL == output_bool)
4688 return RETURN_ERR;
4689 *output_bool = TRUE;
4690 return RETURN_OK;
4691}
4692
4693//Get radio 11n pure mode enable setting
4694INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4695{
4696 if (NULL == output_bool)
4697 return RETURN_ERR;
4698 *output_bool = TRUE;
4699 return RETURN_OK;
4700}
4701
4702//Set radio 11n pure mode enable setting
4703INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4704{
4705 return RETURN_ERR;
4706}
4707
4708//Get radio IGMP snooping enable setting
4709INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4710{
developer81bf2ed2022-09-13 15:31:14 +08004711 char cmd[128]={0};
4712 char buf[4]={0};
4713 bool bridge = FALSE, mac80211 = FALSE;
4714 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4715
4716 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004717 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004718
4719 *output_bool = FALSE;
4720
4721 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4722 _syscmd(cmd, buf, sizeof(buf));
4723 if (strncmp(buf, "1", 1) == 0)
4724 bridge = TRUE;
4725
4726 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4727 _syscmd(cmd, buf, sizeof(buf));
4728 if (strncmp(buf, "1", 1) == 0)
4729 mac80211 = TRUE;
4730
4731 if (bridge && mac80211)
4732 *output_bool = TRUE;
4733
4734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004735 return RETURN_OK;
4736}
4737
4738//Set radio IGMP snooping enable setting
4739INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4740{
developer81bf2ed2022-09-13 15:31:14 +08004741 char cmd[128]={0};
4742 char buf[4]={0};
4743
4744 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4745
4746 // bridge
4747 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4748 _syscmd(cmd, buf, sizeof(buf));
4749
4750 // mac80211
4751 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4752 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4753 _syscmd(cmd, buf, sizeof(buf));
4754 }
4755 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4756 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004757}
4758
4759//Get the Reset count of radio
4760INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4761{
4762 if (NULL == output_int)
4763 return RETURN_ERR;
4764 *output_int = (radioIndex==0)? 1: 3;
4765
4766 return RETURN_OK;
4767}
4768
4769
4770//---------------------------------------------------------------------------------------------------
4771//
4772// Additional Wifi AP level APIs used for Access Point devices
4773//
4774//---------------------------------------------------------------------------------------------------
4775
4776// creates a new ap and pushes these parameters to the hardware
4777INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4778{
4779 char buf[1024];
4780 char cmd[128];
4781
4782 if (NULL == essid)
4783 return RETURN_ERR;
4784
4785 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4786 _syscmd(cmd, buf, sizeof(buf));
4787
4788 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4789 _syscmd(cmd, buf, sizeof(buf));
4790
4791 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4792
4793 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4794 _syscmd(cmd, buf, sizeof(buf));
4795
4796 return RETURN_OK;
4797}
4798
4799// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4800INT wifi_deleteAp(INT apIndex)
4801{
4802 char buf[1024];
4803 char cmd[128];
4804
4805 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4806 _syscmd(cmd, buf, sizeof(buf));
4807
4808 wifi_removeApSecVaribles(apIndex);
4809
4810 return RETURN_OK;
4811}
4812
4813// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4814INT wifi_getApName(INT apIndex, CHAR *output_string)
4815{
4816 if(NULL == output_string)
4817 return RETURN_ERR;
4818
4819 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4820 return RETURN_OK;
4821}
4822
4823// Outputs the index number in that corresponds to the SSID string
4824INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4825{
4826 CHAR *pos = NULL;
4827
4828 *output_int = -1;
4829 pos = strstr(inputSsidString, AP_PREFIX);
4830 if(pos)
4831 {
4832 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4833 return RETURN_OK;
4834 }
4835 return RETURN_ERR;
4836}
4837
4838INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4839{
4840 return wifi_getIndexFromName(inputSsidString, output_int);
4841}
4842
4843// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4844INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4845{
4846 char buf[MAX_BUF_SIZE] = {0};
4847 char cmd[MAX_CMD_SIZE] = {0};
4848 char config_file[MAX_BUF_SIZE] = {0};
4849
4850 if(NULL == output_string)
4851 return RETURN_ERR;
4852
4853 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4854 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4855 if((strcmp(buf,"3")==0))
4856 snprintf(output_string, 32, "WPAand11i");
4857 else if((strcmp(buf,"2")==0))
4858 snprintf(output_string, 32, "11i");
4859 else if((strcmp(buf,"1")==0))
4860 snprintf(output_string, 32, "WPA");
4861 else
4862 snprintf(output_string, 32, "None");
4863
4864 return RETURN_OK;
4865}
4866
4867// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4868INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4869{
4870 char config_file[MAX_BUF_SIZE] = {0};
4871 struct params list;
4872
4873 if (NULL == beaconTypeString)
4874 return RETURN_ERR;
4875 list.name = "wpa";
4876 list.value = "0";
4877
4878 if((strcmp(beaconTypeString,"WPAand11i")==0))
4879 list.value="3";
4880 else if((strcmp(beaconTypeString,"11i")==0))
4881 list.value="2";
4882 else if((strcmp(beaconTypeString,"WPA")==0))
4883 list.value="1";
4884
4885 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4886 wifi_hostapdWrite(config_file, &list, 1);
4887 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4888 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4889 return RETURN_OK;
4890}
4891
4892// sets the beacon interval on the hardware for this AP
4893INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4894{
developer5f222492022-09-13 15:21:52 +08004895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4896 struct params params={'\0'};
4897 char buf[MAX_BUF_SIZE] = {'\0'};
4898 char config_file[MAX_BUF_SIZE] = {'\0'};
4899
4900 params.name = "beacon_int";
4901 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4902 params.value = buf;
4903
4904 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4905 wifi_hostapdWrite(config_file, &params, 1);
4906
4907 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4909 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004910}
4911
4912INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4913{
4914 //save config and apply instantly
4915 return RETURN_ERR;
4916}
4917
4918// Get the packet size threshold supported.
4919INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4920{
4921 //save config and apply instantly
4922 if (NULL == output_bool)
4923 return RETURN_ERR;
4924 *output_bool = FALSE;
4925 return RETURN_OK;
4926}
4927
4928// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4929INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4930{
4931 char cmd[128];
4932 char buf[512];
4933
4934 if (threshold > 0)
4935 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4936 else
4937 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4938 _syscmd(cmd, buf, sizeof(buf));
4939
4940 return RETURN_OK;
4941}
4942
4943// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4944INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4945{
4946 if (NULL == output_string)
4947 return RETURN_ERR;
4948 snprintf(output_string, 32, "TKIPandAESEncryption");
4949 return RETURN_OK;
4950
4951}
4952
4953// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4954INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4955{
4956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4957 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4958
4959 if(NULL == output_string)
4960 return RETURN_ERR;
4961
4962 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4963 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4964
4965 if(strcmp(buf,"0")==0)
4966 {
4967 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4968 snprintf(output_string, 32, "None");
4969 return RETURN_OK;
4970 }
4971 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4972 param_name = "rsn_pairwise";
4973 else if((strcmp(buf,"1")==0))
4974 param_name = "wpa_pairwise";
4975 else
4976 return RETURN_ERR;
4977 memset(output_string,'\0',32);
4978 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4979 wifi_hostapdRead(config_file,param_name,output_string,32);
4980 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4981
4982 if(strcmp(output_string,"TKIP") == 0)
4983 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4984 else if(strcmp(output_string,"CCMP") == 0)
4985 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4986 else if(strcmp(output_string,"TKIP CCMP") == 0)
4987 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4988
4989 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4990 return RETURN_OK;
4991}
4992
4993// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4994INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4995{
4996 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4997 struct params params={'\0'};
4998 char output_string[32];
4999 char config_file[MAX_BUF_SIZE] = {0};
5000
5001 memset(output_string,'\0',32);
5002 wifi_getApWpaEncryptionMode(apIndex,output_string);
5003
5004 if(strcmp(encMode, "TKIPEncryption") == 0)
5005 params.value = "TKIP";
5006 else if(strcmp(encMode,"AESEncryption") == 0)
5007 params.value = "CCMP";
5008 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5009 params.value = "TKIP CCMP";
5010
5011 if((strcmp(output_string,"WPAand11i")==0))
5012 {
5013 params.name = "wpa_pairwise";
5014 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5015 wifi_hostapdWrite(config_file, &params, 1);
5016 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5017
5018 params.name,"rsn_pairwise";
5019 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5020 wifi_hostapdWrite(config_file, &params, 1);
5021 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5022
5023 return RETURN_OK;
5024 }
5025 else if((strcmp(output_string,"11i")==0))
5026 {
5027 params.name = "rsn_pairwise";
5028 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5029 wifi_hostapdWrite(config_file, &params, 1);
5030 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5031 return RETURN_OK;
5032 }
5033 else if((strcmp(output_string,"WPA")==0))
5034 {
5035 params.name = "wpa_pairwise";
5036 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5037 wifi_hostapdWrite(config_file, &params, 1);
5038 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5039 return RETURN_OK;
5040 }
5041
5042 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5043 return RETURN_OK;
5044}
5045
5046// deletes internal security varable settings for this ap
5047INT wifi_removeApSecVaribles(INT apIndex)
5048{
5049 //TODO: remove the entry in hostapd config file
5050 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5051 //_syscmd(cmd, buf, sizeof(buf));
5052
5053 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5054 //_syscmd(cmd, buf, sizeof(buf));
5055 return RETURN_ERR;
5056}
5057
5058// changes the hardware settings to disable encryption on this ap
5059INT wifi_disableApEncryption(INT apIndex)
5060{
5061 //Apply instantly
5062 return RETURN_ERR;
5063}
5064
5065// set the authorization mode on this ap
5066// mode mapping as: 1: open, 2: shared, 4:auto
5067INT wifi_setApAuthMode(INT apIndex, INT mode)
5068{
developeraf95c502022-09-13 16:18:22 +08005069 struct params params={0};
5070 char config_file[64] = {0};
5071 int ret;
5072
5073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5074
5075 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5076 params.name = "auth_algs";
5077
5078 if (mode & 1 && mode & 2)
5079 params.value = "3";
5080 else if (mode & 2)
5081 params.value = "2";
5082 else if (mode & 1)
5083 params.value = "1";
5084 else
5085 params.value = "0";
5086
5087 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5088 wifi_hostapdWrite(config_file, &params, 1);
5089 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5090 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5091
5092 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005093}
5094
5095// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5096INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5097{
5098 //save to wifi config, and wait for wifi restart to apply
5099 struct params params={'\0'};
5100 char config_file[MAX_BUF_SIZE] = {0};
5101 int ret;
5102
5103 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5104 if(authMode == NULL)
5105 return RETURN_ERR;
5106
5107 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5108 params.name = "wpa_key_mgmt";
5109
5110 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5111 params.value = "WPA-PSK";
5112 else if(strcmp(authMode,"EAPAuthentication") == 0)
5113 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005114 else if (strcmp(authMode, "SAEAuthentication") == 0)
5115 params.value = "SAE";
5116 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5117 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005118 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5119 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005120 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5121 return RETURN_OK; //This is taken careof in beaconType
5122
5123 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5124 ret=wifi_hostapdWrite(config_file,&params,1);
5125 if(!ret)
5126 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5127 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5128
5129 return ret;
5130}
5131
5132// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5133INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5134{
5135 //save to wifi config, and wait for wifi restart to apply
5136 char BeaconType[50] = {0};
5137 char config_file[MAX_BUF_SIZE] = {0};
5138
5139 *authMode = 0;
5140 wifi_getApBeaconType(apIndex,BeaconType);
5141 printf("%s____%s \n",__FUNCTION__,BeaconType);
5142
5143 if(strcmp(BeaconType,"None") == 0)
5144 strcpy(authMode,"None");
5145 else
5146 {
5147 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5148 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5149 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5150 if(strcmp(authMode,"WPA-PSK") == 0)
5151 strcpy(authMode,"SharedAuthentication");
5152 else if(strcmp(authMode,"WPA-EAP") == 0)
5153 strcpy(authMode,"EAPAuthentication");
5154 }
5155
5156 return RETURN_OK;
5157}
5158
5159// Outputs the number of stations associated per AP
5160INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5161{
5162 char cmd[128]={0};
5163 char buf[128]={0};
5164 BOOL status = false;
5165
5166 if(apIndex > MAX_APS)
5167 return RETURN_ERR;
5168
5169 wifi_getApEnable(apIndex,&status);
5170 if (!status)
5171 return RETURN_OK;
5172
5173 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5174 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5175 _syscmd(cmd, buf, sizeof(buf));
5176 sscanf(buf,"%lu", output_ulong);
5177
5178 return RETURN_OK;
5179}
5180
5181// manually removes any active wi-fi association with the device specified on this ap
5182INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5183{
5184 char buf[126]={'\0'};
5185
5186 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5187 system(buf);
5188
5189 return RETURN_OK;
5190}
5191
5192// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5193INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5194{
5195 if(NULL == output_int)
5196 return RETURN_ERR;
5197 *output_int = apIndex%2;
5198 return RETURN_OK;
5199}
5200
5201// sets the radio index for the specific ap
5202INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5203{
5204 //set to config only and wait for wifi reset to apply settings
5205 return RETURN_ERR;
5206}
5207
5208// Get the ACL MAC list per AP
5209INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5210{
5211 char cmd[MAX_CMD_SIZE]={'\0'};
5212 int ret = 0;
5213
5214 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5215 ret = _syscmd(cmd,macArray,buf_size);
5216 if (ret != 0)
5217 return RETURN_ERR;
5218
5219 return RETURN_OK;
5220}
5221
developere6aafda2022-09-13 14:59:28 +08005222INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5223{
5224 char cmd[MAX_CMD_SIZE]={'\0'};
5225 int ret = 0;
5226
5227 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5228 ret = _syscmd(cmd,macArray,buf_size);
5229 if (ret != 0)
5230 return RETURN_ERR;
5231
5232 return RETURN_OK;
5233}
5234
5235
developer06a01d92022-09-07 16:32:39 +08005236// Get the list of stations associated per AP
5237INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5238{
5239 char cmd[128];
5240
5241 if(apIndex > 3) //Currently supporting apIndex upto 3
5242 return RETURN_ERR;
5243 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5244 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5245 _syscmd(cmd, macArray, buf_size);
5246
5247 return RETURN_OK;
5248}
5249
5250// adds the mac address to the filter list
5251//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5252INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5253{
5254 char cmd[MAX_CMD_SIZE]={'\0'};
5255 char buf[MAX_BUF_SIZE]={'\0'};
5256
5257#if 0
5258 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5259 if(_syscmd(cmd,buf,sizeof(buf)))
5260 return RETURN_ERR;
5261#endif
5262 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5263 if(_syscmd(cmd,buf,sizeof(buf)))
5264 return RETURN_ERR;
5265
5266 return RETURN_OK;
5267}
5268
5269// deletes the mac address from the filter list
5270//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5271INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5272{
5273 char cmd[MAX_CMD_SIZE]={'\0'};
5274 char buf[MAX_BUF_SIZE]={'\0'};
5275
5276#if 0
5277 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5278 if(_syscmd(cmd,buf,sizeof(buf)))
5279 return RETURN_ERR;
5280
5281#endif
5282 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5283 if(_syscmd(cmd,buf,sizeof(buf)))
5284 return RETURN_ERR;
5285
5286 return RETURN_OK;
5287}
5288
5289// outputs the number of devices in the filter list
5290INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5291{
developere6aafda2022-09-13 14:59:28 +08005292 char cmd[MAX_BUF_SIZE]={0};
5293 char buf[MAX_CMD_SIZE]={0};
5294
5295 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5296 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005297 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005298
5299 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5300 _syscmd(cmd, buf, sizeof(buf));
5301
5302 *output_uint = atoi(buf);
5303
5304 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5305 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005306}
5307
5308INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5309{
5310 char cmd[128]={'\0'};
5311 char buf[128]={'\0'};
5312
5313 if(strcmp(action,"DENY")==0)
5314 {
5315 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5316 system(buf);
5317 return RETURN_OK;
5318 }
5319
5320 if(strcmp(action,"ALLOW")==0)
5321 {
5322 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5323 system(buf);
5324 return RETURN_OK;
5325 }
5326
5327 return RETURN_ERR;
5328
5329}
5330
5331// enable kick for devices on acl black list
5332INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5333{
5334 char aclArray[512] = {0}, *acl = NULL;
5335 char assocArray[512] = {0}, *asso = NULL;
5336
developere6aafda2022-09-13 14:59:28 +08005337 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005338 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5339
5340 // if there are no devices connected there is nothing to do
5341 if (strlen(assocArray) < 17)
5342 return RETURN_OK;
5343
5344 if (enable == TRUE)
5345 {
5346 //kick off the MAC which is in ACL array (deny list)
5347 acl = strtok(aclArray, "\r\n");
5348 while (acl != NULL) {
5349 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5350 wifi_kickApAssociatedDevice(apIndex, acl);
5351
5352 acl = strtok(NULL, "\r\n");
5353 }
developere6aafda2022-09-13 14:59:28 +08005354 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005355 }
5356 else
5357 {
developere6aafda2022-09-13 14:59:28 +08005358 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005359 }
5360
5361#if 0
5362 //TODO: need to revisit below implementation
5363 char aclArray[512]={0}, *acl=NULL;
5364 char assocArray[512]={0}, *asso=NULL;
5365 char buf[256]={'\0'};
5366 char action[10]={'\0'};
5367 FILE *fr=NULL;
5368 char interface[10]={'\0'};
5369 char config_file[MAX_BUF_SIZE] = {0};
5370
5371 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5372 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5373 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5374 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5375
5376 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5377 system(buf);
5378 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5379 system(buf);
5380 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5381 system(buf);
5382 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5383 system(buf);
5384 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5385 system(buf);
5386
5387 if ( enable == TRUE )
5388 {
5389 int device_count=0;
5390 strcpy(action,"DENY");
5391 //kick off the MAC which is in ACL array (deny list)
5392 acl = strtok (aclArray,",");
5393 while (acl != NULL) {
5394 if(strlen(acl)>=17)
5395 {
5396 apply_rules(apIndex, acl,action,interface);
5397 device_count++;
5398 //Register mac to be blocked ,in syscfg.db persistent storage
5399 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5400 system(buf);
5401 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5402 system(buf);
5403 system("syscfg commit");
5404
5405 wifi_kickApAssociatedDevice(apIndex, acl);
5406 }
5407 acl = strtok (NULL, ",");
5408 }
5409 }
5410 else
5411 {
5412 int device_count=0;
5413 char cmdmac[20]={'\0'};
5414 strcpy(action,"ALLOW");
5415 //kick off the MAC which is not in ACL array (allow list)
5416 acl = strtok (aclArray,",");
5417 while (acl != NULL) {
5418 if(strlen(acl)>=17)
5419 {
5420 apply_rules(apIndex, acl,action,interface);
5421 device_count++;
5422 //Register mac to be Allowed ,in syscfg.db persistent storage
5423 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5424 system(buf);
5425 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5426 system(buf);
5427 sprintf(cmdmac,"%s",acl);
5428 }
5429 acl = strtok (NULL, ",");
5430 }
5431 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5432 system(buf);
5433
5434 //Disconnect the mac which is not in ACL
5435 asso = strtok (assocArray,",");
5436 while (asso != NULL) {
5437 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5438 wifi_kickApAssociatedDevice(apIndex, asso);
5439 asso = strtok (NULL, ",");
5440 }
5441 }
5442#endif
5443 return RETURN_OK;
5444}
5445
5446INT wifi_setPreferPrivateConnection(BOOL enable)
5447{
5448 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5449 char buf[1024] = {0};
5450
5451 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5452 if(enable == TRUE)
5453 {
5454 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5455 sprintf(buf,"ifconfig %s down" ,interface_name);
5456 system(buf);
5457 memset(buf,0,sizeof(buf));
5458 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5459 sprintf(buf,"ifconfig %s down" ,interface_name);
5460 system(buf);
5461 }
5462 else
5463 {
5464 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5465 if(strcmp(ssid_cur_value,"1") == 0)
5466 wifi_RestartPrivateWifi_5G();
5467 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5468 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5469 if(strcmp(ssid_cur_value,"1") == 0)
5470 wifi_RestartHostapd_2G();
5471 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5472 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5473 if(strcmp(ssid_cur_value,"1") == 0)
5474 wifi_RestartHostapd_5G();
5475 }
5476 return RETURN_OK;
5477}
5478
5479// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5480INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5481{
5482 int items = 1;
5483 struct params list[2];
5484 char buf[MAX_BUF_SIZE] = {0};
5485 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005486 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005487
5488 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005489
developer10adcc12022-09-13 14:39:17 +08005490 if (filterMode == 0) {
5491 sprintf(buf, "%d", 0);
5492 list[0].value = buf;
5493
5494 char cmd[128], rtn[128];
5495 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5496 _syscmd(cmd, rtn, sizeof(rtn));
5497 memset(cmd,0,sizeof(cmd));
5498 // Delete deny_mac_file in hostapd configuration
5499 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5500 _syscmd(cmd, rtn, sizeof(rtn));
5501 }
5502 else if (filterMode == 1) {
5503 sprintf(buf, "%d", filterMode);
5504 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005505 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5506 list[1].name = "accept_mac_file";
5507 list[1].value = acl_file;
5508 items = 2;
developer10adcc12022-09-13 14:39:17 +08005509 } else if (filterMode == 2) {
5510 //TODO: deny_mac_file
5511 sprintf(buf, "%d", 0);
5512 list[0].value = buf;
5513 list[1].name = "deny_mac_file";
5514 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5515 list[1].value = deny_file;
5516 items = 2;
5517 } else {
5518 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005519 }
developer10adcc12022-09-13 14:39:17 +08005520
developer06a01d92022-09-07 16:32:39 +08005521 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5522 wifi_hostapdWrite(config_file, list, items);
5523
5524 return RETURN_OK;
5525
5526#if 0
5527 if(apIndex==0 || apIndex==1)
5528 {
5529 //set the filtermode
5530 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5531 system(buf);
5532 system("syscfg commit");
5533
5534 if(filterMode==0)
5535 {
5536 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5537 system(buf);
5538 return RETURN_OK;
5539 }
5540 }
5541 return RETURN_OK;
5542#endif
5543}
5544
5545// 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.
5546INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5547{
5548 return RETURN_ERR;
5549}
5550
5551// gets the vlan ID for this ap from an internal enviornment variable
5552INT wifi_getApVlanID(INT apIndex, INT *output_int)
5553{
5554 if(apIndex=0)
5555 {
5556 *output_int=100;
5557 return RETURN_OK;
5558 }
5559
5560 return RETURN_ERR;
5561}
5562
5563// sets the vlan ID for this ap to an internal enviornment variable
5564INT wifi_setApVlanID(INT apIndex, INT vlanId)
5565{
5566 //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)
5567 return RETURN_ERR;
5568}
5569
5570// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5571INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5572{
5573 snprintf(bridgeName, 32, "brlan0");
5574 snprintf(IP, 32, "10.0.0.1");
5575 snprintf(subnet, 32, "255.255.255.0");
5576
5577 return RETURN_OK;
5578}
5579
5580//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5581INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5582{
5583 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5584 return RETURN_ERR;
5585}
5586
5587// reset the vlan configuration for this ap
5588INT wifi_resetApVlanCfg(INT apIndex)
5589{
developerf5fef612022-09-20 19:38:26 +08005590 char original_config_file[64] = {0};
5591 char current_config_file[64] = {0};
5592 char buf[64] = {0};
5593 char cmd[64] = {0};
5594 char vlan_file[64] = {0};
5595 char vlan_tagged_interface[16] = {0};
5596 char vlan_bridge[16] = {0};
5597 char vlan_naming[16] = {0};
5598 struct params list[4] = {0};
5599 wifi_band band;
5600
5601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5602
5603 band = wifi_index_to_band(apIndex);
5604 if (band == band_2_4)
5605 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5606 else if (band = band_5)
5607 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5608 else if (band = band_6)
5609 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5610
5611 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5612
5613 if (strlen(vlan_file) == 0)
5614 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005615
developerf5fef612022-09-20 19:38:26 +08005616 // The file should exist or this vap would not work.
5617 if (access(vlan_file, F_OK) != 0) {
5618 sprintf(cmd, "touch %s", vlan_file);
5619 _syscmd(cmd, buf, sizeof(buf));
5620 }
5621 list[0].name = "vlan_file";
5622 list[0].value = vlan_file;
5623
5624 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5625 list[1].name = "vlan_tagged_interface";
5626 list[1].value = vlan_tagged_interface;
5627
5628 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5629 list[2].name = "vlan_bridge";
5630 list[2].value = vlan_bridge;
5631
5632 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5633 list[3].name = "vlan_naming";
5634 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005635
developerf5fef612022-09-20 19:38:26 +08005636 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5637 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005638 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005639 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005640
developerf5fef612022-09-20 19:38:26 +08005641 // restart this ap
5642 wifi_setApEnable(apIndex, FALSE);
5643 wifi_setApEnable(apIndex, TRUE);
5644
5645 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5646
5647 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005648}
5649
5650// 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.
5651INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5652{
5653 return RETURN_ERR;
5654}
5655
5656// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5657INT wifi_startHostApd()
5658{
5659 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5660 system("systemctl start hostapd.service");
5661 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5662 return RETURN_OK;
5663 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5664}
5665
5666// stops hostapd
5667INT wifi_stopHostApd()
5668{
5669 char cmd[128] = {0};
5670 char buf[128] = {0};
5671
5672 sprintf(cmd,"systemctl stop hostapd");
5673 _syscmd(cmd, buf, sizeof(buf));
5674
5675 return RETURN_OK;
5676}
5677
5678// restart hostapd dummy function
5679INT wifi_restartHostApd()
5680{
5681 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5682 system("systemctl restart hostapd-global");
5683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5684
5685 return RETURN_OK;
5686}
5687
5688static int align_hostapd_config(int index)
5689{
5690 ULONG lval;
5691 wifi_getRadioChannel(index%2, &lval);
5692 wifi_setRadioChannel(index%2, lval);
5693}
5694
5695// sets the AP enable status variable for the specified ap.
5696INT wifi_setApEnable(INT apIndex, BOOL enable)
5697{
5698 char config_file[MAX_BUF_SIZE] = {0};
5699 char cmd[MAX_CMD_SIZE] = {0};
5700 char buf[MAX_BUF_SIZE] = {0};
5701 BOOL status;
5702
5703 wifi_getApEnable(apIndex,&status);
5704 if (enable == status)
5705 return RETURN_OK;
5706
5707 if (enable == TRUE) {
5708 int radioIndex = apIndex % NUMBER_OF_RADIOS;
developer06a01d92022-09-07 16:32:39 +08005709 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5710 //Hostapd will bring up this interface
5711 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5712 _syscmd(cmd, buf, sizeof(buf));
5713 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5714 _syscmd(cmd, buf, sizeof(buf));
5715 }
5716 else {
5717 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5718 _syscmd(cmd, buf, sizeof(buf));
5719 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5720 _syscmd(cmd, buf, sizeof(buf));
5721 }
5722 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5723 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5724 _syscmd(cmd, buf, sizeof(buf));
5725 //Wait for wifi up/down to apply
5726 return RETURN_OK;
5727}
5728
5729// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5730INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5731{
5732 char cmd[MAX_CMD_SIZE] = {'\0'};
5733 char buf[MAX_BUF_SIZE] = {'\0'};
5734
5735 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5736 return RETURN_ERR;
5737
5738 *output_bool = 0;
5739
5740 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5741 {
developer70490032022-09-13 15:45:20 +08005742 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005743 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5744 }
5745
5746 return RETURN_OK;
5747}
5748
5749// Outputs the AP "Enabled" "Disabled" status from driver
5750INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5751{
5752 char cmd[128] = {0};
5753 char buf[128] = {0};
5754 BOOL output_bool;
5755
5756 if ( NULL == output_string)
5757 return RETURN_ERR;
5758 wifi_getApEnable(apIndex,&output_bool);
5759
5760 if(output_bool == 1)
5761 snprintf(output_string, 32, "Up");
5762 else
5763 snprintf(output_string, 32, "Disable");
5764
5765 return RETURN_OK;
5766}
5767
5768//Indicates whether or not beacons include the SSID name.
5769// outputs a 1 if SSID on the AP is enabled, else outputs 0
5770INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5771{
5772 //get the running status
5773 char config_file[MAX_BUF_SIZE] = {0};
5774 char buf[16] = {0};
5775
5776 if (!output)
5777 return RETURN_ERR;
5778
5779 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5780 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5781 *output = (strncmp("0",buf,1) == 0);
5782
5783 return RETURN_OK;
5784}
5785
5786// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5787INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5788{
5789 //store the config, apply instantly
5790 char config_file[MAX_BUF_SIZE] = {0};
5791 struct params list;
5792
5793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5794 list.name = "ignore_broadcast_ssid";
5795 list.value = enable?"0":"1";
5796
5797 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5798 wifi_hostapdWrite(config_file, &list, 1);
5799 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5800 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005801 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005802 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5803
5804 return RETURN_OK;
5805}
5806
5807//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5808INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5809{
5810 //get the running status
5811 if(!output_uint)
5812 return RETURN_ERR;
5813 *output_uint=16;
5814 return RETURN_OK;
5815}
5816
5817INT wifi_setApRetryLimit(INT apIndex, UINT number)
5818{
5819 //apply instantly
5820 return RETURN_ERR;
5821}
5822
5823//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5824INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5825{
5826 if(!output)
5827 return RETURN_ERR;
5828 *output=TRUE;
5829 return RETURN_OK;
5830}
5831
5832//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5833INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5834{
5835 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005836 char cmd[128] = {0};
5837 char buf[128] = {0};
5838 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005839
developer0b246d12022-09-30 15:24:20 +08005840 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005841
developer0b246d12022-09-30 15:24:20 +08005842 wifi_getMaxRadioNumber(&max_radio_num);
5843 radioIndex = apIndex % max_radio_num;
5844 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5845 _syscmd(cmd,buf, sizeof(buf));
5846
5847 if (strlen(buf) > 0)
5848 *output = true;
5849
5850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005851
developer06a01d92022-09-07 16:32:39 +08005852 return RETURN_OK;
5853}
5854
5855//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5856INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5857{
5858 //get the running status from driver
5859 if(!output)
5860 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005861
5862 char config_file[MAX_BUF_SIZE] = {0};
5863 char buf[16] = {0};
5864
5865 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5866 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5867 if (strncmp("1",buf,1) == 0)
5868 *output = TRUE;
5869 else
5870 *output = FALSE;
5871
developer06a01d92022-09-07 16:32:39 +08005872 return RETURN_OK;
5873}
5874
5875// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5876INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5877{
5878 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005879 char config_file[MAX_BUF_SIZE] = {0};
5880 struct params list;
5881
5882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5883 list.name = "wmm_enabled";
5884 list.value = enable?"1":"0";
5885
5886 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5887 wifi_hostapdWrite(config_file, &list, 1);
5888 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5889 wifi_reloadAp(apIndex);
5890 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5891
5892 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005893}
5894
5895//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.
5896INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5897{
5898 //get the running status from driver
5899 if(!output)
5900 return RETURN_ERR;
5901 *output=TRUE;
5902 return RETURN_OK;
5903}
5904
5905// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5906INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5907{
5908 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005909 char config_file[MAX_BUF_SIZE] = {0};
5910 struct params list;
5911
5912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5913 list.name = "uapsd_advertisement_enabled";
5914 list.value = enable?"1":"0";
5915
5916 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5917 wifi_hostapdWrite(config_file, &list, 1);
5918 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5919 wifi_reloadAp(apIndex);
5920 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5921
5922 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005923}
5924
developer6daeb3f2022-09-30 13:36:39 +08005925// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005926INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5927{
developer6daeb3f2022-09-30 13:36:39 +08005928 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5929 char cmd[128] = {0};
5930 char buf[128] = {0};
5931 char ack_filepath[128] = {0};
5932 uint16_t bitmap = 0;
5933 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5934 FILE *f = NULL;
5935
5936 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5937
5938 // Get current setting
5939 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5940 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5941 _syscmd(cmd, buf, sizeof(buf));
5942 if (strlen(buf) > 0)
5943 bitmap = strtoul(buf, NULL, 10);
5944
5945 bitmap = strtoul(buf, NULL, 10);
5946
5947 if (ackPolicy == TRUE) { // True, unset this class
5948 bitmap &= ~class_map[class];
5949 } else { // False, set this class
5950 bitmap |= class_map[class];
5951 }
5952
5953 f = fopen(ack_filepath, "w");
5954 if (f == NULL) {
5955 fprintf(stderr, "%s: fopen failed\n", __func__);
5956 return RETURN_ERR;
5957 }
5958 fprintf(f, "%hu", bitmap);
5959 fclose(f);
5960
5961 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5962 _syscmd(cmd, buf, sizeof(buf));
5963
5964 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5965 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005966}
5967
5968//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.
5969INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5970{
5971 //get the running status from driver
5972 if(!output_uint)
5973 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005974
5975 char output[16]={'\0'};
5976 char config_file[MAX_BUF_SIZE] = {0};
5977
5978 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5979 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5980 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5981 else {
5982 int device_num = atoi(output);
5983 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5984 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5985 return RETURN_ERR;
5986 }
5987 else {
5988 *output_uint = device_num;
5989 }
5990 }
5991
developer06a01d92022-09-07 16:32:39 +08005992 return RETURN_OK;
5993}
5994
5995INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5996{
5997 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005998 char str[MAX_BUF_SIZE]={'\0'};
5999 char cmd[MAX_CMD_SIZE]={'\0'};
6000 struct params params;
6001 char config_file[MAX_BUF_SIZE] = {0};
6002
6003 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6004 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6005 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6006 return RETURN_ERR;
6007 }
6008 sprintf(str, "%d", number);
6009 params.name = "max_num_sta";
6010 params.value = str;
6011
6012 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6013 int ret = wifi_hostapdWrite(config_file, &params, 1);
6014 if (ret) {
6015 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6016 ,__func__, ret);
6017 }
6018
6019 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6020 if (ret) {
6021 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6022 ,__func__, ret);
6023 }
6024 wifi_reloadAp(apIndex);
6025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6026
6027 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006028}
6029
6030//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.
6031INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6032{
6033 //get the current threshold
6034 if(!output_uint)
6035 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006036 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6037 if (*output_uint == 0)
6038 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006039 return RETURN_OK;
6040}
6041
6042INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6043{
6044 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006045 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6046 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006047 return RETURN_ERR;
6048}
6049
6050//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.
6051INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6052{
6053 if(!output_uint)
6054 return RETURN_ERR;
6055 *output_uint = 3;
6056 return RETURN_OK;
6057}
6058
6059//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6060INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6061{
6062 if(!output_uint)
6063 return RETURN_ERR;
6064 *output_uint = 3;
6065 return RETURN_OK;
6066}
6067
6068//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.
6069INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6070{
6071 if(!output_in_seconds)
6072 return RETURN_ERR;
6073 *output_in_seconds = 0;
6074 return RETURN_OK;
6075}
6076
6077//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
6078INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6079{
6080 if(!output || apIndex>=MAX_APS)
6081 return RETURN_ERR;
6082 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006083 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006084 return RETURN_OK;
6085}
6086
6087//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6088INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6089{
developer587c1b62022-09-27 15:58:59 +08006090 char config_file[128] = {0};
6091 char wpa[16] = {0};
6092 char key_mgmt[64] = {0};
6093 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006094 if (!output)
6095 return RETURN_ERR;
6096
6097 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006098 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006099
developer587c1b62022-09-27 15:58:59 +08006100 strcpy(output, "None");//Copying "None" to output string for default case
6101 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6102 if (strstr(key_mgmt, "WPA-PSK")) {
developer517a9792022-10-05 19:37:42 +08006103 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006104 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006105 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006106 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006107 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006108 snprintf(output, 32, "WPA-WPA2-Personal");
6109
6110 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006111 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006112 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006113 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006114 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006115 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006116 snprintf(output, 32, "WPA-WPA2-Enterprise");
6117 } else if (strstr(key_mgmt, "SAE")) {
6118 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6119 int disable = strtol(buf, NULL, 16);
6120 if (disable & 0x1)
6121 snprintf(output, 32, "WPA3-Personal");
6122 else
6123 snprintf(output, 32, "WPA3-Transition");
6124 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6125 snprintf(output, 32, "WPA3-Enterprise");
6126 }
developer06a01d92022-09-07 16:32:39 +08006127
6128 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6129 return RETURN_OK;
6130#if 0
6131 //TODO: need to revisit below implementation
6132 char securityType[32], authMode[32];
6133 int enterpriseMode=0;
6134
6135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6136 if(!output)
6137 return RETURN_ERR;
6138
6139 wifi_getApBeaconType(apIndex, securityType);
6140 strcpy(output,"None");//By default, copying "None" to output string
6141 if (strncmp(securityType,"None", strlen("None")) == 0)
6142 return RETURN_OK;
6143
6144 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6145 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6146
6147 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6148 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6149 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6150 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6151 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6152 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6153 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6154
6155 return RETURN_OK;
6156#endif
6157}
6158
6159INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6160{
6161 char securityType[32];
6162 char authMode[32];
6163
6164 //store settings and wait for wifi up to apply
6165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6166 if(!encMode)
6167 return RETURN_ERR;
6168
developer06a01d92022-09-07 16:32:39 +08006169 if (strcmp(encMode, "None")==0)
6170 {
6171 strcpy(securityType,"None");
6172 strcpy(authMode,"None");
6173 }
6174 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6175 {
6176 strcpy(securityType,"WPAand11i");
6177 strcpy(authMode,"PSKAuthentication");
6178 }
6179 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6180 {
6181 strcpy(securityType,"WPAand11i");
6182 strcpy(authMode,"EAPAuthentication");
6183 }
6184 else if (strcmp(encMode, "WPA-Personal")==0)
6185 {
6186 strcpy(securityType,"WPA");
6187 strcpy(authMode,"PSKAuthentication");
6188 }
6189 else if (strcmp(encMode, "WPA-Enterprise")==0)
6190 {
6191 strcpy(securityType,"WPA");
6192 strcpy(authMode,"EAPAuthentication");
6193 }
6194 else if (strcmp(encMode, "WPA2-Personal")==0)
6195 {
6196 strcpy(securityType,"11i");
6197 strcpy(authMode,"PSKAuthentication");
6198 }
6199 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6200 {
6201 strcpy(securityType,"11i");
6202 strcpy(authMode,"EAPAuthentication");
6203 }
developer587c1b62022-09-27 15:58:59 +08006204 else if (strcmp(encMode, "WPA3-Personal") == 0)
6205 {
6206 strcpy(securityType,"11i");
6207 strcpy(authMode,"SAEAuthentication");
6208 }
developer9df4e652022-10-11 11:27:38 +08006209 else if (strcmp(encMode, "WPA3-Transition") == 0)
6210 {
6211 strcpy(securityType, "11i");
6212 strcpy(authMode, "PSK-SAEAuthentication");
6213 }
developer587c1b62022-09-27 15:58:59 +08006214 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6215 {
6216 strcpy(securityType,"11i");
6217 strcpy(authMode,"EAP_192-bit_Authentication");
6218 }
developer06a01d92022-09-07 16:32:39 +08006219 else
6220 {
6221 strcpy(securityType,"None");
6222 strcpy(authMode,"None");
6223 }
6224 wifi_setApBeaconType(apIndex, securityType);
6225 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6226 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6227
6228 return RETURN_OK;
6229}
6230
6231
6232//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6233// output_string must be pre-allocated as 64 character string by caller
6234// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6235INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6236{
6237 char buf[16];
6238 char config_file[MAX_BUF_SIZE] = {0};
6239
6240 if(output_string==NULL)
6241 return RETURN_ERR;
6242
6243 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6244 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6245
6246 if(strcmp(buf,"0")==0)
6247 {
6248 printf("wpa_mode is %s ......... \n",buf);
6249 return RETURN_ERR;
6250 }
6251
6252 wifi_dbg_printf("\nFunc=%s\n",__func__);
6253 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6254 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6255 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6256
6257 return RETURN_OK;
6258}
6259
6260// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6261// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6262INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6263{
6264 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6265 struct params params={'\0'};
6266 int ret;
6267 char config_file[MAX_BUF_SIZE] = {0};
6268
6269 if(NULL == preSharedKey)
6270 return RETURN_ERR;
6271
6272 params.name = "wpa_passphrase";
6273
6274 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6275 {
6276 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6277 return RETURN_ERR;
6278 }
6279 params.value = preSharedKey;
6280 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6281 ret = wifi_hostapdWrite(config_file, &params, 1);
6282 if(!ret)
6283 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6284 return ret;
6285 //TODO: call hostapd_cli for dynamic_config_control
6286}
6287
6288//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6289// outputs the passphrase, maximum 63 characters
6290INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6291{
6292 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6293
6294 wifi_dbg_printf("\nFunc=%s\n",__func__);
6295 if (NULL == output_string)
6296 return RETURN_ERR;
6297
6298 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6299 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6300 if(strcmp(buf,"0")==0)
6301 {
6302 printf("wpa_mode is %s ......... \n",buf);
6303 return RETURN_ERR;
6304 }
6305
6306 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6307 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6308
6309 return RETURN_OK;
6310}
6311
6312// sets the passphrase enviornment variable, max 63 characters
6313INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6314{
6315 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6316 struct params params={'\0'};
6317 char config_file[MAX_BUF_SIZE] = {0};
6318 int ret;
6319
6320 if(NULL == passPhrase)
6321 return RETURN_ERR;
6322
6323 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6324 {
6325 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6326 return RETURN_ERR;
6327 }
6328 params.name = "wpa_passphrase";
6329 params.value = passPhrase;
6330 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6331 ret=wifi_hostapdWrite(config_file,&params,1);
6332 if(!ret)
6333 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6334
6335 return ret;
6336}
6337
6338//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.
6339INT wifi_setApSecurityReset(INT apIndex)
6340{
developer8d583982022-09-20 11:28:22 +08006341 char original_config_file[64] = {0};
6342 char current_config_file[64] = {0};
6343 char buf[64] = {0};
6344 char cmd[64] = {0};
6345 char wpa[4] = {0};
6346 char wpa_psk[64] = {0};
6347 char wpa_passphrase[64] = {0};
6348 char wpa_psk_file[128] = {0};
6349 char wpa_key_mgmt[64] = {0};
6350 char wpa_pairwise[32] = {0};
6351 wifi_band band;
6352 struct params list[6];
6353
6354 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6355
6356 band = wifi_index_to_band(apIndex);
6357 if (band == band_2_4)
6358 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6359 else if (band = band_5)
6360 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6361 else if (band = band_6)
6362 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6363 else
6364 return RETURN_ERR;
6365
6366 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6367 list[0].name = "wpa";
6368 list[0].value = wpa;
6369
6370 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6371 list[1].name = "wpa_psk";
6372 list[1].value = wpa_psk;
6373
6374 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6375 list[2].name = "wpa_passphrase";
6376 list[2].value = wpa_passphrase;
6377
6378 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6379
6380 if (strlen(wpa_psk_file) == 0)
6381 strcpy(wpa_psk_file, PSK_FILE);
6382
6383 if (access(wpa_psk_file, F_OK) != 0) {
6384 sprintf(cmd, "touch %s", wpa_psk_file);
6385 _syscmd(cmd, buf, sizeof(buf));
6386 }
6387 list[3].name = "wpa_psk_file";
6388 list[3].value = wpa_psk_file;
6389
6390 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6391 list[4].name = "wpa_key_mgmt";
6392 list[4].value = wpa_key_mgmt;
6393
6394 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6395 list[5].name = "wpa_pairwise";
6396 list[5].value = wpa_pairwise;
6397
6398 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6399 wifi_hostapdWrite(current_config_file, list, 6);
6400
6401 wifi_setApEnable(apIndex, FALSE);
6402 wifi_setApEnable(apIndex, TRUE);
6403
6404 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6405 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006406}
6407
6408//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).
6409INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6410{
developer8f2ddd52022-09-13 15:39:24 +08006411 char config_file[64] = {0};
6412 char buf[64] = {0};
6413 char cmd[256] = {0};
6414
6415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6416
developer06a01d92022-09-07 16:32:39 +08006417 if(!IP_output || !Port_output || !RadiusSecret_output)
6418 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006419
developer8f2ddd52022-09-13 15:39:24 +08006420 // Read the first matched config
6421 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6422 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6423 _syscmd(cmd, buf, sizeof(buf));
6424 strncpy(IP_output, buf, 64);
6425
6426 memset(buf, 0, sizeof(buf));
6427 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6428 _syscmd(cmd, buf, sizeof(buf));
6429 *Port_output = atoi(buf);
6430
6431 memset(buf, 0, sizeof(buf));
6432 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6433 _syscmd(cmd, buf, sizeof(buf));
6434 strncpy(RadiusSecret_output, buf, 64);
6435
6436 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006437 return RETURN_OK;
6438}
6439
6440INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6441{
developer8f2ddd52022-09-13 15:39:24 +08006442 char config_file[64] = {0};
6443 char port_str[8] = {0};
6444 char cmd[256] = {0};
6445 char buf[128] = {0};
6446
6447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6448
6449 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6450
6451 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6452 _syscmd(cmd, buf, sizeof(buf));
6453 memset(cmd, 0, sizeof(cmd));
6454
6455 snprintf(port_str, sizeof(port_str), "%d", port);
6456 if (strlen(buf) == 0)
6457 // Append
6458 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6459 "auth_server_addr=%s\\n"
6460 "auth_server_port=%s\\n"
6461 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6462 else {
6463 // Delete the three lines setting after the "# radius 1" comment
6464 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6465 _syscmd(cmd, buf, sizeof(buf));
6466 memset(cmd, 0, sizeof(cmd));
6467 // Use "# radius 1" comment to find the location to insert the radius setting
6468 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6469 "# radius 1\\n"
6470 "auth_server_addr=%s\\n"
6471 "auth_server_port=%s\\n"
6472 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6473 }
6474 if(_syscmd(cmd, buf, sizeof(buf))) {
6475 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6476 return RETURN_ERR;
6477 }
6478
6479 wifi_reloadAp(apIndex);
6480 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6481 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006482}
6483
6484INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6485{
developer8f2ddd52022-09-13 15:39:24 +08006486 char config_file[64] = {0};
6487 char buf[64] = {0};
6488 char cmd[256] = {0};
6489
6490 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6491
developer06a01d92022-09-07 16:32:39 +08006492 if(!IP_output || !Port_output || !RadiusSecret_output)
6493 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006494
6495 // Read the second matched config
6496 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6497 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6498 _syscmd(cmd, buf, sizeof(buf));
6499 strncpy(IP_output, buf, 64);
6500
6501 memset(buf, 0, sizeof(buf));
6502 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6503 _syscmd(cmd, buf, sizeof(buf));
6504 *Port_output = atoi(buf);
6505
6506 memset(buf, 0, sizeof(buf));
6507 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6508 _syscmd(cmd, buf, sizeof(buf));
6509 strncpy(RadiusSecret_output, buf, 64);
6510
6511 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006512 return RETURN_OK;
6513}
6514
6515INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6516{
developer8f2ddd52022-09-13 15:39:24 +08006517 char config_file[64] = {0};
6518 char port_str[8] = {0};
6519 char cmd[256] = {0};
6520 char buf[128] = {0};
6521
6522 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6523
6524 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6525
6526 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6527 _syscmd(cmd, buf, sizeof(buf));
6528 memset(cmd, 0, sizeof(cmd));
6529
6530 snprintf(port_str, sizeof(port_str), "%d", port);
6531 if (strlen(buf) == 0)
6532 // Append
6533 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6534 "auth_server_addr=%s\\n"
6535 "auth_server_port=%s\\n"
6536 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6537 else {
6538 // Delete the three lines setting after the "# radius 2" comment
6539 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6540 _syscmd(cmd, buf, sizeof(buf));
6541 memset(cmd, 0, sizeof(cmd));
6542 // Use "# radius 2" comment to find the location to insert the radius setting
6543 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6544 "# radius 2\\n"
6545 "auth_server_addr=%s\\n"
6546 "auth_server_port=%s\\n"
6547 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6548 }
6549 if(_syscmd(cmd, buf, sizeof(buf))) {
6550 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6551 return RETURN_ERR;
6552 }
6553
6554 wifi_reloadAp(apIndex);
6555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6556 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006557}
6558
6559//RadiusSettings
6560INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6561{
6562 if(!output)
6563 return RETURN_ERR;
6564
6565 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6566 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6567 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6568 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6569 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6570 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.
6571 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6572 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6573 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6574 //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.
6575
6576 return RETURN_OK;
6577}
6578
6579INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6580{
6581 //store the paramters, and apply instantly
6582 return RETURN_ERR;
6583}
6584
6585//Device.WiFi.AccessPoint.{i}.WPS.Enable
6586//Enables or disables WPS functionality for this access point.
6587// outputs the WPS enable state of this ap in output_bool
6588INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6589{
6590 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6591 if(!output_bool || !(apIndex==0 || apIndex==1))
6592 return RETURN_ERR;
6593 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6594 _syscmd(cmd, buf, sizeof(buf));
6595 if(strstr(buf, "configured"))
6596 *output_bool=TRUE;
6597 else
6598 *output_bool=FALSE;
6599
6600 return RETURN_OK;
6601}
6602
6603//Device.WiFi.AccessPoint.{i}.WPS.Enable
6604// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6605INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6606{
6607 char config_file[MAX_BUF_SIZE] = {0};
6608 struct params params;
6609
6610 if(!(apIndex==0 || apIndex==1))
6611 return RETURN_ERR;
6612 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6613 //store the paramters, and wait for wifi up to apply
6614 params.name = "wps_state";
6615 params.value = enable ? "2":"0";
6616
6617 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6618 wifi_hostapdWrite(config_file, &params, 1);
6619 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6620 wifi_reloadAp(apIndex);
6621
6622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6623 return RETURN_OK;
6624}
6625
6626//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
6627INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6628{
6629 if(!output)
6630 return RETURN_ERR;
6631 snprintf(output, 128, "PushButton,PIN");
6632 return RETURN_OK;
6633}
6634
6635//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6636//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.
6637// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6638INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6639{
6640 if(!output)
6641 return RETURN_ERR;
6642 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6643
6644 return RETURN_OK;
6645}
6646
6647//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6648// 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
6649INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6650{
6651 //apply instantly. No setting need to be stored.
6652 char methods[MAX_BUF_SIZE], *token, *next_token;
6653 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6654 struct params params;
6655
6656 if(!methodString || !(apIndex==0 || apIndex==1))
6657 return RETURN_ERR;
6658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6659 //store the paramters, and wait for wifi up to apply
6660
6661 snprintf(methods, sizeof(methods), "%s", methodString);
6662 for(token=methods; *token; token=next_token)
6663 {
6664 strtok_r(token, ",", &next_token);
6665 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6666 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6667 else if(*token=='E')
6668 {
6669 if(!strcmp(methods, "Ethernet"))
6670 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6671 else if(!strcmp(methods, "ExternalNFCToken"))
6672 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6673 else
6674 printf("%s: Unknown WpsConfigMethod\n", __func__);
6675 }
6676 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6677 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6678 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6679 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6680 else if(*token=='P' )
6681 {
6682 if(!strcmp(token, "PushButton"))
6683 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6684 else if(!strcmp(token, "PIN"))
6685 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6686 else
6687 printf("%s: Unknown WpsConfigMethod\n", __func__);
6688 }
6689 else
6690 printf("%s: Unknown WpsConfigMethod\n", __func__);
6691 }
6692 params.name = "config_methods";
6693 params.value = config_methods;
6694 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6695 wifi_hostapdWrite(config_file, &params, 1);
6696 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6698
6699 return RETURN_OK;
6700}
6701
6702// outputs the pin value, ulong_pin must be allocated by the caller
6703INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6704{
6705 char buf[MAX_BUF_SIZE] = {0};
6706 char cmd[MAX_CMD_SIZE] = {0};
6707
6708 if(!output_ulong || !(apIndex==0 || apIndex==1))
6709 return RETURN_ERR;
6710 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6711 _syscmd(cmd, buf, sizeof(buf));
6712 if(strlen(buf) > 0)
6713 *output_ulong=strtoul(buf, NULL, 10);
6714
6715 return RETURN_OK;
6716}
6717
6718// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6719INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6720{
6721 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6722 char ap_pin[16] = {0};
6723 char buf[MAX_BUF_SIZE] = {0};
6724 char config_file[MAX_BUF_SIZE] = {0};
6725 ULONG prev_pin = 0;
6726 struct params params;
6727
6728 if(!(apIndex==0 || apIndex==1))
6729 return RETURN_ERR;
6730 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6731 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6732 params.name = "ap_pin";
6733 params.value = ap_pin;
6734 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6735 wifi_hostapdWrite(config_file, &params, 1);
6736 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6738
6739 return RETURN_OK;
6740}
6741
6742// Output string is either Not configured or Configured, max 32 characters
6743INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6744{
6745 char cmd[MAX_CMD_SIZE];
6746 char buf[MAX_BUF_SIZE]={0};
6747
6748 if(!output_string || !(apIndex==0 || apIndex==1))
6749 return RETURN_ERR;
6750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6751 snprintf(output_string, 32, "Not configured");
6752 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6753 _syscmd(cmd, buf, sizeof(buf));
6754
developer348e3d92022-09-13 14:48:41 +08006755 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006756 snprintf(output_string, 32, "Configured");
6757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6758
6759 return RETURN_OK;
6760}
6761
6762// sets the WPS pin for this AP
6763INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6764{
6765 char cmd[MAX_CMD_SIZE];
6766 char buf[MAX_BUF_SIZE]={0};
6767 BOOL enable;
6768
6769 if(!(apIndex==0 || apIndex==1))
6770 return RETURN_ERR;
6771 wifi_getApEnable(apIndex, &enable);
6772 if (!enable)
6773 return RETURN_ERR;
6774 wifi_getApWpsEnable(apIndex, &enable);
6775 if (!enable)
6776 return RETURN_ERR;
6777
6778 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6779 _syscmd(cmd, buf, sizeof(buf));
6780 if((strstr(buf, "OK"))!=NULL)
6781 return RETURN_OK;
6782
6783 return RETURN_ERR;
6784}
6785
6786// This function is called when the WPS push button has been pressed for this AP
6787INT wifi_setApWpsButtonPush(INT apIndex)
6788{
6789 char cmd[MAX_CMD_SIZE];
6790 char buf[MAX_BUF_SIZE]={0};
6791 BOOL enable=FALSE;
6792
6793 if(!(apIndex==0 || apIndex==1))
6794 return RETURN_ERR;
6795 wifi_getApEnable(apIndex, &enable);
6796 if (!enable)
6797 return RETURN_ERR;
6798
6799 wifi_getApWpsEnable(apIndex, &enable);
6800 if (!enable)
6801 return RETURN_ERR;
6802
6803 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6804 _syscmd(cmd, buf, sizeof(buf));
6805
6806 if((strstr(buf, "OK"))!=NULL)
6807 return RETURN_OK;
6808 return RETURN_ERR;
6809}
6810
6811// cancels WPS mode for this AP
6812INT wifi_cancelApWPS(INT apIndex)
6813{
6814 char cmd[MAX_CMD_SIZE];
6815 char buf[MAX_BUF_SIZE]={0};
6816
6817 if(!(apIndex==0 || apIndex==1))
6818 return RETURN_ERR;
6819 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6820 _syscmd(cmd,buf, sizeof(buf));
6821
6822 if((strstr(buf, "OK"))!=NULL)
6823 return RETURN_OK;
6824 return RETURN_ERR;
6825}
6826
6827//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6828//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6829INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6830{
6831 FILE *f;
6832 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6833 char cmd[256], buf[2048];
6834 char *param , *value, *line=NULL;
6835 size_t len = 0;
6836 ssize_t nread;
6837 wifi_associated_dev_t *dev=NULL;
6838
6839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6840 *associated_dev_array = NULL;
6841 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6842 _syscmd(cmd,buf,sizeof(buf));
6843 *output_array_size = atoi(buf);
6844
6845 if (*output_array_size <= 0)
6846 return RETURN_OK;
6847
6848 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6849 *associated_dev_array = dev;
6850 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6851 _syscmd(cmd,buf,sizeof(buf));
6852 f = fopen("/tmp/connected_devices.txt", "r");
6853 if (f==NULL)
6854 {
6855 *output_array_size=0;
6856 return RETURN_ERR;
6857 }
6858 while ((nread = getline(&line, &len, f)) != -1)
6859 {
6860 param = strtok(line,"=");
6861 value = strtok(NULL,"=");
6862
6863 if( strcmp("flags",param) == 0 )
6864 {
6865 value[strlen(value)-1]='\0';
6866 if(strstr (value,"AUTHORIZED") != NULL )
6867 {
6868 dev[auth_temp].cli_AuthenticationState = 1;
6869 dev[auth_temp].cli_Active = 1;
6870 auth_temp++;
6871 read_flag=1;
6872 }
6873 }
6874 if(read_flag==1)
6875 {
6876 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6877 {
6878 value[strlen(value)-1]='\0';
6879 sscanf(value, "%x:%x:%x:%x:%x:%x",
6880 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6881 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6882 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6883 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6884 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6885 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6886 mac_temp++;
6887 read_flag=0;
6888 }
6889 }
6890 }
6891 *output_array_size = auth_temp;
6892 auth_temp=0;
6893 mac_temp=0;
6894 free(line);
6895 fclose(f);
6896 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6897 return RETURN_OK;
6898}
6899
6900#define MACADDRESS_SIZE 6
6901
6902INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6903{
6904 FILE *fp = NULL;
6905 char str[MAX_BUF_SIZE] = {0};
6906 int wificlientindex = 0 ;
6907 int count = 0;
6908 int signalstrength = 0;
6909 int arr[MACADDRESS_SIZE] = {0};
6910 unsigned char mac[MACADDRESS_SIZE] = {0};
6911 UINT wifi_count = 0;
6912 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6913 char pipeCmd[MAX_CMD_SIZE] = {0};
6914
6915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6916 *output_array_size = 0;
6917 *associated_dev_array = NULL;
6918
6919 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6920 fp = popen(pipeCmd, "r");
6921 if (fp == NULL)
6922 {
6923 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6924 return RETURN_ERR;
6925 }
6926
6927 /* Read the output a line at a time - output it. */
6928 fgets(str, sizeof(str)-1, fp);
6929 wifi_count = (unsigned int) atoi ( str );
6930 *output_array_size = wifi_count;
6931 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6932 pclose(fp);
6933
6934 if(wifi_count == 0)
6935 {
6936 return RETURN_OK;
6937 }
6938 else
6939 {
6940 wifi_associated_dev3_t* temp = NULL;
6941 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6942 if(temp == NULL)
6943 {
6944 printf("Error Statement. Insufficient memory \n");
6945 return RETURN_ERR;
6946 }
6947
6948 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6949 system(pipeCmd);
6950 memset(pipeCmd,0,sizeof(pipeCmd));
6951 if(apIndex == 0)
6952 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6953 else if(apIndex == 1)
6954 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6955 system(pipeCmd);
6956
6957 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6958 if(fp == NULL)
6959 {
6960 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6961 return RETURN_ERR;
6962 }
6963 fclose(fp);
6964
6965 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6966 fp = popen(pipeCmd, "r");
6967 if(fp)
6968 {
6969 for(count =0 ; count < wifi_count; count++)
6970 {
6971 fgets(str, MAX_BUF_SIZE, fp);
6972 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6973 {
6974 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6975 {
6976 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6977
6978 }
6979 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6980 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]);
6981 }
6982 temp[count].cli_AuthenticationState = 1; //TODO
6983 temp[count].cli_Active = 1; //TODO
6984 }
6985 pclose(fp);
6986 }
6987
6988 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6989 fp = popen(pipeCmd, "r");
6990 if(fp)
6991 {
6992 pclose(fp);
6993 }
6994 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6995 if(fp)
6996 {
6997 for(count =0 ; count < wifi_count ;count++)
6998 {
6999 fgets(str, MAX_BUF_SIZE, fp);
7000 signalstrength = atoi(str);
7001 temp[count].cli_SignalStrength = signalstrength;
7002 temp[count].cli_RSSI = signalstrength;
7003 temp[count].cli_SNR = signalstrength + 95;
7004 }
7005 pclose(fp);
7006 }
7007
7008
7009 if((apIndex == 0) || (apIndex == 4))
7010 {
7011 for(count =0 ; count < wifi_count ;count++)
7012 {
7013 strcpy(temp[count].cli_OperatingStandard,"g");
7014 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7015 }
7016
7017 //BytesSent
7018 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7019 fp = popen(pipeCmd, "r");
7020 if(fp)
7021 {
7022 pclose(fp);
7023 }
7024 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7025 if(fp)
7026 {
7027 for (count = 0; count < wifi_count; count++)
7028 {
7029 fgets(str, MAX_BUF_SIZE, fp);
7030 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7031 }
7032 pclose(fp);
7033 }
7034
7035 //BytesReceived
7036 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7037 fp = popen(pipeCmd, "r");
7038 if (fp)
7039 {
7040 pclose(fp);
7041 }
7042 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7043 if (fp)
7044 {
7045 for (count = 0; count < wifi_count; count++)
7046 {
7047 fgets(str, MAX_BUF_SIZE, fp);
7048 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7049 }
7050 pclose(fp);
7051 }
7052
7053 //PacketsSent
7054 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7055 fp = popen(pipeCmd, "r");
7056 if (fp)
7057 {
7058 pclose(fp);
7059 }
7060
7061 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7062 if (fp)
7063 {
7064 for (count = 0; count < wifi_count; count++)
7065 {
7066 fgets(str, MAX_BUF_SIZE, fp);
7067 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7068 }
7069 pclose(fp);
7070 }
7071
7072 //PacketsReceived
7073 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7074 fp = popen(pipeCmd, "r");
7075 if (fp)
7076 {
7077 pclose(fp);
7078 }
7079 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7080 if (fp)
7081 {
7082 for (count = 0; count < wifi_count; count++)
7083 {
7084 fgets(str, MAX_BUF_SIZE, fp);
7085 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7086 }
7087 pclose(fp);
7088 }
7089
7090 //ErrorsSent
7091 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7092 fp = popen(pipeCmd, "r");
7093 if (fp)
7094 {
7095 pclose(fp);
7096 }
7097 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7098 if (fp)
7099 {
7100 for (count = 0; count < wifi_count; count++)
7101 {
7102 fgets(str, MAX_BUF_SIZE, fp);
7103 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7104 }
7105 pclose(fp);
7106 }
7107
7108 //ErrorsSent
7109 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7110 fp = popen(pipeCmd, "r");
7111 if (fp)
7112 {
7113 pclose(fp);
7114 }
7115 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7116 if (fp)
7117 {
7118 for (count = 0; count < wifi_count; count++)
7119 {
7120 fgets(str, MAX_BUF_SIZE, fp);
7121 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7122 }
7123 pclose(fp);
7124 }
7125
7126 //LastDataDownlinkRate
7127 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7128 fp = popen(pipeCmd, "r");
7129 if (fp)
7130 {
7131 pclose(fp);
7132 }
7133 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7134 if (fp)
7135 {
7136 for (count = 0; count < wifi_count; count++)
7137 {
7138 fgets(str, MAX_BUF_SIZE, fp);
7139 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7140 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7141 }
7142 pclose(fp);
7143 }
7144
7145 //LastDataUplinkRate
7146 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7147 fp = popen(pipeCmd, "r");
7148 if (fp)
7149 {
7150 pclose(fp);
7151 }
7152 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7153 if (fp)
7154 {
7155 for (count = 0; count < wifi_count; count++)
7156 {
7157 fgets(str, MAX_BUF_SIZE, fp);
7158 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7159 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7160 }
7161 pclose(fp);
7162 }
7163
7164 }
7165 else if ((apIndex == 1) || (apIndex == 5))
7166 {
7167 for (count = 0; count < wifi_count; count++)
7168 {
7169 strcpy(temp[count].cli_OperatingStandard, "a");
7170 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7171 temp[count].cli_BytesSent = 0;
7172 temp[count].cli_BytesReceived = 0;
7173 temp[count].cli_LastDataUplinkRate = 0;
7174 temp[count].cli_LastDataDownlinkRate = 0;
7175 temp[count].cli_PacketsSent = 0;
7176 temp[count].cli_PacketsReceived = 0;
7177 temp[count].cli_ErrorsSent = 0;
7178 }
7179 }
7180
7181 for (count = 0; count < wifi_count; count++)
7182 {
7183 temp[count].cli_Retransmissions = 0;
7184 temp[count].cli_DataFramesSentAck = 0;
7185 temp[count].cli_DataFramesSentNoAck = 0;
7186 temp[count].cli_MinRSSI = 0;
7187 temp[count].cli_MaxRSSI = 0;
7188 strncpy(temp[count].cli_InterferenceSources, "", 64);
7189 memset(temp[count].cli_IPAddress, 0, 64);
7190 temp[count].cli_RetransCount = 0;
7191 temp[count].cli_FailedRetransCount = 0;
7192 temp[count].cli_RetryCount = 0;
7193 temp[count].cli_MultipleRetryCount = 0;
7194 }
7195 *associated_dev_array = temp;
7196 }
7197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7198 return RETURN_OK;
7199}
7200
7201int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7202{
7203 FILE *fp = NULL;
7204 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7205 char cmd[MAX_CMD_SIZE];
7206 int count = 0;
7207
7208 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7209 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7210 fp = popen(cmd,"r");
7211 if(fp == NULL)
7212 {
7213 printf("Failed to run command in Function %s\n",__FUNCTION__);
7214 return 0;
7215 }
7216 if(fgets(path, sizeof(path)-1, fp) != NULL)
7217 {
7218 for(count=0;path[count]!='\n';count++)
7219 status[count]=path[count];
7220 status[count]='\0';
7221 }
7222 strcpy(wifi_status,status);
7223 pclose(fp);
7224 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7225 return RETURN_OK;
7226}
7227
7228/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7229struct hostapd_sta_param {
7230 char key[50];
7231 char value[100];
7232}
7233
7234static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7235 int i = 0;
7236
7237 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7238 if (strncmp(params[i].key,key,50) == 0){
7239 return &params[i].value;
7240 }
7241 i++;
7242 }
7243 return NULL;
7244
7245} */
7246
7247static unsigned int count_occurences(const char *buf, const char *word)
7248{
7249 unsigned int n = 0;
7250 char *ptr = strstr(buf, word);
7251
7252 while (ptr++) {
7253 n++;
7254 ptr = strstr(ptr, word);
7255 }
7256
7257 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7258 return n;
7259}
7260
7261static const char *get_line_from_str_buf(const char *buf, char *line)
7262{
7263 int i;
7264 int n = strlen(buf);
7265
7266 for (i = 0; i < n; i++) {
7267 line[i] = buf[i];
7268 if (buf[i] == '\n') {
7269 line[i] = '\0';
7270 return &buf[i + 1];
7271 }
7272 }
7273
7274 return NULL;
7275}
7276
7277INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7278{
7279 unsigned int assoc_cnt = 0;
7280 char interface_name[50] = {0};
7281 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7282 char cmd[MAX_CMD_SIZE] = {'\0'};
7283 char line[256] = {'\0'};
7284 int i = 0;
7285 int ret = 0;
7286 const char *ptr = NULL;
7287 char *key = NULL;
7288 char *val = NULL;
7289 wifi_associated_dev3_t *temp = NULL;
7290 int rssi;
7291
7292 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7293
7294 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7295 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7296 return RETURN_ERR;
7297 }
7298
7299 // Example filtered output of 'iw dev' command:
7300 // Station 0a:69:72:10:d2:fa (on wifi0)
7301 // signal avg:-67 [-71, -71] dBm
7302 // Station 28:c2:1f:25:5f:99 (on wifi0)
7303 // signal avg:-67 [-71, -70] dBm
7304 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7305 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7306 return RETURN_ERR;
7307 }
7308
7309 ret = _syscmd(cmd, buf, sizeof(buf));
7310 if (ret == RETURN_ERR) {
7311 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7312 return RETURN_ERR;
7313 }
7314
7315 *output_array_size = count_occurences(buf, "Station");
7316 if (*output_array_size == 0) return RETURN_OK;
7317
7318 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7319 if (temp == NULL) {
7320 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7321 return RETURN_ERR;
7322 }
7323 *associated_dev_array = temp;
7324
7325 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7326 ptr = get_line_from_str_buf(buf, line);
7327 i = -1;
7328 while (ptr) {
7329 if (strstr(line, "Station")) {
7330 i++;
7331 key = strtok(line, " ");
7332 val = strtok(NULL, " ");
7333 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7334 &temp[i].cli_MACAddress[0],
7335 &temp[i].cli_MACAddress[1],
7336 &temp[i].cli_MACAddress[2],
7337 &temp[i].cli_MACAddress[3],
7338 &temp[i].cli_MACAddress[4],
7339 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7340 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7341 free(*associated_dev_array);
7342 return RETURN_ERR;
7343 }
7344 }
7345 else if (i < 0) {
7346 ptr = get_line_from_str_buf(ptr, line);
7347 continue; // We didn't detect 'station' entry yet
7348 }
7349 else if (strstr(line, "signal avg")) {
7350 key = strtok(line, ":");
7351 val = strtok(NULL, " ");
7352 if (sscanf(val, "%d", &rssi) <= 0 ) {
7353 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7354 free(*associated_dev_array);
7355 return RETURN_ERR;
7356 }
7357 temp[i].cli_RSSI = rssi;
7358 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7359 }
7360 // Here other fields can be parsed if added to filter of 'iw dev' command
7361
7362 ptr = get_line_from_str_buf(ptr, line);
7363 };
7364
7365 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7366
7367 return RETURN_OK;
7368}
7369
7370#if 0
7371//To-do
7372INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7373{
7374 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7375
7376 //Using different approach to get required WiFi Parameters from system available commands
7377#if 0
7378 FILE *f;
7379 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7380 char cmd[256], buf[2048];
7381 char *param , *value, *line=NULL;
7382 size_t len = 0;
7383 ssize_t nread;
7384 wifi_associated_dev3_t *dev=NULL;
7385 *associated_dev_array = NULL;
7386 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7387 _syscmd(cmd,buf,sizeof(buf));
7388 *output_array_size = atoi(buf);
7389
7390 if (*output_array_size <= 0)
7391 return RETURN_OK;
7392
7393 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7394 *associated_dev_array = dev;
7395 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7396 _syscmd(cmd,buf,sizeof(buf));
7397 f = fopen("/tmp/connected_devices.txt", "r");
7398 if (f==NULL)
7399 {
7400 *output_array_size=0;
7401 return RETURN_ERR;
7402 }
7403 while ((nread = getline(&line, &len, f)) != -1)
7404 {
7405 param = strtok(line,"=");
7406 value = strtok(NULL,"=");
7407
7408 if( strcmp("flags",param) == 0 )
7409 {
7410 value[strlen(value)-1]='\0';
7411 if(strstr (value,"AUTHORIZED") != NULL )
7412 {
7413 dev[auth_temp].cli_AuthenticationState = 1;
7414 dev[auth_temp].cli_Active = 1;
7415 auth_temp++;
7416 read_flag=1;
7417 }
7418 }
7419 if(read_flag==1)
7420 {
7421 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7422 {
7423 value[strlen(value)-1]='\0';
7424 sscanf(value, "%x:%x:%x:%x:%x:%x",
7425 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7426 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7427 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7428 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7429 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7430 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7431
7432 }
7433 else if( strcmp("rx_packets",param) == 0 )
7434 {
7435 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7436 }
7437
7438 else if( strcmp("tx_packets",param) == 0 )
7439 {
7440 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7441 }
7442
7443 else if( strcmp("rx_bytes",param) == 0 )
7444 {
7445 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7446 }
7447
7448 else if( strcmp("tx_bytes",param) == 0 )
7449 {
7450 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7451 mac_temp++;
7452 read_flag=0;
7453 }
7454 }
7455 }
7456
7457 *output_array_size = auth_temp;
7458 auth_temp=0;
7459 mac_temp=0;
7460 free(line);
7461 fclose(f);
7462#endif
7463 char interface_name[MAX_BUF_SIZE] = {0};
7464 char wifi_status[MAX_BUF_SIZE] = {0};
7465 char hostapdconf[MAX_BUF_SIZE] = {0};
7466
7467 wifi_associated_dev3_t *dev_array = NULL;
7468 ULONG wifi_count = 0;
7469
7470 *associated_dev_array = NULL;
7471 *output_array_size = 0;
7472
7473 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7474 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7475 {
7476 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7477
7478 GetInterfaceName(interface_name, hostapdconf);
7479
7480 if(strlen(interface_name) > 1)
7481 {
7482 wifihal_interfacestatus(wifi_status,interface_name);
7483 if(strcmp(wifi_status,"RUNNING") == 0)
7484 {
7485 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7486
7487 *associated_dev_array = dev_array;
7488 *output_array_size = wifi_count;
7489 }
7490 else
7491 {
7492 *associated_dev_array = NULL;
7493 }
7494 }
7495 }
7496
7497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7498 return RETURN_OK;
7499}
7500#endif
7501
7502/* getIPAddress function */
7503/**
7504* @description Returning IpAddress of the Matched String
7505*
7506* @param
7507* @str Having MacAddress
7508* @ipaddr Having ipaddr
7509* @return The status of the operation
7510* @retval RETURN_OK if successful
7511* @retval RETURN_ERR if any error is detected
7512*
7513*/
7514
7515INT getIPAddress(char *str,char *ipaddr)
7516{
7517 FILE *fp = NULL;
7518 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7519 int LeaseTime = 0,ret = 0;
7520 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7521 {
7522 return RETURN_ERR;
7523 }
7524
7525 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7526 {
7527 /*
7528 Sample:sss
7529 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7530 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7531 */
7532 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7533 &(LeaseTime),
7534 phyAddr,
7535 ipAddr,
7536 hostName
7537 );
7538 if(ret != 4)
7539 continue;
7540 if(strcmp(str,phyAddr) == 0)
7541 strcpy(ipaddr,ipAddr);
7542 }
7543 return RETURN_OK;
7544}
7545
7546/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7547/**
7548* @description Returning Inactive wireless connected clients informations
7549*
7550* @param
7551* @filename Holding private_wifi 2g/5g content files
7552* @associated_dev_array Having inactiv wireless clients informations
7553* @output_array_size Returning Inactive wireless counts
7554* @return The status of the operation
7555* @retval RETURN_OK if successful
7556* @retval RETURN_ERR if any error is detected
7557*
7558*/
7559
7560INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7561{
7562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7563 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7564 FILE *fp = NULL;
7565 int arr[MACADDRESS_SIZE] = {0};
7566 unsigned char mac[MACADDRESS_SIZE] = {0};
7567 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7568 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7569 fp = popen(buf,"r");
7570 if(fp == NULL)
7571 return RETURN_ERR;
7572 else
7573 {
7574 fgets(path,sizeof(path),fp);
7575 maccount = atoi(path);
7576 }
7577 pclose(fp);
7578 *output_array_size = maccount;
7579 wifi_associated_dev3_t* temp = NULL;
7580 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7581 *associated_dev_array = temp;
7582 if(temp == NULL)
7583 {
7584 printf("Error Statement. Insufficient memory \n");
7585 return RETURN_ERR;
7586 }
7587 memset(buf,0,sizeof(buf));
7588 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7589 fp = popen(buf,"r");
7590 for(count = 0; count < maccount ; count++)
7591 {
7592 fgets(path,sizeof(path),fp);
7593 for(i = 0; path[i]!='\n';i++)
7594 str[i]=path[i];
7595 str[i]='\0';
7596 getIPAddress(str,ipaddr);
7597 memset(buf,0,sizeof(buf));
7598 if(strlen(ipaddr) > 0)
7599 {
7600 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7601 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7602 {
7603 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7604 {
7605 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7606 {
7607 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7608
7609 }
7610 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7611 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]);
7612 }
7613 temp[count].cli_AuthenticationState = 0; //TODO
7614 temp[count].cli_Active = 0; //TODO
7615 temp[count].cli_SignalStrength = 0;
7616 }
7617 else //Active wireless clients info
7618 {
7619 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7620 {
7621 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7622 {
7623 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7624
7625 }
7626 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7627 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]);
7628 }
7629 temp[count].cli_Active = 1;
7630 }
7631 }
7632 memset(ipaddr,0,sizeof(ipaddr));
7633 }
7634 pclose(fp);
7635 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7636 return RETURN_OK;
7637}
7638//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7639//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7640//To get Band Steering Capability
7641INT wifi_getBandSteeringCapability(BOOL *support)
7642{
7643 *support = FALSE;
7644 return RETURN_OK;
7645}
7646
7647
7648//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7649//To get Band Steering enable status
7650INT wifi_getBandSteeringEnable(BOOL *enable)
7651{
7652 *enable = FALSE;
7653 return RETURN_OK;
7654}
7655
7656//To turn on/off Band steering
7657INT wifi_setBandSteeringEnable(BOOL enable)
7658{
7659 return RETURN_OK;
7660}
7661
7662//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7663//To get Band Steering AP group
7664INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7665{
7666 if (NULL == output_ApGroup)
7667 return RETURN_ERR;
7668
7669 strcpy(output_ApGroup, "1,2");
7670 return RETURN_OK;
7671}
7672
7673//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7674//to set and read the band steering BandUtilizationThreshold parameters
7675INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7676{
7677 return RETURN_ERR;
7678}
7679
7680INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7681{
7682 return RETURN_ERR;
7683}
7684
7685//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7686//to set and read the band steering RSSIThreshold parameters
7687INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7688{
7689 return RETURN_ERR;
7690}
7691
7692INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7693{
7694 return RETURN_ERR;
7695}
7696
7697
7698//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7699//to set and read the band steering physical modulation rate threshold parameters
7700INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7701{
7702 //If chip is not support, return -1
7703 return RETURN_ERR;
7704}
7705
7706INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7707{
7708 //If chip is not support, return -1
7709 return RETURN_ERR;
7710}
7711
7712//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7713//to set and read the inactivity time (in seconds) for steering under overload condition
7714INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7715{
7716 return RETURN_ERR;
7717}
7718
7719INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7720{
7721 return RETURN_ERR;
7722}
7723
7724//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7725//to set and read the inactivity time (in seconds) for steering under Idle condition
7726INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7727{
7728 return RETURN_ERR;
7729}
7730
7731INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7732{
7733 return RETURN_ERR;
7734}
7735
7736//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7737//pClientMAC[64]
7738//pSourceSSIDIndex[64]
7739//pDestSSIDIndex[64]
7740//pSteeringReason[256]
7741INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7742{
7743 //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
7744 *pSteeringTime=time(NULL);
7745 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7746 return RETURN_OK;
7747}
7748
7749INT wifi_ifConfigDown(INT apIndex)
7750{
7751 INT status = RETURN_OK;
7752 char cmd[64];
7753
7754 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7755 printf("%s: %s\n", __func__, cmd);
7756 system(cmd);
7757
7758 return status;
7759}
7760
7761INT wifi_ifConfigUp(INT apIndex)
7762{
7763 char cmd[128];
7764 char buf[1024];
7765
7766 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7767 _syscmd(cmd, buf, sizeof(buf));
7768 return 0;
7769}
7770
7771//>> Deprecated. Replace with wifi_applyRadioSettings
7772INT wifi_pushBridgeInfo(INT apIndex)
7773{
7774 char ip[32];
7775 char subnet[32];
7776 char bridge[32];
7777 int vlanId;
7778 char cmd[128];
7779 char buf[1024];
7780
7781 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7782 wifi_getApVlanID(apIndex,&vlanId);
7783
7784 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7785 _syscmd(cmd,buf, sizeof(buf));
7786
7787 return 0;
7788}
7789
7790INT wifi_pushChannel(INT radioIndex, UINT channel)
7791{
7792 char cmd[128];
7793 char buf[1024];
7794 int apIndex;
7795
7796 apIndex=(radioIndex==0)?0:1;
7797 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7798 _syscmd(cmd,buf, sizeof(buf));
7799
7800 return 0;
7801}
7802
7803INT wifi_pushChannelMode(INT radioIndex)
7804{
7805 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7806 return RETURN_ERR;
7807}
7808
7809INT wifi_pushDefaultValues(INT radioIndex)
7810{
7811 //Apply Comcast specified default radio settings instantly
7812 //AMPDU=1
7813 //AMPDUFrames=32
7814 //AMPDULim=50000
7815 //txqueuelen=1000
7816
7817 return RETURN_ERR;
7818}
7819
7820INT wifi_pushTxChainMask(INT radioIndex)
7821{
7822 //Apply default TxChainMask instantly
7823 return RETURN_ERR;
7824}
7825
7826INT wifi_pushRxChainMask(INT radioIndex)
7827{
7828 //Apply default RxChainMask instantly
7829 return RETURN_ERR;
7830}
7831
7832INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7833{
7834 INT status;
7835
7836 status = wifi_setSSIDName(apIndex,ssid);
7837 wifi_setApEnable(apIndex,FALSE);
7838 wifi_setApEnable(apIndex,TRUE);
7839
7840 return status;
7841}
7842
7843INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7844{
7845 //Apply default Ssid Advertisement instantly
7846 return RETURN_ERR;
7847}
7848
7849INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7850{
7851 INT status = RETURN_ERR;
7852 *output = 0;
7853 return RETURN_ERR;
7854}
7855
7856INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7857{
7858 return RETURN_OK;
7859}
7860
7861INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7862{
7863 return RETURN_OK;
7864}
7865
7866//To-do
7867INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7868{
developereb199ae2022-09-13 14:04:27 +08007869 char output[16]={'\0'};
7870 char config_file[MAX_BUF_SIZE] = {0};
7871
7872 if (!output_string)
7873 return RETURN_ERR;
7874
7875 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7876 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7877
7878 if (strlen(output) == 0)
7879 snprintf(output_string, 64, "Disabled");
7880 else if (strncmp(output, "0", 1) == 0)
7881 snprintf(output_string, 64, "Disabled");
7882 else if (strncmp(output, "1", 1) == 0)
7883 snprintf(output_string, 64, "Optional");
7884 else if (strncmp(output, "2", 1) == 0)
7885 snprintf(output_string, 64, "Required");
7886 else {
7887 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7888 return RETURN_ERR;
7889 }
7890
7891 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007892 return RETURN_OK;
7893}
7894INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7895{
developereb199ae2022-09-13 14:04:27 +08007896 char str[MAX_BUF_SIZE]={'\0'};
7897 char cmd[MAX_CMD_SIZE]={'\0'};
7898 struct params params;
7899 char config_file[MAX_BUF_SIZE] = {0};
7900
7901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7902 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7903 return RETURN_ERR;
7904
7905 params.name = "ieee80211w";
7906 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7907 params.value = "0";
7908 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7909 params.value = "1";
7910 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7911 params.value = "2";
7912 else{
7913 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7914 return RETURN_ERR;
7915 }
7916 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7917 wifi_hostapdWrite(config_file, &params, 1);
7918 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007919 return RETURN_OK;
7920}
7921INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7922{
7923 char output[16]={'\0'};
7924 char config_file[MAX_BUF_SIZE] = {0};
7925
7926 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7927 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7928 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7929
7930 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7931 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7932
7933 return RETURN_OK;
7934}
7935
7936INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7937{
7938 return RETURN_OK;
7939}
7940
7941INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7942{
7943 return RETURN_OK;
7944}
7945
7946INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7947{
7948 return RETURN_OK;
7949}
7950
7951INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7952{
7953 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7954 char config_file[MAX_BUF_SIZE] = {0};
7955
7956 if (NULL == output)
7957 return RETURN_ERR;
7958 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7959 wifi_hostapdRead(config_file,"hw_mode",output,64);
7960
7961 if(strcmp(output,"b")==0)
7962 sprintf(output, "%s", "1,2,5.5,11");
7963 else if (strcmp(output,"a")==0)
7964 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7965 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7966 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7967
7968 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7969 return RETURN_OK;
7970}
7971
7972INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7973{
7974 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7975 char *temp;
7976 char temp_output[128];
7977 char temp_TransmitRates[128];
7978 char config_file[MAX_BUF_SIZE] = {0};
7979
7980 if (NULL == output)
7981 return RETURN_ERR;
7982
7983 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7984 wifi_hostapdRead(config_file,"supported_rates",output,64);
7985
7986 strcpy(temp_TransmitRates,output);
7987 strcpy(temp_output,"");
7988 temp = strtok(temp_TransmitRates," ");
7989 while(temp!=NULL)
7990 {
7991 temp[strlen(temp)-1]=0;
7992 if((temp[0]=='5') && (temp[1]=='\0'))
7993 {
7994 temp="5.5";
7995 }
7996 strcat(temp_output,temp);
7997 temp = strtok(NULL," ");
7998 if(temp!=NULL)
7999 {
8000 strcat(temp_output,",");
8001 }
8002 }
8003 strcpy(output,temp_output);
8004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8005
8006 return RETURN_OK;
8007}
8008
8009INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8010{
8011 return RETURN_OK;
8012}
8013
8014
8015INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8016{
8017 int i=0;
8018 char *temp;
8019 char temp1[128];
8020 char temp_output[128];
8021 char temp_TransmitRates[128];
8022 struct params params={'\0'};
8023 char config_file[MAX_BUF_SIZE] = {0};
8024
8025 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8026 if(NULL == output)
8027 return RETURN_ERR;
8028
8029 strcpy(temp_TransmitRates,output);
8030
8031 for(i=0;i<strlen(temp_TransmitRates);i++)
8032 {
8033 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
8034 {
8035 continue;
8036 }
8037 else
8038 {
8039 return RETURN_ERR;
8040 }
8041 }
8042 strcpy(temp_output,"");
8043 temp = strtok(temp_TransmitRates," ");
8044 while(temp!=NULL)
8045 {
8046 strcpy(temp1,temp);
8047 if(wlanIndex==1)
8048 {
8049 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8050 {
8051 return RETURN_ERR;
8052 }
8053 }
8054
8055 if(strcmp(temp,"5.5")==0)
8056 {
8057 strcpy(temp1,"55");
8058 }
8059 else
8060 {
8061 strcat(temp1,"0");
8062 }
8063 strcat(temp_output,temp1);
8064 temp = strtok(NULL," ");
8065 if(temp!=NULL)
8066 {
8067 strcat(temp_output," ");
8068 }
8069 }
8070 strcpy(output,temp_output);
8071
8072
8073 params.name = "supported_rates";
8074 params.value = output;
8075
8076 wifi_dbg_printf("\n%s:",__func__);
8077 wifi_dbg_printf("params.value=%s\n",params.value);
8078 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8079 wifi_hostapdWrite(config_file,&params,1);
8080 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8081
8082 return RETURN_OK;
8083}
8084
8085
8086static char *sncopy(char *dst, int dst_sz, const char *src)
8087{
8088 if (src && dst && dst_sz > 0) {
8089 strncpy(dst, src, dst_sz);
8090 dst[dst_sz - 1] = '\0';
8091 }
8092 return dst;
8093}
8094
8095static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8096{
8097 if (0 == strcmp(ht_mode, "HT40") ||
8098 0 == strcmp(ht_mode, "HT80") ||
8099 0 == strcmp(ht_mode, "HT160")) {
8100 switch (channel) {
8101 case 1 ... 7:
8102 case 36:
8103 case 44:
8104 case 52:
8105 case 60:
8106 case 100:
8107 case 108:
8108 case 116:
8109 case 124:
8110 case 132:
8111 case 140:
8112 case 149:
8113 case 157:
8114 return 1;
8115 case 8 ... 13:
8116 case 40:
8117 case 48:
8118 case 56:
8119 case 64:
8120 case 104:
8121 case 112:
8122 case 120:
8123 case 128:
8124 case 136:
8125 case 144:
8126 case 153:
8127 case 161:
8128 return -1;
8129 default:
8130 return -EINVAL;
8131 }
8132 }
8133
8134 return -EINVAL;
8135}
8136
8137static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8138{
8139 if (NULL == hw_mode) return;
8140
8141 if (0 == strcmp(hw_mode, "ac"))
8142 sncopy(bw_mode, bw_mode_len, "ht vht");
8143
8144 if (0 == strcmp(hw_mode, "n"))
8145 sncopy(bw_mode, bw_mode_len, "ht");
8146
8147 return;
8148}
8149
8150static int util_chan_to_freq(int chan)
8151{
8152 if (chan == 14)
8153 return 2484;
8154 else if (chan < 14)
8155 return 2407 + chan * 5;
8156 else if (chan >= 182 && chan <= 196)
8157 return 4000 + chan * 5;
8158 else
8159 return 5000 + chan * 5;
8160 return 0;
8161}
8162
8163const int *util_unii_5g_chan2list(int chan, int width)
8164{
8165 static const int lists[] = {
8166 // <width>, <chan1>, <chan2>..., 0,
8167 20, 36, 0,
8168 20, 40, 0,
8169 20, 44, 0,
8170 20, 48, 0,
8171 20, 52, 0,
8172 20, 56, 0,
8173 20, 60, 0,
8174 20, 64, 0,
8175 20, 100, 0,
8176 20, 104, 0,
8177 20, 108, 0,
8178 20, 112, 0,
8179 20, 116, 0,
8180 20, 120, 0,
8181 20, 124, 0,
8182 20, 128, 0,
8183 20, 132, 0,
8184 20, 136, 0,
8185 20, 140, 0,
8186 20, 144, 0,
8187 20, 149, 0,
8188 20, 153, 0,
8189 20, 157, 0,
8190 20, 161, 0,
8191 20, 165, 0,
8192 40, 36, 40, 0,
8193 40, 44, 48, 0,
8194 40, 52, 56, 0,
8195 40, 60, 64, 0,
8196 40, 100, 104, 0,
8197 40, 108, 112, 0,
8198 40, 116, 120, 0,
8199 40, 124, 128, 0,
8200 40, 132, 136, 0,
8201 40, 140, 144, 0,
8202 40, 149, 153, 0,
8203 40, 157, 161, 0,
8204 80, 36, 40, 44, 48, 0,
8205 80, 52, 56, 60, 64, 0,
8206 80, 100, 104, 108, 112, 0,
8207 80, 116, 120, 124, 128, 0,
8208 80, 132, 136, 140, 144, 0,
8209 80, 149, 153, 157, 161, 0,
8210 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8211 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8212 -1 // final delimiter
8213 };
8214 const int *start;
8215 const int *p;
8216
8217 for (p = lists; *p != -1; p++) {
8218 if (*p == width) {
8219 for (start = ++p; *p != 0; p++) {
8220 if (*p == chan)
8221 return start;
8222 }
8223 }
8224 // move to the end of channel list of given width
8225 while (*p != 0) {
8226 p++;
8227 }
8228 }
8229
8230 return NULL;
8231}
8232
8233static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8234{
8235 if (NULL == ht_mode)
8236 return 0;
8237
8238 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8239 const int *chans = util_unii_5g_chan2list(channel, width);
8240 int sum = 0;
8241 int cnt = 0;
8242
8243 if (NULL == chans)
8244 return 0;
8245
8246 while (*chans) {
8247 sum += *chans;
8248 cnt++;
8249 chans++;
8250 }
8251 return sum / cnt;
8252}
8253
8254static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8255{
8256 BOOL onlyG, onlyN, onlyA;
8257 CHAR tmp[64];
8258 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8259 if (ret == RETURN_OK) {
8260 sncopy(hw_mode, hw_mode_size, tmp);
8261 }
8262 return ret;
8263}
8264
8265INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8266{
8267 // Sample commands:
8268 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8269 // hostapd_cli -i wifi0 chan_switch 30 2437
8270 char cmd[MAX_CMD_SIZE] = {0};
8271 char buf[MAX_BUF_SIZE] = {0};
8272 int freq = 0, ret = 0;
8273 char center_freq1_str[32] = ""; // center_freq1=%d
8274 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8275 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8276 char hw_mode[16] = ""; // n|ac
8277 char bw_mode[16] = ""; // ht|ht vht
8278 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8279 int sec_chan_offset;
8280 int width;
developer4fb0b922022-09-30 14:29:09 +08008281 char config_file[64] = {0};
8282 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008283 char *ext_str = "None";
8284
developer4fb0b922022-09-30 14:29:09 +08008285 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008286
8287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8288
developer5884e982022-10-06 10:52:50 +08008289 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008290
8291 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008292 if (channel){
8293 freq = util_chan_to_freq(channel);
8294 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8295 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8296 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8297 if (sec_chan_offset != -EINVAL)
8298 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008299
8300
developer5884e982022-10-06 10:52:50 +08008301 // Provide bandwith if specified
8302 if (channel_width_MHz > 20) {
8303 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8304 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8305 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008306
developer5884e982022-10-06 10:52:50 +08008307 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8308 }else if (channel_width_MHz == 20){
8309 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8310 }
developer06a01d92022-09-07 16:32:39 +08008311
developer5884e982022-10-06 10:52:50 +08008312 int center_chan = 0;
8313 if (channel_width_MHz > 20) {
8314 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8315 if (center_chan > 0) {
8316 int center_freq1 = util_chan_to_freq(center_chan);
8317 if (center_freq1)
8318 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8319 }
developer06a01d92022-09-07 16:32:39 +08008320 }
developer06a01d92022-09-07 16:32:39 +08008321
developer5884e982022-10-06 10:52:50 +08008322 // Only the first AP, other are hanging on the same radio
8323 int apIndex = radioIndex;
8324 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8325 AP_PREFIX, apIndex, csa_beacon_count, freq,
8326 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8327 wifi_dbg_printf("execute: '%s'\n", cmd);
8328 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008329
developer5884e982022-10-06 10:52:50 +08008330 ret = wifi_setRadioChannel(radioIndex, channel);
8331 if (ret != RETURN_OK) {
8332 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8333 return RETURN_ERR;
8334 }
8335
8336 if (sec_chan_offset == 1) ext_str = "Above";
8337 else if (sec_chan_offset == -1) ext_str = "Below";
8338
8339 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008340
developer5884e982022-10-06 10:52:50 +08008341 } else {
8342 if (channel_width_MHz > 20)
8343 ext_str = "Above";
8344 }
developer4fb0b922022-09-30 14:29:09 +08008345 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8346 _syscmd(cmd, buf, sizeof(buf));
8347 if (strlen(buf) != 0)
8348 stbcEnable = TRUE;
8349
developer06a01d92022-09-07 16:32:39 +08008350 wifi_setRadioExtChannel(radioIndex, ext_str);
8351
developer4fb0b922022-09-30 14:29:09 +08008352 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8353
developer06a01d92022-09-07 16:32:39 +08008354 char mhz_str[16];
8355 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8356 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8357
8358 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8359
8360 return RETURN_OK;
8361}
8362
8363INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8364{
developer615510b2022-09-27 10:14:35 +08008365 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008366 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008367 char cmd[256]={0};
8368 char buf[128]={0};
8369 char file_name[32] = {0};
8370 char filter_SSID[32] = {0};
8371 char line[256] = {0};
8372 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008373 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008374 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008375 size_t len=0;
8376 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008377 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008378 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008379 bool filter_enable = false;
8380 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008381
developer615510b2022-09-27 10:14:35 +08008382 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008383
developer615510b2022-09-27 10:14:35 +08008384 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8385 f = fopen(file_name, "r");
8386 if (f != NULL) {
8387 fgets(filter_SSID, sizeof(file_name), f);
8388 if (strlen(filter_SSID) != 0)
8389 filter_enable = true;
8390 fclose(f);
8391 }
8392
8393 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8394 _syscmd(cmd, buf, sizeof(buf));
8395 channels_num = strtol(buf, NULL, 10);
8396
developer615510b2022-09-27 10:14:35 +08008397 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8398 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radio_index, AP_PREFIX, radio_index);
8399 fprintf(stderr, "cmd: %s\n", cmd);
8400 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008401 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8402 return RETURN_ERR;
8403 }
developer5550e242022-09-30 09:59:32 +08008404
8405 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8406 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8407
developer615510b2022-09-27 10:14:35 +08008408 ret = fgets(line, sizeof(line), f);
8409 while (ret != NULL) {
8410 if(strstr(line, "BSS") != NULL) { // new neighbor info
8411 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8412 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8413 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8414
8415 if (!filter_BSS) {
8416 index++;
8417 wifi_neighbor_ap2_t *tmp;
8418 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8419 if (tmp == NULL) { // no more memory to use
8420 index--;
8421 wifi_dbg_printf("%s: realloc failed\n", __func__);
8422 break;
8423 }
8424 scan_array = tmp;
8425 }
8426 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008427
developer615510b2022-09-27 10:14:35 +08008428 filter_BSS = false;
8429 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8430 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8431 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8432 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8433 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008434 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008435 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008436
developer615510b2022-09-27 10:14:35 +08008437 if (freq >= 2412 && freq <= 2484) {
8438 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8439 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8440 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8441 }
8442 else if (freq >= 5160 && freq <= 5805) {
8443 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8444 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8445 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8446 }
developer06a01d92022-09-07 16:32:39 +08008447
developer615510b2022-09-27 10:14:35 +08008448 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008449 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008450 for (int i = 0; i < channels_num; i++) {
8451 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8452 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8453 break;
8454 }
8455 }
developer06a01d92022-09-07 16:32:39 +08008456 }
developer615510b2022-09-27 10:14:35 +08008457 } else if (strstr(line, "beacon interval") != NULL) {
8458 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8459 } else if (strstr(line, "signal") != NULL) {
8460 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8461 } else if (strstr(line,"SSID") != NULL) {
8462 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8463 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8464 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008465 }
developer615510b2022-09-27 10:14:35 +08008466 } else if (strstr(line, "Supported rates") != NULL) {
8467 char SRate[80] = {0}, *tmp = NULL;
8468 memset(buf, 0, sizeof(buf));
8469 strcpy(SRate, line);
8470 tmp = strtok(SRate, ":");
8471 tmp = strtok(NULL, ":");
8472 strcpy(buf, tmp);
8473 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008474
developer615510b2022-09-27 10:14:35 +08008475 tmp = strtok(buf, " \n");
8476 while (tmp != NULL) {
8477 strcat(SRate, tmp);
8478 if (SRate[strlen(SRate) - 1] == '*') {
8479 SRate[strlen(SRate) - 1] = '\0';
8480 }
8481 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008482
developer615510b2022-09-27 10:14:35 +08008483 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008484 }
developer615510b2022-09-27 10:14:35 +08008485 SRate[strlen(SRate) - 1] = '\0';
8486 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8487 } else if (strstr(line, "DTIM") != NULL) {
8488 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8489 } else if (strstr(line, "VHT capabilities") != NULL) {
8490 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8491 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8492 } else if (strstr(line, "HT capabilities") != NULL) {
8493 strcat(scan_array[index].ap_SupportedStandards, ",n");
8494 strcpy(scan_array[index].ap_OperatingStandards, "n");
8495 } else if (strstr(line, "VHT operation") != NULL) {
8496 ret = fgets(line, sizeof(line), f);
8497 sscanf(line," * channel width: %d", &vht_channel_width);
8498 if(vht_channel_width == 1) {
8499 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8500 } else {
8501 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8502 }
8503 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8504 continue;
8505 } else if (strstr(line, "HT operation") != NULL) {
8506 ret = fgets(line, sizeof(line), f);
8507 sscanf(line," * secondary channel offset: %s", &buf);
8508 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008509 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008510 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 +08008511 }
developer615510b2022-09-27 10:14:35 +08008512 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008513 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008514 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8515 } else {
8516 //20Mhz
8517 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 +08008518 }
developer615510b2022-09-27 10:14:35 +08008519 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008520 continue;
developer615510b2022-09-27 10:14:35 +08008521 } else if (strstr(line, "HE capabilities") != NULL) {
8522 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8523 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8524 ret = fgets(line, sizeof(line), f);
8525 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8526 if (strstr(line, "HE40/2.4GHz") != NULL)
8527 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8528 else
8529 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8530 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8531 if (strstr(line, "HE80/5GHz") != NULL) {
8532 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8533 ret = fgets(line, sizeof(line), f);
8534 } else
8535 continue;
8536 if (strstr(line, "HE160/5GHz") != NULL)
8537 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008538 }
developer615510b2022-09-27 10:14:35 +08008539 continue;
8540 } else if (strstr(line, "WPA") != NULL) {
8541 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8542 } else if (strstr(line, "RSN") != NULL) {
8543 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8544 } else if (strstr(line, "Group cipher") != NULL) {
8545 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8546 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8547 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008548 }
developer06a01d92022-09-07 16:32:39 +08008549 }
developer615510b2022-09-27 10:14:35 +08008550 ret = fgets(line, sizeof(line), f);
8551 }
8552
8553 if (!filter_BSS) {
8554 *output_array_size = index + 1;
8555 } else {
8556 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8557 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008558 }
developer06a01d92022-09-07 16:32:39 +08008559 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008560 pclose(f);
developer5550e242022-09-30 09:59:32 +08008561 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008563 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008564}
developer615510b2022-09-27 10:14:35 +08008565
developer06a01d92022-09-07 16:32:39 +08008566INT wifi_getApAssociatedDeviceStats(
8567 INT apIndex,
8568 mac_address_t *clientMacAddress,
8569 wifi_associated_dev_stats_t *associated_dev_stats,
8570 u64 *handle)
8571{
8572 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8573 char interface_name[50] = {0};
8574 char cmd[1024] = {0};
8575 char mac_str[18] = {0};
8576 char *key = NULL;
8577 char *val = NULL;
8578 FILE *f = NULL;
8579 char *line = NULL;
8580 size_t len = 0;
8581 ssize_t read = 0;
8582
8583 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8584 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8585 return RETURN_ERR;
8586 }
8587
8588 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8589 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8590 if((f = popen(cmd, "r")) == NULL) {
8591 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8592 return RETURN_ERR;
8593 }
8594
8595 while ((read = getline(&line, &len, f)) != -1) {
8596 key = strtok(line,":");
8597 val = strtok(NULL,":");
8598
8599 if(!strncmp(key,"rx bytes",8))
8600 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8601 if(!strncmp(key,"tx bytes",8))
8602 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8603 if(!strncmp(key,"rx packets",10))
8604 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8605 if(!strncmp(key,"tx packets",10))
8606 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8607 if(!strncmp(key,"tx retries",10))
8608 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8609 if(!strncmp(key,"tx failed",9))
8610 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8611 if(!strncmp(key,"rx drop misc",13))
8612 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8613 if(!strncmp(key,"rx bitrate",10)) {
8614 val = strtok(val, " ");
8615 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8616 }
8617 if(!strncmp(key,"tx bitrate",10)) {
8618 val = strtok(val, " ");
8619 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8620 }
8621 }
8622 free(line);
8623 pclose(f);
8624 return RETURN_OK;
8625}
8626
8627INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8628{
8629 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8630
8631 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8632 if (NULL == output_string)
8633 return RETURN_ERR;
8634
8635 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8636 _syscmd(cmd, buf, sizeof(buf));
8637
8638 //size of SSID name restricted to value less than 32 bytes
8639 snprintf(output_string, 32, "%s", buf);
8640 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8641
8642 return RETURN_OK;
8643}
8644
8645INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8646{
8647 //char cmd[MAX_CMD_SIZE] = {0};
8648 char config_file[MAX_BUF_SIZE] = {0};
8649 char buf[32] = {0};
8650
8651 if (!output_filterMode)
8652 return RETURN_ERR;
8653
8654 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8655 //_syscmd(cmd, buf, sizeof(buf));
8656 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8657 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008658 if(strlen(buf) == 0) {
8659 *output_filterMode = 0;
8660 }
8661 else {
8662 int macaddr_acl_mode = strtol(buf, NULL, 10);
8663 if (macaddr_acl_mode == 1) {
8664 *output_filterMode = 1;
8665 } else if (macaddr_acl_mode == 0) {
8666 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8667 if (strlen(buf) == 0) {
8668 *output_filterMode = 0;
8669 } else {
8670 *output_filterMode = 2;
8671 }
8672 } else {
8673 return RETURN_ERR;
8674 }
8675 }
developer06a01d92022-09-07 16:32:39 +08008676
8677 return RETURN_OK;
8678}
8679
8680INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8681{
8682 FILE *fp = NULL;
8683 char str[MAX_BUF_SIZE] = {0};
8684 int wificlientindex = 0 ;
8685 int count = 0;
8686 int signalstrength = 0;
8687 int arr[MACADDRESS_SIZE] = {0};
8688 unsigned char mac[MACADDRESS_SIZE] = {0};
8689 UINT wifi_count = 0;
8690 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8691 char pipeCmd[MAX_CMD_SIZE] = {0};
8692
8693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8694 *output_array_size = 0;
8695 *associated_dev_array = NULL;
8696 char interface_name[50] = {0};
8697
8698 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8699 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8700 return RETURN_ERR;
8701 }
8702
8703 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8704 fp = popen(pipeCmd, "r");
8705 if (fp == NULL)
8706 {
8707 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8708 return RETURN_ERR;
8709 }
8710
8711 /* Read the output a line at a time - output it. */
8712 fgets(str, sizeof(str)-1, fp);
8713 wifi_count = (unsigned int) atoi ( str );
8714 *output_array_size = wifi_count;
8715 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8716 pclose(fp);
8717
8718 if(wifi_count == 0)
8719 {
8720 return RETURN_OK;
8721 }
8722 else
8723 {
8724 wifi_associated_dev2_t* temp = NULL;
8725 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8726 *associated_dev_array = temp;
8727 if(temp == NULL)
8728 {
8729 printf("Error Statement. Insufficient memory \n");
8730 return RETURN_ERR;
8731 }
8732
8733 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8734 system(pipeCmd);
8735
8736 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8737 if(fp == NULL)
8738 {
8739 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8740 return RETURN_ERR;
8741 }
8742 fclose(fp);
8743
8744 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8745 fp = popen(pipeCmd, "r");
8746 if(fp)
8747 {
8748 for(count =0 ; count < wifi_count; count++)
8749 {
8750 fgets(str, MAX_BUF_SIZE, fp);
8751 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8752 {
8753 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8754 {
8755 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8756
8757 }
8758 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8759 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]);
8760 }
8761 temp[count].cli_AuthenticationState = 1; //TODO
8762 temp[count].cli_Active = 1; //TODO
8763 }
8764 pclose(fp);
8765 }
8766
8767 //Updating RSSI per client
8768 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8769 fp = popen(pipeCmd, "r");
8770 if(fp)
8771 {
8772 pclose(fp);
8773 }
8774 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8775 if(fp)
8776 {
8777 for(count =0 ; count < wifi_count ;count++)
8778 {
8779 fgets(str, MAX_BUF_SIZE, fp);
8780 signalstrength = atoi(str);
8781 temp[count].cli_RSSI = signalstrength;
8782 }
8783 pclose(fp);
8784 }
8785
8786
8787 //LastDataDownlinkRate
8788 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8789 fp = popen(pipeCmd, "r");
8790 if (fp)
8791 {
8792 pclose(fp);
8793 }
8794 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8795 if (fp)
8796 {
8797 for (count = 0; count < wifi_count; count++)
8798 {
8799 fgets(str, MAX_BUF_SIZE, fp);
8800 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8801 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8802 }
8803 pclose(fp);
8804 }
8805
8806 //LastDataUplinkRate
8807 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8808 fp = popen(pipeCmd, "r");
8809 if (fp)
8810 {
8811 pclose(fp);
8812 }
8813 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8814 if (fp)
8815 {
8816 for (count = 0; count < wifi_count; count++)
8817 {
8818 fgets(str, MAX_BUF_SIZE, fp);
8819 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8820 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8821 }
8822 pclose(fp);
8823 }
8824 }
8825 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8826 return RETURN_OK;
8827
8828}
8829
8830INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8831{
8832#if 0
8833 /*char buf[1024] = {0};
8834 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8835 _syscmd(cmd, buf, sizeof(buf));*/
8836
8837 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8838 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8839 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8840 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8841
8842 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.
8843 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].
8844 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].
8845 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].
8846 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8847 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8848
8849 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8850 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8851 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8852 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.
8853 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.
8854 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.
8855 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.
8856 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.
8857 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.
8858 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.
8859 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8860#endif
8861
8862 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008863 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008864 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008865 char pipeCmd[128] = {0};
8866 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008867 wifi_ssidTrafficStats2_t *out = output_struct;
8868
developerce736392022-09-13 15:24:34 +08008869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008870 if (!output_struct)
8871 return RETURN_ERR;
8872
developerce736392022-09-13 15:24:34 +08008873 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8874 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8875 GetInterfaceName(interface_name, HConf_file);
8876 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008877
developer06a01d92022-09-07 16:32:39 +08008878 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008879 if (fp == NULL) {
8880 fprintf(stderr, "%s: popen failed\n", __func__);
8881 return RETURN_ERR;
8882 }
8883 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008884
developerce736392022-09-13 15:24:34 +08008885 if (strlen(str) == 0) // interface not exist
8886 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008887
developerce736392022-09-13 15:24:34 +08008888 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8889 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008890 pclose(fp);
8891
developerce736392022-09-13 15:24:34 +08008892 memset(str, 0, sizeof(str));
8893 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008894 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008895 if (fp == NULL) {
8896 fprintf(stderr, "%s: popen failed\n", __func__);
8897 return RETURN_ERR;
8898 }
8899 fgets(str, sizeof(str), fp);
8900
8901 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8902 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008903 pclose(fp);
developerce736392022-09-13 15:24:34 +08008904
8905 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8906 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8907
8908 // Not supported
8909 output_struct->ssid_RetransCount = 0;
8910 output_struct->ssid_FailedRetransCount = 0;
8911 output_struct->ssid_RetryCount = 0;
8912 output_struct->ssid_MultipleRetryCount = 0;
8913 output_struct->ssid_ACKFailureCount = 0;
8914 output_struct->ssid_AggregatedPacketCount = 0;
8915
developer06a01d92022-09-07 16:32:39 +08008916 return RETURN_OK;
8917}
8918
8919//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).
8920INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8921{
8922 char output_val[16]={'\0'};
8923 char config_file[MAX_BUF_SIZE] = {0};
8924
8925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8926 if (!output)
8927 return RETURN_ERR;
8928 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8929 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8930
8931 if( strcmp(output_val,"1") == 0 )
8932 *output = TRUE;
8933 else
8934 *output = FALSE;
8935 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8936
8937 return RETURN_OK;
8938}
8939
8940INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8941{
8942 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8943 char str[MAX_BUF_SIZE]={'\0'};
8944 char string[MAX_BUF_SIZE]={'\0'};
8945 char cmd[MAX_CMD_SIZE]={'\0'};
8946 char *ch;
8947 char config_file[MAX_BUF_SIZE] = {0};
8948 struct params params;
8949
8950 if(enable == TRUE)
8951 strcpy(string,"1");
8952 else
8953 strcpy(string,"0");
8954
8955 params.name = "ap_isolate";
8956 params.value = string;
8957
8958 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8959 wifi_hostapdWrite(config_file,&params,1);
8960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8961
8962 return RETURN_OK;
8963}
8964
8965INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8966{
8967 if (NULL == output_dBm)
8968 return RETURN_ERR;
8969
8970 *output_dBm = 0;
8971 return RETURN_OK;
8972}
8973
8974INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8975{
8976 return RETURN_OK;
8977}
8978INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8979{
8980 return RETURN_OK;
8981}
8982INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8983{
8984 return RETURN_OK;
8985}
8986INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8987{
8988 return RETURN_OK;
8989}
8990INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8991{
8992 return RETURN_OK;
8993}
8994INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8995{
8996 char config_file[MAX_BUF_SIZE] = {0};
8997 struct params list;
8998
8999 list.name = "bss_transition";
9000 list.value = activate?"1":"0";
9001 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9002 wifi_hostapdWrite(config_file, &list, 1);
9003
9004 return RETURN_OK;
9005}
9006wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9007
9008void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9009{
9010 return;
9011}
9012
9013INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9014{
9015 // TODO Implement me!
9016 return RETURN_OK;
9017}
9018
9019INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9020{
developera3c68b92022-09-13 15:27:29 +08009021 char file_name[128] = {0};
9022 char buf[128] = {0};
9023 FILE *f = NULL;
9024
9025 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9026
9027 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9028 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
9029 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9030 f = fopen(file_name, "w");
9031 if (f == NULL)
9032 return RETURN_ERR;
9033 // For mode == 0 is to disable filter, just don't write to the file.
9034 if (mode)
9035 fprintf(f, "%s", essid);
9036
9037 fclose(f);
9038 }
9039 } else { // special case, need to set AP's SSID as filter for each radio.
9040 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9041 f = fopen(file_name, "w");
9042 if (f == NULL)
9043 return RETURN_ERR;
9044
9045 // For mode == 0 is to disable filter, just don't write to the file.
9046 if (mode)
9047 fprintf(f, "%s", essid);
9048
9049 fclose(f);
9050 }
9051
9052 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009053 return RETURN_OK;
9054}
9055
9056INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9057{
9058 // TODO Implement me!
9059 //Apply wifi_pushRadioChannel() instantly
9060 return RETURN_ERR;
9061}
9062
9063INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9064{
9065 // TODO Implement me!
9066 return RETURN_OK;
9067}
9068
9069#ifdef HAL_NETLINK_IMPL
9070static int tidStats_callback(struct nl_msg *msg, void *arg) {
9071 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9072 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9073 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9074 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9075 int rem , tid_index = 0;
9076
9077 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9078 wifi_associated_dev_tid_entry_t *stats_entry;
9079
9080 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9081 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9082 };
9083 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9084 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9085 };
9086
9087 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9088 genlmsg_attrlen(gnlh, 0), NULL);
9089
9090
9091 if (!tb[NL80211_ATTR_STA_INFO]) {
9092 fprintf(stderr, "station stats missing!\n");
9093 return NL_SKIP;
9094 }
9095
9096 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9097 tb[NL80211_ATTR_STA_INFO],
9098 stats_policy)) {
9099 fprintf(stderr, "failed to parse nested attributes!\n");
9100 return NL_SKIP;
9101 }
9102
9103 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9104 {
9105 stats_entry = &out->tid_array[tid_index];
9106
9107 stats_entry->tid = tid_index;
9108 stats_entry->ac = _tid_ac_index_get[tid_index];
9109
9110 if(sinfo[NL80211_STA_INFO_TID_STATS])
9111 {
9112 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9113 printf("failed to parse nested stats attributes!");
9114 return NL_SKIP;
9115 }
9116 }
9117 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9118 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9119
9120 if(tid_index < (PS_MAX_TID - 1))
9121 tid_index++;
9122 }
9123 //ToDo: sum_time_ms, ewma_time_ms
9124 return NL_SKIP;
9125}
9126#endif
9127
9128INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9129{
9130#ifdef HAL_NETLINK_IMPL
9131 Netlink nl;
9132 char if_name[10];
9133
9134 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9135
9136 nl.id = initSock80211(&nl);
9137
9138 if (nl.id < 0) {
9139 fprintf(stderr, "Error initializing netlink \n");
9140 return -1;
9141 }
9142
9143 struct nl_msg* msg = nlmsg_alloc();
9144
9145 if (!msg) {
9146 fprintf(stderr, "Failed to allocate netlink message.\n");
9147 nlfree(&nl);
9148 return -2;
9149 }
9150
9151 genlmsg_put(msg,
9152 NL_AUTO_PORT,
9153 NL_AUTO_SEQ,
9154 nl.id,
9155 0,
9156 0,
9157 NL80211_CMD_GET_STATION,
9158 0);
9159
9160 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9161 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9162 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9163 nl_send_auto(nl.socket, msg);
9164 nl_recvmsgs(nl.socket, nl.cb);
9165 nlmsg_free(msg);
9166 nlfree(&nl);
9167 return RETURN_OK;
9168#else
9169//iw implementation
9170#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9171#define TOTAL_MAX_LINES 50
9172
9173 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9174 char if_name[10];
9175 FILE *fp=NULL;
9176 char pipeCmd[1024]= {'\0'};
9177 int lines,tid_index=0;
9178 char mac_addr[20] = {'\0'};
9179
9180 wifi_associated_dev_tid_entry_t *stats_entry;
9181
9182 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9183 strcpy(mac_addr,clientMacAddress);
9184
9185 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9186 fp= popen(pipeCmd,"r");
9187 if(fp == NULL)
9188 {
9189 perror("popen for station dump failed\n");
9190 return RETURN_ERR;
9191 }
9192 pclose(fp);
9193
9194 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9195 fp=popen(pipeCmd,"r");
9196 if(fp == NULL)
9197 {
9198 perror("popen for grep station failed\n");
9199 return RETURN_ERR;
9200 }
9201 else if(fgets(buf,sizeof(buf),fp) != NULL)
9202 lines=atoi(buf);
9203 else
9204 {
9205 pclose(fp);
9206 fprintf(stderr,"No devices are connected \n");
9207 return RETURN_ERR;
9208 }
9209 pclose(fp);
9210
9211 if(lines == 1)
9212 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9213
9214 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9215 {
9216 stats_entry = &tid_stats->tid_array[tid_index];
9217 stats_entry->tid = tid_index;
9218
9219 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);
9220
9221 fp=popen(pipeCmd,"r");
9222 if(fp ==NULL)
9223 {
9224 perror("Failed to read from tid file \n");
9225 return RETURN_ERR;
9226 }
9227 else if(fgets(buf,sizeof(buf),fp) != NULL)
9228 stats_entry->num_msdus = atol(buf);
9229
9230 pclose(fp);
9231 stats_entry->ac = _tid_ac_index_get[tid_index];
9232// TODO:
9233// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9234// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9235 }
9236 return RETURN_OK;
9237#endif
9238}
9239
9240
9241INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9242{
developer615510b2022-09-27 10:14:35 +08009243 char cmd[128]={0};
9244 char buf[128]={0};
9245 int freq = 0;
9246
9247 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9248
9249 // full mode is used to scan all channels.
9250 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9251 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9252 ieee80211_channel_to_frequency(chan_list[0], &freq);
9253
9254 if (freq)
9255 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9256 else
9257 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9258
9259 _syscmd(cmd, buf, sizeof(buf));
9260 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9261
developer06a01d92022-09-07 16:32:39 +08009262 return RETURN_OK;
9263}
9264
9265
9266INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9267{
9268 // TODO Implement me!
9269 return RETURN_ERR;
9270}
9271
9272INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9273{
9274 // TODO Implement me!
9275 return RETURN_ERR;
9276}
9277
9278INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9279{
9280 // TODO Implement me!
9281 return RETURN_ERR;
9282}
9283
9284INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9285{
9286 // TODO Implement me!
9287 return RETURN_ERR;
9288}
9289
9290INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9291{
9292 // TODO Implement me!
9293 return RETURN_ERR;
9294}
9295
9296INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9297{
9298 // TODO Implement me!
9299 return RETURN_ERR;
9300}
9301
9302INT wifi_steering_eventUnregister(void)
9303{
9304 // TODO Implement me!
9305 return RETURN_ERR;
9306}
9307
9308INT wifi_delApAclDevices(INT apIndex)
9309{
9310#if 0
9311 char cmd[MAX_BUF_SIZE] = {0};
9312 char buf[MAX_BUF_SIZE] = {0};
9313
9314 /* Not reset proof solution */
9315 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9316 if(_syscmd(cmd,buf,sizeof(buf)))
9317 return RETURN_ERR;
9318#endif
developere6aafda2022-09-13 14:59:28 +08009319 char cmd[MAX_CMD_SIZE]={0};
9320 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009321
developere6aafda2022-09-13 14:59:28 +08009322 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9323 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9324 if(_syscmd(cmd, buf, sizeof(buf)))
9325 return RETURN_ERR;
9326 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009327
9328 return RETURN_OK;
9329}
9330
9331#ifdef HAL_NETLINK_IMPL
9332static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9333 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9334 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9335 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9336 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9337 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9338 char mac_addr[20],dev[20];
9339
9340 nla_parse(tb,
9341 NL80211_ATTR_MAX,
9342 genlmsg_attrdata(gnlh, 0),
9343 genlmsg_attrlen(gnlh, 0),
9344 NULL);
9345
9346 if(!tb[NL80211_ATTR_STA_INFO]) {
9347 fprintf(stderr, "sta stats missing!\n");
9348 return NL_SKIP;
9349 }
9350
9351 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9352 fprintf(stderr, "failed to parse nested attributes!\n");
9353 return NL_SKIP;
9354 }
9355 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9356
9357 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9358
9359 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9360 fprintf(stderr, "failed to parse nested rate attributes!");
9361 return NL_SKIP;
9362 }
9363
9364 if(sinfo[NL80211_STA_INFO_TID_STATS])
9365 {
9366 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9367 printf("failed to parse nested stats attributes!");
9368 return NL_SKIP;
9369 }
9370 }
9371
9372 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9373 {
9374 printf("Type is VHT\n");
9375 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9376 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9377
9378 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9379 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9380 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9381 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9382 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9383 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9384 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9385 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9386 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9387 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9388 }
9389 else
9390 {
9391 printf(" OFDM or CCK \n");
9392 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9393 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9394 }
9395
9396 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9397 if(rinfo[NL80211_RATE_INFO_MCS])
9398 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9399 }
9400 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9401 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9402 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9403 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9404
9405 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9406 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9407
9408 if (sinfo[NL80211_STA_INFO_SIGNAL])
9409 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9410 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9411 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9412 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9413 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9414 //rssi_array need to be filled
9415 return NL_SKIP;
9416}
9417#endif
9418
9419INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9420{
9421#ifdef HAL_NETLINK_IMPL
9422 Netlink nl;
9423 char if_name[10];
9424
9425 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9426
9427 if (*output_array_size <= 0)
9428 return RETURN_OK;
9429
9430 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9431 nl.id = initSock80211(&nl);
9432
9433 if (nl.id < 0) {
9434 fprintf(stderr, "Error initializing netlink \n");
9435 return 0;
9436 }
9437
9438 struct nl_msg* msg = nlmsg_alloc();
9439
9440 if (!msg) {
9441 fprintf(stderr, "Failed to allocate netlink message.\n");
9442 nlfree(&nl);
9443 return 0;
9444 }
9445
9446 genlmsg_put(msg,
9447 NL_AUTO_PORT,
9448 NL_AUTO_SEQ,
9449 nl.id,
9450 0,
9451 0,
9452 NL80211_CMD_GET_STATION,
9453 0);
9454
9455 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9456 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9457 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9458 nl_send_auto(nl.socket, msg);
9459 nl_recvmsgs(nl.socket, nl.cb);
9460 nlmsg_free(msg);
9461 nlfree(&nl);
9462 return RETURN_OK;
9463#else
9464 //TODO Implement me
9465 return RETURN_OK;
9466#endif
9467}
9468
9469#ifdef HAL_NETLINK_IMPL
9470static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9471 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9472 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9473 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9474 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9475 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9476 char mac_addr[20],dev[20];
9477
9478 nla_parse(tb,
9479 NL80211_ATTR_MAX,
9480 genlmsg_attrdata(gnlh, 0),
9481 genlmsg_attrlen(gnlh, 0),
9482 NULL);
9483
9484 if(!tb[NL80211_ATTR_STA_INFO]) {
9485 fprintf(stderr, "sta stats missing!\n");
9486 return NL_SKIP;
9487 }
9488
9489 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9490 fprintf(stderr, "failed to parse nested attributes!\n");
9491 return NL_SKIP;
9492 }
9493
9494 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9495
9496 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9497
9498 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9499 fprintf(stderr, "failed to parse nested rate attributes!");
9500 return NL_SKIP;
9501 }
9502
9503 if(sinfo[NL80211_STA_INFO_TID_STATS])
9504 {
9505 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9506 printf("failed to parse nested stats attributes!");
9507 return NL_SKIP;
9508 }
9509 }
9510 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9511 {
9512 printf("Type is VHT\n");
9513 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9514 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9515
9516 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9517 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9518 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9519 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9520 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9521 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9522 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9523 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9524 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9525 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9526 }
9527 else
9528 {
9529 printf(" OFDM or CCK \n");
9530 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9531 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9532 }
9533
9534 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9535 if(rinfo[NL80211_RATE_INFO_MCS])
9536 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9537 }
9538
9539 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9540 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9541 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9542 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9543
9544 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9545 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9546 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9547
9548 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9549 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9550
9551 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9552 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9553
9554 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9555 ((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]);
9556
9557 return NL_SKIP;
9558}
9559#endif
9560
9561INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9562{
9563#ifdef HAL_NETLINK_IMPL
9564 Netlink nl;
9565 char if_name[10];
9566
9567 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9568
9569 if (*output_array_size <= 0)
9570 return RETURN_OK;
9571
9572 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9573
9574 nl.id = initSock80211(&nl);
9575
9576 if(nl.id < 0) {
9577 fprintf(stderr, "Error initializing netlink \n");
9578 return 0;
9579 }
9580
9581 struct nl_msg* msg = nlmsg_alloc();
9582
9583 if(!msg) {
9584 fprintf(stderr, "Failed to allocate netlink message.\n");
9585 nlfree(&nl);
9586 return 0;
9587 }
9588
9589 genlmsg_put(msg,
9590 NL_AUTO_PORT,
9591 NL_AUTO_SEQ,
9592 nl.id,
9593 0,
9594 0,
9595 NL80211_CMD_GET_STATION,
9596 0);
9597
9598 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9599 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9600 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9601 nl_send_auto(nl.socket, msg);
9602 nl_recvmsgs(nl.socket, nl.cb);
9603 nlmsg_free(msg);
9604 nlfree(&nl);
9605 return RETURN_OK;
9606#else
9607 //TODO Implement me
9608 return RETURN_OK;
9609#endif
9610}
9611
9612INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9613{
9614 // TODO Implement me!
9615 char buf[MAX_BUF_SIZE] = {0};
9616 char config_file[MAX_BUF_SIZE] = {0};
9617
9618 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9619 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9620 *activate = (strncmp("1",buf,1) == 0);
9621
9622 return RETURN_OK;
9623}
9624
9625INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9626{
9627 char config_file[MAX_BUF_SIZE] = {0};
9628 struct params list;
9629
9630 list.name = "rrm_neighbor_report";
9631 list.value = activate?"1":"0";
9632 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9633 wifi_hostapdWrite(config_file, &list, 1);
9634
9635 return RETURN_OK;
9636}
9637
9638INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9639{
9640 char buf[32] = {0};
9641 char config_file[MAX_BUF_SIZE] = {0};
9642
9643 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9644 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9645 *activate = (strncmp("1",buf,1) == 0);
9646
9647 return RETURN_OK;
9648}
9649#undef HAL_NETLINK_IMPL
9650#ifdef HAL_NETLINK_IMPL
9651static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9652 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9653 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9654 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9655 char dev[20];
9656 int freq =0 ;
9657 static int i=0;
9658
9659 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9660
9661 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9662 };
9663
9664 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9665
9666 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9667
9668 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9669 fprintf(stderr, "survey data missing!\n");
9670 return NL_SKIP;
9671 }
9672
9673 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9674 {
9675 fprintf(stderr, "failed to parse nested attributes!\n");
9676 return NL_SKIP;
9677 }
9678
9679
9680 if(out[0].array_size == 1 )
9681 {
9682 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9683 {
9684 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9685 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9686 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9687
9688 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9689 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9690 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9691 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9692 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9693 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9694 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9695 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9696 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9697 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9698 if (sinfo[NL80211_SURVEY_INFO_TIME])
9699 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9700 return NL_STOP;
9701 }
9702 }
9703 else
9704 {
9705 if ( i <= out[0].array_size )
9706 {
9707 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9708 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9709 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9710
9711 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9712 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9713 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9714 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9715 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9716 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9717 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9718 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9719 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9720 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9721 if (sinfo[NL80211_SURVEY_INFO_TIME])
9722 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9723 }
9724 }
9725
9726 i++;
9727 return NL_SKIP;
9728}
9729#endif
9730
9731static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9732{
9733 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9734 FILE *fp;
9735
9736 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9737 {
9738 printf("Creating Frequency-Channel Map\n");
9739 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9740 }
9741 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9742 if((fp = popen(command, "r")))
9743 {
9744 fgets(output, sizeof(output), fp);
9745 *freqMHz = atoi(output);
9746 fclose(fp);
9747 }
9748
9749 return 0;
9750}
9751
9752static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9753{
9754 int freqMHz = -1;
9755 char cmd[MAX_CMD_SIZE] = {'\0'};
9756
9757 ieee80211_channel_to_frequency(channel, &freqMHz);
9758 if (freqMHz == -1) {
9759 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9760 return -1;
9761 }
9762
9763 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9764 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9765 radioIndex, freqMHz);
9766 return -1;
9767 }
9768
9769 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9770 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9771 return -1;
9772 }
9773
9774 return 0;
9775}
9776
9777static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9778{
9779 const char *ptr = buf;
9780 char *key = NULL;
9781 char *val = NULL;
9782 char line[256] = { '\0' };
9783
9784 while (ptr = get_line_from_str_buf(ptr, line)) {
9785 if (strstr(line, "Frequency")) continue;
9786
9787 key = strtok(line, ":");
9788 val = strtok(NULL, " ");
9789 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9790
9791 if (!strcmp(key, "noise")) {
9792 sscanf(val, "%d", &stats->ch_noise);
9793 if (stats->ch_noise == 0) {
9794 // Workaround for missing noise information.
9795 // Assume -95 for 2.4G and -103 for 5G
9796 if (radioIndex == 0) stats->ch_noise = -95;
9797 if (radioIndex == 1) stats->ch_noise = -103;
9798 }
9799 }
9800 else if (!strcmp(key, "channel active time")) {
9801 sscanf(val, "%llu", &stats->ch_utilization_total);
9802 }
9803 else if (!strcmp(key, "channel busy time")) {
9804 sscanf(val, "%llu", &stats->ch_utilization_busy);
9805 }
9806 else if (!strcmp(key, "channel receive time")) {
9807 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9808 }
9809 else if (!strcmp(key, "channel transmit time")) {
9810 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9811 }
9812 };
9813
9814 return 0;
9815}
9816
9817INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9818{
9819 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9820#ifdef HAL_NETLINK_IMPL
9821 Netlink nl;
9822 wifi_channelStats_t_loc local[array_size];
9823 char if_name[10];
9824
9825 local[0].array_size = array_size;
9826
9827 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9828
9829 nl.id = initSock80211(&nl);
9830
9831 if (nl.id < 0) {
9832 fprintf(stderr, "Error initializing netlink \n");
9833 return -1;
9834 }
9835
9836 struct nl_msg* msg = nlmsg_alloc();
9837
9838 if (!msg) {
9839 fprintf(stderr, "Failed to allocate netlink message.\n");
9840 nlfree(&nl);
9841 return -2;
9842 }
9843
9844 genlmsg_put(msg,
9845 NL_AUTO_PORT,
9846 NL_AUTO_SEQ,
9847 nl.id,
9848 0,
9849 NLM_F_DUMP,
9850 NL80211_CMD_GET_SURVEY,
9851 0);
9852
9853 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9854 nl_send_auto(nl.socket, msg);
9855 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9856 nl_recvmsgs(nl.socket, nl.cb);
9857 nlmsg_free(msg);
9858 nlfree(&nl);
9859 //Copying the Values
9860 for(int i=0;i<array_size;i++)
9861 {
9862 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9863 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9864 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9865 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9866 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9867 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9868 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9869 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9870 }
9871#else
9872 ULONG channel = 0;
9873 int i;
9874 int number_of_channels = array_size;
9875 char buf[512];
9876 INT ret;
9877 wifi_channelStats_t tmp_stats;
9878
9879 if (number_of_channels == 0) {
9880 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9881 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9882 return RETURN_ERR;
9883 }
9884 number_of_channels = 1;
9885 input_output_channelStats_array[0].ch_number = channel;
9886 }
9887
9888 for (i = 0; i < number_of_channels; i++) {
9889
9890 input_output_channelStats_array[i].ch_noise = 0;
9891 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9892 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9893 input_output_channelStats_array[i].ch_utilization_busy = 0;
9894 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9895 input_output_channelStats_array[i].ch_utilization_total = 0;
9896
9897 memset(buf, 0, sizeof(buf));
9898 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9899 return RETURN_ERR;
9900 }
9901 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9902 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9903 return RETURN_ERR;
9904 }
9905
9906 // XXX: fake missing 'self' counter which is not available in iw survey output
9907 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9908 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9909
9910 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9911 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9912 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9913 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9914 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9915
9916 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",
9917 __func__,
9918 input_output_channelStats_array[i].ch_number,
9919 input_output_channelStats_array[i].ch_noise,
9920 input_output_channelStats_array[i].ch_utilization_total,
9921 input_output_channelStats_array[i].ch_utilization_busy,
9922 input_output_channelStats_array[i].ch_utilization_busy_rx,
9923 input_output_channelStats_array[i].ch_utilization_busy_tx,
9924 input_output_channelStats_array[i].ch_utilization_busy_self,
9925 input_output_channelStats_array[i].ch_utilization_busy_ext);
9926 }
9927#endif
9928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9929 return RETURN_OK;
9930}
9931#define HAL_NETLINK_IMPL
9932
9933/* Hostapd events */
9934
9935#ifndef container_of
9936#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9937#define container_of(ptr, type, member) \
9938 ((type *)((char *)ptr - offset_of(type, member)))
9939#endif /* container_of */
9940
9941struct ctrl {
9942 char sockpath[128];
9943 char sockdir[128];
9944 char bss[IFNAMSIZ];
9945 char reply[4096];
9946 int ssid_index;
9947 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9948 void (*overrun)(struct ctrl *ctrl);
9949 struct wpa_ctrl *wpa;
9950 unsigned int ovfl;
9951 size_t reply_len;
9952 int initialized;
9953 ev_timer retry;
9954 ev_timer watchdog;
9955 ev_stat stat;
9956 ev_io io;
9957};
9958static wifi_newApAssociatedDevice_callback clients_connect_cb;
9959static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9960static struct ctrl wpa_ctrl[MAX_APS];
9961static int initialized;
9962
9963static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9964{
9965 char cbuf[256] = {};
9966 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9967 struct cmsghdr *cmsg;
9968 unsigned int ovfl = ctrl->ovfl;
9969 unsigned int drop;
9970
9971 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9972 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9973 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9974 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9975
9976 drop = ovfl - ctrl->ovfl;
9977 ctrl->ovfl = ovfl;
9978
9979 return drop;
9980}
9981
9982static void ctrl_close(struct ctrl *ctrl)
9983{
9984 if (ctrl->io.cb)
9985 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9986 if (ctrl->retry.cb)
9987 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9988 if (!ctrl->wpa)
9989 return;
9990
9991 wpa_ctrl_detach(ctrl->wpa);
9992 wpa_ctrl_close(ctrl->wpa);
9993 ctrl->wpa = NULL;
9994 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9995}
9996
9997static void ctrl_process(struct ctrl *ctrl)
9998{
9999 const char *str;
10000 int drops;
10001 int level;
10002 int err;
10003
10004 /* Example events:
10005 *
10006 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10007 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10008 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10009 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10010 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10011 */
10012 if (!(str = index(ctrl->reply, '>')))
10013 return;
10014 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10015 return;
10016
10017 str++;
10018
10019 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10020 if (!(str = index(ctrl->reply, ' ')))
10021 return;
10022 wifi_associated_dev_t sta;
10023 memset(&sta, 0, sizeof(sta));
10024
10025 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10026 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10027 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10028
10029 sta.cli_Active=true;
10030
10031 (clients_connect_cb)(ctrl->ssid_index, &sta);
10032 goto handled;
10033 }
10034
10035 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10036 if (!(str = index(ctrl->reply, ' ')))
10037 return;
10038
10039 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10040 goto handled;
10041 }
10042
10043 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10044 printf("CTRL_WPA: handle TERMINATING event\n");
10045 goto retry;
10046 }
10047
10048 if (strncmp("AP-DISABLED", str, 11) == 0) {
10049 printf("CTRL_WPA: handle AP-DISABLED\n");
10050 goto retry;
10051 }
10052
10053 printf("Event not supported!!\n");
10054
10055handled:
10056
10057 if ((drops = ctrl_get_drops(ctrl))) {
10058 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10059 if (ctrl->overrun)
10060 ctrl->overrun(ctrl);
10061 }
10062
10063 return;
10064
10065retry:
10066 printf("WPA_CTRL: closing\n");
10067 ctrl_close(ctrl);
10068 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10069 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10070}
10071
10072static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10073{
10074 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10075 int err;
10076
10077 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10078 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10079 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10080 ctrl->reply[ctrl->reply_len] = 0;
10081 if (err < 0) {
10082 if (errno == EAGAIN || errno == EWOULDBLOCK)
10083 return;
10084 ctrl_close(ctrl);
10085 ev_timer_again(EV_A_ &ctrl->retry);
10086 return;
10087 }
10088
10089 ctrl_process(ctrl);
10090}
10091
10092static int ctrl_open(struct ctrl *ctrl)
10093{
10094 int fd;
10095
10096 if (ctrl->wpa)
10097 return 0;
10098
10099 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10100 if (!ctrl->wpa)
10101 goto err;
10102
10103 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10104 goto err_close;
10105
10106 fd = wpa_ctrl_get_fd(ctrl->wpa);
10107 if (fd < 0)
10108 goto err_detach;
10109
10110 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10111 goto err_detach;
10112
10113 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10114 ev_io_start(EV_DEFAULT_ &ctrl->io);
10115
10116 return 0;
10117
10118err_detach:
10119 wpa_ctrl_detach(ctrl->wpa);
10120err_close:
10121 wpa_ctrl_close(ctrl->wpa);
10122err:
10123 ctrl->wpa = NULL;
10124 return -1;
10125}
10126
10127static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10128{
10129 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10130
10131 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10132 ctrl_open(ctrl);
10133}
10134
10135static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10136{
10137 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10138
10139 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10140 if (ctrl_open(ctrl) == 0) {
10141 printf("WPA_CTRL: retry successful\n");
10142 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10143 }
10144}
10145
10146int ctrl_enable(struct ctrl *ctrl)
10147{
10148 if (ctrl->wpa)
10149 return 0;
10150
10151 if (!ctrl->stat.cb) {
10152 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10153 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10154 }
10155
10156 if (!ctrl->retry.cb) {
10157 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10158 }
10159
10160 return ctrl_open(ctrl);
10161}
10162
10163static void
10164ctrl_msg_cb(char *buf, size_t len)
10165{
10166 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10167
10168 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10169 ctrl_process(ctrl);
10170}
10171
10172static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10173{
10174 int err;
10175
10176 if (!ctrl->wpa)
10177 return -1;
10178 if (*reply_len < 2)
10179 return -1;
10180
10181 (*reply_len)--;
10182 ctrl->reply_len = sizeof(ctrl->reply);
10183 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10184 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10185 if (err < 0)
10186 return err;
10187
10188 if (ctrl->reply_len > *reply_len)
10189 ctrl->reply_len = *reply_len;
10190
10191 *reply_len = ctrl->reply_len;
10192 memcpy(reply, ctrl->reply, *reply_len);
10193 reply[*reply_len - 1] = 0;
10194 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10195 return 0;
10196}
10197
10198static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10199{
10200 const char *pong = "PONG";
10201 const char *ping = "PING";
10202 char reply[1024];
10203 size_t len = sizeof(reply);
10204 int err;
10205 ULONG s, snum;
10206 INT ret;
10207 BOOL status;
10208
10209 printf("WPA_CTRL: watchdog cb\n");
10210
10211 ret = wifi_getSSIDNumberOfEntries(&snum);
10212 if (ret != RETURN_OK) {
10213 printf("%s: failed to get SSID count", __func__);
10214 return;
10215 }
10216
10217 if (snum > MAX_APS) {
10218 printf("more ssid than supported! %lu\n", snum);
10219 return;
10220 }
10221
10222 for (s = 0; s < snum; s++) {
10223 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10224 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10225 continue;
10226 }
10227 if (status == false) continue;
10228
10229 memset(reply, 0, sizeof(reply));
10230 len = sizeof(reply);
10231 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10232 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10233 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10234 continue;
10235
10236 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10237 ctrl_close(&wpa_ctrl[s]);
10238 printf("WPA_CTRL: ev_timer_again %d\n", s);
10239 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10240 }
10241}
10242
10243static int init_wpa()
10244{
10245 int ret = 0, i = 0;
10246 ULONG s, snum;
10247
10248 ret = wifi_getSSIDNumberOfEntries(&snum);
10249 if (ret != RETURN_OK) {
10250 printf("%s: failed to get SSID count", __func__);
10251 return RETURN_ERR;
10252 }
10253
10254 if (snum > MAX_APS) {
10255 printf("more ssid than supported! %lu\n", snum);
10256 return RETURN_ERR;
10257 }
10258
10259 for (s = 0; s < snum; s++) {
10260 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10261 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10262 wpa_ctrl[s].ssid_index = s;
10263 ctrl_enable(&wpa_ctrl[s]);
10264 }
10265
10266 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10267 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10268
10269 initialized = 1;
10270 printf("WPA_CTRL: initialized\n");
10271
10272 return RETURN_OK;
10273}
10274
10275void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10276{
10277 clients_connect_cb = callback_proc;
10278 if (!initialized)
10279 init_wpa();
10280}
10281
10282void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10283{
10284 clients_disconnect_cb = callback_proc;
10285 if (!initialized)
10286 init_wpa();
10287}
10288
10289INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10290{
10291 // TODO Implement me!
10292 return RETURN_ERR;
10293}
10294
10295INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10296{
10297 // TODO Implement me!
10298 return RETURN_ERR;
10299}
10300
10301INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10302{
10303 int i;
10304 char cmd[256];
10305 char channel_numbers_buf[256];
10306 char dfs_state_buf[256];
10307 char line[256];
10308 const char *ptr;
10309
10310 memset(cmd, 0, sizeof(cmd));
10311 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10312 memset(line, 0, sizeof(line));
10313 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10314 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10315
10316 if (radioIndex == 0) { // 2.4G - all allowed
10317 if (outputMapSize < 11) {
10318 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10319 return RETURN_ERR;
10320 }
10321
10322 for (i = 0; i < 11; i++) {
10323 outputMap[i].ch_number = i + 1;
10324 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10325 }
10326
10327 return RETURN_OK;
10328 }
10329
10330 if (radioIndex == 1) { // 5G
10331// Example output of iw list:
10332//
10333// Frequencies:
10334// * 5180 MHz [36] (17.0 dBm)
10335// * 5200 MHz [40] (17.0 dBm)
10336// * 5220 MHz [44] (17.0 dBm)
10337// * 5240 MHz [48] (17.0 dBm)
10338// * 5260 MHz [52] (23.0 dBm) (radar detection)
10339// DFS state: usable (for 78930 sec)
10340// DFS CAC time: 60000 ms
10341// * 5280 MHz [56] (23.0 dBm) (radar detection)
10342// DFS state: usable (for 78930 sec)
10343// DFS CAC time: 60000 ms
10344// * 5300 MHz [60] (23.0 dBm) (radar detection)
10345// DFS state: usable (for 78930 sec)
10346// DFS CAC time: 60000 ms
10347// * 5320 MHz [64] (23.0 dBm) (radar detection)
10348// DFS state: usable (for 78930 sec)
10349// DFS CAC time: 60000 ms
10350// * 5500 MHz [100] (disabled)
10351// * 5520 MHz [104] (disabled)
10352// * 5540 MHz [108] (disabled)
10353// * 5560 MHz [112] (disabled)
10354//
10355// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10356 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10357 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10358 return RETURN_ERR;
10359 }
10360
10361 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10362 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10363 return RETURN_ERR;
10364 }
10365
10366 ptr = channel_numbers_buf;
10367 i = 0;
10368 while (ptr = get_line_from_str_buf(ptr, line)) {
10369 if (i >= outputMapSize) {
10370 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10371 return RETURN_ERR;
10372 }
10373 sscanf(line, "%d", &outputMap[i].ch_number);
10374
10375 memset(cmd, 0, sizeof(cmd));
10376 // Below command should fetch string for DFS state (usable, available or unavailable)
10377 // Example line: "DFS state: usable (for 78930 sec)"
10378 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) {
10379 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10380 return RETURN_ERR;
10381 }
10382
10383 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10384 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10385 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10386 return RETURN_ERR;
10387 }
10388
10389 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10390
10391 if (!strcmp(dfs_state_buf, "usable")) {
10392 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10393 } else if (!strcmp(dfs_state_buf, "available")) {
10394 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10395 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10396 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10397 } else {
10398 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10399 }
10400 i++;
10401 }
10402
10403 return RETURN_OK;
10404 }
10405
10406 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10407 return RETURN_ERR;
10408}
10409
10410INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10411{
10412 // TODO Implement me!
10413 return RETURN_ERR;
10414}
10415
10416INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10417{
10418 return RETURN_OK;
10419}
10420
10421INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10422{
10423 // TODO Implement me!
10424 return RETURN_ERR;
10425}
10426
10427INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10428{
10429 // TODO API refrence Implementaion is present on RPI hal
10430 return RETURN_ERR;
10431}
10432
10433INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10434{
developera5005b62022-09-13 15:43:35 +080010435 char cmd[128]={'\0'};
10436 char buf[128]={'\0'};
10437 char *support;
10438 int maximum_tx = 0, current_tx = 0;
10439
10440 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10441 if(txpwr_pcntg == NULL)
10442 return RETURN_ERR;
10443
10444 // Get the maximum tx power of the device
10445 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10446 _syscmd(cmd, buf, sizeof(buf));
10447 maximum_tx = strtol(buf, NULL, 10);
10448
10449 // Get the current tx power
10450 memset(cmd, 0, sizeof(cmd));
10451 memset(buf, 0, sizeof(buf));
10452 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10453 _syscmd(cmd, buf, sizeof(buf));
10454 current_tx = strtol(buf, NULL, 10);
10455
10456 // Get the power supported list and find the current power percentage in supported list
10457 memset(buf, 0, sizeof(buf));
10458 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10459 support = strtok(buf, ",");
10460 while(true)
10461 {
10462 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10463 *txpwr_pcntg = 0;
10464 wifi_dbg_printf("current power is not in supported list\n");
10465 return RETURN_ERR;
10466 }
10467 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10468 if (tmp == current_tx) {
10469 *txpwr_pcntg = strtol(support, NULL, 10);
10470 break;
10471 }
10472 support = strtok(NULL, ",");
10473 }
10474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010475 return RETURN_OK;
10476}
10477
10478INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10479{
developer58599c22022-09-13 16:40:34 +080010480 // TODO precac feature.
10481 struct params params = {0};
10482 char config_file[128] = {0};
10483
10484 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10485
10486 params.name = "enable_background_radar";
10487 params.value = enable?"1":"0";
10488 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10489 wifi_hostapdWrite(config_file, &params, 1);
10490 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10491
10492 /* TODO precac feature */
10493
10494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10495 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010496}
10497
10498INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10499{
developer58599c22022-09-13 16:40:34 +080010500 char config_file[128] = {0};
10501 char buf[64] = {0};
10502
10503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10504 if (NULL == enable || NULL == precac)
10505 return RETURN_ERR;
10506
10507 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10508 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10509 if (strncmp(enable, "1", 1) == 0)
10510 *enable = true;
10511 else
10512 *enable = false;
10513
10514 /* TODO precac feature */
10515
10516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10517 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010518}
10519
10520INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10521{
developer58599c22022-09-13 16:40:34 +080010522 *supported = TRUE;
10523 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010524}
10525
developer3e6b1692022-09-30 18:04:05 +080010526INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10527{
10528 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10529 struct params params = {0};
10530 char config_file[64] = {0};
10531 char buf[64] = {0};
10532 unsigned int set_mu_type = 0;
10533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10534
10535 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10536 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10537
10538 if (strlen(buf) > 0)
10539 set_mu_type = strtol(buf, NULL, 10);
10540
10541 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10542 set_mu_type &= ~0x05; // unset bit 0, 2
10543 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10544 set_mu_type |= 0x01;
10545 set_mu_type &= ~0x04;
10546 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10547 set_mu_type &= ~0x01;
10548 set_mu_type |= 0x04;
10549 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10550 set_mu_type |= 0x05; // set bit 0, 2
10551 }
10552
10553 params.name = "hemu_onoff";
10554 sprintf(buf, "%u", set_mu_type);
10555 params.value = buf;
10556 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10557 wifi_hostapdWrite(config_file, &params, 1);
10558 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10559
10560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10561 return RETURN_OK;
10562}
10563
10564INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10565{
10566 struct params params={0};
10567 char config_file[64] = {0};
10568 char buf[64] = {0};
10569 unsigned int get_mu_type = 0;
10570
10571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10572
10573 if (mu_type == NULL)
10574 return RETURN_ERR;
10575
10576 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10577 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10578 get_mu_type = strtol(buf, NULL, 10);
10579
10580 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10581 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10582 else if (get_mu_type & 0x04)
10583 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10584 else if (get_mu_type & 0x01)
10585 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10586 else
10587 *mu_type = WIFI_DL_MU_TYPE_NONE;
10588
10589 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10590 return RETURN_OK;
10591}
10592
10593INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10594{
10595 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10596 struct params params={0};
10597 char config_file[64] = {0};
10598 char buf[64] = {0};
10599 unsigned int set_mu_type = 0;
10600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10601
10602 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10603 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10604
10605 if (strlen(buf) > 0)
10606 set_mu_type = strtol(buf, NULL, 10);
10607
10608 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10609 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10610 set_mu_type &= ~0x0a;
10611 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10612 set_mu_type |= 0x02;
10613 set_mu_type &= ~0x08;
10614 }
10615
10616 params.name = "hemu_onoff";
10617 sprintf(buf, "%u", set_mu_type);
10618 params.value = buf;
10619 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10620 wifi_hostapdWrite(config_file, &params, 1);
10621 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10622
10623 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10624 return RETURN_OK;
10625}
10626
10627INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10628{
10629 struct params params={0};
10630 char config_file[64] = {0};
10631 char buf[64] = {0};
10632 unsigned int get_mu_type = 0;
10633
10634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10635
10636 if (mu_type == NULL)
10637 return RETURN_ERR;
10638
10639 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10640 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10641
10642 get_mu_type = strtol(buf, NULL, 10);
10643 if (get_mu_type & 0x02)
10644 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10645 else
10646 *mu_type = WIFI_DL_MU_TYPE_NONE;
10647
10648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10649 return RETURN_OK;
10650}
10651
10652
developer454b9462022-09-13 15:29:16 +080010653INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10654{
10655 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010656 char buf[256] = {0};
10657 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010658 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010659 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010660 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010661 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010662
10663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10664
developer254882b2022-09-30 17:12:31 +080010665 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010666 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10667 return RETURN_ERR;
10668 }
developer454b9462022-09-13 15:29:16 +080010669
developer254882b2022-09-30 17:12:31 +080010670 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010671 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010672
developer254882b2022-09-30 17:12:31 +080010673 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10674 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
10675 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
10676 _syscmd(cmd, buf, sizeof(buf));
10677 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10678 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10679 if (strstr(buf, "[SHORT-GI-") == NULL) {
10680 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
10681 _syscmd(cmd, buf, sizeof(buf));
10682 }
10683 if (band == band_5) {
10684 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10685 if (strstr(buf, "[SHORT-GI-") == NULL) {
10686 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
10687 _syscmd(cmd, buf, sizeof(buf));
10688 }
10689 }
10690 }
10691 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010692
developer254882b2022-09-30 17:12:31 +080010693 if (guard_interval == wifi_guard_interval_400)
10694 strcpy(GI, "0.4");
10695 else if (guard_interval == wifi_guard_interval_800)
10696 strcpy(GI, "0.8");
10697 else if (guard_interval == wifi_guard_interval_1600)
10698 strcpy(GI, "1.6");
10699 else if (guard_interval == wifi_guard_interval_3200)
10700 strcpy(GI, "3.2");
10701 else if (guard_interval == wifi_guard_interval_auto)
10702 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010703 // Record GI for get GI function
10704 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10705 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010706 if (f == NULL)
10707 return RETURN_ERR;
10708 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010709 fclose(f);
10710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10711 return RETURN_OK;
10712}
10713
10714INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10715{
10716 char buf[32] = {0};
10717 char cmd[64] = {0};
10718
10719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10720
10721 if (guard_interval == NULL)
10722 return RETURN_ERR;
10723
10724 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10725 _syscmd(cmd, buf, sizeof(buf));
10726
10727 if (strncmp(buf, "0.4", 3) == 0)
10728 *guard_interval = wifi_guard_interval_400;
10729 else if (strncmp(buf, "0.8", 3) == 0)
10730 *guard_interval = wifi_guard_interval_800;
10731 else if (strncmp(buf, "1.6", 3) == 0)
10732 *guard_interval = wifi_guard_interval_1600;
10733 else if (strncmp(buf, "3.2", 3) == 0)
10734 *guard_interval = wifi_guard_interval_3200;
10735 else
10736 *guard_interval = wifi_guard_interval_auto;
10737
10738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10739 return RETURN_OK;
10740}
10741
developer3cc61d12022-09-13 16:36:05 +080010742INT wifi_setBSSColor(INT radio_index, UCHAR color)
10743{
10744 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10745 struct params params = {0};
10746 char config_file[128] = {0};
10747 char bss_color[4] ={0};
10748
10749 params.name = "he_bss_color";
10750 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10751 params.value = bss_color;
10752 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10753 wifi_hostapdWrite(config_file, &params, 1);
10754 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10755
10756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10757 return RETURN_OK;
10758}
10759
10760INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10761{
10762 char config_file[128] = {0};
10763 char buf[64] = {0};
10764 char temp_output[128] = {'\0'};
10765
10766 wifi_dbg_printf("\nFunc=%s\n", __func__);
10767 if (NULL == color)
10768 return RETURN_ERR;
10769
10770 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10771 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10772
10773 if(strlen(buf) > 0) {
10774 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10775 } else {
10776 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10777 }
10778
10779 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10780 wifi_dbg_printf("\noutput_string=%s\n", color);
10781
10782 return RETURN_OK;
10783}
10784
developer06a01d92022-09-07 16:32:39 +080010785/* multi-psk support */
10786INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10787{
10788 char cmd[256];
10789
10790 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10791 AP_PREFIX,
10792 apIndex,
10793 mac[0],
10794 mac[1],
10795 mac[2],
10796 mac[3],
10797 mac[4],
10798 mac[5]
10799 );
10800 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10801 _syscmd(cmd, key->wifi_keyId, 64);
10802
10803
10804 return RETURN_OK;
10805}
10806
10807INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10808{
10809 FILE *fd = NULL;
10810 char fname[100];
10811 char cmd[128] = {0};
10812 char out[64] = {0};
10813 wifi_key_multi_psk_t * key = NULL;
10814 if(keysNumber < 0)
10815 return RETURN_ERR;
10816
10817 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10818 fd = fopen(fname, "w");
10819 if (!fd) {
10820 return RETURN_ERR;
10821 }
10822 key= (wifi_key_multi_psk_t *) keys;
10823 for(int i=0; i<keysNumber; ++i, key++) {
10824 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10825 }
10826 fclose(fd);
10827
10828 //reload file
10829 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10830 _syscmd(cmd, out, 64);
10831 return RETURN_OK;
10832}
10833
10834INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10835{
10836 FILE *fd = NULL;
10837 char fname[100];
10838 char * line = NULL;
10839 char * pos = NULL;
10840 size_t len = 0;
10841 ssize_t read = 0;
10842 INT ret = RETURN_OK;
10843 wifi_key_multi_psk_t *keys_it = NULL;
10844
10845 if (keysNumber < 1) {
10846 return RETURN_ERR;
10847 }
10848
10849 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10850 fd = fopen(fname, "r");
10851 if (!fd) {
10852 return RETURN_ERR;
10853 }
10854
10855 if (keys == NULL) {
10856 ret = RETURN_ERR;
10857 goto close;
10858 }
10859
10860 keys_it = keys;
10861 while ((read = getline(&line, &len, fd)) != -1) {
10862 //Strip trailing new line if present
10863 if (read > 0 && line[read-1] == '\n') {
10864 line[read-1] = '\0';
10865 }
10866
10867 if(strcmp(line,"keyid=")) {
10868 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10869 if (!(pos = index(line, ' '))) {
10870 ret = RETURN_ERR;
10871 goto close;
10872 }
10873 pos++;
10874 //Here should be 00:00:00:00:00:00
10875 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10876 printf("Not supported MAC: %s\n", pos);
10877 }
10878 if (!(pos = index(pos, ' '))) {
10879 ret = RETURN_ERR;
10880 goto close;
10881 }
10882 pos++;
10883
10884 //The rest is PSK
10885 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10886 keys_it++;
10887
10888 if(--keysNumber <= 0)
10889 break;
10890 }
10891 }
10892
10893close:
10894 free(line);
10895 fclose(fd);
10896 return ret;
10897}
10898/* end of multi-psk support */
10899
10900INT wifi_setNeighborReports(UINT apIndex,
10901 UINT numNeighborReports,
10902 wifi_NeighborReport_t *neighborReports)
10903{
10904 char cmd[256] = { 0 };
10905 char hex_bssid[13] = { 0 };
10906 char bssid[18] = { 0 };
10907 char nr[256] = { 0 };
10908 char ssid[256];
10909 char hex_ssid[256];
10910 INT ret;
10911
10912 /*rmeove all neighbors*/
10913 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10914 sprintf(cmd, "hostapd_cli show_neighbor -i %s%d | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s%d",AP_PREFIX,apIndex,AP_PREFIX,apIndex);
10915 system(cmd);
10916
10917 for(unsigned int i = 0; i < numNeighborReports; i++)
10918 {
10919 memset(ssid, 0, sizeof(ssid));
10920 ret = wifi_getSSIDName(apIndex, ssid);
10921 if (ret != RETURN_OK)
10922 return RETURN_ERR;
10923
10924 memset(hex_ssid, 0, sizeof(hex_ssid));
10925 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10926 sprintf(hex_ssid + k,"%02x", ssid[j]);
10927
10928 snprintf(hex_bssid, sizeof(hex_bssid),
10929 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10930 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10931 snprintf(bssid, sizeof(bssid),
10932 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10933 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10934
10935 snprintf(nr, sizeof(nr),
10936 "%s" // bssid
10937 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10938 "%02hhx" // operclass
10939 "%02hhx" // channel
10940 "%02hhx", // phy_mode
10941 hex_bssid,
10942 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10943 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10944 neighborReports[i].opClass,
10945 neighborReports[i].channel,
10946 neighborReports[i].phyTable);
10947
10948 snprintf(cmd, sizeof(cmd),
10949 "hostapd_cli set_neighbor "
10950 "%s " // bssid
10951 "ssid=%s " // ssid
10952 "nr=%s " // nr
10953 "-i %s%d",
10954 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10955
10956 if (WEXITSTATUS(system(cmd)) != 0)
10957 {
10958 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10959 }
10960 }
10961
10962 return RETURN_OK;
10963}
10964
10965INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10966{
10967 return RETURN_OK;
10968}
10969
10970#ifdef _WIFI_HAL_TEST_
10971int main(int argc,char **argv)
10972{
10973 int index;
10974 INT ret=0;
10975 char buf[1024]="";
10976
10977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10978 if(argc<3)
10979 {
10980 if(argc==2)
10981 {
10982 if(!strcmp(argv[1], "init"))
10983 return wifi_init();
10984 if(!strcmp(argv[1], "reset"))
10985 return wifi_reset();
10986 if(!strcmp(argv[1], "wifi_getHalVersion"))
10987 {
10988 char buffer[64];
10989 if(wifi_getHalVersion(buffer)==RETURN_OK)
10990 printf("Version: %s\n", buffer);
10991 else
10992 printf("Error in wifi_getHalVersion\n");
10993 return RETURN_OK;
10994 }
10995 }
10996 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10997 exit(-1);
10998 }
10999
11000 index = atoi(argv[2]);
11001 if(strstr(argv[1], "wifi_getApName")!=NULL)
11002 {
11003 wifi_getApName(index,buf);
11004 printf("Ap name is %s \n",buf);
11005 return 0;
11006 }
11007 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11008 {
11009 BOOL b = FALSE;
11010 BOOL *output_bool = &b;
11011 wifi_getRadioAutoChannelEnable(index,output_bool);
11012 printf("Channel enabled = %d \n",b);
11013 return 0;
11014 }
11015 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11016 {
11017 wifi_getApWpaEncryptionMode(index,buf);
11018 printf("encryption enabled = %s\n",buf);
11019 return 0;
11020 }
11021 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11022 {
11023 BOOL b = FALSE;
11024 BOOL *output_bool = &b;
11025 wifi_getApSsidAdvertisementEnable(index,output_bool);
11026 printf("advertisment enabled = %d\n",b);
11027 return 0;
11028 }
11029 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11030 {
11031 if(argc <= 3 )
11032 {
11033 printf("Insufficient arguments \n");
11034 exit(-1);
11035 }
11036
11037 char sta[20] = {'\0'};
11038 ULLONG handle= 0;
11039 strcpy(sta,argv[3]);
11040 mac_address_t st;
11041 mac_addr_aton(st,sta);
11042
11043 wifi_associated_dev_tid_stats_t tid_stats;
11044 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11045 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11046 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);
11047 }
11048
11049 if(strstr(argv[1], "getApEnable")!=NULL) {
11050 BOOL enable;
11051 ret=wifi_getApEnable(index, &enable);
11052 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11053 }
11054 else if(strstr(argv[1], "setApEnable")!=NULL) {
11055 BOOL enable = atoi(argv[3]);
11056 ret=wifi_setApEnable(index, enable);
11057 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11058 }
11059 else if(strstr(argv[1], "getApStatus")!=NULL) {
11060 char status[64];
11061 ret=wifi_getApStatus(index, status);
11062 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11063 }
11064 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11065 {
11066 wifi_getSSIDNameStatus(index,buf);
11067 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11068 return 0;
11069 }
11070 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11071 wifi_ssidTrafficStats2_t stats={0};
11072 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11073 printf("%s %d: returns %d\n", argv[1], index, ret);
11074 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11075 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11076 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11077 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11078 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11079 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11080 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11081 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11082 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11083 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11084 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11085 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11086 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11087 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11088 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11089 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11090 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11091 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11092 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11093 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11094 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11095 }
11096 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11097 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11098 UINT array_size=0;
11099 UINT i=0;
11100 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11101 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11102 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11103 printf(" neighbor %d:\n", i);
11104 printf(" ap_SSID =%s\n", pt->ap_SSID);
11105 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11106 printf(" ap_Mode =%s\n", pt->ap_Mode);
11107 printf(" ap_Channel =%d\n", pt->ap_Channel);
11108 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11109 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11110 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11111 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11112 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11113 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11114 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11115 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11116 printf(" ap_Noise =%d\n", pt->ap_Noise);
11117 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11118 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11119 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11120 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11121 }
11122 if(neighbor_ap_array)
11123 free(neighbor_ap_array); //make sure to free the list
11124 }
11125 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11126 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11127 UINT array_size=0;
11128 UINT i=0;
11129 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11130 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11131 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11132 printf(" associated_dev %d:\n", i);
11133 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11134 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11135 printf(" cli_SNR =%d\n", pt->cli_SNR);
11136 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11137 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11138 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11139 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11140 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11141 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11142 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11143 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11144 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11145 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11146 }
11147 if(associated_dev_array)
11148 free(associated_dev_array); //make sure to free the list
11149 }
11150
11151 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11152 {
11153#define MAX_ARRAY_SIZE 64
11154 int i, array_size;
11155 char *p, *ch_str;
11156 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11157
11158 if(argc != 5)
11159 {
11160 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11161 exit(-1);
11162 }
11163 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11164
11165 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11166 {
11167 strtok_r(ch_str, ",", &p);
11168 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11169 }
11170 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11171 if(!array_size)
11172 array_size=1;//Need to print current channel statistics
11173 for(i=0; i<array_size; i++)
11174 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11175 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11176 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11177 input_output_channelStats_array[i].ch_number,\
11178 input_output_channelStats_array[i].ch_noise,\
11179 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11180 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11181 input_output_channelStats_array[i].ch_utilization_busy,\
11182 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11183 input_output_channelStats_array[i].ch_utilization_total);
11184 }
11185
11186 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11187 {
11188 if(argc <= 3 )
11189 {
11190 printf("Insufficient arguments \n");
11191 exit(-1);
11192 }
11193 char mac_addr[20] = {'\0'};
11194 wifi_device_t output_struct;
11195 int dev_index = atoi(argv[3]);
11196
11197 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11198 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11199 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);
11200 }
11201
11202 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11203 {
11204 if (argc <= 3)
11205 {
11206 printf("Insufficient arguments\n");
11207 exit(-1);
11208 }
11209 char args[256];
11210 wifi_NeighborReport_t *neighborReports;
11211
11212 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11213 if (!neighborReports)
11214 {
11215 printf("Failed to allocate memory");
11216 exit(-1);
11217 }
11218
11219 for (int i = 3; i < argc; ++i)
11220 {
11221 char *val;
11222 int j = 0;
11223 memset(args, 0, sizeof(args));
11224 strncpy(args, argv[i], sizeof(args));
11225 val = strtok(args, ";");
11226 while (val != NULL)
11227 {
11228 if (j == 0)
11229 {
11230 mac_addr_aton(neighborReports[i - 3].bssid, val);
11231 } else if (j == 1)
11232 {
11233 neighborReports[i - 3].info = strtol(val, NULL, 16);
11234 } else if (j == 2)
11235 {
11236 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11237 } else if (j == 3)
11238 {
11239 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11240 } else if (j == 4)
11241 {
11242 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11243 } else {
11244 printf("Insufficient arguments]n\n");
11245 exit(-1);
11246 }
11247 val = strtok(NULL, ";");
11248 j++;
11249 }
11250 }
11251
11252 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11253 if (ret != RETURN_OK)
11254 {
11255 printf("wifi_setNeighborReports ret = %d", ret);
11256 exit(-1);
11257 }
11258 }
11259 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11260 {
11261 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11262 printf("%s.\n", buf);
11263 else
11264 printf("Error returned\n");
11265 }
11266 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11267 {
11268 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11269 printf("%s.\n", buf);
11270 else
11271 printf("Error returned\n");
11272 }
11273 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11274 {
11275 if (argc <= 2)
11276 {
11277 printf("Insufficient arguments\n");
11278 exit(-1);
11279 }
11280 char buf[64]= {'\0'};
11281 wifi_getRadioOperatingChannelBandwidth(index,buf);
11282 printf("Current bandwidth is %s \n",buf);
11283 return 0;
11284 }
11285 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11286 {
11287 if (argc <= 5)
11288 {
11289 printf("Insufficient arguments\n");
11290 exit(-1);
11291 }
11292 UINT channel = atoi(argv[3]);
11293 UINT width = atoi(argv[4]);
11294 UINT beacon = atoi(argv[5]);
11295 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11296 printf("Result = %d", ret);
11297 }
11298
11299 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11300 return 0;
11301}
11302
11303#endif
11304
11305#ifdef WIFI_HAL_VERSION_3
11306
developer1e5aa162022-09-13 16:06:24 +080011307INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11308{
11309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11310 if (bitMap & WIFI_BITRATE_1MBPS)
11311 strcat(BasicRate, "1,");
11312 if (bitMap & WIFI_BITRATE_2MBPS)
11313 strcat(BasicRate, "2,");
11314 if (bitMap & WIFI_BITRATE_5_5MBPS)
11315 strcat(BasicRate, "5.5,");
11316 if (bitMap & WIFI_BITRATE_6MBPS)
11317 strcat(BasicRate, "6,");
11318 if (bitMap & WIFI_BITRATE_9MBPS)
11319 strcat(BasicRate, "9,");
11320 if (bitMap & WIFI_BITRATE_11MBPS)
11321 strcat(BasicRate, "11,");
11322 if (bitMap & WIFI_BITRATE_12MBPS)
11323 strcat(BasicRate, "12,");
11324 if (bitMap & WIFI_BITRATE_18MBPS)
11325 strcat(BasicRate, "18,");
11326 if (bitMap & WIFI_BITRATE_24MBPS)
11327 strcat(BasicRate, "24,");
11328 if (bitMap & WIFI_BITRATE_36MBPS)
11329 strcat(BasicRate, "36,");
11330 if (bitMap & WIFI_BITRATE_48MBPS)
11331 strcat(BasicRate, "48,");
11332 if (bitMap & WIFI_BITRATE_54MBPS)
11333 strcat(BasicRate, "54,");
11334 if (strlen(BasicRate) != 0) // remove last comma
11335 BasicRate[strlen(BasicRate) - 1] = '\0';
11336 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11337 return RETURN_OK;
11338}
11339
11340INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11341{
11342 UINT BitMap = 0;
11343 char *rate;
11344
11345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11346 rate = strtok(BasicRatesList, ",");
11347 while(rate != NULL)
11348 {
11349 if (strcmp(rate, "1") == 0)
11350 BitMap |= WIFI_BITRATE_1MBPS;
11351 else if (strcmp(rate, "2") == 0)
11352 BitMap |= WIFI_BITRATE_2MBPS;
11353 else if (strcmp(rate, "5.5") == 0)
11354 BitMap |= WIFI_BITRATE_5_5MBPS;
11355 else if (strcmp(rate, "6") == 0)
11356 BitMap |= WIFI_BITRATE_6MBPS;
11357 else if (strcmp(rate, "9") == 0)
11358 BitMap |= WIFI_BITRATE_9MBPS;
11359 else if (strcmp(rate, "11") == 0)
11360 BitMap |= WIFI_BITRATE_11MBPS;
11361 else if (strcmp(rate, "12") == 0)
11362 BitMap |= WIFI_BITRATE_12MBPS;
11363 else if (strcmp(rate, "18") == 0)
11364 BitMap |= WIFI_BITRATE_18MBPS;
11365 else if (strcmp(rate, "24") == 0)
11366 BitMap |= WIFI_BITRATE_24MBPS;
11367 else if (strcmp(rate, "36") == 0)
11368 BitMap |= WIFI_BITRATE_36MBPS;
11369 else if (strcmp(rate, "48") == 0)
11370 BitMap |= WIFI_BITRATE_48MBPS;
11371 else if (strcmp(rate, "54") == 0)
11372 BitMap |= WIFI_BITRATE_54MBPS;
11373 rate = strtok(NULL, ",");
11374 }
11375 *basicRateBitMap = BitMap;
11376 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11377 return RETURN_OK;
11378}
11379
11380// 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 +080011381INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11382{
developer1e5aa162022-09-13 16:06:24 +080011383 char buf[128] = {0};
11384 char cmd[128] = {0};
11385 char config_file[64] = {0};
11386 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011387 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011388 wifi_radio_operationParam_t current_param;
11389
11390 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11391
11392 multiple_set = TRUE;
11393 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11394 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11395 return RETURN_ERR;
11396 }
11397 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11398 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11399 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11400 return RETURN_ERR;
11401 }
11402 }
developer5884e982022-10-06 10:52:50 +080011403
11404 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11405 bandwidth = 20;
11406 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11407 bandwidth = 40;
11408 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11409 bandwidth = 80;
11410 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11411 bandwidth = 160;
11412 if (operationParam->autoChannelEnabled){
11413 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11414 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11415 return RETURN_ERR;
11416 }
11417 }else{
developer1e5aa162022-09-13 16:06:24 +080011418 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11419 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11420 return RETURN_ERR;
11421 }
11422 }
developer5884e982022-10-06 10:52:50 +080011423
developer1e5aa162022-09-13 16:06:24 +080011424 if (current_param.variant != operationParam->variant) {
11425 // Two different definition bit map, so need to check every bit.
11426 if (operationParam->variant & WIFI_80211_VARIANT_A)
11427 set_mode |= WIFI_MODE_A;
11428 if (operationParam->variant & WIFI_80211_VARIANT_B)
11429 set_mode |= WIFI_MODE_B;
11430 if (operationParam->variant & WIFI_80211_VARIANT_G)
11431 set_mode |= WIFI_MODE_G;
11432 if (operationParam->variant & WIFI_80211_VARIANT_N)
11433 set_mode |= WIFI_MODE_N;
11434 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11435 set_mode |= WIFI_MODE_AC;
11436 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11437 set_mode |= WIFI_MODE_AX;
11438 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11439 memset(buf, 0, sizeof(buf));
11440 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11441 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11442 return RETURN_ERR;
11443 }
11444 }
11445 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11446 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11447 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11448 return RETURN_ERR;
11449 }
11450 }
11451 if (current_param.beaconInterval != operationParam->beaconInterval) {
11452 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11453 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11454 return RETURN_ERR;
11455 }
11456 }
11457 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11458 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11459 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11460 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11461 return RETURN_ERR;
11462 }
11463 }
11464 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11465 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11466 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11467 return RETURN_ERR;
11468 }
11469 }
11470 if (current_param.guardInterval != operationParam->guardInterval) {
11471 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11472 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11473 return RETURN_ERR;
11474 }
11475 }
11476 if (current_param.transmitPower != operationParam->transmitPower) {
11477 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11478 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11479 return RETURN_ERR;
11480 }
11481 }
11482 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11483 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11484 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11485 return RETURN_ERR;
11486 }
11487 }
11488 if (current_param.obssCoex != operationParam->obssCoex) {
11489 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11490 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11491 return RETURN_ERR;
11492 }
11493 }
11494 if (current_param.stbcEnable != operationParam->stbcEnable) {
11495 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11496 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11497 return RETURN_ERR;
11498 }
11499 }
11500 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11501 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11502 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11503 return RETURN_ERR;
11504 }
11505 }
11506
11507 // if enable is true, then restart the radio
11508 wifi_setRadioEnable(index, FALSE);
11509 if (operationParam->enable == TRUE)
11510 wifi_setRadioEnable(index, TRUE);
11511 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11512
developer06a01d92022-09-07 16:32:39 +080011513 return RETURN_OK;
11514}
11515
11516INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11517{
developer1e5aa162022-09-13 16:06:24 +080011518 char band[64] = {0};
11519 char buf[256] = {0};
11520 char config_file[64] = {0};
11521 char cmd[128] = {0};
11522 int ret = RETURN_ERR;
11523 int mode = 0;
11524 ULONG channel = 0;
11525 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011526
11527 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11528 printf("Entering %s index = %d\n", __func__, (int)index);
11529
developer1e5aa162022-09-13 16:06:24 +080011530 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11531 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11532 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011533 {
developer1e5aa162022-09-13 16:06:24 +080011534 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011535 return RETURN_ERR;
11536 }
11537 operationParam->enable = enabled;
11538
11539 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011540 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011541 {
developer1e5aa162022-09-13 16:06:24 +080011542 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011543 return RETURN_ERR;
11544 }
11545
11546 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011547 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011548 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011549 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011550 else if (!strcmp(band, "6GHz"))
11551 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011552 else
11553 {
developer1e5aa162022-09-13 16:06:24 +080011554 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011555 band);
11556 }
11557
developer1e5aa162022-09-13 16:06:24 +080011558 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11559 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11560 operationParam->channel = 0;
11561 operationParam->autoChannelEnabled = TRUE;
11562 } else {
11563 operationParam->channel = strtol(buf, NULL, 10);
11564 operationParam->autoChannelEnabled = FALSE;
11565 }
11566
developer06a01d92022-09-07 16:32:39 +080011567 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011568 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11569 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11570 return RETURN_ERR;
11571 }
developer06a01d92022-09-07 16:32:39 +080011572 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11573 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11574 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011575 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11576 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011577 else
11578 {
developer1e5aa162022-09-13 16:06:24 +080011579 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11580 return false;
developer06a01d92022-09-07 16:32:39 +080011581 }
11582
developer1e5aa162022-09-13 16:06:24 +080011583 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11584 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11585 return RETURN_ERR;
11586 }
11587 // Two different definition bit map, so need to check every bit.
11588 if (mode & WIFI_MODE_A)
11589 operationParam->variant |= WIFI_80211_VARIANT_A;
11590 if (mode & WIFI_MODE_B)
11591 operationParam->variant |= WIFI_80211_VARIANT_B;
11592 if (mode & WIFI_MODE_G)
11593 operationParam->variant |= WIFI_80211_VARIANT_G;
11594 if (mode & WIFI_MODE_N)
11595 operationParam->variant |= WIFI_80211_VARIANT_N;
11596 if (mode & WIFI_MODE_AC)
11597 operationParam->variant |= WIFI_80211_VARIANT_AC;
11598 if (mode & WIFI_MODE_AX)
11599 operationParam->variant |= WIFI_80211_VARIANT_AX;
11600 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11601 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11602 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011603 }
developer1e5aa162022-09-13 16:06:24 +080011604 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11605 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11606 return RETURN_ERR;
11607 }
11608 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11609 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11610 return RETURN_ERR;
11611 }
developer06a01d92022-09-07 16:32:39 +080011612
developer1e5aa162022-09-13 16:06:24 +080011613 memset(buf, 0, sizeof(buf));
11614 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11615 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11616 return RETURN_ERR;
11617 }
11618 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11619
11620 memset(buf, 0, sizeof(buf));
11621 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11622 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11623 return RETURN_ERR;
11624 }
11625 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11626
11627 memset(buf, 0, sizeof(buf));
11628 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11629 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11630
11631 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11632 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11633 return RETURN_ERR;
11634 }
11635 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11636 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11637 return RETURN_ERR;
11638 }
11639
11640 memset(buf, 0, sizeof(buf));
11641 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11642 if (strcmp(buf, "-1") == 0) {
11643 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11644 operationParam->ctsProtection = FALSE;
11645 } else {
11646 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11647 operationParam->ctsProtection = TRUE;
11648 }
11649
11650 memset(buf, 0, sizeof(buf));
11651 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11652 if (strcmp(buf, "0") == 0)
11653 operationParam->obssCoex = FALSE;
11654 else
11655 operationParam->obssCoex = TRUE;
11656
11657 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11658 _syscmd(cmd, buf, sizeof(buf));
11659 if (strlen(buf) != 0)
11660 operationParam->stbcEnable = TRUE;
11661 else
11662 operationParam->stbcEnable = FALSE;
11663
11664 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11665 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11666 return RETURN_ERR;
11667 }
11668
11669 // Below value is hardcoded
11670
11671 operationParam->numSecondaryChannels = 0;
11672 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11673 operationParam->channelSecondary[i] = 0;
11674 }
11675 operationParam->csa_beacon_count = 15;
11676 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011677
11678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11679 return RETURN_OK;
11680}
11681
11682static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11683{
developerc086fb72022-10-04 10:18:22 +080011684 int max_radio_num = 0;
11685
11686 wifi_getMaxRadioNumber(&max_radio_num);
11687 if (radioIndex >= max_radio_num || radioIndex < 0) {
11688 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11689 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011690 }
11691
developerc086fb72022-10-04 10:18:22 +080011692 return (arrayIndex * max_radio_num) + radioIndex;
11693}
developer06a01d92022-09-07 16:32:39 +080011694
developerc086fb72022-10-04 10:18:22 +080011695wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11696 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11697 return WIFI_BITRATE_1MBPS;
11698 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11699 return WIFI_BITRATE_2MBPS;
11700 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11701 return WIFI_BITRATE_5_5MBPS;
11702 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11703 return WIFI_BITRATE_6MBPS;
11704 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11705 return WIFI_BITRATE_9MBPS;
11706 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11707 return WIFI_BITRATE_11MBPS;
11708 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11709 return WIFI_BITRATE_12MBPS;
11710 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11711 return WIFI_BITRATE_18MBPS;
11712 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11713 return WIFI_BITRATE_24MBPS;
11714 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11715 return WIFI_BITRATE_36MBPS;
11716 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11717 return WIFI_BITRATE_48MBPS;
11718 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11719 return WIFI_BITRATE_54MBPS;
11720 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011721}
11722
11723INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11724{
developerc086fb72022-10-04 10:18:22 +080011725 INT mode = 0;
11726 INT ret = -1;
11727 INT output = 0;
11728 int i = 0;
11729 int vap_index = 0;
11730 BOOL enabled = FALSE;
11731 char buf[256] = {0};
11732 wifi_vap_security_t security;
11733 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011734
11735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11736 printf("Entering %s index = %d\n", __func__, (int)index);
11737
developer06a01d92022-09-07 16:32:39 +080011738 for (i = 0; i < 5; i++)
11739 {
developerc086fb72022-10-04 10:18:22 +080011740 map->vap_array[i].radio_index = index;
11741
developer06a01d92022-09-07 16:32:39 +080011742 vap_index = array_index_to_vap_index(index, i);
11743 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011744 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011745
developerc086fb72022-10-04 10:18:22 +080011746 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011747
11748 map->vap_array[i].vap_index = vap_index;
11749
11750 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011751 ret = wifi_getApName(vap_index, buf);
11752 if (ret != RETURN_OK) {
11753 printf("%s: wifi_getApName return error\n", __func__);
11754 return RETURN_ERR;
11755 }
11756 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
11757
11758 memset(buf, 0, sizeof(buf));
11759 ret = wifi_getSSIDNameStatus(vap_index, buf);
11760 if (ret != RETURN_OK) {
11761 printf("%s: wifi_getSSIDNameStatus return error\n", __func__);
11762 return RETURN_ERR;
11763 }
11764 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 +080011765
11766 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080011767 if (ret != RETURN_OK) {
11768 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011769 return RETURN_ERR;
11770 }
11771 map->vap_array[i].u.bss_info.enabled = enabled;
11772
developerc086fb72022-10-04 10:18:22 +080011773 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
11774 if (ret != RETURN_OK) {
11775 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
11776 return RETURN_ERR;
11777 }
developer06a01d92022-09-07 16:32:39 +080011778 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080011779
11780 ret = wifi_getApIsolationEnable(vap_index, &enabled);
11781 if (ret != RETURN_OK) {
11782 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
11783 return RETURN_ERR;
11784 }
11785 map->vap_array[i].u.bss_info.isolation = enabled;
11786
11787 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
11788 if (ret != RETURN_OK) {
11789 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
11790 return RETURN_ERR;
11791 }
11792 map->vap_array[i].u.bss_info.bssMaxSta = output;
11793
11794 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
11795 if (ret != RETURN_OK) {
11796 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
11797 return RETURN_ERR;
11798 }
11799 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011800
developerc086fb72022-10-04 10:18:22 +080011801 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
11802 if (ret != RETURN_OK) {
11803 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
11804 return RETURN_ERR;
11805 }
11806 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011807
developerc086fb72022-10-04 10:18:22 +080011808 ret = wifi_getApSecurity(vap_index, &security);
11809 if (ret != RETURN_OK) {
11810 printf("%s: wifi_getApSecurity return error\n", __func__);
11811 return RETURN_ERR;
11812 }
11813 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080011814
developerc086fb72022-10-04 10:18:22 +080011815 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
11816 if (ret != RETURN_OK) {
11817 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
11818 return RETURN_ERR;
11819 }
11820 if (mode == 0)
11821 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
11822 else
11823 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
11824 if (mode == 1)
11825 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11826 else if (mode == 2)
11827 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080011828
developerc086fb72022-10-04 10:18:22 +080011829 ret = wifi_getApWmmEnable(vap_index, &enabled);
11830 if (ret != RETURN_OK) {
11831 printf("%s: wifi_getApWmmEnable return error\n", __func__);
11832 return RETURN_ERR;
11833 }
11834 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011835
developerc086fb72022-10-04 10:18:22 +080011836 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
11837 if (ret != RETURN_OK) {
11838 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011839 return RETURN_ERR;
11840 }
developerc086fb72022-10-04 10:18:22 +080011841 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011842
11843 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011844 ret = wifi_getApBeaconRate(vap_index, buf);
11845 if (ret != RETURN_OK) {
11846 printf("%s: wifi_getApBeaconRate return error\n", __func__);
11847 return RETURN_ERR;
11848 }
11849 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080011850
developerc086fb72022-10-04 10:18:22 +080011851 memset(buf, 0, sizeof(buf));
11852 ret = wifi_getBaseBSSID(vap_index, buf);
11853 if (ret != RETURN_OK) {
11854 printf("%s: wifi_getBaseBSSID return error\n", __func__);
11855 return RETURN_ERR;
11856 }
11857 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11858 &map->vap_array[i].u.bss_info.bssid[0],
11859 &map->vap_array[i].u.bss_info.bssid[1],
11860 &map->vap_array[i].u.bss_info.bssid[2],
11861 &map->vap_array[i].u.bss_info.bssid[3],
11862 &map->vap_array[i].u.bss_info.bssid[4],
11863 &map->vap_array[i].u.bss_info.bssid[5]);
developer06a01d92022-09-07 16:32:39 +080011864
developerc086fb72022-10-04 10:18:22 +080011865 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080011866 }
11867 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11868 return RETURN_OK;
11869}
11870
11871INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11872{
11873 unsigned int i;
11874 wifi_vap_info_t *vap_info = NULL;
11875 int acl_mode;
11876 char *sec_str = NULL;
11877
11878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11879 printf("Entering %s index = %d\n", __func__, (int)index);
11880 for (i = 0; i < map->num_vaps; i++)
11881 {
11882 vap_info = &map->vap_array[i];
11883 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11884
11885 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11886 else
11887 {
11888 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11889 else acl_mode = 1;
11890 }
11891 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11892 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11893 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11894
11895 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11896 if (sec_str)
11897 {
11898 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11899 }
11900 else
11901 {
11902 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11903 }
11904
11905 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11906 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11907
11908 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11909 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11910
11911 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11912
11913 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11914 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11915 }
11916 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11917 return RETURN_OK;
11918}
11919
11920int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11921{
11922 char *token, *next;
11923 const char s[2] = ",";
11924 int count =0;
11925
11926 /* get the first token */
11927 token = strtok_r(pchannels, s, &next);
11928
11929 /* walk through other tokens */
11930 while( token != NULL && count < MAX_CHANNELS) {
11931 chlistptr->channels_list[count++] = atoi(token);
11932 token = strtok_r(NULL, s, &next);
11933 }
11934
11935 return count;
11936}
11937
11938static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11939{
11940 INT status;
11941 wifi_channels_list_t *chlistp;
11942 CHAR output_string[64];
11943 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011944 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011945
11946 if(rcap == NULL)
11947 {
11948 return RETURN_ERR;
11949 }
11950
11951 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011952 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011953
developer1e5aa162022-09-13 16:06:24 +080011954 if (band == band_2_4)
11955 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11956 else if (band == band_5)
11957 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11958 else if (band == band_6)
11959 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011960
11961 chlistp = &(rcap->channel_list[0]);
11962 memset(pchannels, 0, sizeof(pchannels));
11963
11964 /* possible number of radio channels */
11965 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11966 {
11967 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11968 }
11969 /* Number of channels and list*/
11970 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11971
11972 /* autoChannelSupported */
11973 /* always ON with wifi_getRadioAutoChannelSupported */
11974 rcap->autoChannelSupported = TRUE;
11975
11976 /* DCSSupported */
11977 /* always ON with wifi_getRadioDCSSupported */
11978 rcap->DCSSupported = TRUE;
11979
11980 /* zeroDFSSupported - TBD */
11981 rcap->zeroDFSSupported = FALSE;
11982
11983 /* Supported Country List*/
11984 memset(output_string, 0, sizeof(output_string));
11985 status = wifi_getRadioCountryCode(radioIndex, output_string);
11986 if( status != 0 ) {
11987 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11988 return RETURN_ERR;
11989 } else {
11990 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11991 }
11992 if(!strcmp(output_string,"US")){
11993 rcap->countrySupported[0] = wifi_countrycode_US;
11994 rcap->countrySupported[1] = wifi_countrycode_CA;
11995 } else if (!strcmp(output_string,"CA")) {
11996 rcap->countrySupported[0] = wifi_countrycode_CA;
11997 rcap->countrySupported[1] = wifi_countrycode_US;
11998 } else {
11999 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12000 }
12001
12002 rcap->numcountrySupported = 2;
12003
12004 /* csi */
12005 rcap->csi.maxDevices = 8;
12006 rcap->csi.soudingFrameSupported = TRUE;
12007
12008 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
12009
12010 /* channelWidth - all supported bandwidths */
12011 int i=0;
12012 rcap->channelWidth[i] = 0;
12013 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12014 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12015 WIFI_CHANNELBANDWIDTH_40MHZ);
12016
12017 }
developer1e5aa162022-09-13 16:06:24 +080012018 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012019 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12020 WIFI_CHANNELBANDWIDTH_40MHZ |
12021 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12022 }
12023
12024
12025 /* mode - all supported variants */
12026 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12027 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012028 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 +080012029 }
12030 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012031 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12032 }
12033 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12034 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012035 }
12036 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12037 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12038
12039 /* supportedBitRate - all supported bitrates */
12040 rcap->supportedBitRate[i] = 0;
12041 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12042 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12043 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12044 }
developer1e5aa162022-09-13 16:06:24 +080012045 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012046 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12047 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12048 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12049 }
12050
12051
12052 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12053 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12054 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12055 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12056 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12057 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12058 rcap->cipherSupported = 0;
12059 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12060 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12061
12062 return RETURN_OK;
12063}
12064
12065INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12066{
12067 INT status, radioIndex;
12068 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12069 int iter = 0;
12070 unsigned int j;
12071 wifi_interface_name_idex_map_t *iface_info;
12072
12073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12074
12075 memset(cap, 0, sizeof(wifi_hal_capability_t));
12076
12077 /* version */
12078 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12079 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12080
12081 /* number of radios platform property */
12082 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12083 _syscmd(cmd, output, sizeof(output));
12084 cap->wifi_prop.numRadios = atoi(output);
12085
12086 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12087 {
12088 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12089 if (status != 0) {
12090 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12091 return RETURN_ERR;
12092 }
12093
12094 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12095 {
12096 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12097 {
12098 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12099 return RETURN_ERR;
12100 }
12101 iface_info = &cap->wifi_prop.interface_map[iter];
12102 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12103 iface_info->rdk_radio_index = radioIndex;
12104 memset(output, 0, sizeof(output));
12105 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12106 {
12107 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12108 }
12109 // TODO: bridge name
12110 // TODO: vlan id
12111 // TODO: primary
12112 iface_info->index = array_index_to_vap_index(radioIndex, j);
12113 memset(output, 0, sizeof(output));
12114 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12115 {
12116 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12117 }
12118 iter++;
12119 }
12120 }
12121
12122 cap->BandSteeringSupported = FALSE;
12123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12124 return RETURN_OK;
12125}
12126
developer9df4e652022-10-11 11:27:38 +080012127INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12128{
12129 struct params h_config={0};
12130 char config_file[64] = {0};
12131
12132 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12133
12134 h_config.name = "okc";
12135 h_config.value = okc_enable?"1":"0";
12136
12137 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12138 wifi_hostapdWrite(config_file, &h_config, 1);
12139 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12140
12141 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12142 return RETURN_OK;
12143}
12144
12145INT wifi_setSAEMFP(int ap_index, BOOL enable)
12146{
12147 struct params h_config={0};
12148 char config_file[64] = {0};
12149 char buf[128] = {0};
12150
12151 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12152
12153 h_config.name = "sae_require_mfp";
12154 h_config.value = enable?"1":"0";
12155
12156 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12157 wifi_hostapdWrite(config_file, &h_config, 1);
12158 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12159
12160 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12161 return RETURN_OK;
12162}
12163
12164INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12165{
12166 struct params h_config={0};
12167 char config_file[64] = {0};
12168 char buf[128] = {0};
12169
12170 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12171
12172 h_config.name = "sae_pwe";
12173 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12174 h_config.value = buf;
12175
12176 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12177 wifi_hostapdWrite(config_file, &h_config, 1);
12178 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12179
12180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12181 return RETURN_OK;
12182}
12183
12184INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12185{
12186 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12187 struct params h_config={0};
12188 char config_file[64] = {0};
12189
12190 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12191
12192 h_config.name = "wpa_disable_eapol_key_retries";
12193 h_config.value = disable_EAPOL_retries?"1":"0";
12194
12195 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12196 wifi_hostapdWrite(config_file, &h_config, 1);
12197 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12198
12199 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12200 return RETURN_OK;
12201}
12202
developer06a01d92022-09-07 16:32:39 +080012203INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12204{
developer587c1b62022-09-27 15:58:59 +080012205 char buf[128] = {0};
12206 char config_file[128] = {0};
12207 char password[64] = {0};
12208 char mfp[32] = {0};
12209 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012210 BOOL okc_enable = FALSE;
12211 BOOL sae_MFP = FALSE;
12212 BOOL disable_EAPOL_retries = TRUE;
12213 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012214 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012215 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012216
12217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12218
12219 multiple_set = TRUE;
12220 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12221 if (security->mode == wifi_security_mode_none) {
12222 strcpy(wpa_mode, "None");
12223 } else if (security->mode == wifi_security_mode_wpa_personal)
12224 strcpy(wpa_mode, "WPA-Personal");
12225 else if (security->mode == wifi_security_mode_wpa2_personal)
12226 strcpy(wpa_mode, "WPA2-Personal");
12227 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12228 strcpy(wpa_mode, "WPA-WPA2-Personal");
12229 else if (security->mode == wifi_security_mode_wpa_enterprise)
12230 strcpy(wpa_mode, "WPA-Enterprise");
12231 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12232 strcpy(wpa_mode, "WPA2-Enterprise");
12233 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12234 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012235 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012236 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012237 okc_enable = TRUE;
12238 sae_MFP = TRUE;
12239 sae_pwe = 2;
12240 disable_EAPOL_retries = FALSE;
12241 } else if (security->mode == wifi_security_mode_wpa3_transition) {
12242 strcpy(wpa_mode, "WPA3-Transition");
12243 okc_enable = TRUE;
12244 sae_MFP = TRUE;
12245 sae_pwe = 2;
12246 disable_EAPOL_retries = FALSE;
12247 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012248 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012249 sae_MFP = TRUE;
12250 sae_pwe = 2;
12251 disable_EAPOL_retries = FALSE;
12252 }
12253
12254 band = wifi_index_to_band(ap_index);
12255 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12256 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12257 return RETURN_ERR;
12258 }
developer587c1b62022-09-27 15:58:59 +080012259
12260 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012261 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
12262 wifi_setSAEMFP(ap_index, TRUE);
12263 wifi_setSAEpwe(ap_index, 2);
12264 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012265
developer9df4e652022-10-11 11:27:38 +080012266 if (security->mode != wifi_security_mode_none) {
12267 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12268 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12269 password[63] = '\0';
12270 wifi_setApSecurityKeyPassphrase(ap_index, password);
12271 }
12272 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12273 params.name = "sae_password";
12274 params.value = security->u.key.key;
12275 wifi_hostapdWrite(config_file, &params, 1);
12276 }
12277 }
developer587c1b62022-09-27 15:58:59 +080012278
12279 if (security->mode != wifi_security_mode_none) {
12280 memset(&params, 0, sizeof(params));
12281 params.name = "wpa_pairwise";
12282 if (security->encr == wifi_encryption_tkip)
12283 params.value = "TKIP";
12284 else if (security->encr == wifi_encryption_aes)
12285 params.value = "CCMP";
12286 else if (security->encr == wifi_encryption_aes_tkip)
12287 params.value = "TKIP CCMP";
12288 wifi_hostapdWrite(config_file, &params, 1);
12289 }
12290
12291 if (security->mfp == wifi_mfp_cfg_disabled)
12292 strcpy(mfp, "Disable");
12293 else if (security->mfp == wifi_mfp_cfg_optional)
12294 strcpy(mfp, "Optional");
12295 else if (security->mfp == wifi_mfp_cfg_required)
12296 strcpy(mfp, "Required");
12297 wifi_setApSecurityMFPConfig(ap_index, mfp);
12298
12299 memset(&params, 0, sizeof(params));
12300 params.name = "transition_disable";
12301 if (security->wpa3_transition_disable == TRUE)
12302 params.value = "0x01";
12303 else
12304 params.value = "0x00";
12305 wifi_hostapdWrite(config_file, &params, 1);
12306
12307 memset(&params, 0, sizeof(params));
12308 params.name = "wpa_group_rekey";
12309 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12310 params.value = buf;
12311 wifi_hostapdWrite(config_file, &params, 1);
12312
12313 memset(&params, 0, sizeof(params));
12314 params.name = "wpa_strict_rekey";
12315 params.value = security->strict_rekey?"1":"0";
12316 wifi_hostapdWrite(config_file, &params, 1);
12317
12318 memset(&params, 0, sizeof(params));
12319 params.name = "wpa_pairwise_update_count";
12320 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12321 params.value = buf;
12322 wifi_hostapdWrite(config_file, &params, 1);
12323
12324 memset(&params, 0, sizeof(params));
12325 params.name = "disable_pmksa_caching";
12326 params.value = security->disable_pmksa_caching?"1":"0";
12327 wifi_hostapdWrite(config_file, &params, 1);
12328
12329 wifi_setApEnable(ap_index, FALSE);
12330 wifi_setApEnable(ap_index, TRUE);
12331
12332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12333
developer06a01d92022-09-07 16:32:39 +080012334 return RETURN_OK;
12335}
12336
12337INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12338{
developer9df4e652022-10-11 11:27:38 +080012339 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012340 char config_file[128] = {0};
12341 int disable = 0;
12342 // struct params params = {0};
12343
12344 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12345 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12346 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12347 security->mode = wifi_security_mode_none;
12348 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012349 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012350 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012351 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012352 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012353 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012354 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012355 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012356 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012357 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012358 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012359 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012360 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012361 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012362 security->mode = wifi_security_mode_wpa3_personal;
developer517a9792022-10-05 19:37:42 +080012363 else if (!strcmp(buf, "WPA3-Transition"))
developer587c1b62022-09-27 15:58:59 +080012364 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012365 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012366 security->mode = wifi_security_mode_wpa3_enterprise;
12367 }
12368
12369 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12370 if (security->mode == wifi_security_mode_none)
12371 security->encr = wifi_encryption_none;
12372 else {
12373 if (strcmp(buf, "TKIP") == 0)
12374 security->encr = wifi_encryption_tkip;
12375 else if (strcmp(buf, "CCMP") == 0)
12376 security->encr = wifi_encryption_aes;
12377 else
12378 security->encr = wifi_encryption_aes_tkip;
12379 }
12380
developer9df4e652022-10-11 11:27:38 +080012381 if (security->mode != wifi_encryption_none) {
12382 memset(buf, 0, sizeof(buf));
12383 // wpa3 can use one or both configs as password, so we check sae_password first.
12384 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12385 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12386 security->u.key.type = wifi_security_key_type_sae;
12387 } else {
12388 security->u.key.type = wifi_security_key_type_psk;
12389 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12390 }
12391 strncpy(security->u.key.key, buf, sizeof(buf));
12392 security->u.key.key[255] = '\0';
12393 }
12394
developer587c1b62022-09-27 15:58:59 +080012395 memset(buf, 0, sizeof(buf));
12396 wifi_getApSecurityMFPConfig(ap_index, buf);
12397 if (strcmp(buf, "Disabled") == 0)
12398 security->mfp = wifi_mfp_cfg_disabled;
12399 else if (strcmp(buf, "Optional") == 0)
12400 security->mfp = wifi_mfp_cfg_optional;
12401 else if (strcmp(buf, "Required") == 0)
12402 security->mfp = wifi_mfp_cfg_required;
12403
12404 memset(buf, 0, sizeof(buf));
12405 security->wpa3_transition_disable = FALSE;
12406 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12407 disable = strtol(buf, NULL, 16);
12408 if (disable != 0)
12409 security->wpa3_transition_disable = TRUE;
12410
12411 memset(buf, 0, sizeof(buf));
12412 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12413 if (strlen(buf) == 0)
12414 security->rekey_interval = 86400;
12415 else
12416 security->rekey_interval = strtol(buf, NULL, 10);
12417
12418 memset(buf, 0, sizeof(buf));
12419 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12420 if (strlen(buf) == 0)
12421 security->strict_rekey = 1;
12422 else
12423 security->strict_rekey = strtol(buf, NULL, 10);
12424
12425 memset(buf, 0, sizeof(buf));
12426 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12427 if (strlen(buf) == 0)
12428 security->eapol_key_retries = 4;
12429 else
12430 security->eapol_key_retries = strtol(buf, NULL, 10);
12431
12432 memset(buf, 0, sizeof(buf));
12433 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12434 if (strlen(buf) == 0)
12435 security->disable_pmksa_caching = FALSE;
12436 else
12437 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12438
12439 /* TODO
12440 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12441 */
12442 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12443 security->eap_identity_req_timeout = 0;
12444 security->eap_identity_req_retries = 0;
12445 security->eap_req_timeout = 0;
12446 security->eap_req_retries = 0;
12447 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012448 return RETURN_OK;
12449}
12450
12451#endif /* WIFI_HAL_VERSION_3 */
12452
12453#ifdef WIFI_HAL_VERSION_3_PHASE2
12454INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12455{
developer13df9332022-09-27 16:53:22 +080012456 char cmd[128] = {0};
12457 char buf[128] = {0};
12458 char *mac_addr = NULL;
12459 BOOL status = FALSE;
12460 size_t len = 0;
12461
12462 if(ap_index > MAX_APS)
12463 return RETURN_ERR;
12464
12465 *output_numDevices = 0;
12466 wifi_getApEnable(ap_index, &status);
12467 if (status == FALSE)
12468 return RETURN_OK;
12469
12470 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12471 _syscmd(cmd, buf, sizeof(buf));
12472
12473 mac_addr = strtok(buf, "\n");
12474 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12475 *output_numDevices = i + 1;
12476 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12477 addr_ptr = output_deviceMacAddressArray[i];
12478 mac_addr_aton(addr_ptr, mac_addr);
12479 mac_addr = strtok(NULL, "\n");
12480 }
12481
12482 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012483}
12484#else
12485INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12486{
12487 char cmd[128];
12488 BOOL status = false;
12489
12490 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12491 return RETURN_ERR;
12492
12493 output_buf[0] = '\0';
12494
12495 wifi_getApEnable(ap_index,&status);
12496 if (!status)
12497 return RETURN_OK;
12498
12499 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12500 _syscmd(cmd, output_buf, output_buf_size);
12501
12502 return RETURN_OK;
12503}
12504#endif
developer2f513ab2022-09-13 14:26:06 +080012505
12506INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12507{
12508 char output[16]={'\0'};
12509 char config_file[MAX_BUF_SIZE] = {0};
12510
12511 if (!enable)
12512 return RETURN_ERR;
12513
12514 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12515 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12516
12517 if (strlen(output) == 0)
12518 *enable = FALSE;
12519 else if (strncmp(output, "1", 1) == 0)
12520 *enable = TRUE;
12521 else
12522 *enable = FALSE;
12523
12524 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12525 return RETURN_OK;
12526}
developer2d9c30f2022-09-13 15:06:14 +080012527
12528INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12529{
12530 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12531 return RETURN_ERR;
12532 *output_enable=TRUE;
12533 return RETURN_OK;
12534}
developerfd7d2892022-09-13 16:44:53 +080012535
12536INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12537{
12538 char cmd[128] = {0};
12539 char buf[128] = {0};
12540 char line[128] = {0};
12541 size_t len = 0;
12542 ssize_t read = 0;
12543 FILE *f = NULL;
12544 int index = 0;
12545 int exp = 0;
12546 int mantissa = 0;
12547 int duration = 0;
12548 int radio_index = 0;
12549 int max_radio_num = 0;
12550 uint twt_wake_interval = 0;
12551
12552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12553
12554 wifi_getMaxRadioNumber(&max_radio_num);
12555 radio_index = ap_index % max_radio_num;
12556 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12557 _syscmd(cmd, buf, sizeof(buf));
12558 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12559 if (*numSessionReturned > maxNumberSessions)
12560 *numSessionReturned = maxNumberSessions;
12561 else if (*numSessionReturned < 1) {
12562 *numSessionReturned = 0;
12563 return RETURN_OK;
12564 }
12565
12566 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12567 if ((f = popen(cmd, "r")) == NULL) {
12568 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12569 return RETURN_ERR;
12570 }
12571
12572 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12573 while((read = fgets(line, sizeof(line), f)) != NULL) {
12574 char *tmp = NULL;
12575 strcpy(buf, line);
12576 tmp = strtok(buf, " ");
12577 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12578 tmp = strtok(NULL, " ");
12579 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12580 tmp = strtok(NULL, " ");
12581 if (strstr(tmp, "t")) {
12582 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12583 }
12584 if (strstr(tmp, "a")) {
12585 twtSessions[index].twtParameters.operation.announced = TRUE;
12586 }
12587 tmp = strtok(NULL, " ");
12588 exp = strtol(tmp, NULL, 10);
12589 tmp = strtok(NULL, " ");
12590 mantissa = strtol(tmp, NULL, 10);
12591 tmp = strtok(NULL, " ");
12592 duration = strtol(tmp, NULL, 10);
12593
12594 // only implicit supported
12595 twtSessions[index].twtParameters.operation.implicit = TRUE;
12596 // only individual agreement supported
12597 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12598
12599 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12600 twt_wake_interval = mantissa * (1 << exp);
12601 if (twt_wake_interval/mantissa != (1 << exp)) {
12602 // Overflow handling
12603 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12604 } else {
12605 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12606 }
12607 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12608 index++;
12609 }
12610
12611 pclose(f);
12612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12613 return RETURN_OK;
12614}