blob: 67931d8db1412a5a655b47b5b42940612be03b38 [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";
developer06a01d92022-09-07 16:32:39 +08005118 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5119 return RETURN_OK; //This is taken careof in beaconType
5120
5121 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5122 ret=wifi_hostapdWrite(config_file,&params,1);
5123 if(!ret)
5124 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5125 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5126
5127 return ret;
5128}
5129
5130// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5131INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5132{
5133 //save to wifi config, and wait for wifi restart to apply
5134 char BeaconType[50] = {0};
5135 char config_file[MAX_BUF_SIZE] = {0};
5136
5137 *authMode = 0;
5138 wifi_getApBeaconType(apIndex,BeaconType);
5139 printf("%s____%s \n",__FUNCTION__,BeaconType);
5140
5141 if(strcmp(BeaconType,"None") == 0)
5142 strcpy(authMode,"None");
5143 else
5144 {
5145 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5146 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5147 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5148 if(strcmp(authMode,"WPA-PSK") == 0)
5149 strcpy(authMode,"SharedAuthentication");
5150 else if(strcmp(authMode,"WPA-EAP") == 0)
5151 strcpy(authMode,"EAPAuthentication");
5152 }
5153
5154 return RETURN_OK;
5155}
5156
5157// Outputs the number of stations associated per AP
5158INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5159{
5160 char cmd[128]={0};
5161 char buf[128]={0};
5162 BOOL status = false;
5163
5164 if(apIndex > MAX_APS)
5165 return RETURN_ERR;
5166
5167 wifi_getApEnable(apIndex,&status);
5168 if (!status)
5169 return RETURN_OK;
5170
5171 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5172 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5173 _syscmd(cmd, buf, sizeof(buf));
5174 sscanf(buf,"%lu", output_ulong);
5175
5176 return RETURN_OK;
5177}
5178
5179// manually removes any active wi-fi association with the device specified on this ap
5180INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5181{
5182 char buf[126]={'\0'};
5183
5184 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5185 system(buf);
5186
5187 return RETURN_OK;
5188}
5189
5190// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5191INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5192{
5193 if(NULL == output_int)
5194 return RETURN_ERR;
5195 *output_int = apIndex%2;
5196 return RETURN_OK;
5197}
5198
5199// sets the radio index for the specific ap
5200INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5201{
5202 //set to config only and wait for wifi reset to apply settings
5203 return RETURN_ERR;
5204}
5205
5206// Get the ACL MAC list per AP
5207INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5208{
5209 char cmd[MAX_CMD_SIZE]={'\0'};
5210 int ret = 0;
5211
5212 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5213 ret = _syscmd(cmd,macArray,buf_size);
5214 if (ret != 0)
5215 return RETURN_ERR;
5216
5217 return RETURN_OK;
5218}
5219
developere6aafda2022-09-13 14:59:28 +08005220INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5221{
5222 char cmd[MAX_CMD_SIZE]={'\0'};
5223 int ret = 0;
5224
5225 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5226 ret = _syscmd(cmd,macArray,buf_size);
5227 if (ret != 0)
5228 return RETURN_ERR;
5229
5230 return RETURN_OK;
5231}
5232
5233
developer06a01d92022-09-07 16:32:39 +08005234// Get the list of stations associated per AP
5235INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5236{
5237 char cmd[128];
5238
5239 if(apIndex > 3) //Currently supporting apIndex upto 3
5240 return RETURN_ERR;
5241 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5242 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5243 _syscmd(cmd, macArray, buf_size);
5244
5245 return RETURN_OK;
5246}
5247
5248// adds the mac address to the filter list
5249//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5250INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5251{
5252 char cmd[MAX_CMD_SIZE]={'\0'};
5253 char buf[MAX_BUF_SIZE]={'\0'};
5254
5255#if 0
5256 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5257 if(_syscmd(cmd,buf,sizeof(buf)))
5258 return RETURN_ERR;
5259#endif
5260 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5261 if(_syscmd(cmd,buf,sizeof(buf)))
5262 return RETURN_ERR;
5263
5264 return RETURN_OK;
5265}
5266
5267// deletes the mac address from the filter list
5268//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5269INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5270{
5271 char cmd[MAX_CMD_SIZE]={'\0'};
5272 char buf[MAX_BUF_SIZE]={'\0'};
5273
5274#if 0
5275 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5276 if(_syscmd(cmd,buf,sizeof(buf)))
5277 return RETURN_ERR;
5278
5279#endif
5280 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5281 if(_syscmd(cmd,buf,sizeof(buf)))
5282 return RETURN_ERR;
5283
5284 return RETURN_OK;
5285}
5286
5287// outputs the number of devices in the filter list
5288INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5289{
developere6aafda2022-09-13 14:59:28 +08005290 char cmd[MAX_BUF_SIZE]={0};
5291 char buf[MAX_CMD_SIZE]={0};
5292
5293 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5294 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005295 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005296
5297 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5298 _syscmd(cmd, buf, sizeof(buf));
5299
5300 *output_uint = atoi(buf);
5301
5302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5303 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005304}
5305
5306INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5307{
5308 char cmd[128]={'\0'};
5309 char buf[128]={'\0'};
5310
5311 if(strcmp(action,"DENY")==0)
5312 {
5313 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5314 system(buf);
5315 return RETURN_OK;
5316 }
5317
5318 if(strcmp(action,"ALLOW")==0)
5319 {
5320 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5321 system(buf);
5322 return RETURN_OK;
5323 }
5324
5325 return RETURN_ERR;
5326
5327}
5328
5329// enable kick for devices on acl black list
5330INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5331{
5332 char aclArray[512] = {0}, *acl = NULL;
5333 char assocArray[512] = {0}, *asso = NULL;
5334
developere6aafda2022-09-13 14:59:28 +08005335 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005336 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5337
5338 // if there are no devices connected there is nothing to do
5339 if (strlen(assocArray) < 17)
5340 return RETURN_OK;
5341
5342 if (enable == TRUE)
5343 {
5344 //kick off the MAC which is in ACL array (deny list)
5345 acl = strtok(aclArray, "\r\n");
5346 while (acl != NULL) {
5347 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5348 wifi_kickApAssociatedDevice(apIndex, acl);
5349
5350 acl = strtok(NULL, "\r\n");
5351 }
developere6aafda2022-09-13 14:59:28 +08005352 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005353 }
5354 else
5355 {
developere6aafda2022-09-13 14:59:28 +08005356 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005357 }
5358
5359#if 0
5360 //TODO: need to revisit below implementation
5361 char aclArray[512]={0}, *acl=NULL;
5362 char assocArray[512]={0}, *asso=NULL;
5363 char buf[256]={'\0'};
5364 char action[10]={'\0'};
5365 FILE *fr=NULL;
5366 char interface[10]={'\0'};
5367 char config_file[MAX_BUF_SIZE] = {0};
5368
5369 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5370 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5371 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5372 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5373
5374 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5375 system(buf);
5376 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5377 system(buf);
5378 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5379 system(buf);
5380 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5381 system(buf);
5382 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5383 system(buf);
5384
5385 if ( enable == TRUE )
5386 {
5387 int device_count=0;
5388 strcpy(action,"DENY");
5389 //kick off the MAC which is in ACL array (deny list)
5390 acl = strtok (aclArray,",");
5391 while (acl != NULL) {
5392 if(strlen(acl)>=17)
5393 {
5394 apply_rules(apIndex, acl,action,interface);
5395 device_count++;
5396 //Register mac to be blocked ,in syscfg.db persistent storage
5397 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5398 system(buf);
5399 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5400 system(buf);
5401 system("syscfg commit");
5402
5403 wifi_kickApAssociatedDevice(apIndex, acl);
5404 }
5405 acl = strtok (NULL, ",");
5406 }
5407 }
5408 else
5409 {
5410 int device_count=0;
5411 char cmdmac[20]={'\0'};
5412 strcpy(action,"ALLOW");
5413 //kick off the MAC which is not in ACL array (allow list)
5414 acl = strtok (aclArray,",");
5415 while (acl != NULL) {
5416 if(strlen(acl)>=17)
5417 {
5418 apply_rules(apIndex, acl,action,interface);
5419 device_count++;
5420 //Register mac to be Allowed ,in syscfg.db persistent storage
5421 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5422 system(buf);
5423 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5424 system(buf);
5425 sprintf(cmdmac,"%s",acl);
5426 }
5427 acl = strtok (NULL, ",");
5428 }
5429 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5430 system(buf);
5431
5432 //Disconnect the mac which is not in ACL
5433 asso = strtok (assocArray,",");
5434 while (asso != NULL) {
5435 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5436 wifi_kickApAssociatedDevice(apIndex, asso);
5437 asso = strtok (NULL, ",");
5438 }
5439 }
5440#endif
5441 return RETURN_OK;
5442}
5443
5444INT wifi_setPreferPrivateConnection(BOOL enable)
5445{
5446 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5447 char buf[1024] = {0};
5448
5449 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5450 if(enable == TRUE)
5451 {
5452 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5453 sprintf(buf,"ifconfig %s down" ,interface_name);
5454 system(buf);
5455 memset(buf,0,sizeof(buf));
5456 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5457 sprintf(buf,"ifconfig %s down" ,interface_name);
5458 system(buf);
5459 }
5460 else
5461 {
5462 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5463 if(strcmp(ssid_cur_value,"1") == 0)
5464 wifi_RestartPrivateWifi_5G();
5465 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5466 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5467 if(strcmp(ssid_cur_value,"1") == 0)
5468 wifi_RestartHostapd_2G();
5469 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5470 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5471 if(strcmp(ssid_cur_value,"1") == 0)
5472 wifi_RestartHostapd_5G();
5473 }
5474 return RETURN_OK;
5475}
5476
5477// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5478INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5479{
5480 int items = 1;
5481 struct params list[2];
5482 char buf[MAX_BUF_SIZE] = {0};
5483 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005484 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005485
5486 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005487
developer10adcc12022-09-13 14:39:17 +08005488 if (filterMode == 0) {
5489 sprintf(buf, "%d", 0);
5490 list[0].value = buf;
5491
5492 char cmd[128], rtn[128];
5493 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5494 _syscmd(cmd, rtn, sizeof(rtn));
5495 memset(cmd,0,sizeof(cmd));
5496 // Delete deny_mac_file in hostapd configuration
5497 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5498 _syscmd(cmd, rtn, sizeof(rtn));
5499 }
5500 else if (filterMode == 1) {
5501 sprintf(buf, "%d", filterMode);
5502 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005503 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5504 list[1].name = "accept_mac_file";
5505 list[1].value = acl_file;
5506 items = 2;
developer10adcc12022-09-13 14:39:17 +08005507 } else if (filterMode == 2) {
5508 //TODO: deny_mac_file
5509 sprintf(buf, "%d", 0);
5510 list[0].value = buf;
5511 list[1].name = "deny_mac_file";
5512 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5513 list[1].value = deny_file;
5514 items = 2;
5515 } else {
5516 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005517 }
developer10adcc12022-09-13 14:39:17 +08005518
developer06a01d92022-09-07 16:32:39 +08005519 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5520 wifi_hostapdWrite(config_file, list, items);
5521
5522 return RETURN_OK;
5523
5524#if 0
5525 if(apIndex==0 || apIndex==1)
5526 {
5527 //set the filtermode
5528 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5529 system(buf);
5530 system("syscfg commit");
5531
5532 if(filterMode==0)
5533 {
5534 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5535 system(buf);
5536 return RETURN_OK;
5537 }
5538 }
5539 return RETURN_OK;
5540#endif
5541}
5542
5543// 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.
5544INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5545{
5546 return RETURN_ERR;
5547}
5548
5549// gets the vlan ID for this ap from an internal enviornment variable
5550INT wifi_getApVlanID(INT apIndex, INT *output_int)
5551{
5552 if(apIndex=0)
5553 {
5554 *output_int=100;
5555 return RETURN_OK;
5556 }
5557
5558 return RETURN_ERR;
5559}
5560
5561// sets the vlan ID for this ap to an internal enviornment variable
5562INT wifi_setApVlanID(INT apIndex, INT vlanId)
5563{
5564 //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)
5565 return RETURN_ERR;
5566}
5567
5568// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5569INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5570{
5571 snprintf(bridgeName, 32, "brlan0");
5572 snprintf(IP, 32, "10.0.0.1");
5573 snprintf(subnet, 32, "255.255.255.0");
5574
5575 return RETURN_OK;
5576}
5577
5578//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5579INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5580{
5581 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5582 return RETURN_ERR;
5583}
5584
5585// reset the vlan configuration for this ap
5586INT wifi_resetApVlanCfg(INT apIndex)
5587{
developerf5fef612022-09-20 19:38:26 +08005588 char original_config_file[64] = {0};
5589 char current_config_file[64] = {0};
5590 char buf[64] = {0};
5591 char cmd[64] = {0};
5592 char vlan_file[64] = {0};
5593 char vlan_tagged_interface[16] = {0};
5594 char vlan_bridge[16] = {0};
5595 char vlan_naming[16] = {0};
5596 struct params list[4] = {0};
5597 wifi_band band;
5598
5599 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5600
5601 band = wifi_index_to_band(apIndex);
5602 if (band == band_2_4)
5603 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5604 else if (band = band_5)
5605 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5606 else if (band = band_6)
5607 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5608
5609 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5610
5611 if (strlen(vlan_file) == 0)
5612 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005613
developerf5fef612022-09-20 19:38:26 +08005614 // The file should exist or this vap would not work.
5615 if (access(vlan_file, F_OK) != 0) {
5616 sprintf(cmd, "touch %s", vlan_file);
5617 _syscmd(cmd, buf, sizeof(buf));
5618 }
5619 list[0].name = "vlan_file";
5620 list[0].value = vlan_file;
5621
5622 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5623 list[1].name = "vlan_tagged_interface";
5624 list[1].value = vlan_tagged_interface;
5625
5626 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5627 list[2].name = "vlan_bridge";
5628 list[2].value = vlan_bridge;
5629
5630 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5631 list[3].name = "vlan_naming";
5632 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005633
developerf5fef612022-09-20 19:38:26 +08005634 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5635 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005636 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005637 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005638
developerf5fef612022-09-20 19:38:26 +08005639 // restart this ap
5640 wifi_setApEnable(apIndex, FALSE);
5641 wifi_setApEnable(apIndex, TRUE);
5642
5643 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5644
5645 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005646}
5647
5648// 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.
5649INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5650{
5651 return RETURN_ERR;
5652}
5653
5654// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5655INT wifi_startHostApd()
5656{
5657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5658 system("systemctl start hostapd.service");
5659 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5660 return RETURN_OK;
5661 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5662}
5663
5664// stops hostapd
5665INT wifi_stopHostApd()
5666{
5667 char cmd[128] = {0};
5668 char buf[128] = {0};
5669
5670 sprintf(cmd,"systemctl stop hostapd");
5671 _syscmd(cmd, buf, sizeof(buf));
5672
5673 return RETURN_OK;
5674}
5675
5676// restart hostapd dummy function
5677INT wifi_restartHostApd()
5678{
5679 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5680 system("systemctl restart hostapd-global");
5681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5682
5683 return RETURN_OK;
5684}
5685
5686static int align_hostapd_config(int index)
5687{
5688 ULONG lval;
5689 wifi_getRadioChannel(index%2, &lval);
5690 wifi_setRadioChannel(index%2, lval);
5691}
5692
5693// sets the AP enable status variable for the specified ap.
5694INT wifi_setApEnable(INT apIndex, BOOL enable)
5695{
5696 char config_file[MAX_BUF_SIZE] = {0};
5697 char cmd[MAX_CMD_SIZE] = {0};
5698 char buf[MAX_BUF_SIZE] = {0};
5699 BOOL status;
5700
5701 wifi_getApEnable(apIndex,&status);
5702 if (enable == status)
5703 return RETURN_OK;
5704
5705 if (enable == TRUE) {
5706 int radioIndex = apIndex % NUMBER_OF_RADIOS;
developer06a01d92022-09-07 16:32:39 +08005707 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5708 //Hostapd will bring up this interface
5709 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5710 _syscmd(cmd, buf, sizeof(buf));
5711 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5712 _syscmd(cmd, buf, sizeof(buf));
5713 }
5714 else {
5715 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5716 _syscmd(cmd, buf, sizeof(buf));
5717 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5718 _syscmd(cmd, buf, sizeof(buf));
5719 }
5720 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5721 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5722 _syscmd(cmd, buf, sizeof(buf));
5723 //Wait for wifi up/down to apply
5724 return RETURN_OK;
5725}
5726
5727// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5728INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5729{
5730 char cmd[MAX_CMD_SIZE] = {'\0'};
5731 char buf[MAX_BUF_SIZE] = {'\0'};
5732
5733 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5734 return RETURN_ERR;
5735
5736 *output_bool = 0;
5737
5738 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5739 {
developer70490032022-09-13 15:45:20 +08005740 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005741 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5742 }
5743
5744 return RETURN_OK;
5745}
5746
5747// Outputs the AP "Enabled" "Disabled" status from driver
5748INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5749{
5750 char cmd[128] = {0};
5751 char buf[128] = {0};
5752 BOOL output_bool;
5753
5754 if ( NULL == output_string)
5755 return RETURN_ERR;
5756 wifi_getApEnable(apIndex,&output_bool);
5757
5758 if(output_bool == 1)
5759 snprintf(output_string, 32, "Up");
5760 else
5761 snprintf(output_string, 32, "Disable");
5762
5763 return RETURN_OK;
5764}
5765
5766//Indicates whether or not beacons include the SSID name.
5767// outputs a 1 if SSID on the AP is enabled, else outputs 0
5768INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5769{
5770 //get the running status
5771 char config_file[MAX_BUF_SIZE] = {0};
5772 char buf[16] = {0};
5773
5774 if (!output)
5775 return RETURN_ERR;
5776
5777 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5778 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5779 *output = (strncmp("0",buf,1) == 0);
5780
5781 return RETURN_OK;
5782}
5783
5784// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5785INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5786{
5787 //store the config, apply instantly
5788 char config_file[MAX_BUF_SIZE] = {0};
5789 struct params list;
5790
5791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5792 list.name = "ignore_broadcast_ssid";
5793 list.value = enable?"0":"1";
5794
5795 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5796 wifi_hostapdWrite(config_file, &list, 1);
5797 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5798 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005799 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005800 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5801
5802 return RETURN_OK;
5803}
5804
5805//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5806INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5807{
5808 //get the running status
5809 if(!output_uint)
5810 return RETURN_ERR;
5811 *output_uint=16;
5812 return RETURN_OK;
5813}
5814
5815INT wifi_setApRetryLimit(INT apIndex, UINT number)
5816{
5817 //apply instantly
5818 return RETURN_ERR;
5819}
5820
5821//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5822INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5823{
5824 if(!output)
5825 return RETURN_ERR;
5826 *output=TRUE;
5827 return RETURN_OK;
5828}
5829
5830//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5831INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5832{
5833 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005834 char cmd[128] = {0};
5835 char buf[128] = {0};
5836 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005837
developer0b246d12022-09-30 15:24:20 +08005838 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005839
developer0b246d12022-09-30 15:24:20 +08005840 wifi_getMaxRadioNumber(&max_radio_num);
5841 radioIndex = apIndex % max_radio_num;
5842 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5843 _syscmd(cmd,buf, sizeof(buf));
5844
5845 if (strlen(buf) > 0)
5846 *output = true;
5847
5848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005849
developer06a01d92022-09-07 16:32:39 +08005850 return RETURN_OK;
5851}
5852
5853//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5854INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5855{
5856 //get the running status from driver
5857 if(!output)
5858 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005859
5860 char config_file[MAX_BUF_SIZE] = {0};
5861 char buf[16] = {0};
5862
5863 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5864 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5865 if (strncmp("1",buf,1) == 0)
5866 *output = TRUE;
5867 else
5868 *output = FALSE;
5869
developer06a01d92022-09-07 16:32:39 +08005870 return RETURN_OK;
5871}
5872
5873// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5874INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5875{
5876 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005877 char config_file[MAX_BUF_SIZE] = {0};
5878 struct params list;
5879
5880 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5881 list.name = "wmm_enabled";
5882 list.value = enable?"1":"0";
5883
5884 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5885 wifi_hostapdWrite(config_file, &list, 1);
5886 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5887 wifi_reloadAp(apIndex);
5888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5889
5890 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005891}
5892
5893//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.
5894INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5895{
5896 //get the running status from driver
5897 if(!output)
5898 return RETURN_ERR;
5899 *output=TRUE;
5900 return RETURN_OK;
5901}
5902
5903// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5904INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5905{
5906 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005907 char config_file[MAX_BUF_SIZE] = {0};
5908 struct params list;
5909
5910 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5911 list.name = "uapsd_advertisement_enabled";
5912 list.value = enable?"1":"0";
5913
5914 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5915 wifi_hostapdWrite(config_file, &list, 1);
5916 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5917 wifi_reloadAp(apIndex);
5918 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5919
5920 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005921}
5922
developer6daeb3f2022-09-30 13:36:39 +08005923// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005924INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5925{
developer6daeb3f2022-09-30 13:36:39 +08005926 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5927 char cmd[128] = {0};
5928 char buf[128] = {0};
5929 char ack_filepath[128] = {0};
5930 uint16_t bitmap = 0;
5931 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5932 FILE *f = NULL;
5933
5934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5935
5936 // Get current setting
5937 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5938 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5939 _syscmd(cmd, buf, sizeof(buf));
5940 if (strlen(buf) > 0)
5941 bitmap = strtoul(buf, NULL, 10);
5942
5943 bitmap = strtoul(buf, NULL, 10);
5944
5945 if (ackPolicy == TRUE) { // True, unset this class
5946 bitmap &= ~class_map[class];
5947 } else { // False, set this class
5948 bitmap |= class_map[class];
5949 }
5950
5951 f = fopen(ack_filepath, "w");
5952 if (f == NULL) {
5953 fprintf(stderr, "%s: fopen failed\n", __func__);
5954 return RETURN_ERR;
5955 }
5956 fprintf(f, "%hu", bitmap);
5957 fclose(f);
5958
5959 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5960 _syscmd(cmd, buf, sizeof(buf));
5961
5962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5963 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005964}
5965
5966//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.
5967INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5968{
5969 //get the running status from driver
5970 if(!output_uint)
5971 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005972
5973 char output[16]={'\0'};
5974 char config_file[MAX_BUF_SIZE] = {0};
5975
5976 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5977 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5978 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5979 else {
5980 int device_num = atoi(output);
5981 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5982 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5983 return RETURN_ERR;
5984 }
5985 else {
5986 *output_uint = device_num;
5987 }
5988 }
5989
developer06a01d92022-09-07 16:32:39 +08005990 return RETURN_OK;
5991}
5992
5993INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5994{
5995 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005996 char str[MAX_BUF_SIZE]={'\0'};
5997 char cmd[MAX_CMD_SIZE]={'\0'};
5998 struct params params;
5999 char config_file[MAX_BUF_SIZE] = {0};
6000
6001 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6002 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6003 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6004 return RETURN_ERR;
6005 }
6006 sprintf(str, "%d", number);
6007 params.name = "max_num_sta";
6008 params.value = str;
6009
6010 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6011 int ret = wifi_hostapdWrite(config_file, &params, 1);
6012 if (ret) {
6013 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6014 ,__func__, ret);
6015 }
6016
6017 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6018 if (ret) {
6019 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6020 ,__func__, ret);
6021 }
6022 wifi_reloadAp(apIndex);
6023 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6024
6025 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006026}
6027
6028//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.
6029INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6030{
6031 //get the current threshold
6032 if(!output_uint)
6033 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006034 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6035 if (*output_uint == 0)
6036 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006037 return RETURN_OK;
6038}
6039
6040INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6041{
6042 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006043 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6044 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006045 return RETURN_ERR;
6046}
6047
6048//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.
6049INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6050{
6051 if(!output_uint)
6052 return RETURN_ERR;
6053 *output_uint = 3;
6054 return RETURN_OK;
6055}
6056
6057//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6058INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6059{
6060 if(!output_uint)
6061 return RETURN_ERR;
6062 *output_uint = 3;
6063 return RETURN_OK;
6064}
6065
6066//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.
6067INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6068{
6069 if(!output_in_seconds)
6070 return RETURN_ERR;
6071 *output_in_seconds = 0;
6072 return RETURN_OK;
6073}
6074
6075//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
6076INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6077{
6078 if(!output || apIndex>=MAX_APS)
6079 return RETURN_ERR;
6080 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006081 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006082 return RETURN_OK;
6083}
6084
6085//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6086INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6087{
developer587c1b62022-09-27 15:58:59 +08006088 char config_file[128] = {0};
6089 char wpa[16] = {0};
6090 char key_mgmt[64] = {0};
6091 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006092 if (!output)
6093 return RETURN_ERR;
6094
6095 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006096 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006097
developer587c1b62022-09-27 15:58:59 +08006098 strcpy(output, "None");//Copying "None" to output string for default case
6099 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6100 if (strstr(key_mgmt, "WPA-PSK")) {
developer517a9792022-10-05 19:37:42 +08006101 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006102 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006103 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006104 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006105 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006106 snprintf(output, 32, "WPA-WPA2-Personal");
6107
6108 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006109 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006110 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006111 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006112 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006113 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006114 snprintf(output, 32, "WPA-WPA2-Enterprise");
6115 } else if (strstr(key_mgmt, "SAE")) {
6116 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6117 int disable = strtol(buf, NULL, 16);
6118 if (disable & 0x1)
6119 snprintf(output, 32, "WPA3-Personal");
6120 else
6121 snprintf(output, 32, "WPA3-Transition");
6122 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6123 snprintf(output, 32, "WPA3-Enterprise");
6124 }
developer06a01d92022-09-07 16:32:39 +08006125
6126 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6127 return RETURN_OK;
6128#if 0
6129 //TODO: need to revisit below implementation
6130 char securityType[32], authMode[32];
6131 int enterpriseMode=0;
6132
6133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6134 if(!output)
6135 return RETURN_ERR;
6136
6137 wifi_getApBeaconType(apIndex, securityType);
6138 strcpy(output,"None");//By default, copying "None" to output string
6139 if (strncmp(securityType,"None", strlen("None")) == 0)
6140 return RETURN_OK;
6141
6142 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6143 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6144
6145 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6146 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6147 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6148 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6149 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6150 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6152
6153 return RETURN_OK;
6154#endif
6155}
6156
6157INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6158{
6159 char securityType[32];
6160 char authMode[32];
6161
6162 //store settings and wait for wifi up to apply
6163 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6164 if(!encMode)
6165 return RETURN_ERR;
6166
developer06a01d92022-09-07 16:32:39 +08006167 if (strcmp(encMode, "None")==0)
6168 {
6169 strcpy(securityType,"None");
6170 strcpy(authMode,"None");
6171 }
6172 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6173 {
6174 strcpy(securityType,"WPAand11i");
6175 strcpy(authMode,"PSKAuthentication");
6176 }
6177 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6178 {
6179 strcpy(securityType,"WPAand11i");
6180 strcpy(authMode,"EAPAuthentication");
6181 }
6182 else if (strcmp(encMode, "WPA-Personal")==0)
6183 {
6184 strcpy(securityType,"WPA");
6185 strcpy(authMode,"PSKAuthentication");
6186 }
6187 else if (strcmp(encMode, "WPA-Enterprise")==0)
6188 {
6189 strcpy(securityType,"WPA");
6190 strcpy(authMode,"EAPAuthentication");
6191 }
6192 else if (strcmp(encMode, "WPA2-Personal")==0)
6193 {
6194 strcpy(securityType,"11i");
6195 strcpy(authMode,"PSKAuthentication");
6196 }
6197 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6198 {
6199 strcpy(securityType,"11i");
6200 strcpy(authMode,"EAPAuthentication");
6201 }
developer587c1b62022-09-27 15:58:59 +08006202 else if (strcmp(encMode, "WPA3-Personal") == 0)
6203 {
6204 strcpy(securityType,"11i");
6205 strcpy(authMode,"SAEAuthentication");
6206 }
6207 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6208 {
6209 strcpy(securityType,"11i");
6210 strcpy(authMode,"EAP_192-bit_Authentication");
6211 }
developer06a01d92022-09-07 16:32:39 +08006212 else
6213 {
6214 strcpy(securityType,"None");
6215 strcpy(authMode,"None");
6216 }
6217 wifi_setApBeaconType(apIndex, securityType);
6218 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6219 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6220
6221 return RETURN_OK;
6222}
6223
6224
6225//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6226// output_string must be pre-allocated as 64 character string by caller
6227// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6228INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6229{
6230 char buf[16];
6231 char config_file[MAX_BUF_SIZE] = {0};
6232
6233 if(output_string==NULL)
6234 return RETURN_ERR;
6235
6236 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6237 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6238
6239 if(strcmp(buf,"0")==0)
6240 {
6241 printf("wpa_mode is %s ......... \n",buf);
6242 return RETURN_ERR;
6243 }
6244
6245 wifi_dbg_printf("\nFunc=%s\n",__func__);
6246 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6247 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6248 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6249
6250 return RETURN_OK;
6251}
6252
6253// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6254// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6255INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6256{
6257 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6258 struct params params={'\0'};
6259 int ret;
6260 char config_file[MAX_BUF_SIZE] = {0};
6261
6262 if(NULL == preSharedKey)
6263 return RETURN_ERR;
6264
6265 params.name = "wpa_passphrase";
6266
6267 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6268 {
6269 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6270 return RETURN_ERR;
6271 }
6272 params.value = preSharedKey;
6273 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6274 ret = wifi_hostapdWrite(config_file, &params, 1);
6275 if(!ret)
6276 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6277 return ret;
6278 //TODO: call hostapd_cli for dynamic_config_control
6279}
6280
6281//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6282// outputs the passphrase, maximum 63 characters
6283INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6284{
6285 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6286
6287 wifi_dbg_printf("\nFunc=%s\n",__func__);
6288 if (NULL == output_string)
6289 return RETURN_ERR;
6290
6291 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6292 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6293 if(strcmp(buf,"0")==0)
6294 {
6295 printf("wpa_mode is %s ......... \n",buf);
6296 return RETURN_ERR;
6297 }
6298
6299 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6300 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6301
6302 return RETURN_OK;
6303}
6304
6305// sets the passphrase enviornment variable, max 63 characters
6306INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6307{
6308 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6309 struct params params={'\0'};
6310 char config_file[MAX_BUF_SIZE] = {0};
6311 int ret;
6312
6313 if(NULL == passPhrase)
6314 return RETURN_ERR;
6315
6316 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6317 {
6318 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6319 return RETURN_ERR;
6320 }
6321 params.name = "wpa_passphrase";
6322 params.value = passPhrase;
6323 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6324 ret=wifi_hostapdWrite(config_file,&params,1);
6325 if(!ret)
6326 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6327
6328 return ret;
6329}
6330
6331//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.
6332INT wifi_setApSecurityReset(INT apIndex)
6333{
developer8d583982022-09-20 11:28:22 +08006334 char original_config_file[64] = {0};
6335 char current_config_file[64] = {0};
6336 char buf[64] = {0};
6337 char cmd[64] = {0};
6338 char wpa[4] = {0};
6339 char wpa_psk[64] = {0};
6340 char wpa_passphrase[64] = {0};
6341 char wpa_psk_file[128] = {0};
6342 char wpa_key_mgmt[64] = {0};
6343 char wpa_pairwise[32] = {0};
6344 wifi_band band;
6345 struct params list[6];
6346
6347 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6348
6349 band = wifi_index_to_band(apIndex);
6350 if (band == band_2_4)
6351 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6352 else if (band = band_5)
6353 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6354 else if (band = band_6)
6355 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6356 else
6357 return RETURN_ERR;
6358
6359 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6360 list[0].name = "wpa";
6361 list[0].value = wpa;
6362
6363 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6364 list[1].name = "wpa_psk";
6365 list[1].value = wpa_psk;
6366
6367 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6368 list[2].name = "wpa_passphrase";
6369 list[2].value = wpa_passphrase;
6370
6371 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6372
6373 if (strlen(wpa_psk_file) == 0)
6374 strcpy(wpa_psk_file, PSK_FILE);
6375
6376 if (access(wpa_psk_file, F_OK) != 0) {
6377 sprintf(cmd, "touch %s", wpa_psk_file);
6378 _syscmd(cmd, buf, sizeof(buf));
6379 }
6380 list[3].name = "wpa_psk_file";
6381 list[3].value = wpa_psk_file;
6382
6383 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6384 list[4].name = "wpa_key_mgmt";
6385 list[4].value = wpa_key_mgmt;
6386
6387 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6388 list[5].name = "wpa_pairwise";
6389 list[5].value = wpa_pairwise;
6390
6391 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6392 wifi_hostapdWrite(current_config_file, list, 6);
6393
6394 wifi_setApEnable(apIndex, FALSE);
6395 wifi_setApEnable(apIndex, TRUE);
6396
6397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6398 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006399}
6400
6401//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).
6402INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6403{
developer8f2ddd52022-09-13 15:39:24 +08006404 char config_file[64] = {0};
6405 char buf[64] = {0};
6406 char cmd[256] = {0};
6407
6408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6409
developer06a01d92022-09-07 16:32:39 +08006410 if(!IP_output || !Port_output || !RadiusSecret_output)
6411 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006412
developer8f2ddd52022-09-13 15:39:24 +08006413 // Read the first matched config
6414 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6415 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6416 _syscmd(cmd, buf, sizeof(buf));
6417 strncpy(IP_output, buf, 64);
6418
6419 memset(buf, 0, sizeof(buf));
6420 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6421 _syscmd(cmd, buf, sizeof(buf));
6422 *Port_output = atoi(buf);
6423
6424 memset(buf, 0, sizeof(buf));
6425 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6426 _syscmd(cmd, buf, sizeof(buf));
6427 strncpy(RadiusSecret_output, buf, 64);
6428
6429 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006430 return RETURN_OK;
6431}
6432
6433INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6434{
developer8f2ddd52022-09-13 15:39:24 +08006435 char config_file[64] = {0};
6436 char port_str[8] = {0};
6437 char cmd[256] = {0};
6438 char buf[128] = {0};
6439
6440 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6441
6442 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6443
6444 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6445 _syscmd(cmd, buf, sizeof(buf));
6446 memset(cmd, 0, sizeof(cmd));
6447
6448 snprintf(port_str, sizeof(port_str), "%d", port);
6449 if (strlen(buf) == 0)
6450 // Append
6451 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6452 "auth_server_addr=%s\\n"
6453 "auth_server_port=%s\\n"
6454 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6455 else {
6456 // Delete the three lines setting after the "# radius 1" comment
6457 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6458 _syscmd(cmd, buf, sizeof(buf));
6459 memset(cmd, 0, sizeof(cmd));
6460 // Use "# radius 1" comment to find the location to insert the radius setting
6461 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6462 "# radius 1\\n"
6463 "auth_server_addr=%s\\n"
6464 "auth_server_port=%s\\n"
6465 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6466 }
6467 if(_syscmd(cmd, buf, sizeof(buf))) {
6468 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6469 return RETURN_ERR;
6470 }
6471
6472 wifi_reloadAp(apIndex);
6473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6474 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006475}
6476
6477INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6478{
developer8f2ddd52022-09-13 15:39:24 +08006479 char config_file[64] = {0};
6480 char buf[64] = {0};
6481 char cmd[256] = {0};
6482
6483 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6484
developer06a01d92022-09-07 16:32:39 +08006485 if(!IP_output || !Port_output || !RadiusSecret_output)
6486 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006487
6488 // Read the second matched config
6489 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6490 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6491 _syscmd(cmd, buf, sizeof(buf));
6492 strncpy(IP_output, buf, 64);
6493
6494 memset(buf, 0, sizeof(buf));
6495 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6496 _syscmd(cmd, buf, sizeof(buf));
6497 *Port_output = atoi(buf);
6498
6499 memset(buf, 0, sizeof(buf));
6500 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6501 _syscmd(cmd, buf, sizeof(buf));
6502 strncpy(RadiusSecret_output, buf, 64);
6503
6504 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006505 return RETURN_OK;
6506}
6507
6508INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6509{
developer8f2ddd52022-09-13 15:39:24 +08006510 char config_file[64] = {0};
6511 char port_str[8] = {0};
6512 char cmd[256] = {0};
6513 char buf[128] = {0};
6514
6515 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6516
6517 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6518
6519 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6520 _syscmd(cmd, buf, sizeof(buf));
6521 memset(cmd, 0, sizeof(cmd));
6522
6523 snprintf(port_str, sizeof(port_str), "%d", port);
6524 if (strlen(buf) == 0)
6525 // Append
6526 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6527 "auth_server_addr=%s\\n"
6528 "auth_server_port=%s\\n"
6529 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6530 else {
6531 // Delete the three lines setting after the "# radius 2" comment
6532 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6533 _syscmd(cmd, buf, sizeof(buf));
6534 memset(cmd, 0, sizeof(cmd));
6535 // Use "# radius 2" comment to find the location to insert the radius setting
6536 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6537 "# radius 2\\n"
6538 "auth_server_addr=%s\\n"
6539 "auth_server_port=%s\\n"
6540 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6541 }
6542 if(_syscmd(cmd, buf, sizeof(buf))) {
6543 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6544 return RETURN_ERR;
6545 }
6546
6547 wifi_reloadAp(apIndex);
6548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6549 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006550}
6551
6552//RadiusSettings
6553INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6554{
6555 if(!output)
6556 return RETURN_ERR;
6557
6558 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6559 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6560 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6561 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6562 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6563 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.
6564 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6565 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6566 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6567 //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.
6568
6569 return RETURN_OK;
6570}
6571
6572INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6573{
6574 //store the paramters, and apply instantly
6575 return RETURN_ERR;
6576}
6577
6578//Device.WiFi.AccessPoint.{i}.WPS.Enable
6579//Enables or disables WPS functionality for this access point.
6580// outputs the WPS enable state of this ap in output_bool
6581INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6582{
6583 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6584 if(!output_bool || !(apIndex==0 || apIndex==1))
6585 return RETURN_ERR;
6586 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6587 _syscmd(cmd, buf, sizeof(buf));
6588 if(strstr(buf, "configured"))
6589 *output_bool=TRUE;
6590 else
6591 *output_bool=FALSE;
6592
6593 return RETURN_OK;
6594}
6595
6596//Device.WiFi.AccessPoint.{i}.WPS.Enable
6597// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6598INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6599{
6600 char config_file[MAX_BUF_SIZE] = {0};
6601 struct params params;
6602
6603 if(!(apIndex==0 || apIndex==1))
6604 return RETURN_ERR;
6605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6606 //store the paramters, and wait for wifi up to apply
6607 params.name = "wps_state";
6608 params.value = enable ? "2":"0";
6609
6610 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6611 wifi_hostapdWrite(config_file, &params, 1);
6612 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6613 wifi_reloadAp(apIndex);
6614
6615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6616 return RETURN_OK;
6617}
6618
6619//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
6620INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6621{
6622 if(!output)
6623 return RETURN_ERR;
6624 snprintf(output, 128, "PushButton,PIN");
6625 return RETURN_OK;
6626}
6627
6628//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6629//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.
6630// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6631INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6632{
6633 if(!output)
6634 return RETURN_ERR;
6635 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6636
6637 return RETURN_OK;
6638}
6639
6640//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6641// 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
6642INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6643{
6644 //apply instantly. No setting need to be stored.
6645 char methods[MAX_BUF_SIZE], *token, *next_token;
6646 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6647 struct params params;
6648
6649 if(!methodString || !(apIndex==0 || apIndex==1))
6650 return RETURN_ERR;
6651 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6652 //store the paramters, and wait for wifi up to apply
6653
6654 snprintf(methods, sizeof(methods), "%s", methodString);
6655 for(token=methods; *token; token=next_token)
6656 {
6657 strtok_r(token, ",", &next_token);
6658 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6659 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6660 else if(*token=='E')
6661 {
6662 if(!strcmp(methods, "Ethernet"))
6663 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6664 else if(!strcmp(methods, "ExternalNFCToken"))
6665 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6666 else
6667 printf("%s: Unknown WpsConfigMethod\n", __func__);
6668 }
6669 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6670 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6671 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6672 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6673 else if(*token=='P' )
6674 {
6675 if(!strcmp(token, "PushButton"))
6676 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6677 else if(!strcmp(token, "PIN"))
6678 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6679 else
6680 printf("%s: Unknown WpsConfigMethod\n", __func__);
6681 }
6682 else
6683 printf("%s: Unknown WpsConfigMethod\n", __func__);
6684 }
6685 params.name = "config_methods";
6686 params.value = config_methods;
6687 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6688 wifi_hostapdWrite(config_file, &params, 1);
6689 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6690 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6691
6692 return RETURN_OK;
6693}
6694
6695// outputs the pin value, ulong_pin must be allocated by the caller
6696INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6697{
6698 char buf[MAX_BUF_SIZE] = {0};
6699 char cmd[MAX_CMD_SIZE] = {0};
6700
6701 if(!output_ulong || !(apIndex==0 || apIndex==1))
6702 return RETURN_ERR;
6703 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6704 _syscmd(cmd, buf, sizeof(buf));
6705 if(strlen(buf) > 0)
6706 *output_ulong=strtoul(buf, NULL, 10);
6707
6708 return RETURN_OK;
6709}
6710
6711// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6712INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6713{
6714 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6715 char ap_pin[16] = {0};
6716 char buf[MAX_BUF_SIZE] = {0};
6717 char config_file[MAX_BUF_SIZE] = {0};
6718 ULONG prev_pin = 0;
6719 struct params params;
6720
6721 if(!(apIndex==0 || apIndex==1))
6722 return RETURN_ERR;
6723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6724 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6725 params.name = "ap_pin";
6726 params.value = ap_pin;
6727 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6728 wifi_hostapdWrite(config_file, &params, 1);
6729 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6731
6732 return RETURN_OK;
6733}
6734
6735// Output string is either Not configured or Configured, max 32 characters
6736INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6737{
6738 char cmd[MAX_CMD_SIZE];
6739 char buf[MAX_BUF_SIZE]={0};
6740
6741 if(!output_string || !(apIndex==0 || apIndex==1))
6742 return RETURN_ERR;
6743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6744 snprintf(output_string, 32, "Not configured");
6745 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6746 _syscmd(cmd, buf, sizeof(buf));
6747
developer348e3d92022-09-13 14:48:41 +08006748 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006749 snprintf(output_string, 32, "Configured");
6750 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6751
6752 return RETURN_OK;
6753}
6754
6755// sets the WPS pin for this AP
6756INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6757{
6758 char cmd[MAX_CMD_SIZE];
6759 char buf[MAX_BUF_SIZE]={0};
6760 BOOL enable;
6761
6762 if(!(apIndex==0 || apIndex==1))
6763 return RETURN_ERR;
6764 wifi_getApEnable(apIndex, &enable);
6765 if (!enable)
6766 return RETURN_ERR;
6767 wifi_getApWpsEnable(apIndex, &enable);
6768 if (!enable)
6769 return RETURN_ERR;
6770
6771 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6772 _syscmd(cmd, buf, sizeof(buf));
6773 if((strstr(buf, "OK"))!=NULL)
6774 return RETURN_OK;
6775
6776 return RETURN_ERR;
6777}
6778
6779// This function is called when the WPS push button has been pressed for this AP
6780INT wifi_setApWpsButtonPush(INT apIndex)
6781{
6782 char cmd[MAX_CMD_SIZE];
6783 char buf[MAX_BUF_SIZE]={0};
6784 BOOL enable=FALSE;
6785
6786 if(!(apIndex==0 || apIndex==1))
6787 return RETURN_ERR;
6788 wifi_getApEnable(apIndex, &enable);
6789 if (!enable)
6790 return RETURN_ERR;
6791
6792 wifi_getApWpsEnable(apIndex, &enable);
6793 if (!enable)
6794 return RETURN_ERR;
6795
6796 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6797 _syscmd(cmd, buf, sizeof(buf));
6798
6799 if((strstr(buf, "OK"))!=NULL)
6800 return RETURN_OK;
6801 return RETURN_ERR;
6802}
6803
6804// cancels WPS mode for this AP
6805INT wifi_cancelApWPS(INT apIndex)
6806{
6807 char cmd[MAX_CMD_SIZE];
6808 char buf[MAX_BUF_SIZE]={0};
6809
6810 if(!(apIndex==0 || apIndex==1))
6811 return RETURN_ERR;
6812 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6813 _syscmd(cmd,buf, sizeof(buf));
6814
6815 if((strstr(buf, "OK"))!=NULL)
6816 return RETURN_OK;
6817 return RETURN_ERR;
6818}
6819
6820//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6821//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6822INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6823{
6824 FILE *f;
6825 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6826 char cmd[256], buf[2048];
6827 char *param , *value, *line=NULL;
6828 size_t len = 0;
6829 ssize_t nread;
6830 wifi_associated_dev_t *dev=NULL;
6831
6832 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6833 *associated_dev_array = NULL;
6834 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6835 _syscmd(cmd,buf,sizeof(buf));
6836 *output_array_size = atoi(buf);
6837
6838 if (*output_array_size <= 0)
6839 return RETURN_OK;
6840
6841 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6842 *associated_dev_array = dev;
6843 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6844 _syscmd(cmd,buf,sizeof(buf));
6845 f = fopen("/tmp/connected_devices.txt", "r");
6846 if (f==NULL)
6847 {
6848 *output_array_size=0;
6849 return RETURN_ERR;
6850 }
6851 while ((nread = getline(&line, &len, f)) != -1)
6852 {
6853 param = strtok(line,"=");
6854 value = strtok(NULL,"=");
6855
6856 if( strcmp("flags",param) == 0 )
6857 {
6858 value[strlen(value)-1]='\0';
6859 if(strstr (value,"AUTHORIZED") != NULL )
6860 {
6861 dev[auth_temp].cli_AuthenticationState = 1;
6862 dev[auth_temp].cli_Active = 1;
6863 auth_temp++;
6864 read_flag=1;
6865 }
6866 }
6867 if(read_flag==1)
6868 {
6869 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6870 {
6871 value[strlen(value)-1]='\0';
6872 sscanf(value, "%x:%x:%x:%x:%x:%x",
6873 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6874 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6875 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6876 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6877 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6878 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6879 mac_temp++;
6880 read_flag=0;
6881 }
6882 }
6883 }
6884 *output_array_size = auth_temp;
6885 auth_temp=0;
6886 mac_temp=0;
6887 free(line);
6888 fclose(f);
6889 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6890 return RETURN_OK;
6891}
6892
6893#define MACADDRESS_SIZE 6
6894
6895INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6896{
6897 FILE *fp = NULL;
6898 char str[MAX_BUF_SIZE] = {0};
6899 int wificlientindex = 0 ;
6900 int count = 0;
6901 int signalstrength = 0;
6902 int arr[MACADDRESS_SIZE] = {0};
6903 unsigned char mac[MACADDRESS_SIZE] = {0};
6904 UINT wifi_count = 0;
6905 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6906 char pipeCmd[MAX_CMD_SIZE] = {0};
6907
6908 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6909 *output_array_size = 0;
6910 *associated_dev_array = NULL;
6911
6912 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6913 fp = popen(pipeCmd, "r");
6914 if (fp == NULL)
6915 {
6916 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6917 return RETURN_ERR;
6918 }
6919
6920 /* Read the output a line at a time - output it. */
6921 fgets(str, sizeof(str)-1, fp);
6922 wifi_count = (unsigned int) atoi ( str );
6923 *output_array_size = wifi_count;
6924 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6925 pclose(fp);
6926
6927 if(wifi_count == 0)
6928 {
6929 return RETURN_OK;
6930 }
6931 else
6932 {
6933 wifi_associated_dev3_t* temp = NULL;
6934 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6935 if(temp == NULL)
6936 {
6937 printf("Error Statement. Insufficient memory \n");
6938 return RETURN_ERR;
6939 }
6940
6941 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6942 system(pipeCmd);
6943 memset(pipeCmd,0,sizeof(pipeCmd));
6944 if(apIndex == 0)
6945 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6946 else if(apIndex == 1)
6947 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6948 system(pipeCmd);
6949
6950 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6951 if(fp == NULL)
6952 {
6953 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6954 return RETURN_ERR;
6955 }
6956 fclose(fp);
6957
6958 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6959 fp = popen(pipeCmd, "r");
6960 if(fp)
6961 {
6962 for(count =0 ; count < wifi_count; count++)
6963 {
6964 fgets(str, MAX_BUF_SIZE, fp);
6965 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6966 {
6967 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6968 {
6969 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6970
6971 }
6972 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6973 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]);
6974 }
6975 temp[count].cli_AuthenticationState = 1; //TODO
6976 temp[count].cli_Active = 1; //TODO
6977 }
6978 pclose(fp);
6979 }
6980
6981 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6982 fp = popen(pipeCmd, "r");
6983 if(fp)
6984 {
6985 pclose(fp);
6986 }
6987 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6988 if(fp)
6989 {
6990 for(count =0 ; count < wifi_count ;count++)
6991 {
6992 fgets(str, MAX_BUF_SIZE, fp);
6993 signalstrength = atoi(str);
6994 temp[count].cli_SignalStrength = signalstrength;
6995 temp[count].cli_RSSI = signalstrength;
6996 temp[count].cli_SNR = signalstrength + 95;
6997 }
6998 pclose(fp);
6999 }
7000
7001
7002 if((apIndex == 0) || (apIndex == 4))
7003 {
7004 for(count =0 ; count < wifi_count ;count++)
7005 {
7006 strcpy(temp[count].cli_OperatingStandard,"g");
7007 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7008 }
7009
7010 //BytesSent
7011 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7012 fp = popen(pipeCmd, "r");
7013 if(fp)
7014 {
7015 pclose(fp);
7016 }
7017 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7018 if(fp)
7019 {
7020 for (count = 0; count < wifi_count; count++)
7021 {
7022 fgets(str, MAX_BUF_SIZE, fp);
7023 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7024 }
7025 pclose(fp);
7026 }
7027
7028 //BytesReceived
7029 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7030 fp = popen(pipeCmd, "r");
7031 if (fp)
7032 {
7033 pclose(fp);
7034 }
7035 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7036 if (fp)
7037 {
7038 for (count = 0; count < wifi_count; count++)
7039 {
7040 fgets(str, MAX_BUF_SIZE, fp);
7041 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7042 }
7043 pclose(fp);
7044 }
7045
7046 //PacketsSent
7047 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7048 fp = popen(pipeCmd, "r");
7049 if (fp)
7050 {
7051 pclose(fp);
7052 }
7053
7054 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7055 if (fp)
7056 {
7057 for (count = 0; count < wifi_count; count++)
7058 {
7059 fgets(str, MAX_BUF_SIZE, fp);
7060 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7061 }
7062 pclose(fp);
7063 }
7064
7065 //PacketsReceived
7066 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7067 fp = popen(pipeCmd, "r");
7068 if (fp)
7069 {
7070 pclose(fp);
7071 }
7072 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7073 if (fp)
7074 {
7075 for (count = 0; count < wifi_count; count++)
7076 {
7077 fgets(str, MAX_BUF_SIZE, fp);
7078 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7079 }
7080 pclose(fp);
7081 }
7082
7083 //ErrorsSent
7084 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7085 fp = popen(pipeCmd, "r");
7086 if (fp)
7087 {
7088 pclose(fp);
7089 }
7090 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7091 if (fp)
7092 {
7093 for (count = 0; count < wifi_count; count++)
7094 {
7095 fgets(str, MAX_BUF_SIZE, fp);
7096 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7097 }
7098 pclose(fp);
7099 }
7100
7101 //ErrorsSent
7102 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7103 fp = popen(pipeCmd, "r");
7104 if (fp)
7105 {
7106 pclose(fp);
7107 }
7108 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7109 if (fp)
7110 {
7111 for (count = 0; count < wifi_count; count++)
7112 {
7113 fgets(str, MAX_BUF_SIZE, fp);
7114 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7115 }
7116 pclose(fp);
7117 }
7118
7119 //LastDataDownlinkRate
7120 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7121 fp = popen(pipeCmd, "r");
7122 if (fp)
7123 {
7124 pclose(fp);
7125 }
7126 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7127 if (fp)
7128 {
7129 for (count = 0; count < wifi_count; count++)
7130 {
7131 fgets(str, MAX_BUF_SIZE, fp);
7132 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7133 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7134 }
7135 pclose(fp);
7136 }
7137
7138 //LastDataUplinkRate
7139 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7140 fp = popen(pipeCmd, "r");
7141 if (fp)
7142 {
7143 pclose(fp);
7144 }
7145 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7146 if (fp)
7147 {
7148 for (count = 0; count < wifi_count; count++)
7149 {
7150 fgets(str, MAX_BUF_SIZE, fp);
7151 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7152 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7153 }
7154 pclose(fp);
7155 }
7156
7157 }
7158 else if ((apIndex == 1) || (apIndex == 5))
7159 {
7160 for (count = 0; count < wifi_count; count++)
7161 {
7162 strcpy(temp[count].cli_OperatingStandard, "a");
7163 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7164 temp[count].cli_BytesSent = 0;
7165 temp[count].cli_BytesReceived = 0;
7166 temp[count].cli_LastDataUplinkRate = 0;
7167 temp[count].cli_LastDataDownlinkRate = 0;
7168 temp[count].cli_PacketsSent = 0;
7169 temp[count].cli_PacketsReceived = 0;
7170 temp[count].cli_ErrorsSent = 0;
7171 }
7172 }
7173
7174 for (count = 0; count < wifi_count; count++)
7175 {
7176 temp[count].cli_Retransmissions = 0;
7177 temp[count].cli_DataFramesSentAck = 0;
7178 temp[count].cli_DataFramesSentNoAck = 0;
7179 temp[count].cli_MinRSSI = 0;
7180 temp[count].cli_MaxRSSI = 0;
7181 strncpy(temp[count].cli_InterferenceSources, "", 64);
7182 memset(temp[count].cli_IPAddress, 0, 64);
7183 temp[count].cli_RetransCount = 0;
7184 temp[count].cli_FailedRetransCount = 0;
7185 temp[count].cli_RetryCount = 0;
7186 temp[count].cli_MultipleRetryCount = 0;
7187 }
7188 *associated_dev_array = temp;
7189 }
7190 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7191 return RETURN_OK;
7192}
7193
7194int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7195{
7196 FILE *fp = NULL;
7197 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7198 char cmd[MAX_CMD_SIZE];
7199 int count = 0;
7200
7201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7202 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7203 fp = popen(cmd,"r");
7204 if(fp == NULL)
7205 {
7206 printf("Failed to run command in Function %s\n",__FUNCTION__);
7207 return 0;
7208 }
7209 if(fgets(path, sizeof(path)-1, fp) != NULL)
7210 {
7211 for(count=0;path[count]!='\n';count++)
7212 status[count]=path[count];
7213 status[count]='\0';
7214 }
7215 strcpy(wifi_status,status);
7216 pclose(fp);
7217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7218 return RETURN_OK;
7219}
7220
7221/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7222struct hostapd_sta_param {
7223 char key[50];
7224 char value[100];
7225}
7226
7227static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7228 int i = 0;
7229
7230 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7231 if (strncmp(params[i].key,key,50) == 0){
7232 return &params[i].value;
7233 }
7234 i++;
7235 }
7236 return NULL;
7237
7238} */
7239
7240static unsigned int count_occurences(const char *buf, const char *word)
7241{
7242 unsigned int n = 0;
7243 char *ptr = strstr(buf, word);
7244
7245 while (ptr++) {
7246 n++;
7247 ptr = strstr(ptr, word);
7248 }
7249
7250 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7251 return n;
7252}
7253
7254static const char *get_line_from_str_buf(const char *buf, char *line)
7255{
7256 int i;
7257 int n = strlen(buf);
7258
7259 for (i = 0; i < n; i++) {
7260 line[i] = buf[i];
7261 if (buf[i] == '\n') {
7262 line[i] = '\0';
7263 return &buf[i + 1];
7264 }
7265 }
7266
7267 return NULL;
7268}
7269
7270INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7271{
7272 unsigned int assoc_cnt = 0;
7273 char interface_name[50] = {0};
7274 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7275 char cmd[MAX_CMD_SIZE] = {'\0'};
7276 char line[256] = {'\0'};
7277 int i = 0;
7278 int ret = 0;
7279 const char *ptr = NULL;
7280 char *key = NULL;
7281 char *val = NULL;
7282 wifi_associated_dev3_t *temp = NULL;
7283 int rssi;
7284
7285 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7286
7287 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7288 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7289 return RETURN_ERR;
7290 }
7291
7292 // Example filtered output of 'iw dev' command:
7293 // Station 0a:69:72:10:d2:fa (on wifi0)
7294 // signal avg:-67 [-71, -71] dBm
7295 // Station 28:c2:1f:25:5f:99 (on wifi0)
7296 // signal avg:-67 [-71, -70] dBm
7297 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7298 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7299 return RETURN_ERR;
7300 }
7301
7302 ret = _syscmd(cmd, buf, sizeof(buf));
7303 if (ret == RETURN_ERR) {
7304 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7305 return RETURN_ERR;
7306 }
7307
7308 *output_array_size = count_occurences(buf, "Station");
7309 if (*output_array_size == 0) return RETURN_OK;
7310
7311 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7312 if (temp == NULL) {
7313 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7314 return RETURN_ERR;
7315 }
7316 *associated_dev_array = temp;
7317
7318 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7319 ptr = get_line_from_str_buf(buf, line);
7320 i = -1;
7321 while (ptr) {
7322 if (strstr(line, "Station")) {
7323 i++;
7324 key = strtok(line, " ");
7325 val = strtok(NULL, " ");
7326 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7327 &temp[i].cli_MACAddress[0],
7328 &temp[i].cli_MACAddress[1],
7329 &temp[i].cli_MACAddress[2],
7330 &temp[i].cli_MACAddress[3],
7331 &temp[i].cli_MACAddress[4],
7332 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7333 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7334 free(*associated_dev_array);
7335 return RETURN_ERR;
7336 }
7337 }
7338 else if (i < 0) {
7339 ptr = get_line_from_str_buf(ptr, line);
7340 continue; // We didn't detect 'station' entry yet
7341 }
7342 else if (strstr(line, "signal avg")) {
7343 key = strtok(line, ":");
7344 val = strtok(NULL, " ");
7345 if (sscanf(val, "%d", &rssi) <= 0 ) {
7346 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7347 free(*associated_dev_array);
7348 return RETURN_ERR;
7349 }
7350 temp[i].cli_RSSI = rssi;
7351 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7352 }
7353 // Here other fields can be parsed if added to filter of 'iw dev' command
7354
7355 ptr = get_line_from_str_buf(ptr, line);
7356 };
7357
7358 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7359
7360 return RETURN_OK;
7361}
7362
7363#if 0
7364//To-do
7365INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7366{
7367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7368
7369 //Using different approach to get required WiFi Parameters from system available commands
7370#if 0
7371 FILE *f;
7372 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7373 char cmd[256], buf[2048];
7374 char *param , *value, *line=NULL;
7375 size_t len = 0;
7376 ssize_t nread;
7377 wifi_associated_dev3_t *dev=NULL;
7378 *associated_dev_array = NULL;
7379 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7380 _syscmd(cmd,buf,sizeof(buf));
7381 *output_array_size = atoi(buf);
7382
7383 if (*output_array_size <= 0)
7384 return RETURN_OK;
7385
7386 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7387 *associated_dev_array = dev;
7388 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7389 _syscmd(cmd,buf,sizeof(buf));
7390 f = fopen("/tmp/connected_devices.txt", "r");
7391 if (f==NULL)
7392 {
7393 *output_array_size=0;
7394 return RETURN_ERR;
7395 }
7396 while ((nread = getline(&line, &len, f)) != -1)
7397 {
7398 param = strtok(line,"=");
7399 value = strtok(NULL,"=");
7400
7401 if( strcmp("flags",param) == 0 )
7402 {
7403 value[strlen(value)-1]='\0';
7404 if(strstr (value,"AUTHORIZED") != NULL )
7405 {
7406 dev[auth_temp].cli_AuthenticationState = 1;
7407 dev[auth_temp].cli_Active = 1;
7408 auth_temp++;
7409 read_flag=1;
7410 }
7411 }
7412 if(read_flag==1)
7413 {
7414 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7415 {
7416 value[strlen(value)-1]='\0';
7417 sscanf(value, "%x:%x:%x:%x:%x:%x",
7418 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7419 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7420 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7421 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7422 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7423 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7424
7425 }
7426 else if( strcmp("rx_packets",param) == 0 )
7427 {
7428 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7429 }
7430
7431 else if( strcmp("tx_packets",param) == 0 )
7432 {
7433 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7434 }
7435
7436 else if( strcmp("rx_bytes",param) == 0 )
7437 {
7438 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7439 }
7440
7441 else if( strcmp("tx_bytes",param) == 0 )
7442 {
7443 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7444 mac_temp++;
7445 read_flag=0;
7446 }
7447 }
7448 }
7449
7450 *output_array_size = auth_temp;
7451 auth_temp=0;
7452 mac_temp=0;
7453 free(line);
7454 fclose(f);
7455#endif
7456 char interface_name[MAX_BUF_SIZE] = {0};
7457 char wifi_status[MAX_BUF_SIZE] = {0};
7458 char hostapdconf[MAX_BUF_SIZE] = {0};
7459
7460 wifi_associated_dev3_t *dev_array = NULL;
7461 ULONG wifi_count = 0;
7462
7463 *associated_dev_array = NULL;
7464 *output_array_size = 0;
7465
7466 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7467 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7468 {
7469 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7470
7471 GetInterfaceName(interface_name, hostapdconf);
7472
7473 if(strlen(interface_name) > 1)
7474 {
7475 wifihal_interfacestatus(wifi_status,interface_name);
7476 if(strcmp(wifi_status,"RUNNING") == 0)
7477 {
7478 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7479
7480 *associated_dev_array = dev_array;
7481 *output_array_size = wifi_count;
7482 }
7483 else
7484 {
7485 *associated_dev_array = NULL;
7486 }
7487 }
7488 }
7489
7490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7491 return RETURN_OK;
7492}
7493#endif
7494
7495/* getIPAddress function */
7496/**
7497* @description Returning IpAddress of the Matched String
7498*
7499* @param
7500* @str Having MacAddress
7501* @ipaddr Having ipaddr
7502* @return The status of the operation
7503* @retval RETURN_OK if successful
7504* @retval RETURN_ERR if any error is detected
7505*
7506*/
7507
7508INT getIPAddress(char *str,char *ipaddr)
7509{
7510 FILE *fp = NULL;
7511 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7512 int LeaseTime = 0,ret = 0;
7513 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7514 {
7515 return RETURN_ERR;
7516 }
7517
7518 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7519 {
7520 /*
7521 Sample:sss
7522 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7523 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7524 */
7525 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7526 &(LeaseTime),
7527 phyAddr,
7528 ipAddr,
7529 hostName
7530 );
7531 if(ret != 4)
7532 continue;
7533 if(strcmp(str,phyAddr) == 0)
7534 strcpy(ipaddr,ipAddr);
7535 }
7536 return RETURN_OK;
7537}
7538
7539/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7540/**
7541* @description Returning Inactive wireless connected clients informations
7542*
7543* @param
7544* @filename Holding private_wifi 2g/5g content files
7545* @associated_dev_array Having inactiv wireless clients informations
7546* @output_array_size Returning Inactive wireless counts
7547* @return The status of the operation
7548* @retval RETURN_OK if successful
7549* @retval RETURN_ERR if any error is detected
7550*
7551*/
7552
7553INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7554{
7555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7556 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7557 FILE *fp = NULL;
7558 int arr[MACADDRESS_SIZE] = {0};
7559 unsigned char mac[MACADDRESS_SIZE] = {0};
7560 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7561 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7562 fp = popen(buf,"r");
7563 if(fp == NULL)
7564 return RETURN_ERR;
7565 else
7566 {
7567 fgets(path,sizeof(path),fp);
7568 maccount = atoi(path);
7569 }
7570 pclose(fp);
7571 *output_array_size = maccount;
7572 wifi_associated_dev3_t* temp = NULL;
7573 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7574 *associated_dev_array = temp;
7575 if(temp == NULL)
7576 {
7577 printf("Error Statement. Insufficient memory \n");
7578 return RETURN_ERR;
7579 }
7580 memset(buf,0,sizeof(buf));
7581 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7582 fp = popen(buf,"r");
7583 for(count = 0; count < maccount ; count++)
7584 {
7585 fgets(path,sizeof(path),fp);
7586 for(i = 0; path[i]!='\n';i++)
7587 str[i]=path[i];
7588 str[i]='\0';
7589 getIPAddress(str,ipaddr);
7590 memset(buf,0,sizeof(buf));
7591 if(strlen(ipaddr) > 0)
7592 {
7593 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7594 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7595 {
7596 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7597 {
7598 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7599 {
7600 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7601
7602 }
7603 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7604 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]);
7605 }
7606 temp[count].cli_AuthenticationState = 0; //TODO
7607 temp[count].cli_Active = 0; //TODO
7608 temp[count].cli_SignalStrength = 0;
7609 }
7610 else //Active wireless clients info
7611 {
7612 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7613 {
7614 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7615 {
7616 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7617
7618 }
7619 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7620 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]);
7621 }
7622 temp[count].cli_Active = 1;
7623 }
7624 }
7625 memset(ipaddr,0,sizeof(ipaddr));
7626 }
7627 pclose(fp);
7628 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7629 return RETURN_OK;
7630}
7631//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7632//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7633//To get Band Steering Capability
7634INT wifi_getBandSteeringCapability(BOOL *support)
7635{
7636 *support = FALSE;
7637 return RETURN_OK;
7638}
7639
7640
7641//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7642//To get Band Steering enable status
7643INT wifi_getBandSteeringEnable(BOOL *enable)
7644{
7645 *enable = FALSE;
7646 return RETURN_OK;
7647}
7648
7649//To turn on/off Band steering
7650INT wifi_setBandSteeringEnable(BOOL enable)
7651{
7652 return RETURN_OK;
7653}
7654
7655//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7656//To get Band Steering AP group
7657INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7658{
7659 if (NULL == output_ApGroup)
7660 return RETURN_ERR;
7661
7662 strcpy(output_ApGroup, "1,2");
7663 return RETURN_OK;
7664}
7665
7666//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7667//to set and read the band steering BandUtilizationThreshold parameters
7668INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7669{
7670 return RETURN_ERR;
7671}
7672
7673INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7674{
7675 return RETURN_ERR;
7676}
7677
7678//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7679//to set and read the band steering RSSIThreshold parameters
7680INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7681{
7682 return RETURN_ERR;
7683}
7684
7685INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7686{
7687 return RETURN_ERR;
7688}
7689
7690
7691//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7692//to set and read the band steering physical modulation rate threshold parameters
7693INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7694{
7695 //If chip is not support, return -1
7696 return RETURN_ERR;
7697}
7698
7699INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7700{
7701 //If chip is not support, return -1
7702 return RETURN_ERR;
7703}
7704
7705//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7706//to set and read the inactivity time (in seconds) for steering under overload condition
7707INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7708{
7709 return RETURN_ERR;
7710}
7711
7712INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7713{
7714 return RETURN_ERR;
7715}
7716
7717//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7718//to set and read the inactivity time (in seconds) for steering under Idle condition
7719INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7720{
7721 return RETURN_ERR;
7722}
7723
7724INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7725{
7726 return RETURN_ERR;
7727}
7728
7729//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7730//pClientMAC[64]
7731//pSourceSSIDIndex[64]
7732//pDestSSIDIndex[64]
7733//pSteeringReason[256]
7734INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7735{
7736 //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
7737 *pSteeringTime=time(NULL);
7738 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7739 return RETURN_OK;
7740}
7741
7742INT wifi_ifConfigDown(INT apIndex)
7743{
7744 INT status = RETURN_OK;
7745 char cmd[64];
7746
7747 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7748 printf("%s: %s\n", __func__, cmd);
7749 system(cmd);
7750
7751 return status;
7752}
7753
7754INT wifi_ifConfigUp(INT apIndex)
7755{
7756 char cmd[128];
7757 char buf[1024];
7758
7759 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7760 _syscmd(cmd, buf, sizeof(buf));
7761 return 0;
7762}
7763
7764//>> Deprecated. Replace with wifi_applyRadioSettings
7765INT wifi_pushBridgeInfo(INT apIndex)
7766{
7767 char ip[32];
7768 char subnet[32];
7769 char bridge[32];
7770 int vlanId;
7771 char cmd[128];
7772 char buf[1024];
7773
7774 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7775 wifi_getApVlanID(apIndex,&vlanId);
7776
7777 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7778 _syscmd(cmd,buf, sizeof(buf));
7779
7780 return 0;
7781}
7782
7783INT wifi_pushChannel(INT radioIndex, UINT channel)
7784{
7785 char cmd[128];
7786 char buf[1024];
7787 int apIndex;
7788
7789 apIndex=(radioIndex==0)?0:1;
7790 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7791 _syscmd(cmd,buf, sizeof(buf));
7792
7793 return 0;
7794}
7795
7796INT wifi_pushChannelMode(INT radioIndex)
7797{
7798 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7799 return RETURN_ERR;
7800}
7801
7802INT wifi_pushDefaultValues(INT radioIndex)
7803{
7804 //Apply Comcast specified default radio settings instantly
7805 //AMPDU=1
7806 //AMPDUFrames=32
7807 //AMPDULim=50000
7808 //txqueuelen=1000
7809
7810 return RETURN_ERR;
7811}
7812
7813INT wifi_pushTxChainMask(INT radioIndex)
7814{
7815 //Apply default TxChainMask instantly
7816 return RETURN_ERR;
7817}
7818
7819INT wifi_pushRxChainMask(INT radioIndex)
7820{
7821 //Apply default RxChainMask instantly
7822 return RETURN_ERR;
7823}
7824
7825INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7826{
7827 INT status;
7828
7829 status = wifi_setSSIDName(apIndex,ssid);
7830 wifi_setApEnable(apIndex,FALSE);
7831 wifi_setApEnable(apIndex,TRUE);
7832
7833 return status;
7834}
7835
7836INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7837{
7838 //Apply default Ssid Advertisement instantly
7839 return RETURN_ERR;
7840}
7841
7842INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7843{
7844 INT status = RETURN_ERR;
7845 *output = 0;
7846 return RETURN_ERR;
7847}
7848
7849INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7850{
7851 return RETURN_OK;
7852}
7853
7854INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7855{
7856 return RETURN_OK;
7857}
7858
7859//To-do
7860INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7861{
developereb199ae2022-09-13 14:04:27 +08007862 char output[16]={'\0'};
7863 char config_file[MAX_BUF_SIZE] = {0};
7864
7865 if (!output_string)
7866 return RETURN_ERR;
7867
7868 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7869 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7870
7871 if (strlen(output) == 0)
7872 snprintf(output_string, 64, "Disabled");
7873 else if (strncmp(output, "0", 1) == 0)
7874 snprintf(output_string, 64, "Disabled");
7875 else if (strncmp(output, "1", 1) == 0)
7876 snprintf(output_string, 64, "Optional");
7877 else if (strncmp(output, "2", 1) == 0)
7878 snprintf(output_string, 64, "Required");
7879 else {
7880 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7881 return RETURN_ERR;
7882 }
7883
7884 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007885 return RETURN_OK;
7886}
7887INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7888{
developereb199ae2022-09-13 14:04:27 +08007889 char str[MAX_BUF_SIZE]={'\0'};
7890 char cmd[MAX_CMD_SIZE]={'\0'};
7891 struct params params;
7892 char config_file[MAX_BUF_SIZE] = {0};
7893
7894 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7895 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7896 return RETURN_ERR;
7897
7898 params.name = "ieee80211w";
7899 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7900 params.value = "0";
7901 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7902 params.value = "1";
7903 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7904 params.value = "2";
7905 else{
7906 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7907 return RETURN_ERR;
7908 }
7909 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7910 wifi_hostapdWrite(config_file, &params, 1);
7911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007912 return RETURN_OK;
7913}
7914INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7915{
7916 char output[16]={'\0'};
7917 char config_file[MAX_BUF_SIZE] = {0};
7918
7919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7920 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7921 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7922
7923 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7924 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7925
7926 return RETURN_OK;
7927}
7928
7929INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7930{
7931 return RETURN_OK;
7932}
7933
7934INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7935{
7936 return RETURN_OK;
7937}
7938
7939INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7940{
7941 return RETURN_OK;
7942}
7943
7944INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7945{
7946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7947 char config_file[MAX_BUF_SIZE] = {0};
7948
7949 if (NULL == output)
7950 return RETURN_ERR;
7951 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7952 wifi_hostapdRead(config_file,"hw_mode",output,64);
7953
7954 if(strcmp(output,"b")==0)
7955 sprintf(output, "%s", "1,2,5.5,11");
7956 else if (strcmp(output,"a")==0)
7957 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7958 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7959 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7960
7961 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7962 return RETURN_OK;
7963}
7964
7965INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7966{
7967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7968 char *temp;
7969 char temp_output[128];
7970 char temp_TransmitRates[128];
7971 char config_file[MAX_BUF_SIZE] = {0};
7972
7973 if (NULL == output)
7974 return RETURN_ERR;
7975
7976 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7977 wifi_hostapdRead(config_file,"supported_rates",output,64);
7978
7979 strcpy(temp_TransmitRates,output);
7980 strcpy(temp_output,"");
7981 temp = strtok(temp_TransmitRates," ");
7982 while(temp!=NULL)
7983 {
7984 temp[strlen(temp)-1]=0;
7985 if((temp[0]=='5') && (temp[1]=='\0'))
7986 {
7987 temp="5.5";
7988 }
7989 strcat(temp_output,temp);
7990 temp = strtok(NULL," ");
7991 if(temp!=NULL)
7992 {
7993 strcat(temp_output,",");
7994 }
7995 }
7996 strcpy(output,temp_output);
7997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7998
7999 return RETURN_OK;
8000}
8001
8002INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8003{
8004 return RETURN_OK;
8005}
8006
8007
8008INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8009{
8010 int i=0;
8011 char *temp;
8012 char temp1[128];
8013 char temp_output[128];
8014 char temp_TransmitRates[128];
8015 struct params params={'\0'};
8016 char config_file[MAX_BUF_SIZE] = {0};
8017
8018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8019 if(NULL == output)
8020 return RETURN_ERR;
8021
8022 strcpy(temp_TransmitRates,output);
8023
8024 for(i=0;i<strlen(temp_TransmitRates);i++)
8025 {
8026 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
8027 {
8028 continue;
8029 }
8030 else
8031 {
8032 return RETURN_ERR;
8033 }
8034 }
8035 strcpy(temp_output,"");
8036 temp = strtok(temp_TransmitRates," ");
8037 while(temp!=NULL)
8038 {
8039 strcpy(temp1,temp);
8040 if(wlanIndex==1)
8041 {
8042 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8043 {
8044 return RETURN_ERR;
8045 }
8046 }
8047
8048 if(strcmp(temp,"5.5")==0)
8049 {
8050 strcpy(temp1,"55");
8051 }
8052 else
8053 {
8054 strcat(temp1,"0");
8055 }
8056 strcat(temp_output,temp1);
8057 temp = strtok(NULL," ");
8058 if(temp!=NULL)
8059 {
8060 strcat(temp_output," ");
8061 }
8062 }
8063 strcpy(output,temp_output);
8064
8065
8066 params.name = "supported_rates";
8067 params.value = output;
8068
8069 wifi_dbg_printf("\n%s:",__func__);
8070 wifi_dbg_printf("params.value=%s\n",params.value);
8071 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8072 wifi_hostapdWrite(config_file,&params,1);
8073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8074
8075 return RETURN_OK;
8076}
8077
8078
8079static char *sncopy(char *dst, int dst_sz, const char *src)
8080{
8081 if (src && dst && dst_sz > 0) {
8082 strncpy(dst, src, dst_sz);
8083 dst[dst_sz - 1] = '\0';
8084 }
8085 return dst;
8086}
8087
8088static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8089{
8090 if (0 == strcmp(ht_mode, "HT40") ||
8091 0 == strcmp(ht_mode, "HT80") ||
8092 0 == strcmp(ht_mode, "HT160")) {
8093 switch (channel) {
8094 case 1 ... 7:
8095 case 36:
8096 case 44:
8097 case 52:
8098 case 60:
8099 case 100:
8100 case 108:
8101 case 116:
8102 case 124:
8103 case 132:
8104 case 140:
8105 case 149:
8106 case 157:
8107 return 1;
8108 case 8 ... 13:
8109 case 40:
8110 case 48:
8111 case 56:
8112 case 64:
8113 case 104:
8114 case 112:
8115 case 120:
8116 case 128:
8117 case 136:
8118 case 144:
8119 case 153:
8120 case 161:
8121 return -1;
8122 default:
8123 return -EINVAL;
8124 }
8125 }
8126
8127 return -EINVAL;
8128}
8129
8130static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8131{
8132 if (NULL == hw_mode) return;
8133
8134 if (0 == strcmp(hw_mode, "ac"))
8135 sncopy(bw_mode, bw_mode_len, "ht vht");
8136
8137 if (0 == strcmp(hw_mode, "n"))
8138 sncopy(bw_mode, bw_mode_len, "ht");
8139
8140 return;
8141}
8142
8143static int util_chan_to_freq(int chan)
8144{
8145 if (chan == 14)
8146 return 2484;
8147 else if (chan < 14)
8148 return 2407 + chan * 5;
8149 else if (chan >= 182 && chan <= 196)
8150 return 4000 + chan * 5;
8151 else
8152 return 5000 + chan * 5;
8153 return 0;
8154}
8155
8156const int *util_unii_5g_chan2list(int chan, int width)
8157{
8158 static const int lists[] = {
8159 // <width>, <chan1>, <chan2>..., 0,
8160 20, 36, 0,
8161 20, 40, 0,
8162 20, 44, 0,
8163 20, 48, 0,
8164 20, 52, 0,
8165 20, 56, 0,
8166 20, 60, 0,
8167 20, 64, 0,
8168 20, 100, 0,
8169 20, 104, 0,
8170 20, 108, 0,
8171 20, 112, 0,
8172 20, 116, 0,
8173 20, 120, 0,
8174 20, 124, 0,
8175 20, 128, 0,
8176 20, 132, 0,
8177 20, 136, 0,
8178 20, 140, 0,
8179 20, 144, 0,
8180 20, 149, 0,
8181 20, 153, 0,
8182 20, 157, 0,
8183 20, 161, 0,
8184 20, 165, 0,
8185 40, 36, 40, 0,
8186 40, 44, 48, 0,
8187 40, 52, 56, 0,
8188 40, 60, 64, 0,
8189 40, 100, 104, 0,
8190 40, 108, 112, 0,
8191 40, 116, 120, 0,
8192 40, 124, 128, 0,
8193 40, 132, 136, 0,
8194 40, 140, 144, 0,
8195 40, 149, 153, 0,
8196 40, 157, 161, 0,
8197 80, 36, 40, 44, 48, 0,
8198 80, 52, 56, 60, 64, 0,
8199 80, 100, 104, 108, 112, 0,
8200 80, 116, 120, 124, 128, 0,
8201 80, 132, 136, 140, 144, 0,
8202 80, 149, 153, 157, 161, 0,
8203 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8204 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8205 -1 // final delimiter
8206 };
8207 const int *start;
8208 const int *p;
8209
8210 for (p = lists; *p != -1; p++) {
8211 if (*p == width) {
8212 for (start = ++p; *p != 0; p++) {
8213 if (*p == chan)
8214 return start;
8215 }
8216 }
8217 // move to the end of channel list of given width
8218 while (*p != 0) {
8219 p++;
8220 }
8221 }
8222
8223 return NULL;
8224}
8225
8226static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8227{
8228 if (NULL == ht_mode)
8229 return 0;
8230
8231 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8232 const int *chans = util_unii_5g_chan2list(channel, width);
8233 int sum = 0;
8234 int cnt = 0;
8235
8236 if (NULL == chans)
8237 return 0;
8238
8239 while (*chans) {
8240 sum += *chans;
8241 cnt++;
8242 chans++;
8243 }
8244 return sum / cnt;
8245}
8246
8247static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8248{
8249 BOOL onlyG, onlyN, onlyA;
8250 CHAR tmp[64];
8251 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8252 if (ret == RETURN_OK) {
8253 sncopy(hw_mode, hw_mode_size, tmp);
8254 }
8255 return ret;
8256}
8257
8258INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8259{
8260 // Sample commands:
8261 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8262 // hostapd_cli -i wifi0 chan_switch 30 2437
8263 char cmd[MAX_CMD_SIZE] = {0};
8264 char buf[MAX_BUF_SIZE] = {0};
8265 int freq = 0, ret = 0;
8266 char center_freq1_str[32] = ""; // center_freq1=%d
8267 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8268 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8269 char hw_mode[16] = ""; // n|ac
8270 char bw_mode[16] = ""; // ht|ht vht
8271 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8272 int sec_chan_offset;
8273 int width;
developer4fb0b922022-09-30 14:29:09 +08008274 char config_file[64] = {0};
8275 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008276 char *ext_str = "None";
8277
developer4fb0b922022-09-30 14:29:09 +08008278 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008279
8280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8281
developer5884e982022-10-06 10:52:50 +08008282 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008283
8284 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008285 if (channel){
8286 freq = util_chan_to_freq(channel);
8287 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8288 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8289 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8290 if (sec_chan_offset != -EINVAL)
8291 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008292
8293
developer5884e982022-10-06 10:52:50 +08008294 // Provide bandwith if specified
8295 if (channel_width_MHz > 20) {
8296 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8297 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8298 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008299
developer5884e982022-10-06 10:52:50 +08008300 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8301 }else if (channel_width_MHz == 20){
8302 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8303 }
developer06a01d92022-09-07 16:32:39 +08008304
developer5884e982022-10-06 10:52:50 +08008305 int center_chan = 0;
8306 if (channel_width_MHz > 20) {
8307 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8308 if (center_chan > 0) {
8309 int center_freq1 = util_chan_to_freq(center_chan);
8310 if (center_freq1)
8311 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8312 }
developer06a01d92022-09-07 16:32:39 +08008313 }
developer06a01d92022-09-07 16:32:39 +08008314
developer5884e982022-10-06 10:52:50 +08008315 // Only the first AP, other are hanging on the same radio
8316 int apIndex = radioIndex;
8317 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8318 AP_PREFIX, apIndex, csa_beacon_count, freq,
8319 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8320 wifi_dbg_printf("execute: '%s'\n", cmd);
8321 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008322
developer5884e982022-10-06 10:52:50 +08008323 ret = wifi_setRadioChannel(radioIndex, channel);
8324 if (ret != RETURN_OK) {
8325 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8326 return RETURN_ERR;
8327 }
8328
8329 if (sec_chan_offset == 1) ext_str = "Above";
8330 else if (sec_chan_offset == -1) ext_str = "Below";
8331
8332 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008333
developer5884e982022-10-06 10:52:50 +08008334 } else {
8335 if (channel_width_MHz > 20)
8336 ext_str = "Above";
8337 }
developer4fb0b922022-09-30 14:29:09 +08008338 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8339 _syscmd(cmd, buf, sizeof(buf));
8340 if (strlen(buf) != 0)
8341 stbcEnable = TRUE;
8342
developer06a01d92022-09-07 16:32:39 +08008343 wifi_setRadioExtChannel(radioIndex, ext_str);
8344
developer4fb0b922022-09-30 14:29:09 +08008345 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8346
developer06a01d92022-09-07 16:32:39 +08008347 char mhz_str[16];
8348 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8349 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8350
8351 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8352
8353 return RETURN_OK;
8354}
8355
8356INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8357{
developer615510b2022-09-27 10:14:35 +08008358 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008359 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008360 char cmd[256]={0};
8361 char buf[128]={0};
8362 char file_name[32] = {0};
8363 char filter_SSID[32] = {0};
8364 char line[256] = {0};
8365 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008366 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008367 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008368 size_t len=0;
8369 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008370 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008371 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008372 bool filter_enable = false;
8373 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008374
developer615510b2022-09-27 10:14:35 +08008375 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008376
developer615510b2022-09-27 10:14:35 +08008377 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8378 f = fopen(file_name, "r");
8379 if (f != NULL) {
8380 fgets(filter_SSID, sizeof(file_name), f);
8381 if (strlen(filter_SSID) != 0)
8382 filter_enable = true;
8383 fclose(f);
8384 }
8385
8386 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8387 _syscmd(cmd, buf, sizeof(buf));
8388 channels_num = strtol(buf, NULL, 10);
8389
developer615510b2022-09-27 10:14:35 +08008390 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8391 // 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);
8392 fprintf(stderr, "cmd: %s\n", cmd);
8393 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008394 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8395 return RETURN_ERR;
8396 }
developer5550e242022-09-30 09:59:32 +08008397
8398 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8399 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8400
developer615510b2022-09-27 10:14:35 +08008401 ret = fgets(line, sizeof(line), f);
8402 while (ret != NULL) {
8403 if(strstr(line, "BSS") != NULL) { // new neighbor info
8404 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8405 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8406 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8407
8408 if (!filter_BSS) {
8409 index++;
8410 wifi_neighbor_ap2_t *tmp;
8411 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8412 if (tmp == NULL) { // no more memory to use
8413 index--;
8414 wifi_dbg_printf("%s: realloc failed\n", __func__);
8415 break;
8416 }
8417 scan_array = tmp;
8418 }
8419 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008420
developer615510b2022-09-27 10:14:35 +08008421 filter_BSS = false;
8422 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8423 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8424 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8425 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8426 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008427 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008428 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008429
developer615510b2022-09-27 10:14:35 +08008430 if (freq >= 2412 && freq <= 2484) {
8431 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8432 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8433 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8434 }
8435 else if (freq >= 5160 && freq <= 5805) {
8436 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8437 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8438 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8439 }
developer06a01d92022-09-07 16:32:39 +08008440
developer615510b2022-09-27 10:14:35 +08008441 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008442 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008443 for (int i = 0; i < channels_num; i++) {
8444 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8445 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8446 break;
8447 }
8448 }
developer06a01d92022-09-07 16:32:39 +08008449 }
developer615510b2022-09-27 10:14:35 +08008450 } else if (strstr(line, "beacon interval") != NULL) {
8451 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8452 } else if (strstr(line, "signal") != NULL) {
8453 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8454 } else if (strstr(line,"SSID") != NULL) {
8455 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8456 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8457 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008458 }
developer615510b2022-09-27 10:14:35 +08008459 } else if (strstr(line, "Supported rates") != NULL) {
8460 char SRate[80] = {0}, *tmp = NULL;
8461 memset(buf, 0, sizeof(buf));
8462 strcpy(SRate, line);
8463 tmp = strtok(SRate, ":");
8464 tmp = strtok(NULL, ":");
8465 strcpy(buf, tmp);
8466 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008467
developer615510b2022-09-27 10:14:35 +08008468 tmp = strtok(buf, " \n");
8469 while (tmp != NULL) {
8470 strcat(SRate, tmp);
8471 if (SRate[strlen(SRate) - 1] == '*') {
8472 SRate[strlen(SRate) - 1] = '\0';
8473 }
8474 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008475
developer615510b2022-09-27 10:14:35 +08008476 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008477 }
developer615510b2022-09-27 10:14:35 +08008478 SRate[strlen(SRate) - 1] = '\0';
8479 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8480 } else if (strstr(line, "DTIM") != NULL) {
8481 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8482 } else if (strstr(line, "VHT capabilities") != NULL) {
8483 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8484 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8485 } else if (strstr(line, "HT capabilities") != NULL) {
8486 strcat(scan_array[index].ap_SupportedStandards, ",n");
8487 strcpy(scan_array[index].ap_OperatingStandards, "n");
8488 } else if (strstr(line, "VHT operation") != NULL) {
8489 ret = fgets(line, sizeof(line), f);
8490 sscanf(line," * channel width: %d", &vht_channel_width);
8491 if(vht_channel_width == 1) {
8492 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8493 } else {
8494 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8495 }
8496 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8497 continue;
8498 } else if (strstr(line, "HT operation") != NULL) {
8499 ret = fgets(line, sizeof(line), f);
8500 sscanf(line," * secondary channel offset: %s", &buf);
8501 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008502 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008503 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 +08008504 }
developer615510b2022-09-27 10:14:35 +08008505 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008506 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008507 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8508 } else {
8509 //20Mhz
8510 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 +08008511 }
developer615510b2022-09-27 10:14:35 +08008512 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008513 continue;
developer615510b2022-09-27 10:14:35 +08008514 } else if (strstr(line, "HE capabilities") != NULL) {
8515 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8516 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8517 ret = fgets(line, sizeof(line), f);
8518 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8519 if (strstr(line, "HE40/2.4GHz") != NULL)
8520 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8521 else
8522 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8523 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8524 if (strstr(line, "HE80/5GHz") != NULL) {
8525 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8526 ret = fgets(line, sizeof(line), f);
8527 } else
8528 continue;
8529 if (strstr(line, "HE160/5GHz") != NULL)
8530 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008531 }
developer615510b2022-09-27 10:14:35 +08008532 continue;
8533 } else if (strstr(line, "WPA") != NULL) {
8534 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8535 } else if (strstr(line, "RSN") != NULL) {
8536 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8537 } else if (strstr(line, "Group cipher") != NULL) {
8538 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8539 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8540 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008541 }
developer06a01d92022-09-07 16:32:39 +08008542 }
developer615510b2022-09-27 10:14:35 +08008543 ret = fgets(line, sizeof(line), f);
8544 }
8545
8546 if (!filter_BSS) {
8547 *output_array_size = index + 1;
8548 } else {
8549 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8550 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008551 }
developer06a01d92022-09-07 16:32:39 +08008552 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008553 pclose(f);
developer5550e242022-09-30 09:59:32 +08008554 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008556 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008557}
developer615510b2022-09-27 10:14:35 +08008558
developer06a01d92022-09-07 16:32:39 +08008559INT wifi_getApAssociatedDeviceStats(
8560 INT apIndex,
8561 mac_address_t *clientMacAddress,
8562 wifi_associated_dev_stats_t *associated_dev_stats,
8563 u64 *handle)
8564{
8565 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8566 char interface_name[50] = {0};
8567 char cmd[1024] = {0};
8568 char mac_str[18] = {0};
8569 char *key = NULL;
8570 char *val = NULL;
8571 FILE *f = NULL;
8572 char *line = NULL;
8573 size_t len = 0;
8574 ssize_t read = 0;
8575
8576 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8577 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8578 return RETURN_ERR;
8579 }
8580
8581 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8582 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8583 if((f = popen(cmd, "r")) == NULL) {
8584 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8585 return RETURN_ERR;
8586 }
8587
8588 while ((read = getline(&line, &len, f)) != -1) {
8589 key = strtok(line,":");
8590 val = strtok(NULL,":");
8591
8592 if(!strncmp(key,"rx bytes",8))
8593 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8594 if(!strncmp(key,"tx bytes",8))
8595 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8596 if(!strncmp(key,"rx packets",10))
8597 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8598 if(!strncmp(key,"tx packets",10))
8599 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8600 if(!strncmp(key,"tx retries",10))
8601 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8602 if(!strncmp(key,"tx failed",9))
8603 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8604 if(!strncmp(key,"rx drop misc",13))
8605 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8606 if(!strncmp(key,"rx bitrate",10)) {
8607 val = strtok(val, " ");
8608 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8609 }
8610 if(!strncmp(key,"tx bitrate",10)) {
8611 val = strtok(val, " ");
8612 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8613 }
8614 }
8615 free(line);
8616 pclose(f);
8617 return RETURN_OK;
8618}
8619
8620INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8621{
8622 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8623
8624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8625 if (NULL == output_string)
8626 return RETURN_ERR;
8627
8628 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8629 _syscmd(cmd, buf, sizeof(buf));
8630
8631 //size of SSID name restricted to value less than 32 bytes
8632 snprintf(output_string, 32, "%s", buf);
8633 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8634
8635 return RETURN_OK;
8636}
8637
8638INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8639{
8640 //char cmd[MAX_CMD_SIZE] = {0};
8641 char config_file[MAX_BUF_SIZE] = {0};
8642 char buf[32] = {0};
8643
8644 if (!output_filterMode)
8645 return RETURN_ERR;
8646
8647 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8648 //_syscmd(cmd, buf, sizeof(buf));
8649 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8650 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008651 if(strlen(buf) == 0) {
8652 *output_filterMode = 0;
8653 }
8654 else {
8655 int macaddr_acl_mode = strtol(buf, NULL, 10);
8656 if (macaddr_acl_mode == 1) {
8657 *output_filterMode = 1;
8658 } else if (macaddr_acl_mode == 0) {
8659 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8660 if (strlen(buf) == 0) {
8661 *output_filterMode = 0;
8662 } else {
8663 *output_filterMode = 2;
8664 }
8665 } else {
8666 return RETURN_ERR;
8667 }
8668 }
developer06a01d92022-09-07 16:32:39 +08008669
8670 return RETURN_OK;
8671}
8672
8673INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8674{
8675 FILE *fp = NULL;
8676 char str[MAX_BUF_SIZE] = {0};
8677 int wificlientindex = 0 ;
8678 int count = 0;
8679 int signalstrength = 0;
8680 int arr[MACADDRESS_SIZE] = {0};
8681 unsigned char mac[MACADDRESS_SIZE] = {0};
8682 UINT wifi_count = 0;
8683 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8684 char pipeCmd[MAX_CMD_SIZE] = {0};
8685
8686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8687 *output_array_size = 0;
8688 *associated_dev_array = NULL;
8689 char interface_name[50] = {0};
8690
8691 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8692 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8693 return RETURN_ERR;
8694 }
8695
8696 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8697 fp = popen(pipeCmd, "r");
8698 if (fp == NULL)
8699 {
8700 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8701 return RETURN_ERR;
8702 }
8703
8704 /* Read the output a line at a time - output it. */
8705 fgets(str, sizeof(str)-1, fp);
8706 wifi_count = (unsigned int) atoi ( str );
8707 *output_array_size = wifi_count;
8708 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8709 pclose(fp);
8710
8711 if(wifi_count == 0)
8712 {
8713 return RETURN_OK;
8714 }
8715 else
8716 {
8717 wifi_associated_dev2_t* temp = NULL;
8718 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8719 *associated_dev_array = temp;
8720 if(temp == NULL)
8721 {
8722 printf("Error Statement. Insufficient memory \n");
8723 return RETURN_ERR;
8724 }
8725
8726 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8727 system(pipeCmd);
8728
8729 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8730 if(fp == NULL)
8731 {
8732 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8733 return RETURN_ERR;
8734 }
8735 fclose(fp);
8736
8737 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8738 fp = popen(pipeCmd, "r");
8739 if(fp)
8740 {
8741 for(count =0 ; count < wifi_count; count++)
8742 {
8743 fgets(str, MAX_BUF_SIZE, fp);
8744 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8745 {
8746 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8747 {
8748 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8749
8750 }
8751 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8752 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]);
8753 }
8754 temp[count].cli_AuthenticationState = 1; //TODO
8755 temp[count].cli_Active = 1; //TODO
8756 }
8757 pclose(fp);
8758 }
8759
8760 //Updating RSSI per client
8761 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8762 fp = popen(pipeCmd, "r");
8763 if(fp)
8764 {
8765 pclose(fp);
8766 }
8767 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8768 if(fp)
8769 {
8770 for(count =0 ; count < wifi_count ;count++)
8771 {
8772 fgets(str, MAX_BUF_SIZE, fp);
8773 signalstrength = atoi(str);
8774 temp[count].cli_RSSI = signalstrength;
8775 }
8776 pclose(fp);
8777 }
8778
8779
8780 //LastDataDownlinkRate
8781 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8782 fp = popen(pipeCmd, "r");
8783 if (fp)
8784 {
8785 pclose(fp);
8786 }
8787 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8788 if (fp)
8789 {
8790 for (count = 0; count < wifi_count; count++)
8791 {
8792 fgets(str, MAX_BUF_SIZE, fp);
8793 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8794 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8795 }
8796 pclose(fp);
8797 }
8798
8799 //LastDataUplinkRate
8800 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8801 fp = popen(pipeCmd, "r");
8802 if (fp)
8803 {
8804 pclose(fp);
8805 }
8806 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8807 if (fp)
8808 {
8809 for (count = 0; count < wifi_count; count++)
8810 {
8811 fgets(str, MAX_BUF_SIZE, fp);
8812 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8813 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8814 }
8815 pclose(fp);
8816 }
8817 }
8818 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8819 return RETURN_OK;
8820
8821}
8822
8823INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8824{
8825#if 0
8826 /*char buf[1024] = {0};
8827 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8828 _syscmd(cmd, buf, sizeof(buf));*/
8829
8830 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8831 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8832 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8833 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8834
8835 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.
8836 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].
8837 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].
8838 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].
8839 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8840 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8841
8842 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8843 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8844 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8845 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.
8846 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.
8847 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.
8848 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.
8849 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.
8850 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.
8851 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.
8852 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8853#endif
8854
8855 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008856 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008857 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008858 char pipeCmd[128] = {0};
8859 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008860 wifi_ssidTrafficStats2_t *out = output_struct;
8861
developerce736392022-09-13 15:24:34 +08008862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008863 if (!output_struct)
8864 return RETURN_ERR;
8865
developerce736392022-09-13 15:24:34 +08008866 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8867 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8868 GetInterfaceName(interface_name, HConf_file);
8869 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008870
developer06a01d92022-09-07 16:32:39 +08008871 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008872 if (fp == NULL) {
8873 fprintf(stderr, "%s: popen failed\n", __func__);
8874 return RETURN_ERR;
8875 }
8876 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008877
developerce736392022-09-13 15:24:34 +08008878 if (strlen(str) == 0) // interface not exist
8879 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008880
developerce736392022-09-13 15:24:34 +08008881 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8882 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008883 pclose(fp);
8884
developerce736392022-09-13 15:24:34 +08008885 memset(str, 0, sizeof(str));
8886 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008887 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008888 if (fp == NULL) {
8889 fprintf(stderr, "%s: popen failed\n", __func__);
8890 return RETURN_ERR;
8891 }
8892 fgets(str, sizeof(str), fp);
8893
8894 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8895 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008896 pclose(fp);
developerce736392022-09-13 15:24:34 +08008897
8898 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8899 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8900
8901 // Not supported
8902 output_struct->ssid_RetransCount = 0;
8903 output_struct->ssid_FailedRetransCount = 0;
8904 output_struct->ssid_RetryCount = 0;
8905 output_struct->ssid_MultipleRetryCount = 0;
8906 output_struct->ssid_ACKFailureCount = 0;
8907 output_struct->ssid_AggregatedPacketCount = 0;
8908
developer06a01d92022-09-07 16:32:39 +08008909 return RETURN_OK;
8910}
8911
8912//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).
8913INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8914{
8915 char output_val[16]={'\0'};
8916 char config_file[MAX_BUF_SIZE] = {0};
8917
8918 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8919 if (!output)
8920 return RETURN_ERR;
8921 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8922 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8923
8924 if( strcmp(output_val,"1") == 0 )
8925 *output = TRUE;
8926 else
8927 *output = FALSE;
8928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8929
8930 return RETURN_OK;
8931}
8932
8933INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8934{
8935 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8936 char str[MAX_BUF_SIZE]={'\0'};
8937 char string[MAX_BUF_SIZE]={'\0'};
8938 char cmd[MAX_CMD_SIZE]={'\0'};
8939 char *ch;
8940 char config_file[MAX_BUF_SIZE] = {0};
8941 struct params params;
8942
8943 if(enable == TRUE)
8944 strcpy(string,"1");
8945 else
8946 strcpy(string,"0");
8947
8948 params.name = "ap_isolate";
8949 params.value = string;
8950
8951 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8952 wifi_hostapdWrite(config_file,&params,1);
8953 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8954
8955 return RETURN_OK;
8956}
8957
8958INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8959{
8960 if (NULL == output_dBm)
8961 return RETURN_ERR;
8962
8963 *output_dBm = 0;
8964 return RETURN_OK;
8965}
8966
8967INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8968{
8969 return RETURN_OK;
8970}
8971INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8972{
8973 return RETURN_OK;
8974}
8975INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8976{
8977 return RETURN_OK;
8978}
8979INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8980{
8981 return RETURN_OK;
8982}
8983INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8984{
8985 return RETURN_OK;
8986}
8987INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8988{
8989 char config_file[MAX_BUF_SIZE] = {0};
8990 struct params list;
8991
8992 list.name = "bss_transition";
8993 list.value = activate?"1":"0";
8994 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8995 wifi_hostapdWrite(config_file, &list, 1);
8996
8997 return RETURN_OK;
8998}
8999wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9000
9001void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9002{
9003 return;
9004}
9005
9006INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9007{
9008 // TODO Implement me!
9009 return RETURN_OK;
9010}
9011
9012INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9013{
developera3c68b92022-09-13 15:27:29 +08009014 char file_name[128] = {0};
9015 char buf[128] = {0};
9016 FILE *f = NULL;
9017
9018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9019
9020 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9021 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
9022 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9023 f = fopen(file_name, "w");
9024 if (f == NULL)
9025 return RETURN_ERR;
9026 // For mode == 0 is to disable filter, just don't write to the file.
9027 if (mode)
9028 fprintf(f, "%s", essid);
9029
9030 fclose(f);
9031 }
9032 } else { // special case, need to set AP's SSID as filter for each radio.
9033 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9034 f = fopen(file_name, "w");
9035 if (f == NULL)
9036 return RETURN_ERR;
9037
9038 // For mode == 0 is to disable filter, just don't write to the file.
9039 if (mode)
9040 fprintf(f, "%s", essid);
9041
9042 fclose(f);
9043 }
9044
9045 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009046 return RETURN_OK;
9047}
9048
9049INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9050{
9051 // TODO Implement me!
9052 //Apply wifi_pushRadioChannel() instantly
9053 return RETURN_ERR;
9054}
9055
9056INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9057{
9058 // TODO Implement me!
9059 return RETURN_OK;
9060}
9061
9062#ifdef HAL_NETLINK_IMPL
9063static int tidStats_callback(struct nl_msg *msg, void *arg) {
9064 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9065 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9066 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9067 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9068 int rem , tid_index = 0;
9069
9070 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9071 wifi_associated_dev_tid_entry_t *stats_entry;
9072
9073 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9074 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9075 };
9076 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9077 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9078 };
9079
9080 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9081 genlmsg_attrlen(gnlh, 0), NULL);
9082
9083
9084 if (!tb[NL80211_ATTR_STA_INFO]) {
9085 fprintf(stderr, "station stats missing!\n");
9086 return NL_SKIP;
9087 }
9088
9089 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9090 tb[NL80211_ATTR_STA_INFO],
9091 stats_policy)) {
9092 fprintf(stderr, "failed to parse nested attributes!\n");
9093 return NL_SKIP;
9094 }
9095
9096 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9097 {
9098 stats_entry = &out->tid_array[tid_index];
9099
9100 stats_entry->tid = tid_index;
9101 stats_entry->ac = _tid_ac_index_get[tid_index];
9102
9103 if(sinfo[NL80211_STA_INFO_TID_STATS])
9104 {
9105 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9106 printf("failed to parse nested stats attributes!");
9107 return NL_SKIP;
9108 }
9109 }
9110 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9111 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9112
9113 if(tid_index < (PS_MAX_TID - 1))
9114 tid_index++;
9115 }
9116 //ToDo: sum_time_ms, ewma_time_ms
9117 return NL_SKIP;
9118}
9119#endif
9120
9121INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9122{
9123#ifdef HAL_NETLINK_IMPL
9124 Netlink nl;
9125 char if_name[10];
9126
9127 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9128
9129 nl.id = initSock80211(&nl);
9130
9131 if (nl.id < 0) {
9132 fprintf(stderr, "Error initializing netlink \n");
9133 return -1;
9134 }
9135
9136 struct nl_msg* msg = nlmsg_alloc();
9137
9138 if (!msg) {
9139 fprintf(stderr, "Failed to allocate netlink message.\n");
9140 nlfree(&nl);
9141 return -2;
9142 }
9143
9144 genlmsg_put(msg,
9145 NL_AUTO_PORT,
9146 NL_AUTO_SEQ,
9147 nl.id,
9148 0,
9149 0,
9150 NL80211_CMD_GET_STATION,
9151 0);
9152
9153 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9154 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9155 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9156 nl_send_auto(nl.socket, msg);
9157 nl_recvmsgs(nl.socket, nl.cb);
9158 nlmsg_free(msg);
9159 nlfree(&nl);
9160 return RETURN_OK;
9161#else
9162//iw implementation
9163#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9164#define TOTAL_MAX_LINES 50
9165
9166 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9167 char if_name[10];
9168 FILE *fp=NULL;
9169 char pipeCmd[1024]= {'\0'};
9170 int lines,tid_index=0;
9171 char mac_addr[20] = {'\0'};
9172
9173 wifi_associated_dev_tid_entry_t *stats_entry;
9174
9175 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9176 strcpy(mac_addr,clientMacAddress);
9177
9178 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9179 fp= popen(pipeCmd,"r");
9180 if(fp == NULL)
9181 {
9182 perror("popen for station dump failed\n");
9183 return RETURN_ERR;
9184 }
9185 pclose(fp);
9186
9187 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9188 fp=popen(pipeCmd,"r");
9189 if(fp == NULL)
9190 {
9191 perror("popen for grep station failed\n");
9192 return RETURN_ERR;
9193 }
9194 else if(fgets(buf,sizeof(buf),fp) != NULL)
9195 lines=atoi(buf);
9196 else
9197 {
9198 pclose(fp);
9199 fprintf(stderr,"No devices are connected \n");
9200 return RETURN_ERR;
9201 }
9202 pclose(fp);
9203
9204 if(lines == 1)
9205 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9206
9207 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9208 {
9209 stats_entry = &tid_stats->tid_array[tid_index];
9210 stats_entry->tid = tid_index;
9211
9212 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);
9213
9214 fp=popen(pipeCmd,"r");
9215 if(fp ==NULL)
9216 {
9217 perror("Failed to read from tid file \n");
9218 return RETURN_ERR;
9219 }
9220 else if(fgets(buf,sizeof(buf),fp) != NULL)
9221 stats_entry->num_msdus = atol(buf);
9222
9223 pclose(fp);
9224 stats_entry->ac = _tid_ac_index_get[tid_index];
9225// TODO:
9226// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9227// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9228 }
9229 return RETURN_OK;
9230#endif
9231}
9232
9233
9234INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9235{
developer615510b2022-09-27 10:14:35 +08009236 char cmd[128]={0};
9237 char buf[128]={0};
9238 int freq = 0;
9239
9240 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9241
9242 // full mode is used to scan all channels.
9243 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9244 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9245 ieee80211_channel_to_frequency(chan_list[0], &freq);
9246
9247 if (freq)
9248 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9249 else
9250 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9251
9252 _syscmd(cmd, buf, sizeof(buf));
9253 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9254
developer06a01d92022-09-07 16:32:39 +08009255 return RETURN_OK;
9256}
9257
9258
9259INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9260{
9261 // TODO Implement me!
9262 return RETURN_ERR;
9263}
9264
9265INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9266{
9267 // TODO Implement me!
9268 return RETURN_ERR;
9269}
9270
9271INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9272{
9273 // TODO Implement me!
9274 return RETURN_ERR;
9275}
9276
9277INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9278{
9279 // TODO Implement me!
9280 return RETURN_ERR;
9281}
9282
9283INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9284{
9285 // TODO Implement me!
9286 return RETURN_ERR;
9287}
9288
9289INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9290{
9291 // TODO Implement me!
9292 return RETURN_ERR;
9293}
9294
9295INT wifi_steering_eventUnregister(void)
9296{
9297 // TODO Implement me!
9298 return RETURN_ERR;
9299}
9300
9301INT wifi_delApAclDevices(INT apIndex)
9302{
9303#if 0
9304 char cmd[MAX_BUF_SIZE] = {0};
9305 char buf[MAX_BUF_SIZE] = {0};
9306
9307 /* Not reset proof solution */
9308 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9309 if(_syscmd(cmd,buf,sizeof(buf)))
9310 return RETURN_ERR;
9311#endif
developere6aafda2022-09-13 14:59:28 +08009312 char cmd[MAX_CMD_SIZE]={0};
9313 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009314
developere6aafda2022-09-13 14:59:28 +08009315 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9316 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9317 if(_syscmd(cmd, buf, sizeof(buf)))
9318 return RETURN_ERR;
9319 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009320
9321 return RETURN_OK;
9322}
9323
9324#ifdef HAL_NETLINK_IMPL
9325static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9326 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9327 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9328 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9329 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9330 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9331 char mac_addr[20],dev[20];
9332
9333 nla_parse(tb,
9334 NL80211_ATTR_MAX,
9335 genlmsg_attrdata(gnlh, 0),
9336 genlmsg_attrlen(gnlh, 0),
9337 NULL);
9338
9339 if(!tb[NL80211_ATTR_STA_INFO]) {
9340 fprintf(stderr, "sta stats missing!\n");
9341 return NL_SKIP;
9342 }
9343
9344 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9345 fprintf(stderr, "failed to parse nested attributes!\n");
9346 return NL_SKIP;
9347 }
9348 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9349
9350 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9351
9352 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9353 fprintf(stderr, "failed to parse nested rate attributes!");
9354 return NL_SKIP;
9355 }
9356
9357 if(sinfo[NL80211_STA_INFO_TID_STATS])
9358 {
9359 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9360 printf("failed to parse nested stats attributes!");
9361 return NL_SKIP;
9362 }
9363 }
9364
9365 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9366 {
9367 printf("Type is VHT\n");
9368 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9369 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9370
9371 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9372 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9373 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9374 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9375 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9376 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9377 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9378 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9379 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9380 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9381 }
9382 else
9383 {
9384 printf(" OFDM or CCK \n");
9385 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9386 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9387 }
9388
9389 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9390 if(rinfo[NL80211_RATE_INFO_MCS])
9391 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9392 }
9393 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9394 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9395 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9396 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9397
9398 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9399 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9400
9401 if (sinfo[NL80211_STA_INFO_SIGNAL])
9402 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9403 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9404 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9405 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9406 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9407 //rssi_array need to be filled
9408 return NL_SKIP;
9409}
9410#endif
9411
9412INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9413{
9414#ifdef HAL_NETLINK_IMPL
9415 Netlink nl;
9416 char if_name[10];
9417
9418 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9419
9420 if (*output_array_size <= 0)
9421 return RETURN_OK;
9422
9423 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9424 nl.id = initSock80211(&nl);
9425
9426 if (nl.id < 0) {
9427 fprintf(stderr, "Error initializing netlink \n");
9428 return 0;
9429 }
9430
9431 struct nl_msg* msg = nlmsg_alloc();
9432
9433 if (!msg) {
9434 fprintf(stderr, "Failed to allocate netlink message.\n");
9435 nlfree(&nl);
9436 return 0;
9437 }
9438
9439 genlmsg_put(msg,
9440 NL_AUTO_PORT,
9441 NL_AUTO_SEQ,
9442 nl.id,
9443 0,
9444 0,
9445 NL80211_CMD_GET_STATION,
9446 0);
9447
9448 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9449 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9450 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9451 nl_send_auto(nl.socket, msg);
9452 nl_recvmsgs(nl.socket, nl.cb);
9453 nlmsg_free(msg);
9454 nlfree(&nl);
9455 return RETURN_OK;
9456#else
9457 //TODO Implement me
9458 return RETURN_OK;
9459#endif
9460}
9461
9462#ifdef HAL_NETLINK_IMPL
9463static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9464 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9465 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9466 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9467 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9468 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9469 char mac_addr[20],dev[20];
9470
9471 nla_parse(tb,
9472 NL80211_ATTR_MAX,
9473 genlmsg_attrdata(gnlh, 0),
9474 genlmsg_attrlen(gnlh, 0),
9475 NULL);
9476
9477 if(!tb[NL80211_ATTR_STA_INFO]) {
9478 fprintf(stderr, "sta stats missing!\n");
9479 return NL_SKIP;
9480 }
9481
9482 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9483 fprintf(stderr, "failed to parse nested attributes!\n");
9484 return NL_SKIP;
9485 }
9486
9487 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9488
9489 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9490
9491 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9492 fprintf(stderr, "failed to parse nested rate attributes!");
9493 return NL_SKIP;
9494 }
9495
9496 if(sinfo[NL80211_STA_INFO_TID_STATS])
9497 {
9498 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9499 printf("failed to parse nested stats attributes!");
9500 return NL_SKIP;
9501 }
9502 }
9503 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9504 {
9505 printf("Type is VHT\n");
9506 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9507 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9508
9509 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9510 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9511 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9512 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9513 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9514 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9515 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9516 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9517 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9518 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9519 }
9520 else
9521 {
9522 printf(" OFDM or CCK \n");
9523 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9524 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9525 }
9526
9527 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9528 if(rinfo[NL80211_RATE_INFO_MCS])
9529 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9530 }
9531
9532 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9533 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9534 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9535 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9536
9537 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9538 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9539 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9540
9541 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9542 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9543
9544 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9545 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9546
9547 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9548 ((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]);
9549
9550 return NL_SKIP;
9551}
9552#endif
9553
9554INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9555{
9556#ifdef HAL_NETLINK_IMPL
9557 Netlink nl;
9558 char if_name[10];
9559
9560 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9561
9562 if (*output_array_size <= 0)
9563 return RETURN_OK;
9564
9565 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9566
9567 nl.id = initSock80211(&nl);
9568
9569 if(nl.id < 0) {
9570 fprintf(stderr, "Error initializing netlink \n");
9571 return 0;
9572 }
9573
9574 struct nl_msg* msg = nlmsg_alloc();
9575
9576 if(!msg) {
9577 fprintf(stderr, "Failed to allocate netlink message.\n");
9578 nlfree(&nl);
9579 return 0;
9580 }
9581
9582 genlmsg_put(msg,
9583 NL_AUTO_PORT,
9584 NL_AUTO_SEQ,
9585 nl.id,
9586 0,
9587 0,
9588 NL80211_CMD_GET_STATION,
9589 0);
9590
9591 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9592 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9593 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9594 nl_send_auto(nl.socket, msg);
9595 nl_recvmsgs(nl.socket, nl.cb);
9596 nlmsg_free(msg);
9597 nlfree(&nl);
9598 return RETURN_OK;
9599#else
9600 //TODO Implement me
9601 return RETURN_OK;
9602#endif
9603}
9604
9605INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9606{
9607 // TODO Implement me!
9608 char buf[MAX_BUF_SIZE] = {0};
9609 char config_file[MAX_BUF_SIZE] = {0};
9610
9611 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9612 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9613 *activate = (strncmp("1",buf,1) == 0);
9614
9615 return RETURN_OK;
9616}
9617
9618INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9619{
9620 char config_file[MAX_BUF_SIZE] = {0};
9621 struct params list;
9622
9623 list.name = "rrm_neighbor_report";
9624 list.value = activate?"1":"0";
9625 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9626 wifi_hostapdWrite(config_file, &list, 1);
9627
9628 return RETURN_OK;
9629}
9630
9631INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9632{
9633 char buf[32] = {0};
9634 char config_file[MAX_BUF_SIZE] = {0};
9635
9636 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9637 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9638 *activate = (strncmp("1",buf,1) == 0);
9639
9640 return RETURN_OK;
9641}
9642#undef HAL_NETLINK_IMPL
9643#ifdef HAL_NETLINK_IMPL
9644static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9645 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9646 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9647 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9648 char dev[20];
9649 int freq =0 ;
9650 static int i=0;
9651
9652 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9653
9654 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9655 };
9656
9657 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9658
9659 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9660
9661 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9662 fprintf(stderr, "survey data missing!\n");
9663 return NL_SKIP;
9664 }
9665
9666 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9667 {
9668 fprintf(stderr, "failed to parse nested attributes!\n");
9669 return NL_SKIP;
9670 }
9671
9672
9673 if(out[0].array_size == 1 )
9674 {
9675 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9676 {
9677 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9678 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9679 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9680
9681 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9682 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9683 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9684 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9685 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9686 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9687 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9688 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9689 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9690 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9691 if (sinfo[NL80211_SURVEY_INFO_TIME])
9692 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9693 return NL_STOP;
9694 }
9695 }
9696 else
9697 {
9698 if ( i <= out[0].array_size )
9699 {
9700 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9701 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9702 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9703
9704 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9705 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9706 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9707 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9708 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9709 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9710 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9711 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9712 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9713 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9714 if (sinfo[NL80211_SURVEY_INFO_TIME])
9715 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9716 }
9717 }
9718
9719 i++;
9720 return NL_SKIP;
9721}
9722#endif
9723
9724static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9725{
9726 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9727 FILE *fp;
9728
9729 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9730 {
9731 printf("Creating Frequency-Channel Map\n");
9732 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9733 }
9734 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9735 if((fp = popen(command, "r")))
9736 {
9737 fgets(output, sizeof(output), fp);
9738 *freqMHz = atoi(output);
9739 fclose(fp);
9740 }
9741
9742 return 0;
9743}
9744
9745static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9746{
9747 int freqMHz = -1;
9748 char cmd[MAX_CMD_SIZE] = {'\0'};
9749
9750 ieee80211_channel_to_frequency(channel, &freqMHz);
9751 if (freqMHz == -1) {
9752 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9753 return -1;
9754 }
9755
9756 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9757 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9758 radioIndex, freqMHz);
9759 return -1;
9760 }
9761
9762 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9763 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9764 return -1;
9765 }
9766
9767 return 0;
9768}
9769
9770static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9771{
9772 const char *ptr = buf;
9773 char *key = NULL;
9774 char *val = NULL;
9775 char line[256] = { '\0' };
9776
9777 while (ptr = get_line_from_str_buf(ptr, line)) {
9778 if (strstr(line, "Frequency")) continue;
9779
9780 key = strtok(line, ":");
9781 val = strtok(NULL, " ");
9782 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9783
9784 if (!strcmp(key, "noise")) {
9785 sscanf(val, "%d", &stats->ch_noise);
9786 if (stats->ch_noise == 0) {
9787 // Workaround for missing noise information.
9788 // Assume -95 for 2.4G and -103 for 5G
9789 if (radioIndex == 0) stats->ch_noise = -95;
9790 if (radioIndex == 1) stats->ch_noise = -103;
9791 }
9792 }
9793 else if (!strcmp(key, "channel active time")) {
9794 sscanf(val, "%llu", &stats->ch_utilization_total);
9795 }
9796 else if (!strcmp(key, "channel busy time")) {
9797 sscanf(val, "%llu", &stats->ch_utilization_busy);
9798 }
9799 else if (!strcmp(key, "channel receive time")) {
9800 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9801 }
9802 else if (!strcmp(key, "channel transmit time")) {
9803 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9804 }
9805 };
9806
9807 return 0;
9808}
9809
9810INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9811{
9812 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9813#ifdef HAL_NETLINK_IMPL
9814 Netlink nl;
9815 wifi_channelStats_t_loc local[array_size];
9816 char if_name[10];
9817
9818 local[0].array_size = array_size;
9819
9820 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9821
9822 nl.id = initSock80211(&nl);
9823
9824 if (nl.id < 0) {
9825 fprintf(stderr, "Error initializing netlink \n");
9826 return -1;
9827 }
9828
9829 struct nl_msg* msg = nlmsg_alloc();
9830
9831 if (!msg) {
9832 fprintf(stderr, "Failed to allocate netlink message.\n");
9833 nlfree(&nl);
9834 return -2;
9835 }
9836
9837 genlmsg_put(msg,
9838 NL_AUTO_PORT,
9839 NL_AUTO_SEQ,
9840 nl.id,
9841 0,
9842 NLM_F_DUMP,
9843 NL80211_CMD_GET_SURVEY,
9844 0);
9845
9846 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9847 nl_send_auto(nl.socket, msg);
9848 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9849 nl_recvmsgs(nl.socket, nl.cb);
9850 nlmsg_free(msg);
9851 nlfree(&nl);
9852 //Copying the Values
9853 for(int i=0;i<array_size;i++)
9854 {
9855 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9856 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9857 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9858 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9859 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9860 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9861 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9862 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9863 }
9864#else
9865 ULONG channel = 0;
9866 int i;
9867 int number_of_channels = array_size;
9868 char buf[512];
9869 INT ret;
9870 wifi_channelStats_t tmp_stats;
9871
9872 if (number_of_channels == 0) {
9873 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9874 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9875 return RETURN_ERR;
9876 }
9877 number_of_channels = 1;
9878 input_output_channelStats_array[0].ch_number = channel;
9879 }
9880
9881 for (i = 0; i < number_of_channels; i++) {
9882
9883 input_output_channelStats_array[i].ch_noise = 0;
9884 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9885 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9886 input_output_channelStats_array[i].ch_utilization_busy = 0;
9887 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9888 input_output_channelStats_array[i].ch_utilization_total = 0;
9889
9890 memset(buf, 0, sizeof(buf));
9891 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9892 return RETURN_ERR;
9893 }
9894 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9895 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9896 return RETURN_ERR;
9897 }
9898
9899 // XXX: fake missing 'self' counter which is not available in iw survey output
9900 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9901 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9902
9903 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9904 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9905 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9906 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9907 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9908
9909 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",
9910 __func__,
9911 input_output_channelStats_array[i].ch_number,
9912 input_output_channelStats_array[i].ch_noise,
9913 input_output_channelStats_array[i].ch_utilization_total,
9914 input_output_channelStats_array[i].ch_utilization_busy,
9915 input_output_channelStats_array[i].ch_utilization_busy_rx,
9916 input_output_channelStats_array[i].ch_utilization_busy_tx,
9917 input_output_channelStats_array[i].ch_utilization_busy_self,
9918 input_output_channelStats_array[i].ch_utilization_busy_ext);
9919 }
9920#endif
9921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9922 return RETURN_OK;
9923}
9924#define HAL_NETLINK_IMPL
9925
9926/* Hostapd events */
9927
9928#ifndef container_of
9929#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9930#define container_of(ptr, type, member) \
9931 ((type *)((char *)ptr - offset_of(type, member)))
9932#endif /* container_of */
9933
9934struct ctrl {
9935 char sockpath[128];
9936 char sockdir[128];
9937 char bss[IFNAMSIZ];
9938 char reply[4096];
9939 int ssid_index;
9940 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9941 void (*overrun)(struct ctrl *ctrl);
9942 struct wpa_ctrl *wpa;
9943 unsigned int ovfl;
9944 size_t reply_len;
9945 int initialized;
9946 ev_timer retry;
9947 ev_timer watchdog;
9948 ev_stat stat;
9949 ev_io io;
9950};
9951static wifi_newApAssociatedDevice_callback clients_connect_cb;
9952static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9953static struct ctrl wpa_ctrl[MAX_APS];
9954static int initialized;
9955
9956static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9957{
9958 char cbuf[256] = {};
9959 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9960 struct cmsghdr *cmsg;
9961 unsigned int ovfl = ctrl->ovfl;
9962 unsigned int drop;
9963
9964 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9965 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9966 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9967 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9968
9969 drop = ovfl - ctrl->ovfl;
9970 ctrl->ovfl = ovfl;
9971
9972 return drop;
9973}
9974
9975static void ctrl_close(struct ctrl *ctrl)
9976{
9977 if (ctrl->io.cb)
9978 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9979 if (ctrl->retry.cb)
9980 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9981 if (!ctrl->wpa)
9982 return;
9983
9984 wpa_ctrl_detach(ctrl->wpa);
9985 wpa_ctrl_close(ctrl->wpa);
9986 ctrl->wpa = NULL;
9987 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9988}
9989
9990static void ctrl_process(struct ctrl *ctrl)
9991{
9992 const char *str;
9993 int drops;
9994 int level;
9995 int err;
9996
9997 /* Example events:
9998 *
9999 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10000 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10001 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10002 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10003 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10004 */
10005 if (!(str = index(ctrl->reply, '>')))
10006 return;
10007 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10008 return;
10009
10010 str++;
10011
10012 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10013 if (!(str = index(ctrl->reply, ' ')))
10014 return;
10015 wifi_associated_dev_t sta;
10016 memset(&sta, 0, sizeof(sta));
10017
10018 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10019 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10020 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10021
10022 sta.cli_Active=true;
10023
10024 (clients_connect_cb)(ctrl->ssid_index, &sta);
10025 goto handled;
10026 }
10027
10028 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10029 if (!(str = index(ctrl->reply, ' ')))
10030 return;
10031
10032 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10033 goto handled;
10034 }
10035
10036 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10037 printf("CTRL_WPA: handle TERMINATING event\n");
10038 goto retry;
10039 }
10040
10041 if (strncmp("AP-DISABLED", str, 11) == 0) {
10042 printf("CTRL_WPA: handle AP-DISABLED\n");
10043 goto retry;
10044 }
10045
10046 printf("Event not supported!!\n");
10047
10048handled:
10049
10050 if ((drops = ctrl_get_drops(ctrl))) {
10051 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10052 if (ctrl->overrun)
10053 ctrl->overrun(ctrl);
10054 }
10055
10056 return;
10057
10058retry:
10059 printf("WPA_CTRL: closing\n");
10060 ctrl_close(ctrl);
10061 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10062 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10063}
10064
10065static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10066{
10067 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10068 int err;
10069
10070 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10071 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10072 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10073 ctrl->reply[ctrl->reply_len] = 0;
10074 if (err < 0) {
10075 if (errno == EAGAIN || errno == EWOULDBLOCK)
10076 return;
10077 ctrl_close(ctrl);
10078 ev_timer_again(EV_A_ &ctrl->retry);
10079 return;
10080 }
10081
10082 ctrl_process(ctrl);
10083}
10084
10085static int ctrl_open(struct ctrl *ctrl)
10086{
10087 int fd;
10088
10089 if (ctrl->wpa)
10090 return 0;
10091
10092 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10093 if (!ctrl->wpa)
10094 goto err;
10095
10096 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10097 goto err_close;
10098
10099 fd = wpa_ctrl_get_fd(ctrl->wpa);
10100 if (fd < 0)
10101 goto err_detach;
10102
10103 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10104 goto err_detach;
10105
10106 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10107 ev_io_start(EV_DEFAULT_ &ctrl->io);
10108
10109 return 0;
10110
10111err_detach:
10112 wpa_ctrl_detach(ctrl->wpa);
10113err_close:
10114 wpa_ctrl_close(ctrl->wpa);
10115err:
10116 ctrl->wpa = NULL;
10117 return -1;
10118}
10119
10120static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10121{
10122 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10123
10124 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10125 ctrl_open(ctrl);
10126}
10127
10128static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10129{
10130 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10131
10132 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10133 if (ctrl_open(ctrl) == 0) {
10134 printf("WPA_CTRL: retry successful\n");
10135 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10136 }
10137}
10138
10139int ctrl_enable(struct ctrl *ctrl)
10140{
10141 if (ctrl->wpa)
10142 return 0;
10143
10144 if (!ctrl->stat.cb) {
10145 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10146 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10147 }
10148
10149 if (!ctrl->retry.cb) {
10150 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10151 }
10152
10153 return ctrl_open(ctrl);
10154}
10155
10156static void
10157ctrl_msg_cb(char *buf, size_t len)
10158{
10159 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10160
10161 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10162 ctrl_process(ctrl);
10163}
10164
10165static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10166{
10167 int err;
10168
10169 if (!ctrl->wpa)
10170 return -1;
10171 if (*reply_len < 2)
10172 return -1;
10173
10174 (*reply_len)--;
10175 ctrl->reply_len = sizeof(ctrl->reply);
10176 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10177 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10178 if (err < 0)
10179 return err;
10180
10181 if (ctrl->reply_len > *reply_len)
10182 ctrl->reply_len = *reply_len;
10183
10184 *reply_len = ctrl->reply_len;
10185 memcpy(reply, ctrl->reply, *reply_len);
10186 reply[*reply_len - 1] = 0;
10187 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10188 return 0;
10189}
10190
10191static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10192{
10193 const char *pong = "PONG";
10194 const char *ping = "PING";
10195 char reply[1024];
10196 size_t len = sizeof(reply);
10197 int err;
10198 ULONG s, snum;
10199 INT ret;
10200 BOOL status;
10201
10202 printf("WPA_CTRL: watchdog cb\n");
10203
10204 ret = wifi_getSSIDNumberOfEntries(&snum);
10205 if (ret != RETURN_OK) {
10206 printf("%s: failed to get SSID count", __func__);
10207 return;
10208 }
10209
10210 if (snum > MAX_APS) {
10211 printf("more ssid than supported! %lu\n", snum);
10212 return;
10213 }
10214
10215 for (s = 0; s < snum; s++) {
10216 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10217 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10218 continue;
10219 }
10220 if (status == false) continue;
10221
10222 memset(reply, 0, sizeof(reply));
10223 len = sizeof(reply);
10224 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10225 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10226 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10227 continue;
10228
10229 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10230 ctrl_close(&wpa_ctrl[s]);
10231 printf("WPA_CTRL: ev_timer_again %d\n", s);
10232 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10233 }
10234}
10235
10236static int init_wpa()
10237{
10238 int ret = 0, i = 0;
10239 ULONG s, snum;
10240
10241 ret = wifi_getSSIDNumberOfEntries(&snum);
10242 if (ret != RETURN_OK) {
10243 printf("%s: failed to get SSID count", __func__);
10244 return RETURN_ERR;
10245 }
10246
10247 if (snum > MAX_APS) {
10248 printf("more ssid than supported! %lu\n", snum);
10249 return RETURN_ERR;
10250 }
10251
10252 for (s = 0; s < snum; s++) {
10253 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10254 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10255 wpa_ctrl[s].ssid_index = s;
10256 ctrl_enable(&wpa_ctrl[s]);
10257 }
10258
10259 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10260 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10261
10262 initialized = 1;
10263 printf("WPA_CTRL: initialized\n");
10264
10265 return RETURN_OK;
10266}
10267
10268void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10269{
10270 clients_connect_cb = callback_proc;
10271 if (!initialized)
10272 init_wpa();
10273}
10274
10275void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10276{
10277 clients_disconnect_cb = callback_proc;
10278 if (!initialized)
10279 init_wpa();
10280}
10281
10282INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10283{
10284 // TODO Implement me!
10285 return RETURN_ERR;
10286}
10287
10288INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10289{
10290 // TODO Implement me!
10291 return RETURN_ERR;
10292}
10293
10294INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10295{
10296 int i;
10297 char cmd[256];
10298 char channel_numbers_buf[256];
10299 char dfs_state_buf[256];
10300 char line[256];
10301 const char *ptr;
10302
10303 memset(cmd, 0, sizeof(cmd));
10304 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10305 memset(line, 0, sizeof(line));
10306 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10307 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10308
10309 if (radioIndex == 0) { // 2.4G - all allowed
10310 if (outputMapSize < 11) {
10311 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10312 return RETURN_ERR;
10313 }
10314
10315 for (i = 0; i < 11; i++) {
10316 outputMap[i].ch_number = i + 1;
10317 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10318 }
10319
10320 return RETURN_OK;
10321 }
10322
10323 if (radioIndex == 1) { // 5G
10324// Example output of iw list:
10325//
10326// Frequencies:
10327// * 5180 MHz [36] (17.0 dBm)
10328// * 5200 MHz [40] (17.0 dBm)
10329// * 5220 MHz [44] (17.0 dBm)
10330// * 5240 MHz [48] (17.0 dBm)
10331// * 5260 MHz [52] (23.0 dBm) (radar detection)
10332// DFS state: usable (for 78930 sec)
10333// DFS CAC time: 60000 ms
10334// * 5280 MHz [56] (23.0 dBm) (radar detection)
10335// DFS state: usable (for 78930 sec)
10336// DFS CAC time: 60000 ms
10337// * 5300 MHz [60] (23.0 dBm) (radar detection)
10338// DFS state: usable (for 78930 sec)
10339// DFS CAC time: 60000 ms
10340// * 5320 MHz [64] (23.0 dBm) (radar detection)
10341// DFS state: usable (for 78930 sec)
10342// DFS CAC time: 60000 ms
10343// * 5500 MHz [100] (disabled)
10344// * 5520 MHz [104] (disabled)
10345// * 5540 MHz [108] (disabled)
10346// * 5560 MHz [112] (disabled)
10347//
10348// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10349 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10350 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10351 return RETURN_ERR;
10352 }
10353
10354 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10355 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10356 return RETURN_ERR;
10357 }
10358
10359 ptr = channel_numbers_buf;
10360 i = 0;
10361 while (ptr = get_line_from_str_buf(ptr, line)) {
10362 if (i >= outputMapSize) {
10363 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10364 return RETURN_ERR;
10365 }
10366 sscanf(line, "%d", &outputMap[i].ch_number);
10367
10368 memset(cmd, 0, sizeof(cmd));
10369 // Below command should fetch string for DFS state (usable, available or unavailable)
10370 // Example line: "DFS state: usable (for 78930 sec)"
10371 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) {
10372 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10373 return RETURN_ERR;
10374 }
10375
10376 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10377 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10378 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10379 return RETURN_ERR;
10380 }
10381
10382 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10383
10384 if (!strcmp(dfs_state_buf, "usable")) {
10385 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10386 } else if (!strcmp(dfs_state_buf, "available")) {
10387 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10388 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10389 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10390 } else {
10391 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10392 }
10393 i++;
10394 }
10395
10396 return RETURN_OK;
10397 }
10398
10399 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10400 return RETURN_ERR;
10401}
10402
10403INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10404{
10405 // TODO Implement me!
10406 return RETURN_ERR;
10407}
10408
10409INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10410{
10411 return RETURN_OK;
10412}
10413
10414INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10415{
10416 // TODO Implement me!
10417 return RETURN_ERR;
10418}
10419
10420INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10421{
10422 // TODO API refrence Implementaion is present on RPI hal
10423 return RETURN_ERR;
10424}
10425
10426INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10427{
developera5005b62022-09-13 15:43:35 +080010428 char cmd[128]={'\0'};
10429 char buf[128]={'\0'};
10430 char *support;
10431 int maximum_tx = 0, current_tx = 0;
10432
10433 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10434 if(txpwr_pcntg == NULL)
10435 return RETURN_ERR;
10436
10437 // Get the maximum tx power of the device
10438 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10439 _syscmd(cmd, buf, sizeof(buf));
10440 maximum_tx = strtol(buf, NULL, 10);
10441
10442 // Get the current tx power
10443 memset(cmd, 0, sizeof(cmd));
10444 memset(buf, 0, sizeof(buf));
10445 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10446 _syscmd(cmd, buf, sizeof(buf));
10447 current_tx = strtol(buf, NULL, 10);
10448
10449 // Get the power supported list and find the current power percentage in supported list
10450 memset(buf, 0, sizeof(buf));
10451 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10452 support = strtok(buf, ",");
10453 while(true)
10454 {
10455 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10456 *txpwr_pcntg = 0;
10457 wifi_dbg_printf("current power is not in supported list\n");
10458 return RETURN_ERR;
10459 }
10460 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10461 if (tmp == current_tx) {
10462 *txpwr_pcntg = strtol(support, NULL, 10);
10463 break;
10464 }
10465 support = strtok(NULL, ",");
10466 }
10467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010468 return RETURN_OK;
10469}
10470
10471INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10472{
developer58599c22022-09-13 16:40:34 +080010473 // TODO precac feature.
10474 struct params params = {0};
10475 char config_file[128] = {0};
10476
10477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10478
10479 params.name = "enable_background_radar";
10480 params.value = enable?"1":"0";
10481 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10482 wifi_hostapdWrite(config_file, &params, 1);
10483 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10484
10485 /* TODO precac feature */
10486
10487 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10488 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010489}
10490
10491INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10492{
developer58599c22022-09-13 16:40:34 +080010493 char config_file[128] = {0};
10494 char buf[64] = {0};
10495
10496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10497 if (NULL == enable || NULL == precac)
10498 return RETURN_ERR;
10499
10500 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10501 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10502 if (strncmp(enable, "1", 1) == 0)
10503 *enable = true;
10504 else
10505 *enable = false;
10506
10507 /* TODO precac feature */
10508
10509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10510 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010511}
10512
10513INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10514{
developer58599c22022-09-13 16:40:34 +080010515 *supported = TRUE;
10516 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010517}
10518
developer3e6b1692022-09-30 18:04:05 +080010519INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10520{
10521 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10522 struct params params = {0};
10523 char config_file[64] = {0};
10524 char buf[64] = {0};
10525 unsigned int set_mu_type = 0;
10526 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10527
10528 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10529 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10530
10531 if (strlen(buf) > 0)
10532 set_mu_type = strtol(buf, NULL, 10);
10533
10534 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10535 set_mu_type &= ~0x05; // unset bit 0, 2
10536 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10537 set_mu_type |= 0x01;
10538 set_mu_type &= ~0x04;
10539 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10540 set_mu_type &= ~0x01;
10541 set_mu_type |= 0x04;
10542 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10543 set_mu_type |= 0x05; // set bit 0, 2
10544 }
10545
10546 params.name = "hemu_onoff";
10547 sprintf(buf, "%u", set_mu_type);
10548 params.value = buf;
10549 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10550 wifi_hostapdWrite(config_file, &params, 1);
10551 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10552
10553 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10554 return RETURN_OK;
10555}
10556
10557INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10558{
10559 struct params params={0};
10560 char config_file[64] = {0};
10561 char buf[64] = {0};
10562 unsigned int get_mu_type = 0;
10563
10564 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10565
10566 if (mu_type == NULL)
10567 return RETURN_ERR;
10568
10569 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10570 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10571 get_mu_type = strtol(buf, NULL, 10);
10572
10573 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10574 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10575 else if (get_mu_type & 0x04)
10576 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10577 else if (get_mu_type & 0x01)
10578 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10579 else
10580 *mu_type = WIFI_DL_MU_TYPE_NONE;
10581
10582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10583 return RETURN_OK;
10584}
10585
10586INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10587{
10588 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10589 struct params params={0};
10590 char config_file[64] = {0};
10591 char buf[64] = {0};
10592 unsigned int set_mu_type = 0;
10593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10594
10595 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10596 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10597
10598 if (strlen(buf) > 0)
10599 set_mu_type = strtol(buf, NULL, 10);
10600
10601 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10602 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10603 set_mu_type &= ~0x0a;
10604 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10605 set_mu_type |= 0x02;
10606 set_mu_type &= ~0x08;
10607 }
10608
10609 params.name = "hemu_onoff";
10610 sprintf(buf, "%u", set_mu_type);
10611 params.value = buf;
10612 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10613 wifi_hostapdWrite(config_file, &params, 1);
10614 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10615
10616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10617 return RETURN_OK;
10618}
10619
10620INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10621{
10622 struct params params={0};
10623 char config_file[64] = {0};
10624 char buf[64] = {0};
10625 unsigned int get_mu_type = 0;
10626
10627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10628
10629 if (mu_type == NULL)
10630 return RETURN_ERR;
10631
10632 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10633 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10634
10635 get_mu_type = strtol(buf, NULL, 10);
10636 if (get_mu_type & 0x02)
10637 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10638 else
10639 *mu_type = WIFI_DL_MU_TYPE_NONE;
10640
10641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10642 return RETURN_OK;
10643}
10644
10645
developer454b9462022-09-13 15:29:16 +080010646INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10647{
10648 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010649 char buf[256] = {0};
10650 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010651 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010652 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010653 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010654 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010655
10656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10657
developer254882b2022-09-30 17:12:31 +080010658 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010659 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10660 return RETURN_ERR;
10661 }
developer454b9462022-09-13 15:29:16 +080010662
developer254882b2022-09-30 17:12:31 +080010663 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010664 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010665
developer254882b2022-09-30 17:12:31 +080010666 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10667 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
10668 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
10669 _syscmd(cmd, buf, sizeof(buf));
10670 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10671 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10672 if (strstr(buf, "[SHORT-GI-") == NULL) {
10673 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
10674 _syscmd(cmd, buf, sizeof(buf));
10675 }
10676 if (band == band_5) {
10677 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10678 if (strstr(buf, "[SHORT-GI-") == NULL) {
10679 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
10680 _syscmd(cmd, buf, sizeof(buf));
10681 }
10682 }
10683 }
10684 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010685
developer254882b2022-09-30 17:12:31 +080010686 if (guard_interval == wifi_guard_interval_400)
10687 strcpy(GI, "0.4");
10688 else if (guard_interval == wifi_guard_interval_800)
10689 strcpy(GI, "0.8");
10690 else if (guard_interval == wifi_guard_interval_1600)
10691 strcpy(GI, "1.6");
10692 else if (guard_interval == wifi_guard_interval_3200)
10693 strcpy(GI, "3.2");
10694 else if (guard_interval == wifi_guard_interval_auto)
10695 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010696 // Record GI for get GI function
10697 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10698 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010699 if (f == NULL)
10700 return RETURN_ERR;
10701 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010702 fclose(f);
10703 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10704 return RETURN_OK;
10705}
10706
10707INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10708{
10709 char buf[32] = {0};
10710 char cmd[64] = {0};
10711
10712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10713
10714 if (guard_interval == NULL)
10715 return RETURN_ERR;
10716
10717 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10718 _syscmd(cmd, buf, sizeof(buf));
10719
10720 if (strncmp(buf, "0.4", 3) == 0)
10721 *guard_interval = wifi_guard_interval_400;
10722 else if (strncmp(buf, "0.8", 3) == 0)
10723 *guard_interval = wifi_guard_interval_800;
10724 else if (strncmp(buf, "1.6", 3) == 0)
10725 *guard_interval = wifi_guard_interval_1600;
10726 else if (strncmp(buf, "3.2", 3) == 0)
10727 *guard_interval = wifi_guard_interval_3200;
10728 else
10729 *guard_interval = wifi_guard_interval_auto;
10730
10731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10732 return RETURN_OK;
10733}
10734
developer3cc61d12022-09-13 16:36:05 +080010735INT wifi_setBSSColor(INT radio_index, UCHAR color)
10736{
10737 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10738 struct params params = {0};
10739 char config_file[128] = {0};
10740 char bss_color[4] ={0};
10741
10742 params.name = "he_bss_color";
10743 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10744 params.value = bss_color;
10745 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10746 wifi_hostapdWrite(config_file, &params, 1);
10747 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10748
10749 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10750 return RETURN_OK;
10751}
10752
10753INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10754{
10755 char config_file[128] = {0};
10756 char buf[64] = {0};
10757 char temp_output[128] = {'\0'};
10758
10759 wifi_dbg_printf("\nFunc=%s\n", __func__);
10760 if (NULL == color)
10761 return RETURN_ERR;
10762
10763 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10764 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10765
10766 if(strlen(buf) > 0) {
10767 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10768 } else {
10769 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10770 }
10771
10772 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10773 wifi_dbg_printf("\noutput_string=%s\n", color);
10774
10775 return RETURN_OK;
10776}
10777
developer06a01d92022-09-07 16:32:39 +080010778/* multi-psk support */
10779INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10780{
10781 char cmd[256];
10782
10783 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10784 AP_PREFIX,
10785 apIndex,
10786 mac[0],
10787 mac[1],
10788 mac[2],
10789 mac[3],
10790 mac[4],
10791 mac[5]
10792 );
10793 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10794 _syscmd(cmd, key->wifi_keyId, 64);
10795
10796
10797 return RETURN_OK;
10798}
10799
10800INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10801{
10802 FILE *fd = NULL;
10803 char fname[100];
10804 char cmd[128] = {0};
10805 char out[64] = {0};
10806 wifi_key_multi_psk_t * key = NULL;
10807 if(keysNumber < 0)
10808 return RETURN_ERR;
10809
10810 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10811 fd = fopen(fname, "w");
10812 if (!fd) {
10813 return RETURN_ERR;
10814 }
10815 key= (wifi_key_multi_psk_t *) keys;
10816 for(int i=0; i<keysNumber; ++i, key++) {
10817 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10818 }
10819 fclose(fd);
10820
10821 //reload file
10822 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10823 _syscmd(cmd, out, 64);
10824 return RETURN_OK;
10825}
10826
10827INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10828{
10829 FILE *fd = NULL;
10830 char fname[100];
10831 char * line = NULL;
10832 char * pos = NULL;
10833 size_t len = 0;
10834 ssize_t read = 0;
10835 INT ret = RETURN_OK;
10836 wifi_key_multi_psk_t *keys_it = NULL;
10837
10838 if (keysNumber < 1) {
10839 return RETURN_ERR;
10840 }
10841
10842 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10843 fd = fopen(fname, "r");
10844 if (!fd) {
10845 return RETURN_ERR;
10846 }
10847
10848 if (keys == NULL) {
10849 ret = RETURN_ERR;
10850 goto close;
10851 }
10852
10853 keys_it = keys;
10854 while ((read = getline(&line, &len, fd)) != -1) {
10855 //Strip trailing new line if present
10856 if (read > 0 && line[read-1] == '\n') {
10857 line[read-1] = '\0';
10858 }
10859
10860 if(strcmp(line,"keyid=")) {
10861 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10862 if (!(pos = index(line, ' '))) {
10863 ret = RETURN_ERR;
10864 goto close;
10865 }
10866 pos++;
10867 //Here should be 00:00:00:00:00:00
10868 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10869 printf("Not supported MAC: %s\n", pos);
10870 }
10871 if (!(pos = index(pos, ' '))) {
10872 ret = RETURN_ERR;
10873 goto close;
10874 }
10875 pos++;
10876
10877 //The rest is PSK
10878 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10879 keys_it++;
10880
10881 if(--keysNumber <= 0)
10882 break;
10883 }
10884 }
10885
10886close:
10887 free(line);
10888 fclose(fd);
10889 return ret;
10890}
10891/* end of multi-psk support */
10892
10893INT wifi_setNeighborReports(UINT apIndex,
10894 UINT numNeighborReports,
10895 wifi_NeighborReport_t *neighborReports)
10896{
10897 char cmd[256] = { 0 };
10898 char hex_bssid[13] = { 0 };
10899 char bssid[18] = { 0 };
10900 char nr[256] = { 0 };
10901 char ssid[256];
10902 char hex_ssid[256];
10903 INT ret;
10904
10905 /*rmeove all neighbors*/
10906 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10907 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);
10908 system(cmd);
10909
10910 for(unsigned int i = 0; i < numNeighborReports; i++)
10911 {
10912 memset(ssid, 0, sizeof(ssid));
10913 ret = wifi_getSSIDName(apIndex, ssid);
10914 if (ret != RETURN_OK)
10915 return RETURN_ERR;
10916
10917 memset(hex_ssid, 0, sizeof(hex_ssid));
10918 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10919 sprintf(hex_ssid + k,"%02x", ssid[j]);
10920
10921 snprintf(hex_bssid, sizeof(hex_bssid),
10922 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10923 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10924 snprintf(bssid, sizeof(bssid),
10925 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10926 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10927
10928 snprintf(nr, sizeof(nr),
10929 "%s" // bssid
10930 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10931 "%02hhx" // operclass
10932 "%02hhx" // channel
10933 "%02hhx", // phy_mode
10934 hex_bssid,
10935 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10936 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10937 neighborReports[i].opClass,
10938 neighborReports[i].channel,
10939 neighborReports[i].phyTable);
10940
10941 snprintf(cmd, sizeof(cmd),
10942 "hostapd_cli set_neighbor "
10943 "%s " // bssid
10944 "ssid=%s " // ssid
10945 "nr=%s " // nr
10946 "-i %s%d",
10947 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10948
10949 if (WEXITSTATUS(system(cmd)) != 0)
10950 {
10951 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10952 }
10953 }
10954
10955 return RETURN_OK;
10956}
10957
10958INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10959{
10960 return RETURN_OK;
10961}
10962
10963#ifdef _WIFI_HAL_TEST_
10964int main(int argc,char **argv)
10965{
10966 int index;
10967 INT ret=0;
10968 char buf[1024]="";
10969
10970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10971 if(argc<3)
10972 {
10973 if(argc==2)
10974 {
10975 if(!strcmp(argv[1], "init"))
10976 return wifi_init();
10977 if(!strcmp(argv[1], "reset"))
10978 return wifi_reset();
10979 if(!strcmp(argv[1], "wifi_getHalVersion"))
10980 {
10981 char buffer[64];
10982 if(wifi_getHalVersion(buffer)==RETURN_OK)
10983 printf("Version: %s\n", buffer);
10984 else
10985 printf("Error in wifi_getHalVersion\n");
10986 return RETURN_OK;
10987 }
10988 }
10989 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10990 exit(-1);
10991 }
10992
10993 index = atoi(argv[2]);
10994 if(strstr(argv[1], "wifi_getApName")!=NULL)
10995 {
10996 wifi_getApName(index,buf);
10997 printf("Ap name is %s \n",buf);
10998 return 0;
10999 }
11000 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11001 {
11002 BOOL b = FALSE;
11003 BOOL *output_bool = &b;
11004 wifi_getRadioAutoChannelEnable(index,output_bool);
11005 printf("Channel enabled = %d \n",b);
11006 return 0;
11007 }
11008 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11009 {
11010 wifi_getApWpaEncryptionMode(index,buf);
11011 printf("encryption enabled = %s\n",buf);
11012 return 0;
11013 }
11014 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11015 {
11016 BOOL b = FALSE;
11017 BOOL *output_bool = &b;
11018 wifi_getApSsidAdvertisementEnable(index,output_bool);
11019 printf("advertisment enabled = %d\n",b);
11020 return 0;
11021 }
11022 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11023 {
11024 if(argc <= 3 )
11025 {
11026 printf("Insufficient arguments \n");
11027 exit(-1);
11028 }
11029
11030 char sta[20] = {'\0'};
11031 ULLONG handle= 0;
11032 strcpy(sta,argv[3]);
11033 mac_address_t st;
11034 mac_addr_aton(st,sta);
11035
11036 wifi_associated_dev_tid_stats_t tid_stats;
11037 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11038 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11039 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);
11040 }
11041
11042 if(strstr(argv[1], "getApEnable")!=NULL) {
11043 BOOL enable;
11044 ret=wifi_getApEnable(index, &enable);
11045 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11046 }
11047 else if(strstr(argv[1], "setApEnable")!=NULL) {
11048 BOOL enable = atoi(argv[3]);
11049 ret=wifi_setApEnable(index, enable);
11050 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11051 }
11052 else if(strstr(argv[1], "getApStatus")!=NULL) {
11053 char status[64];
11054 ret=wifi_getApStatus(index, status);
11055 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11056 }
11057 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11058 {
11059 wifi_getSSIDNameStatus(index,buf);
11060 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11061 return 0;
11062 }
11063 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11064 wifi_ssidTrafficStats2_t stats={0};
11065 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11066 printf("%s %d: returns %d\n", argv[1], index, ret);
11067 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11068 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11069 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11070 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11071 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11072 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11073 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11074 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11075 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11076 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11077 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11078 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11079 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11080 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11081 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11082 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11083 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11084 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11085 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11086 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11087 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11088 }
11089 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11090 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11091 UINT array_size=0;
11092 UINT i=0;
11093 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11094 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11095 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11096 printf(" neighbor %d:\n", i);
11097 printf(" ap_SSID =%s\n", pt->ap_SSID);
11098 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11099 printf(" ap_Mode =%s\n", pt->ap_Mode);
11100 printf(" ap_Channel =%d\n", pt->ap_Channel);
11101 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11102 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11103 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11104 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11105 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11106 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11107 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11108 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11109 printf(" ap_Noise =%d\n", pt->ap_Noise);
11110 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11111 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11112 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11113 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11114 }
11115 if(neighbor_ap_array)
11116 free(neighbor_ap_array); //make sure to free the list
11117 }
11118 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11119 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11120 UINT array_size=0;
11121 UINT i=0;
11122 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11123 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11124 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11125 printf(" associated_dev %d:\n", i);
11126 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11127 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11128 printf(" cli_SNR =%d\n", pt->cli_SNR);
11129 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11130 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11131 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11132 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11133 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11134 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11135 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11136 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11137 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11138 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11139 }
11140 if(associated_dev_array)
11141 free(associated_dev_array); //make sure to free the list
11142 }
11143
11144 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11145 {
11146#define MAX_ARRAY_SIZE 64
11147 int i, array_size;
11148 char *p, *ch_str;
11149 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11150
11151 if(argc != 5)
11152 {
11153 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11154 exit(-1);
11155 }
11156 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11157
11158 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11159 {
11160 strtok_r(ch_str, ",", &p);
11161 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11162 }
11163 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11164 if(!array_size)
11165 array_size=1;//Need to print current channel statistics
11166 for(i=0; i<array_size; i++)
11167 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11168 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11169 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11170 input_output_channelStats_array[i].ch_number,\
11171 input_output_channelStats_array[i].ch_noise,\
11172 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11173 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11174 input_output_channelStats_array[i].ch_utilization_busy,\
11175 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11176 input_output_channelStats_array[i].ch_utilization_total);
11177 }
11178
11179 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11180 {
11181 if(argc <= 3 )
11182 {
11183 printf("Insufficient arguments \n");
11184 exit(-1);
11185 }
11186 char mac_addr[20] = {'\0'};
11187 wifi_device_t output_struct;
11188 int dev_index = atoi(argv[3]);
11189
11190 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11191 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11192 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);
11193 }
11194
11195 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11196 {
11197 if (argc <= 3)
11198 {
11199 printf("Insufficient arguments\n");
11200 exit(-1);
11201 }
11202 char args[256];
11203 wifi_NeighborReport_t *neighborReports;
11204
11205 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11206 if (!neighborReports)
11207 {
11208 printf("Failed to allocate memory");
11209 exit(-1);
11210 }
11211
11212 for (int i = 3; i < argc; ++i)
11213 {
11214 char *val;
11215 int j = 0;
11216 memset(args, 0, sizeof(args));
11217 strncpy(args, argv[i], sizeof(args));
11218 val = strtok(args, ";");
11219 while (val != NULL)
11220 {
11221 if (j == 0)
11222 {
11223 mac_addr_aton(neighborReports[i - 3].bssid, val);
11224 } else if (j == 1)
11225 {
11226 neighborReports[i - 3].info = strtol(val, NULL, 16);
11227 } else if (j == 2)
11228 {
11229 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11230 } else if (j == 3)
11231 {
11232 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11233 } else if (j == 4)
11234 {
11235 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11236 } else {
11237 printf("Insufficient arguments]n\n");
11238 exit(-1);
11239 }
11240 val = strtok(NULL, ";");
11241 j++;
11242 }
11243 }
11244
11245 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11246 if (ret != RETURN_OK)
11247 {
11248 printf("wifi_setNeighborReports ret = %d", ret);
11249 exit(-1);
11250 }
11251 }
11252 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11253 {
11254 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11255 printf("%s.\n", buf);
11256 else
11257 printf("Error returned\n");
11258 }
11259 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11260 {
11261 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11262 printf("%s.\n", buf);
11263 else
11264 printf("Error returned\n");
11265 }
11266 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11267 {
11268 if (argc <= 2)
11269 {
11270 printf("Insufficient arguments\n");
11271 exit(-1);
11272 }
11273 char buf[64]= {'\0'};
11274 wifi_getRadioOperatingChannelBandwidth(index,buf);
11275 printf("Current bandwidth is %s \n",buf);
11276 return 0;
11277 }
11278 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11279 {
11280 if (argc <= 5)
11281 {
11282 printf("Insufficient arguments\n");
11283 exit(-1);
11284 }
11285 UINT channel = atoi(argv[3]);
11286 UINT width = atoi(argv[4]);
11287 UINT beacon = atoi(argv[5]);
11288 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11289 printf("Result = %d", ret);
11290 }
11291
11292 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11293 return 0;
11294}
11295
11296#endif
11297
11298#ifdef WIFI_HAL_VERSION_3
11299
developer1e5aa162022-09-13 16:06:24 +080011300INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11301{
11302 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11303 if (bitMap & WIFI_BITRATE_1MBPS)
11304 strcat(BasicRate, "1,");
11305 if (bitMap & WIFI_BITRATE_2MBPS)
11306 strcat(BasicRate, "2,");
11307 if (bitMap & WIFI_BITRATE_5_5MBPS)
11308 strcat(BasicRate, "5.5,");
11309 if (bitMap & WIFI_BITRATE_6MBPS)
11310 strcat(BasicRate, "6,");
11311 if (bitMap & WIFI_BITRATE_9MBPS)
11312 strcat(BasicRate, "9,");
11313 if (bitMap & WIFI_BITRATE_11MBPS)
11314 strcat(BasicRate, "11,");
11315 if (bitMap & WIFI_BITRATE_12MBPS)
11316 strcat(BasicRate, "12,");
11317 if (bitMap & WIFI_BITRATE_18MBPS)
11318 strcat(BasicRate, "18,");
11319 if (bitMap & WIFI_BITRATE_24MBPS)
11320 strcat(BasicRate, "24,");
11321 if (bitMap & WIFI_BITRATE_36MBPS)
11322 strcat(BasicRate, "36,");
11323 if (bitMap & WIFI_BITRATE_48MBPS)
11324 strcat(BasicRate, "48,");
11325 if (bitMap & WIFI_BITRATE_54MBPS)
11326 strcat(BasicRate, "54,");
11327 if (strlen(BasicRate) != 0) // remove last comma
11328 BasicRate[strlen(BasicRate) - 1] = '\0';
11329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11330 return RETURN_OK;
11331}
11332
11333INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11334{
11335 UINT BitMap = 0;
11336 char *rate;
11337
11338 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11339 rate = strtok(BasicRatesList, ",");
11340 while(rate != NULL)
11341 {
11342 if (strcmp(rate, "1") == 0)
11343 BitMap |= WIFI_BITRATE_1MBPS;
11344 else if (strcmp(rate, "2") == 0)
11345 BitMap |= WIFI_BITRATE_2MBPS;
11346 else if (strcmp(rate, "5.5") == 0)
11347 BitMap |= WIFI_BITRATE_5_5MBPS;
11348 else if (strcmp(rate, "6") == 0)
11349 BitMap |= WIFI_BITRATE_6MBPS;
11350 else if (strcmp(rate, "9") == 0)
11351 BitMap |= WIFI_BITRATE_9MBPS;
11352 else if (strcmp(rate, "11") == 0)
11353 BitMap |= WIFI_BITRATE_11MBPS;
11354 else if (strcmp(rate, "12") == 0)
11355 BitMap |= WIFI_BITRATE_12MBPS;
11356 else if (strcmp(rate, "18") == 0)
11357 BitMap |= WIFI_BITRATE_18MBPS;
11358 else if (strcmp(rate, "24") == 0)
11359 BitMap |= WIFI_BITRATE_24MBPS;
11360 else if (strcmp(rate, "36") == 0)
11361 BitMap |= WIFI_BITRATE_36MBPS;
11362 else if (strcmp(rate, "48") == 0)
11363 BitMap |= WIFI_BITRATE_48MBPS;
11364 else if (strcmp(rate, "54") == 0)
11365 BitMap |= WIFI_BITRATE_54MBPS;
11366 rate = strtok(NULL, ",");
11367 }
11368 *basicRateBitMap = BitMap;
11369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11370 return RETURN_OK;
11371}
11372
11373// 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 +080011374INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11375{
developer1e5aa162022-09-13 16:06:24 +080011376 char buf[128] = {0};
11377 char cmd[128] = {0};
11378 char config_file[64] = {0};
11379 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011380 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011381 wifi_radio_operationParam_t current_param;
11382
11383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11384
11385 multiple_set = TRUE;
11386 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11387 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11388 return RETURN_ERR;
11389 }
11390 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11391 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11392 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11393 return RETURN_ERR;
11394 }
11395 }
developer5884e982022-10-06 10:52:50 +080011396
11397 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11398 bandwidth = 20;
11399 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11400 bandwidth = 40;
11401 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11402 bandwidth = 80;
11403 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11404 bandwidth = 160;
11405 if (operationParam->autoChannelEnabled){
11406 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11407 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11408 return RETURN_ERR;
11409 }
11410 }else{
developer1e5aa162022-09-13 16:06:24 +080011411 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11412 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11413 return RETURN_ERR;
11414 }
11415 }
developer5884e982022-10-06 10:52:50 +080011416
developer1e5aa162022-09-13 16:06:24 +080011417 if (current_param.variant != operationParam->variant) {
11418 // Two different definition bit map, so need to check every bit.
11419 if (operationParam->variant & WIFI_80211_VARIANT_A)
11420 set_mode |= WIFI_MODE_A;
11421 if (operationParam->variant & WIFI_80211_VARIANT_B)
11422 set_mode |= WIFI_MODE_B;
11423 if (operationParam->variant & WIFI_80211_VARIANT_G)
11424 set_mode |= WIFI_MODE_G;
11425 if (operationParam->variant & WIFI_80211_VARIANT_N)
11426 set_mode |= WIFI_MODE_N;
11427 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11428 set_mode |= WIFI_MODE_AC;
11429 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11430 set_mode |= WIFI_MODE_AX;
11431 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11432 memset(buf, 0, sizeof(buf));
11433 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11434 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11435 return RETURN_ERR;
11436 }
11437 }
11438 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11439 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11440 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11441 return RETURN_ERR;
11442 }
11443 }
11444 if (current_param.beaconInterval != operationParam->beaconInterval) {
11445 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11446 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11447 return RETURN_ERR;
11448 }
11449 }
11450 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11451 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11452 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11453 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11454 return RETURN_ERR;
11455 }
11456 }
11457 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11458 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11459 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11460 return RETURN_ERR;
11461 }
11462 }
11463 if (current_param.guardInterval != operationParam->guardInterval) {
11464 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11465 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11466 return RETURN_ERR;
11467 }
11468 }
11469 if (current_param.transmitPower != operationParam->transmitPower) {
11470 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11471 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11472 return RETURN_ERR;
11473 }
11474 }
11475 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11476 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11477 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11478 return RETURN_ERR;
11479 }
11480 }
11481 if (current_param.obssCoex != operationParam->obssCoex) {
11482 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11483 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11484 return RETURN_ERR;
11485 }
11486 }
11487 if (current_param.stbcEnable != operationParam->stbcEnable) {
11488 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11489 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11490 return RETURN_ERR;
11491 }
11492 }
11493 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11494 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11495 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11496 return RETURN_ERR;
11497 }
11498 }
11499
11500 // if enable is true, then restart the radio
11501 wifi_setRadioEnable(index, FALSE);
11502 if (operationParam->enable == TRUE)
11503 wifi_setRadioEnable(index, TRUE);
11504 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11505
developer06a01d92022-09-07 16:32:39 +080011506 return RETURN_OK;
11507}
11508
11509INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11510{
developer1e5aa162022-09-13 16:06:24 +080011511 char band[64] = {0};
11512 char buf[256] = {0};
11513 char config_file[64] = {0};
11514 char cmd[128] = {0};
11515 int ret = RETURN_ERR;
11516 int mode = 0;
11517 ULONG channel = 0;
11518 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011519
11520 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11521 printf("Entering %s index = %d\n", __func__, (int)index);
11522
developer1e5aa162022-09-13 16:06:24 +080011523 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11524 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11525 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011526 {
developer1e5aa162022-09-13 16:06:24 +080011527 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011528 return RETURN_ERR;
11529 }
11530 operationParam->enable = enabled;
11531
11532 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011533 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011534 {
developer1e5aa162022-09-13 16:06:24 +080011535 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011536 return RETURN_ERR;
11537 }
11538
11539 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011540 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011541 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011542 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011543 else if (!strcmp(band, "6GHz"))
11544 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011545 else
11546 {
developer1e5aa162022-09-13 16:06:24 +080011547 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011548 band);
11549 }
11550
developer1e5aa162022-09-13 16:06:24 +080011551 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11552 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11553 operationParam->channel = 0;
11554 operationParam->autoChannelEnabled = TRUE;
11555 } else {
11556 operationParam->channel = strtol(buf, NULL, 10);
11557 operationParam->autoChannelEnabled = FALSE;
11558 }
11559
developer06a01d92022-09-07 16:32:39 +080011560 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011561 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11562 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11563 return RETURN_ERR;
11564 }
developer06a01d92022-09-07 16:32:39 +080011565 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11566 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11567 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011568 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11569 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011570 else
11571 {
developer1e5aa162022-09-13 16:06:24 +080011572 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11573 return false;
developer06a01d92022-09-07 16:32:39 +080011574 }
11575
developer1e5aa162022-09-13 16:06:24 +080011576 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11577 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11578 return RETURN_ERR;
11579 }
11580 // Two different definition bit map, so need to check every bit.
11581 if (mode & WIFI_MODE_A)
11582 operationParam->variant |= WIFI_80211_VARIANT_A;
11583 if (mode & WIFI_MODE_B)
11584 operationParam->variant |= WIFI_80211_VARIANT_B;
11585 if (mode & WIFI_MODE_G)
11586 operationParam->variant |= WIFI_80211_VARIANT_G;
11587 if (mode & WIFI_MODE_N)
11588 operationParam->variant |= WIFI_80211_VARIANT_N;
11589 if (mode & WIFI_MODE_AC)
11590 operationParam->variant |= WIFI_80211_VARIANT_AC;
11591 if (mode & WIFI_MODE_AX)
11592 operationParam->variant |= WIFI_80211_VARIANT_AX;
11593 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11594 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11595 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011596 }
developer1e5aa162022-09-13 16:06:24 +080011597 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11598 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11599 return RETURN_ERR;
11600 }
11601 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11602 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11603 return RETURN_ERR;
11604 }
developer06a01d92022-09-07 16:32:39 +080011605
developer1e5aa162022-09-13 16:06:24 +080011606 memset(buf, 0, sizeof(buf));
11607 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11608 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11609 return RETURN_ERR;
11610 }
11611 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11612
11613 memset(buf, 0, sizeof(buf));
11614 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11615 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11616 return RETURN_ERR;
11617 }
11618 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11619
11620 memset(buf, 0, sizeof(buf));
11621 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11622 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11623
11624 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11625 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11626 return RETURN_ERR;
11627 }
11628 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11629 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11630 return RETURN_ERR;
11631 }
11632
11633 memset(buf, 0, sizeof(buf));
11634 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11635 if (strcmp(buf, "-1") == 0) {
11636 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11637 operationParam->ctsProtection = FALSE;
11638 } else {
11639 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11640 operationParam->ctsProtection = TRUE;
11641 }
11642
11643 memset(buf, 0, sizeof(buf));
11644 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11645 if (strcmp(buf, "0") == 0)
11646 operationParam->obssCoex = FALSE;
11647 else
11648 operationParam->obssCoex = TRUE;
11649
11650 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11651 _syscmd(cmd, buf, sizeof(buf));
11652 if (strlen(buf) != 0)
11653 operationParam->stbcEnable = TRUE;
11654 else
11655 operationParam->stbcEnable = FALSE;
11656
11657 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11658 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11659 return RETURN_ERR;
11660 }
11661
11662 // Below value is hardcoded
11663
11664 operationParam->numSecondaryChannels = 0;
11665 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11666 operationParam->channelSecondary[i] = 0;
11667 }
11668 operationParam->csa_beacon_count = 15;
11669 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011670
11671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11672 return RETURN_OK;
11673}
11674
11675static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11676{
developerc086fb72022-10-04 10:18:22 +080011677 int max_radio_num = 0;
11678
11679 wifi_getMaxRadioNumber(&max_radio_num);
11680 if (radioIndex >= max_radio_num || radioIndex < 0) {
11681 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11682 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011683 }
11684
developerc086fb72022-10-04 10:18:22 +080011685 return (arrayIndex * max_radio_num) + radioIndex;
11686}
developer06a01d92022-09-07 16:32:39 +080011687
developerc086fb72022-10-04 10:18:22 +080011688wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11689 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11690 return WIFI_BITRATE_1MBPS;
11691 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11692 return WIFI_BITRATE_2MBPS;
11693 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11694 return WIFI_BITRATE_5_5MBPS;
11695 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11696 return WIFI_BITRATE_6MBPS;
11697 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11698 return WIFI_BITRATE_9MBPS;
11699 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11700 return WIFI_BITRATE_11MBPS;
11701 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11702 return WIFI_BITRATE_12MBPS;
11703 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11704 return WIFI_BITRATE_18MBPS;
11705 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11706 return WIFI_BITRATE_24MBPS;
11707 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11708 return WIFI_BITRATE_36MBPS;
11709 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11710 return WIFI_BITRATE_48MBPS;
11711 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11712 return WIFI_BITRATE_54MBPS;
11713 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011714}
11715
11716INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11717{
developerc086fb72022-10-04 10:18:22 +080011718 INT mode = 0;
11719 INT ret = -1;
11720 INT output = 0;
11721 int i = 0;
11722 int vap_index = 0;
11723 BOOL enabled = FALSE;
11724 char buf[256] = {0};
11725 wifi_vap_security_t security;
11726 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011727
11728 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11729 printf("Entering %s index = %d\n", __func__, (int)index);
11730
developer06a01d92022-09-07 16:32:39 +080011731 for (i = 0; i < 5; i++)
11732 {
developerc086fb72022-10-04 10:18:22 +080011733 map->vap_array[i].radio_index = index;
11734
developer06a01d92022-09-07 16:32:39 +080011735 vap_index = array_index_to_vap_index(index, i);
11736 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011737 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011738
developerc086fb72022-10-04 10:18:22 +080011739 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011740
11741 map->vap_array[i].vap_index = vap_index;
11742
11743 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011744 ret = wifi_getApName(vap_index, buf);
11745 if (ret != RETURN_OK) {
11746 printf("%s: wifi_getApName return error\n", __func__);
11747 return RETURN_ERR;
11748 }
11749 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
11750
11751 memset(buf, 0, sizeof(buf));
11752 ret = wifi_getSSIDNameStatus(vap_index, buf);
11753 if (ret != RETURN_OK) {
11754 printf("%s: wifi_getSSIDNameStatus return error\n", __func__);
11755 return RETURN_ERR;
11756 }
11757 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 +080011758
11759 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080011760 if (ret != RETURN_OK) {
11761 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011762 return RETURN_ERR;
11763 }
11764 map->vap_array[i].u.bss_info.enabled = enabled;
11765
developerc086fb72022-10-04 10:18:22 +080011766 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
11767 if (ret != RETURN_OK) {
11768 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
11769 return RETURN_ERR;
11770 }
developer06a01d92022-09-07 16:32:39 +080011771 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080011772
11773 ret = wifi_getApIsolationEnable(vap_index, &enabled);
11774 if (ret != RETURN_OK) {
11775 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
11776 return RETURN_ERR;
11777 }
11778 map->vap_array[i].u.bss_info.isolation = enabled;
11779
11780 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
11781 if (ret != RETURN_OK) {
11782 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
11783 return RETURN_ERR;
11784 }
11785 map->vap_array[i].u.bss_info.bssMaxSta = output;
11786
11787 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
11788 if (ret != RETURN_OK) {
11789 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
11790 return RETURN_ERR;
11791 }
11792 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011793
developerc086fb72022-10-04 10:18:22 +080011794 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
11795 if (ret != RETURN_OK) {
11796 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
11797 return RETURN_ERR;
11798 }
11799 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011800
developerc086fb72022-10-04 10:18:22 +080011801 ret = wifi_getApSecurity(vap_index, &security);
11802 if (ret != RETURN_OK) {
11803 printf("%s: wifi_getApSecurity return error\n", __func__);
11804 return RETURN_ERR;
11805 }
11806 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080011807
developerc086fb72022-10-04 10:18:22 +080011808 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
11809 if (ret != RETURN_OK) {
11810 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
11811 return RETURN_ERR;
11812 }
11813 if (mode == 0)
11814 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
11815 else
11816 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
11817 if (mode == 1)
11818 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11819 else if (mode == 2)
11820 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080011821
developerc086fb72022-10-04 10:18:22 +080011822 ret = wifi_getApWmmEnable(vap_index, &enabled);
11823 if (ret != RETURN_OK) {
11824 printf("%s: wifi_getApWmmEnable return error\n", __func__);
11825 return RETURN_ERR;
11826 }
11827 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011828
developerc086fb72022-10-04 10:18:22 +080011829 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
11830 if (ret != RETURN_OK) {
11831 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011832 return RETURN_ERR;
11833 }
developerc086fb72022-10-04 10:18:22 +080011834 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011835
11836 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011837 ret = wifi_getApBeaconRate(vap_index, buf);
11838 if (ret != RETURN_OK) {
11839 printf("%s: wifi_getApBeaconRate return error\n", __func__);
11840 return RETURN_ERR;
11841 }
11842 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080011843
developerc086fb72022-10-04 10:18:22 +080011844 memset(buf, 0, sizeof(buf));
11845 ret = wifi_getBaseBSSID(vap_index, buf);
11846 if (ret != RETURN_OK) {
11847 printf("%s: wifi_getBaseBSSID return error\n", __func__);
11848 return RETURN_ERR;
11849 }
11850 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11851 &map->vap_array[i].u.bss_info.bssid[0],
11852 &map->vap_array[i].u.bss_info.bssid[1],
11853 &map->vap_array[i].u.bss_info.bssid[2],
11854 &map->vap_array[i].u.bss_info.bssid[3],
11855 &map->vap_array[i].u.bss_info.bssid[4],
11856 &map->vap_array[i].u.bss_info.bssid[5]);
developer06a01d92022-09-07 16:32:39 +080011857
developerc086fb72022-10-04 10:18:22 +080011858 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080011859 }
11860 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11861 return RETURN_OK;
11862}
11863
11864INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11865{
11866 unsigned int i;
11867 wifi_vap_info_t *vap_info = NULL;
11868 int acl_mode;
11869 char *sec_str = NULL;
11870
11871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11872 printf("Entering %s index = %d\n", __func__, (int)index);
11873 for (i = 0; i < map->num_vaps; i++)
11874 {
11875 vap_info = &map->vap_array[i];
11876 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11877
11878 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11879 else
11880 {
11881 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11882 else acl_mode = 1;
11883 }
11884 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11885 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11886 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11887
11888 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11889 if (sec_str)
11890 {
11891 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11892 }
11893 else
11894 {
11895 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11896 }
11897
11898 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11899 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11900
11901 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11902 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11903
11904 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11905
11906 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11907 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11908 }
11909 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11910 return RETURN_OK;
11911}
11912
11913int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11914{
11915 char *token, *next;
11916 const char s[2] = ",";
11917 int count =0;
11918
11919 /* get the first token */
11920 token = strtok_r(pchannels, s, &next);
11921
11922 /* walk through other tokens */
11923 while( token != NULL && count < MAX_CHANNELS) {
11924 chlistptr->channels_list[count++] = atoi(token);
11925 token = strtok_r(NULL, s, &next);
11926 }
11927
11928 return count;
11929}
11930
11931static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11932{
11933 INT status;
11934 wifi_channels_list_t *chlistp;
11935 CHAR output_string[64];
11936 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011937 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011938
11939 if(rcap == NULL)
11940 {
11941 return RETURN_ERR;
11942 }
11943
11944 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011945 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011946
developer1e5aa162022-09-13 16:06:24 +080011947 if (band == band_2_4)
11948 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11949 else if (band == band_5)
11950 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11951 else if (band == band_6)
11952 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011953
11954 chlistp = &(rcap->channel_list[0]);
11955 memset(pchannels, 0, sizeof(pchannels));
11956
11957 /* possible number of radio channels */
11958 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11959 {
11960 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11961 }
11962 /* Number of channels and list*/
11963 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11964
11965 /* autoChannelSupported */
11966 /* always ON with wifi_getRadioAutoChannelSupported */
11967 rcap->autoChannelSupported = TRUE;
11968
11969 /* DCSSupported */
11970 /* always ON with wifi_getRadioDCSSupported */
11971 rcap->DCSSupported = TRUE;
11972
11973 /* zeroDFSSupported - TBD */
11974 rcap->zeroDFSSupported = FALSE;
11975
11976 /* Supported Country List*/
11977 memset(output_string, 0, sizeof(output_string));
11978 status = wifi_getRadioCountryCode(radioIndex, output_string);
11979 if( status != 0 ) {
11980 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11981 return RETURN_ERR;
11982 } else {
11983 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11984 }
11985 if(!strcmp(output_string,"US")){
11986 rcap->countrySupported[0] = wifi_countrycode_US;
11987 rcap->countrySupported[1] = wifi_countrycode_CA;
11988 } else if (!strcmp(output_string,"CA")) {
11989 rcap->countrySupported[0] = wifi_countrycode_CA;
11990 rcap->countrySupported[1] = wifi_countrycode_US;
11991 } else {
11992 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11993 }
11994
11995 rcap->numcountrySupported = 2;
11996
11997 /* csi */
11998 rcap->csi.maxDevices = 8;
11999 rcap->csi.soudingFrameSupported = TRUE;
12000
12001 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
12002
12003 /* channelWidth - all supported bandwidths */
12004 int i=0;
12005 rcap->channelWidth[i] = 0;
12006 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12007 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12008 WIFI_CHANNELBANDWIDTH_40MHZ);
12009
12010 }
developer1e5aa162022-09-13 16:06:24 +080012011 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012012 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12013 WIFI_CHANNELBANDWIDTH_40MHZ |
12014 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12015 }
12016
12017
12018 /* mode - all supported variants */
12019 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12020 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012021 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 +080012022 }
12023 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012024 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12025 }
12026 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12027 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012028 }
12029 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12030 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12031
12032 /* supportedBitRate - all supported bitrates */
12033 rcap->supportedBitRate[i] = 0;
12034 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12035 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12036 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12037 }
developer1e5aa162022-09-13 16:06:24 +080012038 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012039 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12040 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12041 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12042 }
12043
12044
12045 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12046 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12047 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12048 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12049 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12050 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12051 rcap->cipherSupported = 0;
12052 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12053 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12054
12055 return RETURN_OK;
12056}
12057
12058INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12059{
12060 INT status, radioIndex;
12061 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12062 int iter = 0;
12063 unsigned int j;
12064 wifi_interface_name_idex_map_t *iface_info;
12065
12066 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12067
12068 memset(cap, 0, sizeof(wifi_hal_capability_t));
12069
12070 /* version */
12071 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12072 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12073
12074 /* number of radios platform property */
12075 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12076 _syscmd(cmd, output, sizeof(output));
12077 cap->wifi_prop.numRadios = atoi(output);
12078
12079 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12080 {
12081 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12082 if (status != 0) {
12083 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12084 return RETURN_ERR;
12085 }
12086
12087 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12088 {
12089 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12090 {
12091 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12092 return RETURN_ERR;
12093 }
12094 iface_info = &cap->wifi_prop.interface_map[iter];
12095 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12096 iface_info->rdk_radio_index = radioIndex;
12097 memset(output, 0, sizeof(output));
12098 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12099 {
12100 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12101 }
12102 // TODO: bridge name
12103 // TODO: vlan id
12104 // TODO: primary
12105 iface_info->index = array_index_to_vap_index(radioIndex, j);
12106 memset(output, 0, sizeof(output));
12107 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12108 {
12109 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12110 }
12111 iter++;
12112 }
12113 }
12114
12115 cap->BandSteeringSupported = FALSE;
12116 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12117 return RETURN_OK;
12118}
12119
12120INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12121{
developer587c1b62022-09-27 15:58:59 +080012122 char buf[128] = {0};
12123 char config_file[128] = {0};
12124 char password[64] = {0};
12125 char mfp[32] = {0};
12126 char wpa_mode[32] = {0};
12127 struct params params = {0};
12128
12129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12130
12131 multiple_set = TRUE;
12132 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12133 if (security->mode == wifi_security_mode_none) {
12134 strcpy(wpa_mode, "None");
12135 } else if (security->mode == wifi_security_mode_wpa_personal)
12136 strcpy(wpa_mode, "WPA-Personal");
12137 else if (security->mode == wifi_security_mode_wpa2_personal)
12138 strcpy(wpa_mode, "WPA2-Personal");
12139 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12140 strcpy(wpa_mode, "WPA-WPA2-Personal");
12141 else if (security->mode == wifi_security_mode_wpa_enterprise)
12142 strcpy(wpa_mode, "WPA-Enterprise");
12143 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12144 strcpy(wpa_mode, "WPA2-Enterprise");
12145 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12146 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
12147 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
12148 strcpy(wpa_mode, "WPA3-Personal");
12149 else if (security->mode == wifi_security_mode_wpa3_enterprise)
12150 strcpy(wpa_mode, "WPA3-Enterprise");
12151
12152 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
12153
12154 strncpy(password, security->u.key.key, 63);
12155 password[63] = '\0';
12156 wifi_setApSecurityKeyPassphrase(ap_index, password);
12157
12158 if (security->mode != wifi_security_mode_none) {
12159 memset(&params, 0, sizeof(params));
12160 params.name = "wpa_pairwise";
12161 if (security->encr == wifi_encryption_tkip)
12162 params.value = "TKIP";
12163 else if (security->encr == wifi_encryption_aes)
12164 params.value = "CCMP";
12165 else if (security->encr == wifi_encryption_aes_tkip)
12166 params.value = "TKIP CCMP";
12167 wifi_hostapdWrite(config_file, &params, 1);
12168 }
12169
12170 if (security->mfp == wifi_mfp_cfg_disabled)
12171 strcpy(mfp, "Disable");
12172 else if (security->mfp == wifi_mfp_cfg_optional)
12173 strcpy(mfp, "Optional");
12174 else if (security->mfp == wifi_mfp_cfg_required)
12175 strcpy(mfp, "Required");
12176 wifi_setApSecurityMFPConfig(ap_index, mfp);
12177
12178 memset(&params, 0, sizeof(params));
12179 params.name = "transition_disable";
12180 if (security->wpa3_transition_disable == TRUE)
12181 params.value = "0x01";
12182 else
12183 params.value = "0x00";
12184 wifi_hostapdWrite(config_file, &params, 1);
12185
12186 memset(&params, 0, sizeof(params));
12187 params.name = "wpa_group_rekey";
12188 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12189 params.value = buf;
12190 wifi_hostapdWrite(config_file, &params, 1);
12191
12192 memset(&params, 0, sizeof(params));
12193 params.name = "wpa_strict_rekey";
12194 params.value = security->strict_rekey?"1":"0";
12195 wifi_hostapdWrite(config_file, &params, 1);
12196
12197 memset(&params, 0, sizeof(params));
12198 params.name = "wpa_pairwise_update_count";
12199 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12200 params.value = buf;
12201 wifi_hostapdWrite(config_file, &params, 1);
12202
12203 memset(&params, 0, sizeof(params));
12204 params.name = "disable_pmksa_caching";
12205 params.value = security->disable_pmksa_caching?"1":"0";
12206 wifi_hostapdWrite(config_file, &params, 1);
12207
12208 wifi_setApEnable(ap_index, FALSE);
12209 wifi_setApEnable(ap_index, TRUE);
12210
12211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12212
developer06a01d92022-09-07 16:32:39 +080012213 return RETURN_OK;
12214}
12215
12216INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12217{
developer587c1b62022-09-27 15:58:59 +080012218 char buf[128] = {0};
12219 char config_file[128] = {0};
12220 int disable = 0;
12221 // struct params params = {0};
12222
12223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12224 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12225 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12226 security->mode = wifi_security_mode_none;
12227 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012228 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012229 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012230 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012231 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012232 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012233 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012234 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012235 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012236 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012237 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012238 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012239 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012240 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012241 security->mode = wifi_security_mode_wpa3_personal;
developer517a9792022-10-05 19:37:42 +080012242 else if (!strcmp(buf, "WPA3-Transition"))
developer587c1b62022-09-27 15:58:59 +080012243 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012244 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012245 security->mode = wifi_security_mode_wpa3_enterprise;
12246 }
12247
12248 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12249 if (security->mode == wifi_security_mode_none)
12250 security->encr = wifi_encryption_none;
12251 else {
12252 if (strcmp(buf, "TKIP") == 0)
12253 security->encr = wifi_encryption_tkip;
12254 else if (strcmp(buf, "CCMP") == 0)
12255 security->encr = wifi_encryption_aes;
12256 else
12257 security->encr = wifi_encryption_aes_tkip;
12258 }
12259
12260 memset(buf, 0, sizeof(buf));
12261 wifi_getApSecurityMFPConfig(ap_index, buf);
12262 if (strcmp(buf, "Disabled") == 0)
12263 security->mfp = wifi_mfp_cfg_disabled;
12264 else if (strcmp(buf, "Optional") == 0)
12265 security->mfp = wifi_mfp_cfg_optional;
12266 else if (strcmp(buf, "Required") == 0)
12267 security->mfp = wifi_mfp_cfg_required;
12268
12269 memset(buf, 0, sizeof(buf));
12270 security->wpa3_transition_disable = FALSE;
12271 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12272 disable = strtol(buf, NULL, 16);
12273 if (disable != 0)
12274 security->wpa3_transition_disable = TRUE;
12275
12276 memset(buf, 0, sizeof(buf));
12277 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12278 if (strlen(buf) == 0)
12279 security->rekey_interval = 86400;
12280 else
12281 security->rekey_interval = strtol(buf, NULL, 10);
12282
12283 memset(buf, 0, sizeof(buf));
12284 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12285 if (strlen(buf) == 0)
12286 security->strict_rekey = 1;
12287 else
12288 security->strict_rekey = strtol(buf, NULL, 10);
12289
12290 memset(buf, 0, sizeof(buf));
12291 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12292 if (strlen(buf) == 0)
12293 security->eapol_key_retries = 4;
12294 else
12295 security->eapol_key_retries = strtol(buf, NULL, 10);
12296
12297 memset(buf, 0, sizeof(buf));
12298 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12299 if (strlen(buf) == 0)
12300 security->disable_pmksa_caching = FALSE;
12301 else
12302 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12303
12304 /* TODO
12305 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12306 */
12307 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12308 security->eap_identity_req_timeout = 0;
12309 security->eap_identity_req_retries = 0;
12310 security->eap_req_timeout = 0;
12311 security->eap_req_retries = 0;
12312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012313 return RETURN_OK;
12314}
12315
12316#endif /* WIFI_HAL_VERSION_3 */
12317
12318#ifdef WIFI_HAL_VERSION_3_PHASE2
12319INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12320{
developer13df9332022-09-27 16:53:22 +080012321 char cmd[128] = {0};
12322 char buf[128] = {0};
12323 char *mac_addr = NULL;
12324 BOOL status = FALSE;
12325 size_t len = 0;
12326
12327 if(ap_index > MAX_APS)
12328 return RETURN_ERR;
12329
12330 *output_numDevices = 0;
12331 wifi_getApEnable(ap_index, &status);
12332 if (status == FALSE)
12333 return RETURN_OK;
12334
12335 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12336 _syscmd(cmd, buf, sizeof(buf));
12337
12338 mac_addr = strtok(buf, "\n");
12339 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12340 *output_numDevices = i + 1;
12341 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12342 addr_ptr = output_deviceMacAddressArray[i];
12343 mac_addr_aton(addr_ptr, mac_addr);
12344 mac_addr = strtok(NULL, "\n");
12345 }
12346
12347 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012348}
12349#else
12350INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12351{
12352 char cmd[128];
12353 BOOL status = false;
12354
12355 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12356 return RETURN_ERR;
12357
12358 output_buf[0] = '\0';
12359
12360 wifi_getApEnable(ap_index,&status);
12361 if (!status)
12362 return RETURN_OK;
12363
12364 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12365 _syscmd(cmd, output_buf, output_buf_size);
12366
12367 return RETURN_OK;
12368}
12369#endif
developer2f513ab2022-09-13 14:26:06 +080012370
12371INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12372{
12373 char output[16]={'\0'};
12374 char config_file[MAX_BUF_SIZE] = {0};
12375
12376 if (!enable)
12377 return RETURN_ERR;
12378
12379 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12380 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12381
12382 if (strlen(output) == 0)
12383 *enable = FALSE;
12384 else if (strncmp(output, "1", 1) == 0)
12385 *enable = TRUE;
12386 else
12387 *enable = FALSE;
12388
12389 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12390 return RETURN_OK;
12391}
developer2d9c30f2022-09-13 15:06:14 +080012392
12393INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12394{
12395 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12396 return RETURN_ERR;
12397 *output_enable=TRUE;
12398 return RETURN_OK;
12399}
developerfd7d2892022-09-13 16:44:53 +080012400
12401INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12402{
12403 char cmd[128] = {0};
12404 char buf[128] = {0};
12405 char line[128] = {0};
12406 size_t len = 0;
12407 ssize_t read = 0;
12408 FILE *f = NULL;
12409 int index = 0;
12410 int exp = 0;
12411 int mantissa = 0;
12412 int duration = 0;
12413 int radio_index = 0;
12414 int max_radio_num = 0;
12415 uint twt_wake_interval = 0;
12416
12417 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12418
12419 wifi_getMaxRadioNumber(&max_radio_num);
12420 radio_index = ap_index % max_radio_num;
12421 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12422 _syscmd(cmd, buf, sizeof(buf));
12423 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12424 if (*numSessionReturned > maxNumberSessions)
12425 *numSessionReturned = maxNumberSessions;
12426 else if (*numSessionReturned < 1) {
12427 *numSessionReturned = 0;
12428 return RETURN_OK;
12429 }
12430
12431 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12432 if ((f = popen(cmd, "r")) == NULL) {
12433 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12434 return RETURN_ERR;
12435 }
12436
12437 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12438 while((read = fgets(line, sizeof(line), f)) != NULL) {
12439 char *tmp = NULL;
12440 strcpy(buf, line);
12441 tmp = strtok(buf, " ");
12442 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12443 tmp = strtok(NULL, " ");
12444 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12445 tmp = strtok(NULL, " ");
12446 if (strstr(tmp, "t")) {
12447 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12448 }
12449 if (strstr(tmp, "a")) {
12450 twtSessions[index].twtParameters.operation.announced = TRUE;
12451 }
12452 tmp = strtok(NULL, " ");
12453 exp = strtol(tmp, NULL, 10);
12454 tmp = strtok(NULL, " ");
12455 mantissa = strtol(tmp, NULL, 10);
12456 tmp = strtok(NULL, " ");
12457 duration = strtol(tmp, NULL, 10);
12458
12459 // only implicit supported
12460 twtSessions[index].twtParameters.operation.implicit = TRUE;
12461 // only individual agreement supported
12462 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12463
12464 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12465 twt_wake_interval = mantissa * (1 << exp);
12466 if (twt_wake_interval/mantissa != (1 << exp)) {
12467 // Overflow handling
12468 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12469 } else {
12470 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12471 }
12472 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12473 index++;
12474 }
12475
12476 pclose(f);
12477 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12478 return RETURN_OK;
12479}