blob: fbb8930a18dbc10bdd155504e12e6a7596c10778 [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"),
developerc0830312022-10-13 13:22:36 +0800217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800219 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800220 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800221};
222
223wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
224{
225 wifi_secur_list *item;
226 int i;
227
228 for (item = list,i = 0;i < list_sz; item++, i++) {
229 if ((int)(item->key) == key) {
230 return item;
231 }
232 }
233
234 return NULL;
235}
236
237char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
238{
239 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
240
241 if (!item) {
242 return "";
243 }
244
245 return (char *)(item->data);
246}
247
248wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
249{
250 wifi_secur_list *item;
251 int i;
252
253 for (item = list,i = 0;i < list_sz; item++, i++) {
254 if (strcmp((char *)(item->data), str) == 0) {
255 return item;
256 }
257 }
258
259 return NULL;
260}
261#endif /* WIFI_HAL_VERSION_3 */
262
263#ifdef HAL_NETLINK_IMPL
264typedef struct {
265 int id;
266 struct nl_sock* socket;
267 struct nl_cb* cb;
268} Netlink;
269
270static int mac_addr_aton(unsigned char *mac_addr, char *arg)
271{
272 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800273 sscanf(arg, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
developer06a01d92022-09-07 16:32:39 +0800274 mac_addr[0] = mac_addr_int[0];
275 mac_addr[1] = mac_addr_int[1];
276 mac_addr[2] = mac_addr_int[2];
277 mac_addr[3] = mac_addr_int[3];
278 mac_addr[4] = mac_addr_int[4];
279 mac_addr[5] = mac_addr_int[5];
280 return 0;
281}
282
283static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
284{
285 unsigned int mac_addr_int[6]={};
286 mac_addr_int[0] = arg[0];
287 mac_addr_int[1] = arg[1];
288 mac_addr_int[2] = arg[2];
289 mac_addr_int[3] = arg[3];
290 mac_addr_int[4] = arg[4];
291 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800292 snprintf(mac_addr, 20, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
developer06a01d92022-09-07 16:32:39 +0800293 return;
294}
295
296static int ieee80211_frequency_to_channel(int freq)
297{
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800299 if (freq == 2484)
300 return 14;
developerf5745ee2022-10-05 16:09:53 +0800301 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
302 else if (freq == 5935)
303 return 2;
developer06a01d92022-09-07 16:32:39 +0800304 else if (freq < 2484)
305 return (freq - 2407) / 5;
306 else if (freq >= 4910 && freq <= 4980)
307 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800308 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800309 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800310 else if (freq <= 45000) /* DMG band lower limit */
311 /* see 802.11ax D6.1 27.3.23.2 */
312 return (freq - 5950) / 5;
313 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800314 return (freq - 56160) / 2160;
315 else
316 return 0;
317}
318
319static int initSock80211(Netlink* nl) {
320 nl->socket = nl_socket_alloc();
321 if (!nl->socket) {
322 fprintf(stderr, "Failing to allocate the sock\n");
323 return -ENOMEM;
324 }
325
326 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
327
328 if (genl_connect(nl->socket)) {
329 fprintf(stderr, "Failed to connect\n");
330 nl_close(nl->socket);
331 nl_socket_free(nl->socket);
332 return -ENOLINK;
333 }
334
335 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
336 if (nl->id< 0) {
337 fprintf(stderr, "interface not found.\n");
338 nl_close(nl->socket);
339 nl_socket_free(nl->socket);
340 return -ENOENT;
341 }
342
343 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
344 if ((!nl->cb)) {
345 fprintf(stderr, "Failed to allocate netlink callback.\n");
346 nl_close(nl->socket);
347 nl_socket_free(nl->socket);
348 return ENOMEM;
349 }
350
351 return nl->id;
352}
353
354static int nlfree(Netlink *nl)
355{
356 nl_cb_put(nl->cb);
357 nl_close(nl->socket);
358 nl_socket_free(nl->socket);
359 return 0;
360}
361
362static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
363 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
364 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
365 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
366};
367
368static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
369};
370
371static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
372};
373
374typedef struct _wifi_channelStats_loc {
375 INT array_size;
376 INT ch_number;
377 BOOL ch_in_pool;
378 INT ch_noise;
379 BOOL ch_radar_noise;
380 INT ch_max_80211_rssi;
381 INT ch_non_80211_noise;
382 INT ch_utilization;
383 ULLONG ch_utilization_total;
384 ULLONG ch_utilization_busy;
385 ULLONG ch_utilization_busy_tx;
386 ULLONG ch_utilization_busy_rx;
387 ULLONG ch_utilization_busy_self;
388 ULLONG ch_utilization_busy_ext;
389} wifi_channelStats_t_loc;
390
391typedef struct wifi_device_info {
392 INT wifi_devIndex;
393 UCHAR wifi_devMacAddress[6];
394 CHAR wifi_devIPAddress[64];
395 BOOL wifi_devAssociatedDeviceAuthentiationState;
396 INT wifi_devSignalStrength;
397 INT wifi_devTxRate;
398 INT wifi_devRxRate;
399} wifi_device_info_t;
400
401#endif
402
403//For 5g Alias Interfaces
404static BOOL priv_flag = TRUE;
405static BOOL pub_flag = TRUE;
406static BOOL Radio_flag = TRUE;
407//wifi_setApBeaconRate(1, beaconRate);
408
developer1e5aa162022-09-13 16:06:24 +0800409BOOL multiple_set = FALSE;
410
developer06a01d92022-09-07 16:32:39 +0800411struct params
412{
413 char * name;
414 char * value;
415};
416
417static int _syscmd(char *cmd, char *retBuf, int retBufSize)
418{
419 FILE *f;
420 char *ptr = retBuf;
421 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
422
423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
424 if((f = popen(cmd, "r")) == NULL) {
425 fprintf(stderr,"\npopen %s error\n", cmd);
426 return RETURN_ERR;
427 }
428
429 while(!feof(f))
430 {
431 *ptr = 0;
432 if(bufSize>=128) {
433 bufbytes=128;
434 } else {
435 bufbytes=bufSize-1;
436 }
437
438 fgets(ptr,bufbytes,f);
439 readbytes=strlen(ptr);
440
441 if(!readbytes)
442 break;
443
444 bufSize-=readbytes;
445 ptr += readbytes;
446 }
447 cmd_ret = pclose(f);
448 retBuf[retBufSize-1]=0;
449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
450
451 return cmd_ret >> 8;
452}
453
developerc707e972022-09-13 15:38:02 +0800454wifi_band wifi_index_to_band(int apIndex)
455{
456 char cmd[128] = {0};
457 char buf[64] = {0};
458 int freq = 0;
developer5884e982022-10-06 10:52:50 +0800459 int i = 0;
developerc707e972022-09-13 15:38:02 +0800460 wifi_band band = band_invalid;
461
462 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5884e982022-10-06 10:52:50 +0800463 while(i < 10){
464 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
465 _syscmd(cmd, buf, sizeof(buf));
466 freq = strtol(buf, NULL, 10);
467 if (freq > 2401 && freq < 2495)
468 band = band_2_4;
469 else if (freq > 5160 && freq < 5915)
470 band = band_5;
471 else if (freq > 5955 && freq < 7125)
472 band = band_6;
473
474 if(band != band_invalid)
475 break;
476
477 i++;
478 sleep(1);
479 }
developerc707e972022-09-13 15:38:02 +0800480
481 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
482 return band;
483}
484
developer06a01d92022-09-07 16:32:39 +0800485static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
486{
487 char cmd[MAX_CMD_SIZE]={'\0'};
488 char buf[MAX_BUF_SIZE]={'\0'};
489 int ret = 0;
490
491 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
492 ret = _syscmd(cmd, buf, sizeof(buf));
493 if ((ret != 0) && (strlen(buf) == 0))
494 return -1;
495 snprintf(output, output_size, "%s", buf);
496
497 return 0;
498}
499
500static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
501{
502 char cmd[MAX_CMD_SIZE]={'\0'};
503 char buf[MAX_BUF_SIZE]={'\0'};
504
505 for(int i=0;i<item_count;i++)
506 {
507 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
508 if (strlen(buf) == 0) //Insert
509 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
510 else //Update
511 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 +0800512
developer06a01d92022-09-07 16:32:39 +0800513 if(_syscmd(cmd, buf, sizeof(buf)))
514 return -1;
515 }
516
517 return 0;
518}
519
520static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
521{
developer1e5aa162022-09-13 16:06:24 +0800522 if (multiple_set == TRUE)
523 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800524 char cmd[MAX_CMD_SIZE]="", output[32]="";
525 FILE *fp;
526 int i;
527 //NOTE RELOAD should be done in ApplySSIDSettings
528
529 for(i=0; i<item_count; i++, list++)
530 {
531 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
532 if((fp = popen(cmd, "r"))==NULL)
533 {
534 perror("popen failed");
535 return -1;
536 }
537 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
538 {
539 pclose(fp);
540 perror("fgets failed");
541 return -1;
542 }
543 pclose(fp);
544 }
545 return 0;
546}
547
548static int wifi_reloadAp(int apIndex)
549{
developer1e5aa162022-09-13 16:06:24 +0800550 if (multiple_set == TRUE)
551 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800552 char cmd[MAX_CMD_SIZE]="";
553 char buf[MAX_BUF_SIZE]="";
554
555 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
556 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
557 return RETURN_ERR;
558
559 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
560 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
561 return RETURN_ERR;
562
563 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
564 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
565 return RETURN_ERR;
566
567 return RETURN_OK;
568}
569
570
571//For Getting Current Interface Name from corresponding hostapd configuration
572void GetInterfaceName(char *interface_name, char *conf_file)
573{
574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
575 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
577}
578
579INT File_Reading(CHAR *file, char *Value)
580{
581 FILE *fp = NULL;
582 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
583 int count = 0;
584
585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
586 fp = popen(file,"r");
587 if(fp == NULL)
588 return RETURN_ERR;
589
590 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
591 {
592 for(count=0;buf[count]!='\n';count++)
593 copy_buf[count]=buf[count];
594 copy_buf[count]='\0';
595 }
596 strcpy(Value,copy_buf);
597 pclose(fp);
598 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
599
600 return RETURN_OK;
601}
602
603void wifi_RestartHostapd_2G()
604{
605 int Public2GApIndex = 4;
606
607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
608 wifi_setApEnable(Public2GApIndex, FALSE);
609 wifi_setApEnable(Public2GApIndex, TRUE);
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611}
612
613void wifi_RestartHostapd_5G()
614{
615 int Public5GApIndex = 5;
616
617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
618 wifi_setApEnable(Public5GApIndex, FALSE);
619 wifi_setApEnable(Public5GApIndex, TRUE);
620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
621}
622
623void wifi_RestartPrivateWifi_2G()
624{
625 int PrivateApIndex = 0;
626
627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
628 wifi_setApEnable(PrivateApIndex, FALSE);
629 wifi_setApEnable(PrivateApIndex, TRUE);
630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
631}
632
633void wifi_RestartPrivateWifi_5G()
634{
635 int Private5GApIndex = 1;
636
637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
638 wifi_setApEnable(Private5GApIndex, FALSE);
639 wifi_setApEnable(Private5GApIndex, TRUE);
640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
641}
642
643static int writeBandWidth(int radioIndex,char *bw_value)
644{
645 char buf[MAX_BUF_SIZE];
646 char cmd[MAX_CMD_SIZE];
647
648 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
649 if(_syscmd(cmd, buf, sizeof(buf)))
650 {
651 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
652 _syscmd(cmd, buf, sizeof(buf));
653 return RETURN_OK;
654 }
655
656 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
657 _syscmd(cmd,buf,sizeof(buf));
658 return RETURN_OK;
659}
660
661static int readBandWidth(int radioIndex,char *bw_value)
662{
663 char buf[MAX_BUF_SIZE];
664 char cmd[MAX_CMD_SIZE];
665 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
666 _syscmd(cmd,buf,sizeof(buf));
667 if(NULL!=strstr(buf,"20MHz"))
668 {
669 strcpy(bw_value,"20MHz");
670 }
671 else if(NULL!=strstr(buf,"40MHz"))
672 {
673 strcpy(bw_value,"40MHz");
674 }
675 else if(NULL!=strstr(buf,"80MHz"))
676 {
677 strcpy(bw_value,"80MHz");
678 }
679 else
680 {
681 return RETURN_ERR;
682 }
683 return RETURN_OK;
684}
685
developer39a5efb2022-09-13 16:09:06 +0800686INT wifi_getMaxRadioNumber(INT *max_radio_num)
687{
688 char cmd[64] = {0};
689 char buf[4] = {0};
690
691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
692
693 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
694 _syscmd(cmd, buf, sizeof(buf));
695 *max_radio_num = strtoul(buf, NULL, 10);
696
697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
698
699 return RETURN_OK;
700}
701
developer5f222492022-09-13 15:21:52 +0800702// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800703INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
704{
developer5f222492022-09-13 15:21:52 +0800705 struct params params={'\0'};
706 char config_file[MAX_BUF_SIZE] = {0};
707 char buf[MAX_BUF_SIZE] = {'\0'};
708
709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
710 if (strlen (beaconRate) < 5)
711 return RETURN_ERR;
712 // Copy the numeric value
713 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
714 buf[strlen(beaconRate) - 4] = '\0';
715
716 params.name = "beacon_rate";
717 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
718 if (strncmp(buf, "5.5", 3) == 0) {
719 snprintf(buf, sizeof(buf), "55");
720 params.value = buf;
721 } else {
722 strcat(buf, "0");
723 params.value = buf;
724 }
725
726 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
727 wifi_hostapdWrite(config_file, &params, 1);
728 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
729 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
730
731 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800732}
733
734INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
735{
developer1d57d002022-10-12 18:03:15 +0800736 char config_file[128] = {'\0'};
737 char temp_output[128] = {'\0'};
738 char buf[128] = {'\0'};
739 char cmd[128] = {'\0'};
740 int rate = 0;
developer5f222492022-09-13 15:21:52 +0800741
742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
743 if (NULL == beaconRate)
744 return RETURN_ERR;
745
746 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
747 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
748 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
749 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800750 if (strncmp(buf, "55", 2) == 0)
751 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
752 else {
753 rate = strtol(buf, NULL, 10)/10;
754 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
755 }
developer5f222492022-09-13 15:21:52 +0800756 } else {
developer1d57d002022-10-12 18:03:15 +0800757 // config not set, so we would use lowest rate as default
758 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", radioIndex);
759 _syscmd(cmd, buf, sizeof(buf));
760 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800761 }
762 strncpy(beaconRate, temp_output, sizeof(temp_output));
763 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
764
765 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800766}
767
768INT wifi_setLED(INT radioIndex, BOOL enable)
769{
770 return 0;
771}
772INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
773{
774 return RETURN_OK;
775}
776/**********************************************************************************
777 *
778 * Wifi Subsystem level function prototypes
779 *
780**********************************************************************************/
781//---------------------------------------------------------------------------------------------------
782//Wifi system api
783//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
784INT wifi_getHalVersion(CHAR *output_string) //RDKB
785{
786 if(!output_string)
787 return RETURN_ERR;
788 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
789
790 return RETURN_OK;
791}
792
793
794/* wifi_factoryReset() function */
795/**
796* @description Clears internal variables to implement a factory reset of the Wi-Fi
797* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
798*
799* @param None
800*
801* @return The status of the operation.
802* @retval RETURN_OK if successful.
803* @retval RETURN_ERR if any error is detected
804*
805* @execution Synchronous
806* @sideeffect None
807*
808* @note This function must not suspend and must not invoke any blocking system
809* calls. It should probably just send a message to a driver event handler task.
810*
811*/
812INT wifi_factoryReset()
813{
814 char cmd[128];
815
816 /*delete running hostapd conf files*/
817 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
818 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
819 system(cmd);
820 system("systemctl restart hostapd.service");
821
822 return RETURN_OK;
823}
824
825/* wifi_factoryResetRadios() function */
826/**
827* @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.
828*
829* @param None
830* @return The status of the operation
831* @retval RETURN_OK if successful
832* @retval RETURN_ERR if any error is detected
833*
834* @execution Synchronous
835*
836* @sideeffect None
837*
838* @note This function must not suspend and must not invoke any blocking system
839* calls. It should probably just send a message to a driver event handler task.
840*
841*/
842INT wifi_factoryResetRadios()
843{
844 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
845 return RETURN_OK;
846
847 return RETURN_ERR;
848}
849
850
851/* wifi_factoryResetRadio() function */
852/**
853* @description Restore selected radio parameters without touching access point parameters
854*
855* @param radioIndex - Index of Wi-Fi Radio channel
856*
857* @return The status of the operation.
858* @retval RETURN_OK if successful.
859* @retval RETURN_ERR if any error is detected
860*
861* @execution Synchronous.
862* @sideeffect None.
863*
864* @note This function must not suspend and must not invoke any blocking system
865* calls. It should probably just send a message to a driver event handler task.
866*
867*/
868INT wifi_factoryResetRadio(int radioIndex) //RDKB
869{
developer5ff7f5f2022-09-13 15:12:16 +0800870 system("systemctl stop hostapd.service");
871
developer06a01d92022-09-07 16:32:39 +0800872 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
873 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800874 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800875 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800876 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800877 else
878 return RETURN_ERR;
879
developer5ff7f5f2022-09-13 15:12:16 +0800880 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800881 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
882 return RETURN_OK;
883}
884
885/* wifi_initRadio() function */
886/**
887* Description: This function call initializes the specified radio.
888* Implementation specifics may dictate the functionality since
889* different hardware implementations may have different initilization requirements.
890* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
891*
892* @return The status of the operation.
893* @retval RETURN_OK if successful.
894* @retval RETURN_ERR if any error is detected
895*
896* @execution Synchronous.
897* @sideeffect None.
898*
899* @note This function must not suspend and must not invoke any blocking system
900* calls. It should probably just send a message to a driver event handler task.
901*
902*/
903INT wifi_initRadio(INT radioIndex)
904{
905 //TODO: Initializes the wifi subsystem (for specified radio)
906 return RETURN_OK;
907}
908void macfilter_init()
909{
910 char count[4]={'\0'};
911 char buf[253]={'\0'};
912 char tmp[19]={'\0'};
913 int dev_count,block,mac_entry=0;
914 char res[4]={'\0'};
915 char acl_file_path[64] = {'\0'};
916 FILE *fp = NULL;
917 int index=0;
918 char iface[10]={'\0'};
919 char config_file[MAX_BUF_SIZE] = {0};
920
921
922 sprintf(acl_file_path,"/tmp/mac_filter.sh");
923
924 fp=fopen(acl_file_path,"w+");
925 sprintf(buf,"#!/bin/sh \n");
926 fprintf(fp,"%s\n",buf);
927
928 system("chmod 0777 /tmp/mac_filter.sh");
929
930 for(index=0;index<=1;index++)
931 {
932 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
933 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
934 sprintf(buf,"syscfg get %dcountfilter",index);
935 _syscmd(buf,count,sizeof(count));
936 mac_entry=atoi(count);
937
938 sprintf(buf,"syscfg get %dblockall",index);
939 _syscmd(buf,res,sizeof(res));
940 block = atoi(res);
941
942 //Allow only those macs mentioned in ACL
943 if(block==1)
944 {
945 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
946 fprintf(fp,"%s\n",buf);
947 for(dev_count=1;dev_count<=mac_entry;dev_count++)
948 {
949 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
950 _syscmd(buf,tmp,sizeof(tmp));
951 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
952 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
953 fprintf(fp,"%s\n",buf);
954 }
955 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
956 fprintf(fp,"%s\n",buf);
957 }
958
959 //Block all the macs mentioned in ACL
960 else if(block==2)
961 {
962 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
963 fprintf(fp,"%s\n",buf);
964
965 for(dev_count=1;dev_count<=mac_entry;dev_count++)
966 {
967 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
968 _syscmd(buf,tmp,sizeof(tmp));
969 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
970 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
971 fprintf(fp,"%s\n",buf);
972 }
973 }
974 }
975 fclose(fp);
976}
977
978// Initializes the wifi subsystem (all radios)
979INT wifi_init() //RDKB
980{
981 char interface[MAX_BUF_SIZE]={'\0'};
982 char bridge_name[MAX_BUF_SIZE]={'\0'};
983 INT len=0;
984
985 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
986 //Not intitializing macfilter for Turris-Omnia Platform for now
987 //macfilter_init();
988
989 system("/usr/sbin/iw reg set US");
990 system("systemctl start hostapd.service");
991 sleep(2);//sleep to wait for hostapd to start
992
993 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
994
995 return RETURN_OK;
996}
997
998/* wifi_reset() function */
999/**
1000* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1001* Implementation specifics may dictate what is actualy reset since
1002* different hardware implementations may have different requirements.
1003* Parameters : None
1004*
1005* @return The status of the operation.
1006* @retval RETURN_OK if successful.
1007* @retval RETURN_ERR if any error is detected
1008*
1009* @execution Synchronous.
1010* @sideeffect None.
1011*
1012* @note This function must not suspend and must not invoke any blocking system
1013* calls. It should probably just send a message to a driver event handler task.
1014*
1015*/
1016INT wifi_reset()
1017{
1018 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001019 system("systemctl stop hostapd.service");
1020 sleep(2);
1021 system("systemctl start hostapd.service");
1022 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001023 return RETURN_OK;
1024}
1025
1026/* wifi_down() function */
1027/**
1028* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1029* Implementation specifics may dictate some functionality since
1030* different hardware implementations may have different requirements.
1031*
1032* @param None
1033*
1034* @return The status of the operation
1035* @retval RETURN_OK if successful
1036* @retval RETURN_ERR if any error is detected
1037*
1038* @execution Synchronous
1039* @sideeffect None
1040*
1041* @note This function must not suspend and must not invoke any blocking system
1042* calls. It should probably just send a message to a driver event handler task.
1043*
1044*/
1045INT wifi_down()
1046{
1047 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001048 system("systemctl stop hostapd.service");
1049 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001050 return RETURN_OK;
1051}
1052
1053
1054/* wifi_createInitialConfigFiles() function */
1055/**
1056* @description This function creates wifi configuration files. The format
1057* and content of these files are implementation dependent. This function call is
1058* used to trigger this task if necessary. Some implementations may not need this
1059* function. If an implementation does not need to create config files the function call can
1060* do nothing and return RETURN_OK.
1061*
1062* @param None
1063*
1064* @return The status of the operation
1065* @retval RETURN_OK if successful
1066* @retval RETURN_ERR if any error is detected
1067*
1068* @execution Synchronous
1069* @sideeffect None
1070*
1071* @note This function must not suspend and must not invoke any blocking system
1072* calls. It should probably just send a message to a driver event handler task.
1073*
1074*/
1075INT wifi_createInitialConfigFiles()
1076{
1077 //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)
1078 return RETURN_OK;
1079}
1080
1081// outputs the country code to a max 64 character string
1082INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1083{
developer7543b3b2022-09-13 13:47:17 +08001084 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1085 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001086 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001087
1088 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1089 _syscmd(cmd, buf, sizeof(buf));
1090 if(strlen(buf) > 0)
1091 snprintf(output_string, 64, "%s", buf);
1092 else
1093 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001094
1095 return RETURN_OK;
1096}
1097
1098INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1099{
1100 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001101 char str[MAX_BUF_SIZE]={'\0'};
1102 char cmd[MAX_CMD_SIZE]={'\0'};
1103 struct params params;
1104 char config_file[MAX_BUF_SIZE] = {0};
1105
1106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1107 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1108 return RETURN_ERR;
1109
developerb86c6f32022-10-07 14:34:58 +08001110 if (strlen(CountryCode) == 0)
1111 strcpy(CountryCode, "US");
1112
developer7543b3b2022-09-13 13:47:17 +08001113 params.name = "country_code";
1114 params.value = CountryCode;
1115 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1116 int ret = wifi_hostapdWrite(config_file, &params, 1);
1117 if (ret) {
1118 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1119 ,__func__, ret);
1120 }
1121
1122 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1123 if (ret) {
1124 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1125 ,__func__, ret);
1126 }
1127 wifi_reloadAp(radioIndex);
1128 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1129
developer06a01d92022-09-07 16:32:39 +08001130 return RETURN_OK;
1131}
1132
developera748dcf2022-09-13 15:56:48 +08001133INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1134{
1135 char channel_util_file[64] = {0};
1136 char cmd[128] = {0};
1137 char buf[128] = {0};
1138 char line[128] = {0};
1139 char *param = NULL, *value = NULL;
1140 int read = 0;
1141 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1142 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1143 size_t len = 0;
1144 FILE *f = NULL;
1145
1146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1147
1148 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1149 _syscmd(cmd, buf, sizeof(buf));
1150 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1151
1152 memset(cmd, 0, sizeof(cmd));
1153 memset(buf, 0, sizeof(buf));
1154 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1155 if ((f = popen(cmd, "r")) == NULL) {
1156 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1157 return RETURN_ERR;
1158 }
1159
1160 read = getline(&line, &len, f);
1161 while (read != -1) {
1162 param = strtok(line, ":\t");
1163 value = strtok(NULL, " ");
1164 if(strstr(param, "frequency") != NULL) {
1165 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1166 }
1167 if(strstr(param, "noise") != NULL) {
1168 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1169 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1170 }
1171 if(strstr(param, "channel active time") != NULL) {
1172 ActiveTime = strtol(value, NULL, 10);
1173 }
1174 if(strstr(param, "channel busy time") != NULL) {
1175 BusyTime = strtol(value, NULL, 10);
1176 }
1177 if(strstr(param, "channel transmit time") != NULL) {
1178 TransmitTime = strtol(value, NULL, 10);
1179 }
1180 read = getline(&line, &len, f);
1181 }
1182 pclose(f);
1183
1184 // The file should store the last active, busy and transmit time
1185 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1186 f = fopen(channel_util_file, "r");
1187 if (f != NULL) {
1188 read = getline(&line, &len, f);
1189 preActiveTime = strtol(line, NULL, 10);
1190 read = getline(&line, &len, f);
1191 preBusyTime = strtol(line, NULL, 10);
1192 read = getline(&line, &len, f);
1193 preTransmitTime = strtol(line, NULL, 10);
1194 fclose(f);
1195 }
1196
1197 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1198 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1199
1200 f = fopen(channel_util_file, "w");
1201 if (f != NULL) {
1202 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1203 fclose(f);
1204 }
1205 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1206 return RETURN_OK;
1207}
1208
developer06a01d92022-09-07 16:32:39 +08001209/**********************************************************************************
1210 *
1211 * Wifi radio level function prototypes
1212 *
1213**********************************************************************************/
1214
1215//Get the total number of radios in this wifi subsystem
1216INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1217{
1218 if (NULL == output)
1219 return RETURN_ERR;
1220 *output = 2;
1221
1222 return RETURN_OK;
1223}
1224
1225//Get the total number of SSID entries in this wifi subsystem
1226INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1227{
1228 if (NULL == output)
1229 return RETURN_ERR;
1230 *output = MAX_APS;
1231
1232 return RETURN_OK;
1233}
1234
1235//Get the Radio enable config parameter
1236INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1237{
1238 char interface_path[MAX_CMD_SIZE] = {0};
1239 FILE *fp = NULL;
1240
1241 if (NULL == output_bool)
1242 return RETURN_ERR;
1243
1244 *output_bool = FALSE;
1245 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1246 return RETURN_ERR;
1247
1248 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1249 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001250 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001251 {
developercf48e482022-09-13 14:49:50 +08001252 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001253 }
1254 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001255 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1256 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1257 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001258
developercf48e482022-09-13 14:49:50 +08001259 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1260 *output_bool = TRUE;
1261 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001262 return RETURN_OK;
1263}
1264
1265INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1266{
1267 char cmd[MAX_CMD_SIZE] = {0};
1268 char buf[MAX_CMD_SIZE] = {0};
1269 int apIndex, ret;
1270 FILE *fp = NULL;
1271
1272 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1273 if(enable==FALSE)
1274 {
1275 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1276 {
1277 //Detaching %s%d from hostapd daemon
1278 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1279 _syscmd(cmd, buf, sizeof(buf));
1280 if(strncmp(buf, "OK", 2))
1281 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1282 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1283 _syscmd(cmd, buf, sizeof(buf));
1284 }
developer456aa3e2022-09-13 14:27:36 +08001285 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001286 _syscmd(cmd, buf, sizeof(buf));
1287 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001288 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001289 }
1290 else
1291 {
developer456aa3e2022-09-13 14:27:36 +08001292 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001293 _syscmd(cmd, buf, sizeof(buf));
1294 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001295 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001296 sleep(1);
1297 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1298 {
1299 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1300 fp = fopen(cmd, "r");
1301 if(!fp)
1302 {
1303 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1304 _syscmd(cmd, buf, sizeof(buf));
1305 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1306 _syscmd(cmd, buf, sizeof(buf));
1307 }
1308 if(fp)
1309 fclose(fp);
1310 }
1311 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1312 {
1313 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1314 ret = _syscmd(cmd, buf, sizeof(buf));
1315 if ( ret == RETURN_ERR)
1316 {
1317 fprintf(stderr, "VAP interface creation failed\n");
1318 continue;
1319 }
1320 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1321 _syscmd(cmd, buf, sizeof(buf));
1322 if(*buf == '1')
1323 {
1324 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1325 radioIndex, apIndex);
1326 _syscmd(cmd, buf, sizeof(buf));
1327 if(strncmp(buf, "OK", 2))
1328 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1329 }
1330 }
1331 }
1332
1333 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1334 return RETURN_OK;
1335}
1336
1337//Get the Radio enable status
1338INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1339{
1340 if (NULL == output_bool)
1341 return RETURN_ERR;
1342
1343 return wifi_getRadioEnable(radioIndex, output_bool);
1344}
1345
1346//Get the Radio Interface name from platform, eg "wlan0"
1347INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1348{
1349 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1350 return RETURN_ERR;
1351 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1352
1353 return RETURN_OK;
1354}
1355
1356//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1357//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.
1358INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1359{
developerbcc556a2022-09-22 20:02:45 +08001360 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1361 // For max bit rate, we should always choose the best MCS
1362 char mode[64] = {0};
1363 char channel_bandwidth_str[16] = {0};
1364 char *tmp = NULL;
1365 UINT mode_map = 0;
1366 UINT num_subcarrier = 0;
1367 UINT code_bits = 0;
1368 float code_rate = 0; // use max code rate
1369 int NSS = 0;
1370 UINT Symbol_duration = 0;
1371 UINT GI_duration = 0;
1372 wifi_band band = band_invalid;
1373 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1374 BOOL enable = FALSE;
1375 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001376
1377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1378 if (NULL == output_string)
1379 return RETURN_ERR;
1380
developerbcc556a2022-09-22 20:02:45 +08001381 wifi_getRadioEnable(radioIndex, &enable);
1382 if (enable == FALSE) {
1383 snprintf(output_string, 64, "0 Mb/s");
1384 return RETURN_OK;
1385 }
1386
1387 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1388 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1389 return RETURN_ERR;
1390 }
1391
1392 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1393 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1394 return RETURN_ERR;
1395 }
1396
1397 if (gi == wifi_guard_interval_3200)
1398 GI_duration = 32;
1399 else if (gi == wifi_guard_interval_1600)
1400 GI_duration = 16;
1401 else if (gi == wifi_guard_interval_800)
1402 GI_duration = 8;
1403 else // auto, 400
1404 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001405
developerbcc556a2022-09-22 20:02:45 +08001406 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1407 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1408 return RETURN_ERR;
1409 }
1410
1411 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1412 strcpy(channel_bandwidth_str, "160");
1413
1414 if (mode_map & WIFI_MODE_AX) {
1415 if (strstr(channel_bandwidth_str, "160") != NULL)
1416 num_subcarrier = 1960;
1417 else if (strstr(channel_bandwidth_str, "80") != NULL)
1418 num_subcarrier = 980;
1419 else if (strstr(channel_bandwidth_str, "40") != NULL)
1420 num_subcarrier = 468;
1421 else if (strstr(channel_bandwidth_str, "20") != NULL)
1422 num_subcarrier = 234;
1423 code_bits = 10;
1424 code_rate = (float)5/6;
1425 Symbol_duration = 128;
1426 } else if (mode_map & WIFI_MODE_AC) {
1427 if (strstr(channel_bandwidth_str, "160") != NULL)
1428 num_subcarrier = 468;
1429 else if (strstr(channel_bandwidth_str, "80") != NULL)
1430 num_subcarrier = 234;
1431 else if (strstr(channel_bandwidth_str, "40") != NULL)
1432 num_subcarrier = 108;
1433 else if (strstr(channel_bandwidth_str, "20") != NULL)
1434 num_subcarrier = 52;
1435 code_bits = 8;
1436 code_rate = (float)5/6;
1437 Symbol_duration = 32;
1438 } else if (mode_map & WIFI_MODE_N) {
1439 if (strstr(channel_bandwidth_str, "160") != NULL)
1440 num_subcarrier = 468;
1441 else if (strstr(channel_bandwidth_str, "80") != NULL)
1442 num_subcarrier = 234;
1443 else if (strstr(channel_bandwidth_str, "40") != NULL)
1444 num_subcarrier = 108;
1445 else if (strstr(channel_bandwidth_str, "20") != NULL)
1446 num_subcarrier = 52;
1447 code_bits = 6;
1448 code_rate = (float)3/4;
1449 Symbol_duration = 32;
1450 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1451 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1452 snprintf(output_string, 64, "65 Mb/s");
1453 return RETURN_OK;
1454 } else {
1455 snprintf(output_string, 64, "0 Mb/s");
1456 return RETURN_OK;
1457 }
developer06a01d92022-09-07 16:32:39 +08001458
developerbcc556a2022-09-22 20:02:45 +08001459 // Spatial streams
1460 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1461 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1462 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001463 }
developerbcc556a2022-09-22 20:02:45 +08001464
1465 // multiple 10 is to align duration unit (0.1 us)
1466 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1467 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1468
developer06a01d92022-09-07 16:32:39 +08001469 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1470
1471 return RETURN_OK;
1472}
1473#if 0
1474INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1475{
1476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1477 char cmd[64];
1478 char buf[1024];
1479 int apIndex;
1480
1481 if (NULL == output_string)
1482 return RETURN_ERR;
1483
1484 apIndex=(radioIndex==0)?0:1;
1485
1486 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1487 _syscmd(cmd,buf, sizeof(buf));
1488
1489 snprintf(output_string, 64, "%s", buf);
1490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1491 return RETURN_OK;
1492}
1493#endif
1494
1495
1496//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1497//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.
1498INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1499{
developer963da0c2022-09-13 15:58:27 +08001500 wifi_band band = band_invalid;
1501
developer06a01d92022-09-07 16:32:39 +08001502 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1503 if (NULL == output_string)
1504 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001505
1506 band = wifi_index_to_band(radioIndex);
1507
1508 memset(output_string, 0, 10);
1509 if (band == band_2_4)
1510 strcpy(output_string, "2.4GHz");
1511 else if (band == band_5)
1512 strcpy(output_string, "5GHz");
1513 else if (band == band_6)
1514 strcpy(output_string, "6GHz");
1515 else
1516 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1518
1519 return RETURN_OK;
1520#if 0
1521 char buf[MAX_BUF_SIZE]={'\0'};
1522 char str[MAX_BUF_SIZE]={'\0'};
1523 char cmd[MAX_CMD_SIZE]={'\0'};
1524 char *ch=NULL;
1525 char *ch2=NULL;
1526
1527 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1528 if (NULL == output_string)
1529 return RETURN_ERR;
1530
1531
1532 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1533
1534 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1535 {
1536 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1537 return RETURN_ERR;
1538 }
1539 ch=strchr(buf,'\n');
1540 *ch='\0';
1541 ch=strchr(buf,'=');
1542 if(ch==NULL)
1543 return RETURN_ERR;
1544
1545
1546 ch++;
1547
1548 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1549 strcpy(buf,"0");
1550 if(strlen(ch) == 1)
1551 ch=strcat(buf,ch);
1552
1553
1554 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1555
1556 if(_syscmd(cmd,str,64) == RETURN_ERR)
1557 {
1558 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1559 return RETURN_ERR;
1560 }
1561
1562
1563 ch2=strchr(str,'\n');
1564 //replace \n with \0
1565 *ch2='\0';
1566 ch2=strchr(str,'=');
1567 if(ch2==NULL)
1568 {
1569 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1570 return RETURN_ERR;
1571 }
1572 else
1573 wifi_dbg_printf("%s",ch2+1);
1574
1575
1576 ch2++;
1577
1578
1579 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1580
1581 memset(buf,'\0',sizeof(buf));
1582 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1583 {
1584 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1585 return RETURN_ERR;
1586 }
1587 if (strstr(buf,"2.4") != NULL )
1588 strcpy(output_string,"2.4GHz");
1589 else if(strstr(buf,"5.") != NULL )
1590 strcpy(output_string,"5GHz");
1591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1592
1593 return RETURN_OK;
1594#endif
1595}
1596
1597//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1598//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.
1599INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1600{
developerb7593de2022-10-18 09:51:57 +08001601 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001602 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1603 if (NULL == output_string)
1604 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001605 band = wifi_index_to_band(radioIndex);
1606
1607 if (band == band_2_4)
1608 snprintf(output_string, 64, "2.4GHz");
1609 else if (band == band_5)
1610 snprintf(output_string, 64, "5GHz");
1611 else if (band == band_6)
1612 snprintf(output_string, 64, "6GHz");
1613
developer06a01d92022-09-07 16:32:39 +08001614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1615
1616 return RETURN_OK;
1617#if 0
1618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1619 char buf[MAX_BUF_SIZE]={'\0'};
1620 char str[MAX_BUF_SIZE]={'\0'};
1621 char cmd[MAX_CMD_SIZE]={'\0'};
1622 char *ch=NULL;
1623 char *ch2=NULL;
1624 char ch1[5]="0";
1625
1626 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1627
1628 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1629 {
1630 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1631 return RETURN_ERR;
1632 }
1633
1634 ch=strchr(buf,'\n');
1635 *ch='\0';
1636 ch=strchr(buf,'=');
1637 if(ch==NULL)
1638 return RETURN_ERR;
1639 ch++;
1640
1641 if(strlen(ch)==1)
1642 {
1643 strcat(ch1,ch);
1644
1645 }
1646 else
1647 {
1648 strcpy(ch1,ch);
1649 }
1650
1651
1652
1653 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1654 if(_syscmd(cmd,str,64) == RETURN_ERR)
1655 {
1656 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1657 return RETURN_ERR;
1658 }
1659
1660
1661 ch2=strchr(str,'\n');
1662 //replace \n with \0
1663 *ch2='\0';
1664 ch2=strchr(str,'=');
1665 if(ch2==NULL)
1666 {
1667 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1668 return RETURN_ERR;
1669 }
1670 else
1671 wifi_dbg_printf("%s",ch2+1);
1672 ch2++;
1673
1674
1675 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1676 memset(buf,'\0',sizeof(buf));
1677 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1678 {
1679 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1680 return RETURN_ERR;
1681 }
1682
1683
1684 if(strstr(buf,"2.4")!=NULL)
1685 {
1686 strcpy(output_string,"2.4GHz");
1687 }
1688 if(strstr(buf,"5.")!=NULL)
1689 {
1690 strcpy(output_string,"5GHz");
1691 }
1692 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1693 return RETURN_OK;
1694#endif
1695}
1696
1697//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1698//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.
1699INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1700{
developer963da0c2022-09-13 15:58:27 +08001701 char cmd[128]={0};
1702 char buf[128]={0};
1703 char temp_output[128] = {0};
1704 wifi_band band;
1705
1706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001707 if (NULL == output_string)
1708 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001709
1710 band = wifi_index_to_band(radioIndex);
1711 if (band == band_2_4) {
1712 strcat(temp_output, "b,g,");
1713 } else if (band == band_5) {
1714 strcat(temp_output, "a,");
1715 }
1716
1717 // ht capabilities
1718 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);
1719 _syscmd(cmd, buf, sizeof(buf));
1720 if (strncmp(buf, "0x00", 4) != 0) {
1721 strcat(temp_output, "n,");
1722 }
developer06a01d92022-09-07 16:32:39 +08001723
developer963da0c2022-09-13 15:58:27 +08001724 // vht capabilities
1725 if (band == band_5) {
1726 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1727 _syscmd(cmd, buf, sizeof(buf));
1728 if (strncmp(buf, "0x00000000", 10) != 0) {
1729 strcat(temp_output, "ac,");
1730 }
1731 }
1732
1733 // he capabilities
1734 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);
1735 _syscmd(cmd, buf, sizeof(buf));
1736 if (strncmp (buf, "0x0000", 6) != 0) {
1737 strcat(temp_output, "ax,");
1738 }
1739
1740 // Remove the last comma
1741 if (strlen(temp_output) != 0)
1742 temp_output[strlen(temp_output)-1] = '\0';
1743 strncpy(output_string, temp_output, strlen(temp_output));
1744 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001745 return RETURN_OK;
1746}
1747
1748//Get the radio operating mode, and pure mode flag. eg: "ac"
1749//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.
1750INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1751{
1752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1753 if (NULL == output_string)
1754 return RETURN_ERR;
1755
1756 if (radioIndex == 0) {
1757 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1758 *gOnly = FALSE;
1759 *nOnly = TRUE;
1760 *acOnly = FALSE;
1761 } else {
1762 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1763 *gOnly = FALSE;
1764 *nOnly = FALSE;
1765 *acOnly = FALSE;
1766 }
1767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1768
1769 return RETURN_OK;
1770#if 0
1771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1772 char buf[64] = {0};
1773 char config_file[MAX_BUF_SIZE] = {0};
1774
1775 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1776 return RETURN_ERR;
1777
1778 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1779 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1780
1781 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1782 if (strlen(buf) == 0)
1783 {
1784 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1785 return RETURN_ERR;
1786 }
1787 if(strcmp(buf,"g")==0)
1788 {
1789 wifi_dbg_printf("\nG\n");
1790 *gOnly=TRUE;
1791 *nOnly=FALSE;
1792 *acOnly=FALSE;
1793 }
1794 else if(strcmp(buf,"n")==0)
1795 {
1796 wifi_dbg_printf("\nN\n");
1797 *gOnly=FALSE;
1798 *nOnly=TRUE;
1799 *acOnly=FALSE;
1800 }
1801 else if(strcmp(buf,"ac")==0)
1802 {
1803 wifi_dbg_printf("\nac\n");
1804 *gOnly=FALSE;
1805 *nOnly=FALSE;
1806 *acOnly=TRUE;
1807 }
1808 /* hostapd-5G.conf has "a" as hw_mode */
1809 else if(strcmp(buf,"a")==0)
1810 {
1811 wifi_dbg_printf("\na\n");
1812 *gOnly=FALSE;
1813 *nOnly=FALSE;
1814 *acOnly=FALSE;
1815 }
1816 else
1817 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1818
1819 //for a,n mode
1820 if(radioIndex == 1)
1821 {
1822 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1823 if(strcmp(buf,"1")==0)
1824 {
1825 strncpy(output_string, "n", 1);
1826 *nOnly=FALSE;
1827 }
1828 }
1829
1830 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1831 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1832 return RETURN_OK;
1833#endif
1834}
1835
developerdb744382022-09-13 15:34:54 +08001836INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1837{
1838 char cmd[128] = {0};
1839 char buf[64] = {0};
1840 char config_file[64] = {0};
1841 wifi_band band;
1842
1843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1844 if(NULL == output_string || NULL == pureMode)
1845 return RETURN_ERR;
1846
1847 // grep all of the ieee80211 protocol config set to 1
1848 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1849 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1850 _syscmd(cmd, buf, sizeof(buf));
1851
1852 band = wifi_index_to_band(radioIndex);
1853 // puremode is a bit map
1854 *pureMode = 0;
1855 if (band == band_2_4) {
1856 strcat(output_string, "b,g");
1857 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1858 if (strstr(buf, "n") != NULL) {
1859 strcat(output_string, ",n");
1860 *pureMode |= WIFI_MODE_N;
1861 }
1862 if (strstr(buf, "ax") != NULL) {
1863 strcat(output_string, ",ax");
1864 *pureMode |= WIFI_MODE_AX;
1865 }
1866 } else if (band == band_5) {
1867 strcat(output_string, "a");
1868 *pureMode |= WIFI_MODE_A;
1869 if (strstr(buf, "n") != NULL) {
1870 strcat(output_string, ",n");
1871 *pureMode |= WIFI_MODE_N;
1872 }
1873 if (strstr(buf, "ac") != NULL) {
1874 strcat(output_string, ",ac");
1875 *pureMode |= WIFI_MODE_AC;
1876 }
1877 if (strstr(buf, "ax") != NULL) {
1878 strcat(output_string, ",ax");
1879 *pureMode |= WIFI_MODE_AX;
1880 }
1881 } else if (band == band_6) {
1882 if (strstr(buf, "ax") != NULL) {
1883 strcat(output_string, "ax");
1884 *pureMode |= WIFI_MODE_AX;
1885 }
1886 }
1887
1888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1889 return RETURN_OK;
1890}
1891
1892// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001893INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1894{
1895 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1896 if (strcmp (channelMode,"11A") == 0)
1897 {
1898 writeBandWidth(radioIndex,"20MHz");
1899 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1900 printf("\nChannel Mode is 802.11a (5GHz)\n");
1901 }
1902 else if (strcmp (channelMode,"11NAHT20") == 0)
1903 {
1904 writeBandWidth(radioIndex,"20MHz");
1905 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1906 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1907 }
1908 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1909 {
1910 writeBandWidth(radioIndex,"40MHz");
1911 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1912 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1913 }
1914 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1915 {
1916 writeBandWidth(radioIndex,"40MHz");
1917 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1918 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1919 }
1920 else if (strcmp (channelMode,"11ACVHT20") == 0)
1921 {
1922 writeBandWidth(radioIndex,"20MHz");
1923 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1924 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1925 }
1926 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1927 {
1928 writeBandWidth(radioIndex,"40MHz");
1929 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1930 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1931 }
1932 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1933 {
1934 writeBandWidth(radioIndex,"40MHz");
1935 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1936 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1937 }
1938 else if (strcmp (channelMode,"11ACVHT80") == 0)
1939 {
1940 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1941 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1942 }
1943 else if (strcmp (channelMode,"11ACVHT160") == 0)
1944 {
1945 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1946 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1947 }
1948 else if (strcmp (channelMode,"11B") == 0)
1949 {
1950 writeBandWidth(radioIndex,"20MHz");
1951 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1952 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1953 }
1954 else if (strcmp (channelMode,"11G") == 0)
1955 {
1956 writeBandWidth(radioIndex,"20MHz");
1957 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1958 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1959 }
1960 else if (strcmp (channelMode,"11NGHT20") == 0)
1961 {
1962 writeBandWidth(radioIndex,"20MHz");
1963 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1964 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1965 }
1966 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1967 {
1968 writeBandWidth(radioIndex,"40MHz");
1969 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1970 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1971 }
1972 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1973 {
1974 writeBandWidth(radioIndex,"40MHz");
1975 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1976 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1977 }
1978 else
1979 {
1980 return RETURN_ERR;
1981 }
1982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1983
1984 return RETURN_OK;
1985}
1986
developerdb744382022-09-13 15:34:54 +08001987// Set the radio operating mode, and pure mode flag.
1988INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1989{
1990 int num_hostapd_support_mode = 3; // n, ac, ax
1991 struct params list[num_hostapd_support_mode];
1992 char config_file[64] = {0};
1993 char bandwidth[16] = {0};
1994 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08001995
developerdb744382022-09-13 15:34:54 +08001996
1997 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1998 // Set radio mode
1999 list[0].name = "ieee80211n";
2000 list[1].name = "ieee80211ac";
2001 list[2].name = "ieee80211ax";
2002 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2003
2004 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002005 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002006 list[0].value = "1";
2007 else
2008 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002009 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002010 list[1].value = "1";
2011 else
2012 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002013 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002014 list[2].value = "1";
2015 else
2016 list[2].value = "0";
2017 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2018
2019 if (channelMode == NULL || strlen(channelMode) == 0)
2020 return RETURN_OK;
2021 // Set bandwidth
2022 if (strstr(channelMode, "40") != NULL)
2023 strcpy(bandwidth, "40MHz");
2024 else if (strstr(channelMode, "80") != NULL)
2025 strcpy(bandwidth, "80MHz");
2026 else if (strstr(channelMode, "160") != NULL)
2027 strcpy(bandwidth, "160MHz");
2028 else // 11A, 11B, 11G....
2029 strcpy(bandwidth, "20MHz");
2030
2031 writeBandWidth(radioIndex, bandwidth);
2032 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2033
2034 wifi_reloadAp(radioIndex);
2035 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2036
2037 return RETURN_OK;
2038}
2039
developer1d12ebf2022-10-04 15:13:38 +08002040INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2041
2042 char config_file[64] = {0};
2043 struct params params = {0};
2044 wifi_band band = band_invalid;
2045
2046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2047
2048 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002049
2050 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002051 return RETURN_ERR;
2052 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2053 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002054 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2055 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002056
2057 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2058 params.name = "hw_mode";
2059 params.value = hw_mode;
2060 wifi_hostapdWrite(config_file, &params, 1);
2061 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2062
2063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2064 return RETURN_OK;
2065}
2066
developere8988ba2022-10-18 17:42:30 +08002067INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2068{
2069 char config_file[64] = {0};
2070 struct params params = {0};
2071 wifi_band band = band_invalid;
2072
2073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2074
2075 band = wifi_index_to_band(radioIndex);
2076
2077 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2078 params.name = "noscan";
2079 params.value = noscan;
2080 wifi_hostapdWrite(config_file, &params, 1);
2081 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2082
2083 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2084 return RETURN_OK;
2085}
2086
developer06a01d92022-09-07 16:32:39 +08002087//Get the list of supported channel. eg: "1-11"
2088//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.
2089INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2090{
developer6318ed52022-09-13 15:17:58 +08002091 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002092 if (NULL == output_string)
2093 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002094 char cmd[256] = {0};
2095 char buf[128] = {0};
2096 BOOL dfs_enable = false;
2097 // Parse possible channel number and separate them with commas.
2098 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer76989232022-10-04 14:13:19 +08002099 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002100 if (dfs_enable)
developer76989232022-10-04 14:13:19 +08002101 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 +08002102 else
developer76989232022-10-04 14:13:19 +08002103 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 +08002104
2105 _syscmd(cmd,buf,sizeof(buf));
2106 strncpy(output_string, buf, sizeof(buf));
2107
2108 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2109 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002110}
2111
2112//Get the list for used channel. eg: "1,6,9,11"
2113//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.
2114INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2115{
developerf5745ee2022-10-05 16:09:53 +08002116 char cmd[128] = {0};
2117 char buf[128] = {0};
2118 char config_file[64] = {0};
2119 int channel = 0;
2120 int freq = 0;
2121 int bandwidth = 0;
2122 int center_freq = 0;
2123 int center_channel = 0;
2124 int channel_delta = 0;
2125 wifi_band band = band_invalid;
2126
2127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2128
developer06a01d92022-09-07 16:32:39 +08002129 if (NULL == output_string)
2130 return RETURN_ERR;
2131
developerf5745ee2022-10-05 16:09:53 +08002132 sprintf(cmd, "iw %s%d info | grep channel | sed -e 's/[^0-9 ]//g'", AP_PREFIX, radioIndex);
2133 _syscmd(cmd, buf, sizeof(buf));
2134 if (strlen(buf) == 0) {
2135 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2136 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002137 }
developerf5745ee2022-10-05 16:09:53 +08002138 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2139
2140 if (bandwidth == 20) {
2141 snprintf(output_string, 256, "%d", channel);
2142 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002143 }
developerf5745ee2022-10-05 16:09:53 +08002144
2145 center_channel = ieee80211_frequency_to_channel(center_freq);
2146
2147 band = wifi_index_to_band(radioIndex);
2148 if (band == band_2_4 && bandwidth == 40) {
2149 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2150 memset(buf, 0, sizeof(buf));
2151 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2152
2153 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2154 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2155 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2156 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2157 } else {
2158 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2159 return RETURN_ERR;
2160 }
2161 } else if (band == band_5 || band == band_6){
2162 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2163 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2164 channel_delta = (bandwidth-20)/10;
2165 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2166 } else
2167 return RETURN_ERR;
2168
2169 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002170 return RETURN_OK;
2171}
2172
2173//Get the running channel number
2174INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2175{
developerda1ed692022-09-13 13:59:20 +08002176#ifdef MTK_IMPL
2177 if(!wifi_getApChannel(radioIndex, output_ulong))
2178 return RETURN_OK;
2179 else
2180 return RETURN_ERR;
2181#else
developer06a01d92022-09-07 16:32:39 +08002182 char cmd[1024] = {0}, buf[5] = {0};
2183
2184 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2185 if (NULL == output_ulong)
2186 return RETURN_ERR;
2187
2188 snprintf(cmd, sizeof(cmd),
2189 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2190 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2191 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2192 _syscmd(cmd, buf, sizeof(buf));
2193
2194 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2195 if (*output_ulong <= 0) {
2196 *output_ulong = 0;
2197 return RETURN_ERR;
2198 }
2199
2200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2201 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002202#endif
developer06a01d92022-09-07 16:32:39 +08002203}
2204
2205
2206INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2207{
2208 char cmd[1024] = {0}, buf[5] = {0};
2209 char interface_name[50] = {0};
2210
2211 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2212 if (NULL == output_ulong)
2213 return RETURN_ERR;
2214
2215 wifi_getApName(apIndex,interface_name);
2216 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2217 _syscmd(cmd,buf,sizeof(buf));
2218 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2219 if (*output_ulong == 0) {
2220 return RETURN_ERR;
2221 }
2222
2223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2224 return RETURN_OK;
2225}
2226
2227//Storing the previous channel value
2228INT wifi_storeprevchanval(INT radioIndex)
2229{
2230 char buf[256] = {0};
2231 char output[4]={'\0'};
2232 char config_file[MAX_BUF_SIZE] = {0};
2233 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2234 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2235 if(radioIndex == 0)
2236 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2237 else if(radioIndex == 1)
2238 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2239 system(buf);
2240 Radio_flag = FALSE;
2241 return RETURN_OK;
2242}
2243
2244//Set the running channel number
2245INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2246{
developer76989232022-10-04 14:13:19 +08002247 // We only write hostapd config here
2248 char str_channel[8]={0};
2249 char *list_channel;
2250 char config_file[128] = {0};
2251 char possible_channels[256] = {0};
2252 int max_radio_num = 0;
2253 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002254
developer76989232022-10-04 14:13:19 +08002255 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002256
developer76989232022-10-04 14:13:19 +08002257 // Check valid
2258 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002259
developer76989232022-10-04 14:13:19 +08002260 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2261 list_channel = strtok(possible_channels, ",");
2262 while(true)
developer06a01d92022-09-07 16:32:39 +08002263 {
developer76989232022-10-04 14:13:19 +08002264 if(list_channel == NULL) { // input not in the list
2265 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2266 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002267 }
developer76989232022-10-04 14:13:19 +08002268 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2269 break;
2270 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002271 }
2272
developer76989232022-10-04 14:13:19 +08002273 list.name = "channel";
2274 list.value = str_channel;
2275 wifi_getMaxRadioNumber(&max_radio_num);
2276 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002277 {
developer76989232022-10-04 14:13:19 +08002278 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2279 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002280 }
2281
developer76989232022-10-04 14:13:19 +08002282 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002283 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002284}
developer06a01d92022-09-07 16:32:39 +08002285
2286INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2287{
developer76989232022-10-04 14:13:19 +08002288 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002289 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002290 char config_file[64];
2291 int max_num_radios = 0;
2292 wifi_band band = band_invalid;
2293
2294 band = wifi_index_to_band(radioIndex);
2295 if (band == band_2_4)
2296 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002297
developer06a01d92022-09-07 16:32:39 +08002298 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002299 list[0].name = "vht_oper_centr_freq_seg0_idx";
2300 list[0].value = str_idx;
2301 list[1].name = "he_oper_centr_freq_seg0_idx";
2302 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002303
developer76989232022-10-04 14:13:19 +08002304 wifi_getMaxRadioNumber(&max_num_radios);
2305 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002306 {
developer76989232022-10-04 14:13:19 +08002307 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2308 if (band == band_6)
2309 wifi_hostapdWrite(config_file, &list[1], 1);
2310 else
2311 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002312 }
2313
2314 return RETURN_OK;
2315}
2316
2317//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2318//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2319INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2320{
2321 //Set to wifi config only. Wait for wifi reset to apply.
2322 char buf[256] = {0};
2323 char str_channel[256] = {0};
2324 int count = 0;
2325 ULONG Value = 0;
2326 FILE *fp = NULL;
2327 if(enable == TRUE)
2328 {
developer06a01d92022-09-07 16:32:39 +08002329 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002330 }
developer5884e982022-10-06 10:52:50 +08002331 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002332}
2333
developer0b246d12022-09-30 15:24:20 +08002334INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2335{
2336 if (output_bool == NULL)
2337 return RETURN_ERR;
2338
2339 *output_bool = TRUE;
2340
2341 return RETURN_OK;
2342}
2343
developer06a01d92022-09-07 16:32:39 +08002344INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2345{
2346 if (NULL == output_bool)
2347 return RETURN_ERR;
2348 *output_bool=FALSE;
2349 return RETURN_OK;
2350}
2351
2352INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2353{
2354 if (NULL == output_bool)
2355 return RETURN_ERR;
2356 *output_bool=FALSE;
2357 return RETURN_OK;
2358}
2359
2360INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2361{
2362 //Set to wifi config only. Wait for wifi reset to apply.
2363 return RETURN_OK;
2364}
2365
2366INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2367{
2368 return RETURN_OK;
2369}
2370
2371INT wifi_factoryResetAP(int apIndex)
2372{
developer838cca92022-10-03 13:19:57 +08002373 char ap_config_file[64] = {0};
2374 char cmd[128] = {0};
2375
developer06a01d92022-09-07 16:32:39 +08002376 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002377
2378 wifi_setApEnable(apIndex, FALSE);
2379 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2380 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2381 wifi_setApEnable(apIndex, TRUE);
2382
developer06a01d92022-09-07 16:32:39 +08002383 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002384
developer06a01d92022-09-07 16:32:39 +08002385 return RETURN_OK;
2386}
2387
2388//To set Band Steering AP group
2389//To-do
2390INT wifi_setBandSteeringApGroup(char *ApGroup)
2391{
2392 return RETURN_OK;
2393}
2394
developer1e5aa162022-09-13 16:06:24 +08002395INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2396{
2397 char config_file[128] = {'\0'};
2398 char buf[128] = {'\0'};
2399
2400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2401 if (dtimInterval == NULL)
2402 return RETURN_ERR;
2403
2404 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2405 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2406
2407 if (strlen(buf) == 0) {
2408 *dtimInterval = 2;
2409 } else {
2410 *dtimInterval = strtoul(buf, NULL, 10);
2411 }
2412
2413 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2414 return RETURN_OK;
2415}
2416
developer06a01d92022-09-07 16:32:39 +08002417INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2418{
developer5f222492022-09-13 15:21:52 +08002419 struct params params={0};
2420 char config_file[MAX_BUF_SIZE] = {'\0'};
2421 char buf[MAX_BUF_SIZE] = {'\0'};
2422
2423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2424 if (dtimInterval < 1 || dtimInterval > 255) {
2425 return RETURN_ERR;
2426 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2427 }
2428
2429 params.name = "dtim_period";
2430 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2431 params.value = buf;
2432
2433 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2434 wifi_hostapdWrite(config_file, &params, 1);
2435 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2436
2437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2438 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002439}
2440
2441//Check if the driver support the Dfs
2442INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2443{
2444 if (NULL == output_bool)
2445 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002446 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002447 return RETURN_OK;
2448}
2449
2450//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.
2451//The value of this parameter is a comma seperated list of channel number
2452INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2453{
2454 if (NULL == output_pool)
2455 return RETURN_ERR;
2456 if (radioIndex==1)
2457 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2458 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2459
2460 return RETURN_OK;
2461}
2462
2463INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2464{
2465 //Set to wifi config. And apply instantly.
2466 return RETURN_OK;
2467}
2468
2469INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2470{
2471 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2472 return RETURN_ERR;
2473 *output_interval_seconds=1800;
2474 *output_dwell_milliseconds=40;
2475
2476 return RETURN_OK;
2477}
2478
2479INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2480{
2481 //Set to wifi config. And apply instantly.
2482 return RETURN_OK;
2483}
2484
developerbfc18512022-10-05 17:54:28 +08002485INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2486{
2487 if (output_bool == NULL)
2488 return RETURN_ERR;
2489 *output_bool = true;
2490 return RETURN_OK;
2491}
2492
2493INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2494{
2495 return RETURN_OK;
2496}
2497
developer06a01d92022-09-07 16:32:39 +08002498//Get the Dfs enable status
2499INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2500{
developer9964b5b2022-09-13 15:59:34 +08002501 char buf[16] = {0};
2502 FILE *f = NULL;
2503 wifi_band band;
2504
2505 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2506
2507 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002508 if (NULL == output_bool)
2509 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002510
2511 band = wifi_index_to_band(radioIndex);
2512 if (band != band_5)
2513 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002514
developer9964b5b2022-09-13 15:59:34 +08002515 f = fopen(DFS_ENABLE_FILE, "r");
2516 if (f != NULL) {
2517 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002518 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002519 *output_bool = FALSE;
2520 fclose(f);
2521 }
2522 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002523 return RETURN_OK;
2524}
2525
2526//Set the Dfs enable status
2527INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2528{
developer9964b5b2022-09-13 15:59:34 +08002529 char config_file[128] = {0};
2530 FILE *f = NULL;
2531 struct params params={0};
2532 wifi_band band;
2533
2534 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2535
2536 band = wifi_index_to_band(radioIndex);
2537 if (band != band_5)
2538 return RETURN_OK;
2539
2540 f = fopen(DFS_ENABLE_FILE, "w");
2541 if (f == NULL)
2542 return RETURN_ERR;
2543 fprintf(f, "%d", enable);
2544 fclose(f);
2545
2546 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002547 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002548 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2549 wifi_hostapdWrite(config_file, &params, 1);
2550 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2551
2552 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2553
developer9964b5b2022-09-13 15:59:34 +08002554 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002555 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002556}
2557
2558//Check if the driver support the AutoChannelRefreshPeriod
2559INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2560{
2561 if (NULL == output_bool)
2562 return RETURN_ERR;
2563 *output_bool=FALSE; //not support
2564
2565 return RETURN_OK;
2566}
2567
2568//Get the ACS refresh period in seconds
2569INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2570{
2571 if (NULL == output_ulong)
2572 return RETURN_ERR;
2573 *output_ulong=300;
2574
2575 return RETURN_OK;
2576}
2577
2578//Set the ACS refresh period in seconds
2579INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2580{
2581 return RETURN_ERR;
2582}
2583
2584//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2585//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.
2586INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2587{
developer70490032022-09-13 15:45:20 +08002588 char cmd[128] = {0}, buf[64] = {0};
2589 char interface_name[64] = {0};
2590 int ret = 0, len=0;
2591 BOOL radio_enable = FALSE;
2592
2593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2594
developer06a01d92022-09-07 16:32:39 +08002595 if (NULL == output_string)
2596 return RETURN_ERR;
2597
developer70490032022-09-13 15:45:20 +08002598 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2599 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002600
developer70490032022-09-13 15:45:20 +08002601 if (radio_enable != TRUE)
2602 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002603
developer70490032022-09-13 15:45:20 +08002604 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002605 ret = _syscmd(cmd, buf, sizeof(buf));
2606 len = strlen(buf);
2607 if((ret != 0) || (len == 0))
2608 {
2609 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2610 return RETURN_ERR;
2611 }
2612
2613 buf[len-1] = '\0';
2614 snprintf(output_string, 64, "%sMHz", buf);
2615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2616
2617#if 0
2618 //TODO: revisit below implementation
2619 char output_buf[8]={0};
2620 char bw_value[10];
2621 char config_file[MAX_BUF_SIZE] = {0};
2622
2623 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2624 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2625 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2626 readBandWidth(radioIndex,bw_value);
2627
2628 if(strstr (output_buf,"0") != NULL )
2629 {
2630 strcpy(output_string,bw_value);
2631 }
2632 else if (strstr (output_buf,"1") != NULL)
2633 {
2634 strcpy(output_string,"80MHz");
2635 }
2636 else if (strstr (output_buf,"2") != NULL)
2637 {
2638 strcpy(output_string,"160MHz");
2639 }
2640 else if (strstr (output_buf,"3") != NULL)
2641 {
2642 strcpy(output_string,"80+80");
2643 }
2644 else
2645 {
2646 strcpy(output_string,"Auto");
2647 }
2648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2649#endif
2650
2651 return RETURN_OK;
2652}
2653
2654//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002655INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002656{
developerf7a466e2022-09-29 11:55:56 +08002657 char config_file[128];
2658 char set_value[16];
2659 struct params params[2];
2660 int max_radio_num = 0;
2661
developer06a01d92022-09-07 16:32:39 +08002662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002663
developerf7a466e2022-09-29 11:55:56 +08002664 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002665 return RETURN_ERR;
2666
developerf7a466e2022-09-29 11:55:56 +08002667 if(strstr(bandwidth,"80+80") != NULL)
2668 strcpy(set_value, "3");
2669 else if(strstr(bandwidth,"160") != NULL)
2670 strcpy(set_value, "2");
2671 else if(strstr(bandwidth,"80") != NULL)
2672 strcpy(set_value, "1");
2673 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2674 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002675 else
2676 {
developerf7a466e2022-09-29 11:55:56 +08002677 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002678 return RETURN_ERR;
2679 }
2680
developerf7a466e2022-09-29 11:55:56 +08002681 params[0].name = "vht_oper_chwidth";
2682 params[0].value = set_value;
2683 params[1].name = "he_oper_chwidth";
2684 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002685
developerf7a466e2022-09-29 11:55:56 +08002686 wifi_getMaxRadioNumber(&max_radio_num);
2687 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002688 {
developerf7a466e2022-09-29 11:55:56 +08002689 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2690 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002691 }
2692
2693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2694 return RETURN_OK;
2695}
2696
2697//Getting current radio extension channel
2698INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2699{
2700 CHAR buf[150] = {0};
2701 CHAR cmd[150] = {0};
2702 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2703 _syscmd(cmd, buf, sizeof(buf));
2704 if(NULL != strstr(buf,"HT40+"))
2705 strcpy(Value,"AboveControlChannel");
2706 else if(NULL != strstr(buf,"HT40-"))
2707 strcpy(Value,"BelowControlChannel");
2708 return RETURN_OK;
2709}
2710
2711//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2712//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.
2713INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2714{
2715 if (NULL == output_string)
2716 return RETURN_ERR;
2717
2718 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2719#if 0
2720 CHAR Value[100] = {0};
2721 if (NULL == output_string)
2722 return RETURN_ERR;
2723 if(radioIndex == 0)
2724 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2725 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2726 {
2727 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2728 if(strcmp(Value,"40MHz") == 0)
2729 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2730 else
2731 strcpy(Value,"Auto");
2732 }
2733 strcpy(output_string,Value);
2734#endif
2735
2736 return RETURN_OK;
2737}
2738
2739//Set the extension channel.
2740INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2741{
2742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2743 struct params params={'\0'};
2744 char config_file[MAX_BUF_SIZE] = {0};
2745 char ext_channel[127]={'\0'};
2746
2747 params.name = "ht_capab";
2748
2749 if(radioIndex == 0)
2750 {
2751 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002752 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002753 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002754 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002755 else
developer3cc0f2e2022-09-15 18:25:39 +08002756 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002757 }
2758 else if(radioIndex == 1)
2759 {
2760 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002761 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002762 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002763 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002764 else
developer3cc0f2e2022-09-15 18:25:39 +08002765 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002766 }
2767
2768 params.value = ext_channel;
2769 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2770 {
2771 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2772 wifi_hostapdWrite(config_file, &params, 1);
2773 }
2774
2775 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2776 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2777 return RETURN_OK;
2778}
2779
2780//Get the guard interval value. eg "400nsec" or "800nsec"
2781//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.
2782INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2783{
developer454b9462022-09-13 15:29:16 +08002784 wifi_guard_interval_t GI;
2785
2786 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2787
2788 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002789 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002790
2791 if (GI == wifi_guard_interval_400)
2792 strcpy(output_string, "400nsec");
2793 else if (GI == wifi_guard_interval_800)
2794 strcpy(output_string, "800nsec");
2795 else if (GI == wifi_guard_interval_1600)
2796 strcpy(output_string, "1600nsec");
2797 else if (GI == wifi_guard_interval_3200)
2798 strcpy(output_string, "3200nsec");
2799 else
2800 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002801
developer454b9462022-09-13 15:29:16 +08002802 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002803 return RETURN_OK;
2804}
2805
2806//Set the guard interval value.
2807INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2808{
developer454b9462022-09-13 15:29:16 +08002809 wifi_guard_interval_t GI;
2810 int ret = 0;
2811
2812 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2813
2814 if (strcmp(string, "400nsec") == 0)
2815 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002816 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002817 GI = wifi_guard_interval_800;
2818 else if (strcmp(string , "1600nsec") == 0)
2819 GI = wifi_guard_interval_1600;
2820 else if (strcmp(string , "3200nsec") == 0)
2821 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002822 else
2823 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002824
2825 ret = wifi_setGuardInterval(radioIndex, GI);
2826
2827 if (ret == RETURN_ERR) {
2828 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2829 return RETURN_ERR;
2830 }
2831
2832 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2833 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002834}
2835
2836//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2837INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2838{
developerf49437e2022-09-29 19:58:21 +08002839 char buf[32]={0};
2840 char mcs_file[64] = {0};
2841 char cmd[64] = {0};
2842 int mode_bitmap = 0;
2843
2844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2845 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002846 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002847 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2848
2849 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2850 _syscmd(cmd, buf, sizeof(buf));
2851 if (strlen(buf) > 0)
2852 *output_int = strtol(buf, NULL, 10);
2853 else {
2854 // output the max MCS for the current radio mode
2855 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2856 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2857 return RETURN_ERR;
2858 }
2859 if (mode_bitmap & WIFI_MODE_AX) {
2860 *output_int = 11;
2861 } else if (mode_bitmap & WIFI_MODE_AC) {
2862 *output_int = 9;
2863 } else if (mode_bitmap & WIFI_MODE_N) {
2864 *output_int = 7;
2865 }
2866 }
2867 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002868
2869 return RETURN_OK;
2870}
2871
2872//Set the Modulation Coding Scheme index
2873INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2874{
developerf49437e2022-09-29 19:58:21 +08002875 // 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).
2876 char config_file[64] = {0};
2877 char set_value[16] = {0};
2878 char mcs_file[32] = {0};
2879 wifi_band band = band_invalid;
2880 struct params set_config = {0};
2881 FILE *f = NULL;
2882
2883 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2884
2885 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2886
2887 if (MCS > 11 || MCS < 0) {
2888 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2889 return RETURN_ERR;
2890 }
2891
2892 if (MCS <= 7)
2893 strcpy(set_value, "0");
2894 else if (MCS <= 9)
2895 strcpy(set_value, "1");
2896 else
2897 strcpy(set_value, "2");
2898
2899 set_config.name = "he_basic_mcs_nss_set";
2900 set_config.value = set_value;
2901
2902 wifi_hostapdWrite(config_file, &set_config, 1);
2903 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2904
2905 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2906 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2907 f = fopen(mcs_file, "w");
2908 if (f == NULL) {
2909 fprintf(stderr, "%s: fopen failed\n", __func__);
2910 return RETURN_ERR;
2911 }
2912 fprintf(f, "%d", MCS);
2913 fclose(f);
2914
2915 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2916 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002917}
2918
2919//Get supported Transmit Power list, eg : "0,25,50,75,100"
2920//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.
2921INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2922{
2923 if (NULL == output_list)
2924 return RETURN_ERR;
2925 snprintf(output_list, 64,"0,25,50,75,100");
2926 return RETURN_OK;
2927}
2928
developera5005b62022-09-13 15:43:35 +08002929//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002930//The transmite power level is in units of full power for this radio.
2931INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2932{
2933 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002934 char buf[16]={0};
2935 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002936
developera5005b62022-09-13 15:43:35 +08002937 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002938 return RETURN_ERR;
2939
developera5005b62022-09-13 15:43:35 +08002940 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 +08002941 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002942
developera5005b62022-09-13 15:43:35 +08002943 *output_ulong = strtol(buf, NULL, 10);
2944
2945 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002946 return RETURN_OK;
2947}
2948
2949//Set Transmit Power
2950//The transmite power level is in units of full power for this radio.
2951INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2952{
developera5005b62022-09-13 15:43:35 +08002953 char *support;
developer06a01d92022-09-07 16:32:39 +08002954 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002955 char buf[128]={0};
2956 char txpower_str[64] = {0};
2957 int txpower = 0;
2958 int maximum_tx = 0;
2959
2960 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002961
developera5005b62022-09-13 15:43:35 +08002962 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 +08002963 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002964 maximum_tx = strtol(buf, NULL, 10);
2965
2966 // Get the Tx power supported list and check that is the input in the list
2967 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2968 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2969 support = strtok(buf, ",");
2970 while(true)
2971 {
2972 if(support == NULL) { // input not in the list
2973 wifi_dbg_printf("Input value is invalid.\n");
2974 return RETURN_ERR;
2975 }
2976 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2977 break;
2978 }
2979 support = strtok(NULL, ",");
2980 }
2981 txpower = TransmitPower*maximum_tx/100;
2982 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2983 _syscmd(cmd, buf, sizeof(buf));
2984 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002985
2986 return RETURN_OK;
2987}
2988
2989//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2990INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2991{
2992 if (NULL == Supported)
2993 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002994 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002995
2996 return RETURN_OK;
2997}
2998
2999//Get 80211h feature enable
3000INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3001{
developer3885fec2022-09-13 15:13:47 +08003002 char buf[64]={'\0'};
3003 char config_file[64] = {'\0'};
3004
3005 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3006 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003007 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003008
3009 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3010 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003011
developer3885fec2022-09-13 15:13:47 +08003012 if (strncmp(buf, "1", 1) == 0)
3013 *enable = TRUE;
3014 else
3015 *enable = FALSE;
3016
3017 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003018 return RETURN_OK;
3019}
3020
3021//Set 80211h feature enable
3022INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3023{
developer3885fec2022-09-13 15:13:47 +08003024 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3025 struct params params={'\0'};
3026 char config_file[MAX_BUF_SIZE] = {0};
3027
3028 params.name = "ieee80211h";
3029
3030 if (enable) {
3031 params.value = "1";
3032 } else {
3033 params.value = "0";
3034 }
3035
3036 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3037 wifi_hostapdWrite(config_file, &params, 1);
3038
3039 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3040 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3041 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003042}
3043
3044//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.
3045INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3046{
3047 if (NULL == output)
3048 return RETURN_ERR;
3049 *output=100;
3050
3051 return RETURN_OK;
3052}
3053
3054//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.
3055INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3056{
3057 if (NULL == output)
3058 return RETURN_ERR;
3059 *output = -99;
3060
3061 return RETURN_OK;
3062}
3063
3064INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3065{
3066 return RETURN_ERR;
3067}
3068
3069
3070//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3071INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3072{
developer5f222492022-09-13 15:21:52 +08003073 char cmd[MAX_BUF_SIZE]={'\0'};
3074 char buf[MAX_CMD_SIZE]={'\0'};
3075
3076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3077 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003078 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003079
3080 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3081 _syscmd(cmd, buf, sizeof(buf));
3082 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003083
developer5f222492022-09-13 15:21:52 +08003084 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003085 return RETURN_OK;
3086}
3087
3088INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3089{
developer5f222492022-09-13 15:21:52 +08003090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3091 struct params params={'\0'};
3092 char buf[MAX_BUF_SIZE] = {'\0'};
3093 char config_file[MAX_BUF_SIZE] = {'\0'};
3094
3095 params.name = "beacon_int";
3096 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3097 params.value = buf;
3098
3099 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3100 wifi_hostapdWrite(config_file, &params, 1);
3101
3102 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3103 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3104 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003105}
3106
3107//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.
3108INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3109{
developer06a01d92022-09-07 16:32:39 +08003110 //TODO: need to revisit below implementation
3111 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003112 char temp_output[128] = {0};
3113 char temp_TransmitRates[64] = {0};
3114 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003115
3116 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3117 if (NULL == output)
3118 return RETURN_ERR;
3119 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003120 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3121
3122 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3123 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3124 } else {
3125 temp = strtok(temp_TransmitRates," ");
3126 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003127 {
developere9d0abd2022-09-13 15:40:57 +08003128 // Convert 100 kbps to Mbps
3129 temp[strlen(temp)-1]=0;
3130 if((temp[0]=='5') && (temp[1]=='\0'))
3131 {
3132 temp="5.5";
3133 }
3134 strcat(temp_output,temp);
3135 temp = strtok(NULL," ");
3136 if(temp!=NULL)
3137 {
3138 strcat(temp_output,",");
3139 }
developer06a01d92022-09-07 16:32:39 +08003140 }
developere9d0abd2022-09-13 15:40:57 +08003141 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003142 }
developer06a01d92022-09-07 16:32:39 +08003143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003144 return RETURN_OK;
3145}
3146
3147INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3148{
3149 char *temp;
3150 char temp1[128];
3151 char temp_output[128];
3152 char temp_TransmitRates[128];
3153 char set[128];
3154 char sub_set[128];
3155 int set_count=0,subset_count=0;
3156 int set_index=0,subset_index=0;
3157 char *token;
3158 int flag=0, i=0;
3159 struct params params={'\0'};
3160 char config_file[MAX_BUF_SIZE] = {0};
3161
3162 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3163 if(NULL == TransmitRates)
3164 return RETURN_ERR;
3165 strcpy(sub_set,TransmitRates);
3166
3167 //Allow only supported Data transmit rate to be set
3168 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3169 token = strtok(sub_set,",");
3170 while( token != NULL ) /* split the basic rate to be set, by comma */
3171 {
3172 sub_set[subset_count]=atoi(token);
3173 subset_count++;
3174 token=strtok(NULL,",");
3175 }
3176 token=strtok(set,",");
3177 while(token!=NULL) /* split the supported rate by comma */
3178 {
3179 set[set_count]=atoi(token);
3180 set_count++;
3181 token=strtok(NULL,",");
3182 }
3183 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3184 {
3185 for(set_index=0;set_index < set_count;set_index++)
3186 {
3187 flag=0;
3188 if(sub_set[subset_index]==set[set_index])
3189 break;
3190 else
3191 flag=1; /* No match found */
3192 }
3193 if(flag==1)
3194 return RETURN_ERR; //If value not found return Error
3195 }
3196 strcpy(temp_TransmitRates,TransmitRates);
3197
3198 for(i=0;i<strlen(temp_TransmitRates);i++)
3199 {
3200 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3201 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3202 {
3203 continue;
3204 }
3205 else
3206 {
3207 return RETURN_ERR;
3208 }
3209 }
3210 strcpy(temp_output,"");
3211 temp = strtok(temp_TransmitRates,",");
3212 while(temp!=NULL)
3213 {
3214 strcpy(temp1,temp);
3215 if(radioIndex==1)
3216 {
3217 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3218 {
3219 return RETURN_ERR;
3220 }
3221 }
3222
3223 if(strcmp(temp,"5.5")==0)
3224 {
3225 strcpy(temp1,"55");
3226 }
3227 else
3228 {
3229 strcat(temp1,"0");
3230 }
3231 strcat(temp_output,temp1);
3232 temp = strtok(NULL,",");
3233 if(temp!=NULL)
3234 {
3235 strcat(temp_output," ");
3236 }
3237 }
3238 strcpy(TransmitRates,temp_output);
3239
3240 params.name= "basic_rates";
3241 params.value =TransmitRates;
3242
3243 wifi_dbg_printf("\n%s:",__func__);
3244 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3245 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3246 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3247 wifi_hostapdWrite(config_file,&params,1);
3248 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3249 return RETURN_OK;
3250}
3251
3252//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3253INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3254{
3255 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3256 FILE *fp = NULL;
3257 char path[256] = {0}, output_string[256] = {0};
3258 int count = 0;
3259 char *interface = NULL;
3260
3261 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3262 if (fp == NULL)
3263 {
3264 printf("Failed to run command in Function %s\n", __FUNCTION__);
3265 return RETURN_ERR;
3266 }
3267 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3268 {
3269 interface = strchr(path, '=');
3270
3271 if (interface != NULL)
3272 {
3273 strcpy(output_string, interface + 1);
3274 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3275 interface_name[count] = output_string[count];
3276
3277 interface_name[count] = '\0';
3278 }
3279 }
3280 pclose(fp);
3281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3282 return RETURN_OK;
3283}
3284
3285INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3286{
3287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3288 output_struct->radio_BytesSent = 0;
3289 output_struct->radio_BytesReceived = 0;
3290 output_struct->radio_PacketsSent = 0;
3291 output_struct->radio_PacketsReceived = 0;
3292 output_struct->radio_ErrorsSent = 0;
3293 output_struct->radio_ErrorsReceived = 0;
3294 output_struct->radio_DiscardPacketsSent = 0;
3295 output_struct->radio_DiscardPacketsReceived = 0;
3296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3297 return RETURN_OK;
3298}
3299
3300
3301INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3302{
3303 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3304 CHAR buf[MAX_CMD_SIZE] = {0};
3305 CHAR Value[MAX_BUF_SIZE] = {0};
3306 FILE *fp = NULL;
3307
3308 if (ifname == NULL || strlen(ifname) <= 1)
3309 return RETURN_OK;
3310
3311 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3312 system(buf);
3313
3314 fp = fopen("/tmp/Radio_Stats.txt", "r");
3315 if(fp == NULL)
3316 {
3317 printf("/tmp/Radio_Stats.txt not exists \n");
3318 return RETURN_ERR;
3319 }
3320 fclose(fp);
3321
3322 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3323 File_Reading(buf, Value);
3324 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3325
3326 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3327 File_Reading(buf, Value);
3328 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3329
3330 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3331 File_Reading(buf, Value);
3332 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3333
3334 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3335 File_Reading(buf, Value);
3336 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3337
3338 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3339 File_Reading(buf, Value);
3340 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3341
3342 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3343 File_Reading(buf, Value);
3344 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3345
3346 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3347 File_Reading(buf, Value);
3348 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3349
3350 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3351 File_Reading(buf, Value);
3352 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3353
3354 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3355 return RETURN_OK;
3356}
3357
3358INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3359{
3360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3361 CHAR buf[MAX_CMD_SIZE] = {0};
3362 FILE *fp = NULL;
3363 INT count = 0;
3364
3365 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3366 {
3367 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3368 File_Reading(buf, status);
3369 }
3370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3371 return RETURN_OK;
3372}
3373
3374//Get detail radio traffic static info
3375INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3376{
3377
3378#if 0
3379 //ifconfig radio_x
3380 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3381 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3382 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3383 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3384
3385 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3386 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3387 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.
3388 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.
3389
3390 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3391 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].
3392 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3393 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.
3394 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
3395 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
3396 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
3397 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
3398 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
3399
3400 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
3401 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
3402 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
3403 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.
3404
3405 return RETURN_OK;
3406#endif
3407
developera91d99f2022-09-29 15:59:10 +08003408 CHAR interface_name[64] = {0};
3409 CHAR config_path[64] = {0};
3410 BOOL iface_status = FALSE;
3411 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003412
3413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3414 if (NULL == output_struct)
3415 return RETURN_ERR;
3416
developera91d99f2022-09-29 15:59:10 +08003417 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3418 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003419
developera91d99f2022-09-29 15:59:10 +08003420 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003421
developera91d99f2022-09-29 15:59:10 +08003422 if (iface_status == TRUE)
3423 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3424 else
3425 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003426
developera91d99f2022-09-29 15:59:10 +08003427 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3428 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3429 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3430 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3431 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3432 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3433 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3434 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003435
3436 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3437 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].
3438 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3439 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.
3440 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
3441 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
3442 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
3443 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
3444 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
3445
3446 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
3447 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
3448 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
3449 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.
3450
3451 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3452
3453 return RETURN_OK;
3454}
3455
3456//Set radio traffic static Measureing rules
3457INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3458{
3459 //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
3460 // Else, save the MeasuringRate and MeasuringInterval for future usage
3461
3462 return RETURN_OK;
3463}
3464
3465//To start or stop RadioTrafficStats
3466INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3467{
3468 //zqiu: If the RadioTrafficStats process running
3469 // if(enable)
3470 // return RETURN_OK.
3471 // else
3472 // Stop RadioTrafficStats process
3473 // Else
3474 // if(enable)
3475 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3476 // else
3477 // return RETURN_OK.
3478
3479 return RETURN_OK;
3480}
3481
3482//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
3483INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3484{
3485 //zqiu: Please ignor signalIndex.
3486 if (NULL == SignalLevel)
3487 return RETURN_ERR;
3488 *SignalLevel=(radioIndex==0)?-19:-19;
3489
3490 return RETURN_OK;
3491}
3492
3493//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3494INT wifi_applyRadioSettings(INT radioIndex)
3495{
3496 return RETURN_OK;
3497}
3498
3499//Get the radio index assocated with this SSID entry
3500INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3501{
3502 if (NULL == radioIndex)
3503 return RETURN_ERR;
3504 *radioIndex=ssidIndex%2;
3505
3506 return RETURN_OK;
3507}
3508
3509//Device.WiFi.SSID.{i}.Enable
3510//Get SSID enable configuration parameters (not the SSID enable status)
3511INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3512{
3513 if (NULL == output_bool)
3514 return RETURN_ERR;
3515
3516 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3517 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3518 return wifi_getApEnable(ssidIndex, output_bool);
3519}
3520
3521//Device.WiFi.SSID.{i}.Enable
3522//Set SSID enable configuration parameters
3523INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3524{
3525 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3526 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3527 return wifi_setApEnable(ssidIndex, enable);
3528}
3529
3530//Device.WiFi.SSID.{i}.Status
3531//Get the SSID enable status
3532INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3533{
3534 char cmd[MAX_CMD_SIZE]={0};
3535 char buf[MAX_BUF_SIZE]={0};
3536 BOOL output_bool;
3537
3538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3539 if (NULL == output_string)
3540 return RETURN_ERR;
3541 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3542 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3543
3544 wifi_getApEnable(ssidIndex,&output_bool);
3545 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3546
3547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3548 return RETURN_OK;
3549}
3550
3551// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3552INT wifi_getSSIDName(INT apIndex, CHAR *output)
3553{
3554 char config_file[MAX_BUF_SIZE] = {0};
3555
3556 if (NULL == output)
3557 return RETURN_ERR;
3558
3559 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3560 wifi_hostapdRead(config_file,"ssid",output,32);
3561
3562 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3563 return RETURN_OK;
3564}
3565
3566// Set a max 32 byte string and sets an internal variable to the SSID name
3567INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3568{
3569 char str[MAX_BUF_SIZE]={'\0'};
3570 char cmd[MAX_CMD_SIZE]={'\0'};
3571 struct params params;
3572 char config_file[MAX_BUF_SIZE] = {0};
3573
3574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3575 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3576 return RETURN_ERR;
3577
3578 params.name = "ssid";
3579 params.value = ssid_string;
3580 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3581 wifi_hostapdWrite(config_file, &params, 1);
3582 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3584
3585 return RETURN_OK;
3586}
3587
3588//Get the BSSID
3589INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3590{
3591 char cmd[MAX_CMD_SIZE]="";
3592
3593 if (NULL == output_string)
3594 return RETURN_ERR;
3595
3596 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3597 {
developer1d57d002022-10-12 18:03:15 +08003598 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
developer06a01d92022-09-07 16:32:39 +08003599 _syscmd(cmd, output_string, 64);
3600 return RETURN_OK;
3601 }
3602 strncpy(output_string, "\0", 1);
3603
3604 return RETURN_ERR;
3605}
3606
3607//Get the MAC address associated with this Wifi SSID
3608INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3609{
3610 wifi_getBaseBSSID(ssidIndex,output_string);
3611 return RETURN_OK;
3612}
3613
3614//Get the basic SSID traffic static info
3615//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3616//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3617INT wifi_applySSIDSettings(INT ssidIndex)
3618{
3619 BOOL status = false;
3620 char cmd[MAX_CMD_SIZE] = {0};
3621 char buf[MAX_CMD_SIZE] = {0};
3622 int apIndex, ret;
3623 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3624
3625 wifi_getApEnable(ssidIndex,&status);
3626 // Do not apply when ssid index is disabled
3627 if (status == false)
3628 return RETURN_OK;
3629
3630 /* Doing full remove and add for ssid Index
3631 * Not all hostapd options are supported with reload
3632 * for example macaddr_acl
3633 */
3634 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3635 return RETURN_ERR;
3636
3637 ret = wifi_setApEnable(ssidIndex,true);
3638
3639 /* Workaround for hostapd issue with multiple bss definitions
3640 * when first created interface will be removed
3641 * then all vaps other vaps on same phy are removed
3642 * after calling setApEnable to false readd all enabled vaps */
3643 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3644 apIndex = 2*i+radioIndex;
3645 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3646 _syscmd(cmd, buf, sizeof(buf));
3647 if(*buf == '1')
3648 wifi_setApEnable(apIndex, true);
3649 }
3650
3651 return ret;
3652}
3653
developera3c68b92022-09-13 15:27:29 +08003654struct channels_noise {
3655 int channel;
3656 int noise;
3657};
3658
3659// Return noise array for each channel
3660int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3661{
3662 FILE *f = NULL;
3663 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003664 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003665 size_t len = 0;
3666 ssize_t read = 0;
3667 int tmp = 0, arr_index = -1;
3668
3669 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3670
3671 if ((f = popen(cmd, "r")) == NULL) {
3672 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3673 return RETURN_ERR;
3674 }
developer5550e242022-09-30 09:59:32 +08003675
3676 while(fgets(line, sizeof(line), f) != NULL) {
3677 if(arr_index < channels_num){
3678 sscanf(line, "%d", &tmp);
3679 if (tmp > 0) { // channel frequency, the first line must be frequency
3680 arr_index++;
3681 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3682 } else { // noise
3683 channels_noise_arr[arr_index].noise = tmp;
3684 }
3685 }else{
3686 break;
developera3c68b92022-09-13 15:27:29 +08003687 }
3688 }
developera3c68b92022-09-13 15:27:29 +08003689 pclose(f);
3690 return RETURN_OK;
3691}
3692
developer06a01d92022-09-07 16:32:39 +08003693//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3694//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3695INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3696{
developera3c68b92022-09-13 15:27:29 +08003697 int index = -1;
3698 wifi_neighbor_ap2_t *scan_array = NULL;
3699 char cmd[256]={0};
3700 char buf[128]={0};
3701 char file_name[32] = {0};
3702 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003703 char line[256] = {0};
3704 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003705 int freq=0;
3706 FILE *f = NULL;
3707 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003708 int channels_num = 0;
3709 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003710 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003711 bool filter_enable = false;
3712 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003713
developer615510b2022-09-27 10:14:35 +08003714 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003715
3716 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3717 f = fopen(file_name, "r");
3718 if (f != NULL) {
3719 fgets(filter_SSID, sizeof(file_name), f);
3720 if (strlen(filter_SSID) != 0)
3721 filter_enable = true;
3722 fclose(f);
3723 }
3724
3725 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003726 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003727 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003728
developer5550e242022-09-30 09:59:32 +08003729
developer06a01d92022-09-07 16:32:39 +08003730
developera3c68b92022-09-13 15:27:29 +08003731 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 +08003732 // 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 +08003733 fprintf(stderr, "cmd: %s\n", cmd);
3734 if ((f = popen(cmd, "r")) == NULL) {
3735 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3736 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003737 }
developer5550e242022-09-30 09:59:32 +08003738
3739 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3740 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3741
developer615510b2022-09-27 10:14:35 +08003742 ret = fgets(line, sizeof(line), f);
3743 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003744 if(strstr(line, "BSS") != NULL) { // new neighbor info
3745 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3746 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3747 // 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 +08003748
developera3c68b92022-09-13 15:27:29 +08003749 if (!filter_BSS) {
3750 index++;
3751 wifi_neighbor_ap2_t *tmp;
3752 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3753 if (tmp == NULL) { // no more memory to use
3754 index--;
3755 wifi_dbg_printf("%s: realloc failed\n", __func__);
3756 break;
3757 }
3758 scan_array = tmp;
3759 }
3760 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3761
3762 filter_BSS = false;
3763 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3764 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3765 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3766 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3767 } else if (strstr(line, "freq") != NULL) {
3768 sscanf(line," freq: %d", &freq);
3769 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3770
3771 if (freq >= 2412 && freq <= 2484) {
3772 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3773 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3774 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3775 }
3776 else if (freq >= 5160 && freq <= 5805) {
3777 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3778 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3779 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3780 }
3781
3782 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003783 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003784 for (int i = 0; i < channels_num; i++) {
3785 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3786 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3787 break;
3788 }
3789 }
3790 }
3791 } else if (strstr(line, "beacon interval") != NULL) {
3792 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3793 } else if (strstr(line, "signal") != NULL) {
3794 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3795 } else if (strstr(line,"SSID") != NULL) {
3796 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3797 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3798 filter_BSS = true;
3799 }
3800 } else if (strstr(line, "Supported rates") != NULL) {
3801 char SRate[80] = {0}, *tmp = NULL;
3802 memset(buf, 0, sizeof(buf));
3803 strcpy(SRate, line);
3804 tmp = strtok(SRate, ":");
3805 tmp = strtok(NULL, ":");
3806 strcpy(buf, tmp);
3807 memset(SRate, 0, sizeof(SRate));
3808
3809 tmp = strtok(buf, " \n");
3810 while (tmp != NULL) {
3811 strcat(SRate, tmp);
3812 if (SRate[strlen(SRate) - 1] == '*') {
3813 SRate[strlen(SRate) - 1] = '\0';
3814 }
3815 strcat(SRate, ",");
3816
3817 tmp = strtok(NULL, " \n");
3818 }
3819 SRate[strlen(SRate) - 1] = '\0';
3820 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3821 } else if (strstr(line, "DTIM") != NULL) {
3822 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3823 } else if (strstr(line, "VHT capabilities") != NULL) {
3824 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3825 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3826 } else if (strstr(line, "HT capabilities") != NULL) {
3827 strcat(scan_array[index].ap_SupportedStandards, ",n");
3828 strcpy(scan_array[index].ap_OperatingStandards, "n");
3829 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003830 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003831 sscanf(line," * channel width: %d", &vht_channel_width);
3832 if(vht_channel_width == 1) {
3833 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3834 } else {
3835 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3836 }
3837 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3838 continue;
3839 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003840 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003841 sscanf(line," * secondary channel offset: %s", &buf);
3842 if (!strcmp(buf, "above")) {
3843 //40Mhz +
3844 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3845 }
3846 else if (!strcmp(buf, "below")) {
3847 //40Mhz -
3848 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3849 } else {
3850 //20Mhz
3851 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3852 }
3853 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3854 continue;
3855 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003856 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3857 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3858 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003859 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3860 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003861 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003862 else
developer615510b2022-09-27 10:14:35 +08003863 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003864 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003865 if (strstr(line, "HE80/5GHz") != NULL) {
3866 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3867 ret = fgets(line, sizeof(line), f);
3868 } else
3869 continue;
developera3c68b92022-09-13 15:27:29 +08003870 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003871 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003872 }
developer615510b2022-09-27 10:14:35 +08003873 continue;
developera3c68b92022-09-13 15:27:29 +08003874 } else if (strstr(line, "WPA") != NULL) {
3875 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3876 } else if (strstr(line, "RSN") != NULL) {
3877 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3878 } else if (strstr(line, "Group cipher") != NULL) {
3879 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3880 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3881 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3882 }
3883 }
developer615510b2022-09-27 10:14:35 +08003884 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003885 }
3886
3887 if (!filter_BSS) {
3888 *output_array_size = index + 1;
3889 } else {
3890 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3891 *output_array_size = index;
3892 }
3893 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003894 pclose(f);
developer5550e242022-09-30 09:59:32 +08003895 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003896 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003897 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003898}
3899
3900//>> Deprecated: used for old RDKB code.
3901INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3902{
3903 INT status = RETURN_ERR;
3904
3905 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3906 output_struct->wifi_PLCPErrorCount = 0;
3907 output_struct->wifi_FCSErrorCount = 0;
3908 output_struct->wifi_InvalidMACCount = 0;
3909 output_struct->wifi_PacketsOtherReceived = 0;
3910 output_struct->wifi_Noise = 0;
3911 status = RETURN_OK;
3912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3913 return status;
3914}
3915
3916INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3917{
3918 char cmd[128];
3919 char buf[1280];
3920 char *pos = NULL;
3921
3922 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3923 if (NULL == output_struct)
3924 return RETURN_ERR;
3925
3926 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3927
3928 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3929 _syscmd(cmd, buf, sizeof(buf));
3930
3931 pos = buf;
3932 if ((pos = strstr(pos, "RX packets:")) == NULL)
3933 return RETURN_ERR;
3934 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3935
3936 if ((pos = strstr(pos, "TX packets:")) == NULL)
3937 return RETURN_ERR;
3938 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3939
3940 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3941 return RETURN_ERR;
3942 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3943
3944 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3945 return RETURN_ERR;
3946 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3947
3948 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3949 _syscmd(cmd, buf, sizeof(buf));
3950 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3951
3952#if 0
3953 //TODO: need to revisit below implementation
3954 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3955 char interface_name[MAX_BUF_SIZE] = {0};
3956 char interface_status[MAX_BUF_SIZE] = {0};
3957 char Value[MAX_BUF_SIZE] = {0};
3958 char buf[MAX_CMD_SIZE] = {0};
3959 char cmd[MAX_CMD_SIZE] = {0};
3960 FILE *fp = NULL;
3961
3962 if (NULL == output_struct) {
3963 return RETURN_ERR;
3964 }
3965
3966 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3967
3968 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3969 {
3970 if(apIndex == 0) //private_wifi for 2.4G
3971 {
3972 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3973 }
3974 else if(apIndex == 1) //private_wifi for 5G
3975 {
3976 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3977 }
3978 else if(apIndex == 4) //public_wifi for 2.4G
3979 {
3980 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3981 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3982 {
3983 return RETURN_ERR;
3984 }
3985 if(buf[0] == '#')//tp-link
3986 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3987 else//tenda
3988 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3989 }
3990 else if(apIndex == 5) //public_wifi for 5G
3991 {
3992 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3993 }
3994
3995 GetIfacestatus(interface_name, interface_status);
3996
3997 if(0 != strcmp(interface_status, "1"))
3998 return RETURN_ERR;
3999
4000 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4001 system(cmd);
4002
4003 fp = fopen("/tmp/SSID_Stats.txt", "r");
4004 if(fp == NULL)
4005 {
4006 printf("/tmp/SSID_Stats.txt not exists \n");
4007 return RETURN_ERR;
4008 }
4009 fclose(fp);
4010
4011 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4012 File_Reading(buf, Value);
4013 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4014
4015 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4016 File_Reading(buf, Value);
4017 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4018
4019 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4020 File_Reading(buf, Value);
4021 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4022
4023 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4024 File_Reading(buf, Value);
4025 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4026
4027 /* There is no specific parameter from caller to associate the value wifi_Associations */
4028 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4029 //_syscmd(cmd, buf, sizeof(buf));
4030 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4031 }
4032#endif
4033 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4034 return RETURN_OK;
4035}
4036
4037INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4038{
4039 char interface_name[MAX_BUF_SIZE] = {0};
4040 char interface_status[MAX_BUF_SIZE] = {0};
4041 char Value[MAX_BUF_SIZE] = {0};
4042 char buf[MAX_CMD_SIZE] = {0};
4043 char cmd[MAX_CMD_SIZE] = {0};
4044 FILE *fp = NULL;
4045
4046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4047 if (NULL == output_struct)
4048 return RETURN_ERR;
4049
4050 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4051
4052 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4053 {
4054 if(apIndex == 0) //private_wifi for 2.4G
4055 {
4056 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4057 }
4058 else if(apIndex == 1) //private_wifi for 5G
4059 {
4060 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4061 }
4062 else if(apIndex == 4) //public_wifi for 2.4G
4063 {
4064 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4065 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4066 {
4067 return RETURN_ERR;
4068 }
4069 if(buf[0] == '#')
4070 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4071 else
4072 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4073 }
4074 else if(apIndex == 5) //public_wifi for 5G
4075 {
4076 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4077 }
4078
4079 GetIfacestatus(interface_name, interface_status);
4080
4081 if(0 != strcmp(interface_status, "1"))
4082 return RETURN_ERR;
4083
4084 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4085 system(cmd);
4086
4087 fp = fopen("/tmp/SSID_Stats.txt", "r");
4088 if(fp == NULL)
4089 {
4090 printf("/tmp/SSID_Stats.txt not exists \n");
4091 return RETURN_ERR;
4092 }
4093 fclose(fp);
4094
4095 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4096 File_Reading(buf, Value);
4097 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4098
4099 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4100 File_Reading(buf, Value);
4101 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4102
4103 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4104 File_Reading(buf, Value);
4105 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4106
4107 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4108 File_Reading(buf, Value);
4109 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4110 }
4111
4112 output_struct->wifi_UnicastPacketsSent = 0;
4113 output_struct->wifi_UnicastPacketsReceived = 0;
4114 output_struct->wifi_MulticastPacketsSent = 0;
4115 output_struct->wifi_MulticastPacketsReceived = 0;
4116 output_struct->wifi_BroadcastPacketsSent = 0;
4117 output_struct->wifi_BroadcastPacketsRecevied = 0;
4118 output_struct->wifi_UnknownPacketsReceived = 0;
4119
4120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4121 return RETURN_OK;
4122}
4123
4124INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4125{
4126 INT status = RETURN_ERR;
4127
4128 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4129 //Below values should get updated from hal
4130 output_struct->wifi_RetransCount=0;
4131 output_struct->wifi_FailedRetransCount=0;
4132 output_struct->wifi_RetryCount=0;
4133 output_struct->wifi_MultipleRetryCount=0;
4134 output_struct->wifi_ACKFailureCount=0;
4135 output_struct->wifi_AggregatedPacketCount=0;
4136
4137 status = RETURN_OK;
4138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4139
4140 return status;
4141}
4142
4143INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4144{
4145 INT status = RETURN_ERR;
4146 UINT index;
4147 wifi_neighbor_ap_t *pt=NULL;
4148
4149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4150 *output_array_size=2;
4151 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4152 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4153 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4154 strcpy(pt->ap_Radio,"");
4155 strcpy(pt->ap_SSID,"");
4156 strcpy(pt->ap_BSSID,"");
4157 strcpy(pt->ap_Mode,"");
4158 pt->ap_Channel=1;
4159 pt->ap_SignalStrength=0;
4160 strcpy(pt->ap_SecurityModeEnabled,"");
4161 strcpy(pt->ap_EncryptionMode,"");
4162 strcpy(pt->ap_OperatingFrequencyBand,"");
4163 strcpy(pt->ap_SupportedStandards,"");
4164 strcpy(pt->ap_OperatingStandards,"");
4165 strcpy(pt->ap_OperatingChannelBandwidth,"");
4166 pt->ap_BeaconPeriod=1;
4167 pt->ap_Noise=0;
4168 strcpy(pt->ap_BasicDataTransferRates,"");
4169 strcpy(pt->ap_SupportedDataTransferRates,"");
4170 pt->ap_DTIMPeriod=1;
4171 pt->ap_ChannelUtilization = 1;
4172 }
4173
4174 status = RETURN_OK;
4175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4176
4177 return status;
4178}
4179
4180//----------------- AP HAL -------------------------------
4181
4182//>> Deprecated: used for old RDKB code.
4183INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4184{
4185 if (NULL == output_ulong || NULL == output_struct)
4186 return RETURN_ERR;
4187 *output_ulong = 0;
4188 *output_struct = NULL;
4189 return RETURN_OK;
4190}
4191
4192#ifdef HAL_NETLINK_IMPL
4193static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4194 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4195 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4196 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4197 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4198 char mac_addr[20];
4199 static int count=0;
4200 int rate=0;
4201
4202 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4203
4204 nla_parse(tb,
4205 NL80211_ATTR_MAX,
4206 genlmsg_attrdata(gnlh, 0),
4207 genlmsg_attrlen(gnlh, 0),
4208 NULL);
4209
4210 if(!tb[NL80211_ATTR_STA_INFO]) {
4211 fprintf(stderr, "sta stats missing!\n");
4212 return NL_SKIP;
4213 }
4214
4215
4216 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4217 fprintf(stderr, "failed to parse nested attributes!\n");
4218 return NL_SKIP;
4219 }
4220
4221 //devIndex starts from 1
4222 if( ++count == out->wifi_devIndex )
4223 {
4224 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4225 //Getting the mac addrress
4226 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4227
4228 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4229 fprintf(stderr, "failed to parse nested rate attributes!");
4230 return NL_SKIP;
4231 }
4232
4233 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4234 if(rinfo[NL80211_RATE_INFO_BITRATE])
4235 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4236 out->wifi_devTxRate = rate/10;
4237 }
4238
4239 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4240 fprintf(stderr, "failed to parse nested rate attributes!");
4241 return NL_SKIP;
4242 }
4243
4244 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4245 if(rinfo[NL80211_RATE_INFO_BITRATE])
4246 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4247 out->wifi_devRxRate = rate/10;
4248 }
4249 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4250 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4251
4252 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4253 count = 0; //starts the count for next cycle
4254 return NL_STOP;
4255 }
4256
4257 return NL_SKIP;
4258
4259}
4260#endif
4261
4262INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4263{
4264#ifdef HAL_NETLINK_IMPL
4265 Netlink nl;
4266 char if_name[10];
4267
4268 wifi_device_info_t info;
4269 info.wifi_devIndex = devIndex;
4270
4271 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4272
4273 nl.id = initSock80211(&nl);
4274
4275 if (nl.id < 0) {
4276 fprintf(stderr, "Error initializing netlink \n");
4277 return -1;
4278 }
4279
4280 struct nl_msg* msg = nlmsg_alloc();
4281
4282 if (!msg) {
4283 fprintf(stderr, "Failed to allocate netlink message.\n");
4284 nlfree(&nl);
4285 return -2;
4286 }
4287
4288 genlmsg_put(msg,
4289 NL_AUTO_PORT,
4290 NL_AUTO_SEQ,
4291 nl.id,
4292 0,
4293 NLM_F_DUMP,
4294 NL80211_CMD_GET_STATION,
4295 0);
4296
4297 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4298 nl_send_auto(nl.socket, msg);
4299 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4300 nl_recvmsgs(nl.socket, nl.cb);
4301 nlmsg_free(msg);
4302 nlfree(&nl);
4303
4304 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4305 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4306 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4307 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4308 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4309 return RETURN_OK;
4310#else
4311 //iw utility to retrieve station information
4312#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4313#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4314#define MACFILE "/tmp/wifi_AssoMac.txt"
4315#define TXRATEFILE "/tmp/wifi_txrate.txt"
4316#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4317 FILE *file = NULL;
4318 char if_name[10] = {'\0'};
4319 char pipeCmd[256] = {'\0'};
4320 char line[256];
4321 int count,device = 0;
4322
4323 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4324
4325 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4326 file = popen(pipeCmd, "r");
4327
4328 if(file == NULL)
4329 return RETURN_ERR; //popen failed
4330
4331 fgets(line, sizeof line, file);
4332 device = atoi(line);
4333 pclose(file);
4334
4335 if(device == 0)
4336 return RETURN_ERR; //No devices are connected
4337
4338 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4339 system(pipeCmd);
4340
4341 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4342
4343 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4344
4345 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4346
4347 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4348
4349 //devIndex starts from 1, ++count
4350 if((file = fopen(SIGNALFILE, "r")) != NULL )
4351 {
4352 for(count =0;fgets(line, sizeof line, file) != NULL;)
4353 {
4354 if (++count == devIndex)
4355 {
4356 output_struct->wifi_devSignalStrength = atoi(line);
4357 break;
4358 }
4359 }
4360 fclose(file);
4361 }
4362 else
4363 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4364
4365 if((file = fopen(MACFILE, "r")) != NULL )
4366 {
4367 for(count =0;fgets(line, sizeof line, file) != NULL;)
4368 {
4369 if (++count == devIndex)
4370 {
4371 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]);
4372 break;
4373 }
4374 }
4375 fclose(file);
4376 }
4377 else
4378 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4379
4380 if((file = fopen(TXRATEFILE, "r")) != NULL )
4381 {
4382 for(count =0;fgets(line, sizeof line, file) != NULL;)
4383 {
4384 if (++count == devIndex)
4385 {
4386 output_struct->wifi_devTxRate = atoi(line);
4387 break;
4388 }
4389 }
4390 fclose(file);
4391 }
4392 else
4393 fprintf(stderr,"fopen wifi_txrate.txt failed");
4394
4395 if((file = fopen(RXRATEFILE, "r")) != NULL)
4396 {
4397 for(count =0;fgets(line, sizeof line, file) != NULL;)
4398 {
4399 if (++count == devIndex)
4400 {
4401 output_struct->wifi_devRxRate = atoi(line);
4402 break;
4403 }
4404 }
4405 fclose(file);
4406 }
4407 else
4408 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4409
4410 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4411
4412 return RETURN_OK;
4413#endif
4414}
4415
4416INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4417{
4418 if (NULL == device)
4419 return RETURN_ERR;
4420 return RETURN_OK;
4421}
4422//<<
4423
4424
4425//--------------wifi_ap_hal-----------------------------
4426//enables CTS protection for the radio used by this AP
4427INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4428{
4429 //save config and Apply instantly
4430 return RETURN_ERR;
4431}
4432
4433// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4434INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4435{
developer463d39a2022-09-13 15:32:51 +08004436 char config_file[64] = {'\0'};
4437 char buf[64] = {'\0'};
4438 struct params list;
4439
4440 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4441 list.name = "ht_coex";
4442 snprintf(buf, sizeof(buf), "%d", enable);
4443 list.value = buf;
4444
4445 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4446 wifi_hostapdWrite(config_file, &list, 1);
4447 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4448
4449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4450
4451 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004452}
4453
4454//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4455INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4456{
developerea4bcce2022-09-13 15:26:13 +08004457 char config_file[MAX_BUF_SIZE] = {'\0'};
4458 char buf[MAX_BUF_SIZE] = {'\0'};
4459 struct params list;
4460
4461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4462 if (threshold < 256 || threshold > 2346 )
4463 return RETURN_ERR;
4464 list.name = "fragm_threshold";
4465 snprintf(buf, sizeof(buf), "%d", threshold);
4466 list.value = buf;
4467
4468 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4469 wifi_hostapdWrite(config_file, &list, 1);
4470 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004471
developerea4bcce2022-09-13 15:26:13 +08004472 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004473
4474 return RETURN_OK;
4475}
4476
4477// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4478INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4479{
developer51a927d2022-09-13 15:42:22 +08004480 char config_file[64] = {'\0'};
4481 char cmd[128] = {'\0'};
4482 char buf[64] = {'\0'};
4483 char stbc_config[16] = {'\0'};
4484 wifi_band band;
4485 int iterator = 0;
4486 BOOL current_stbc = FALSE;
4487
4488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4489
4490 band = wifi_index_to_band(radioIndex);
4491 if (band == band_invalid)
4492 return RETURN_ERR;
4493
4494 if (band == band_2_4)
4495 iterator = 1;
4496 else if (band == band_5)
4497 iterator = 2;
4498 else
4499 return RETURN_OK;
4500
4501 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4502
4503 // set ht and vht config
4504 for (int i = 0; i < iterator; i++) {
4505 memset(stbc_config, 0, sizeof(stbc_config));
4506 memset(cmd, 0, sizeof(cmd));
4507 memset(buf, 0, sizeof(buf));
4508 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4509 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4510 _syscmd(cmd, buf, sizeof(buf));
4511 if (strlen(buf) != 0)
4512 current_stbc = TRUE;
4513 if (current_stbc == STBC_Enable)
4514 continue;
4515
4516 if (STBC_Enable == TRUE) {
4517 // Append the STBC flags in capab config
4518 memset(cmd, 0, sizeof(cmd));
4519 if (i == 0)
4520 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4521 else
4522 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4523 _syscmd(cmd, buf, sizeof(buf));
4524 } else if (STBC_Enable == FALSE) {
4525 // Remove the STBC flags and remain other flags in capab
4526 memset(cmd, 0, sizeof(cmd));
4527 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4528 _syscmd(cmd, buf, sizeof(buf));
4529 memset(cmd, 0, sizeof(cmd));
4530 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4531 _syscmd(cmd, buf, sizeof(buf));
4532 }
4533 }
4534
4535 wifi_reloadAp(radioIndex);
4536
4537 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4538 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004539}
4540
4541// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4542INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4543{
developer54e6b9f2022-09-28 14:41:20 +08004544 char AMSDU_file_path[64] = {0};
4545
4546 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4547
4548 if(output_bool == NULL)
4549 return RETURN_ERR;
4550
4551 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4552
4553 if (access(AMSDU_file_path, F_OK) == 0)
4554 *output_bool = TRUE;
4555 else
4556 *output_bool = FALSE;
4557
4558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4559 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004560}
4561
4562// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4563INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4564{
developer54e6b9f2022-09-28 14:41:20 +08004565 char cmd[64]={0};
4566 char buf[64]={0};
4567 char AMSDU_file_path[64] = {0};
4568
4569 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4570
4571 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4572 _syscmd(cmd, buf, sizeof(buf));
4573
4574 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4575 memset(cmd, 0, sizeof(cmd));
4576 if (amsduEnable == TRUE)
4577 sprintf(cmd, "touch %s", AMSDU_file_path);
4578 else
4579 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4580 _syscmd(cmd, buf, sizeof(buf));
4581
4582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4583 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004584}
4585
4586//P2 // outputs the number of Tx streams
4587INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4588{
developer2de97692022-09-26 14:00:03 +08004589 char buf[8] = {0};
4590 char cmd[128] = {0};
4591
4592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4593
4594 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4595 _syscmd(cmd, buf, sizeof(buf));
4596
4597 // if there is no record, output the max number of spatial streams
4598 if (strlen(buf) == 0) {
4599 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4600 _syscmd(cmd, buf, sizeof(buf));
4601 }
4602
4603 *output_int = (INT)strtol(buf, NULL, 10);
4604
4605 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4606
4607 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004608}
4609
4610//P2 // sets the number of Tx streams to an enviornment variable
4611INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4612{
developer2de97692022-09-26 14:00:03 +08004613 char cmd[128] = {0};
4614 char buf[128] = {0};
4615 char chain_mask_file[128] = {0};
4616 FILE *f = NULL;
4617
4618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4619
4620 if (numStreams == 0) {
4621 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4622 return RETURN_ERR;
4623 }
4624 wifi_setRadioEnable(radioIndex, FALSE);
4625 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4626 _syscmd(cmd, buf, sizeof(buf));
4627
4628 if (strlen(buf) > 0) {
4629 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4630 return RETURN_ERR;
4631 }
4632 wifi_setRadioEnable(radioIndex, TRUE);
4633
4634 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4635 f = fopen(chain_mask_file, "w");
4636 if (f == NULL) {
4637 fprintf(stderr, "%s: fopen failed.\n", __func__);
4638 return RETURN_ERR;
4639 }
4640 fprintf(f, "%d", numStreams);
4641 fclose(f);
4642 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4643 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004644}
4645
4646//P2 // outputs the number of Rx streams
4647INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4648{
developer2de97692022-09-26 14:00:03 +08004649 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4650 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4651 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004652 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004653 }
4654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004655 return RETURN_OK;
4656}
4657
4658//P2 // sets the number of Rx streams to an enviornment variable
4659INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4660{
developer2de97692022-09-26 14:00:03 +08004661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4662 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4663 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4664 return RETURN_ERR;
4665 }
4666 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004667 return RETURN_ERR;
4668}
4669
4670//Get radio RDG enable setting
4671INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4672{
4673 if (NULL == output_bool)
4674 return RETURN_ERR;
4675 *output_bool = TRUE;
4676 return RETURN_OK;
4677}
4678
4679//Get radio RDG enable setting
4680INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4681{
4682 if (NULL == output_bool)
4683 return RETURN_ERR;
4684 *output_bool = TRUE;
4685 return RETURN_OK;
4686}
4687
4688//Set radio RDG enable setting
4689INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4690{
4691 return RETURN_ERR;
4692}
4693
4694//Get radio ADDBA enable setting
4695INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4696{
4697 if (NULL == output_bool)
4698 return RETURN_ERR;
4699 *output_bool = TRUE;
4700 return RETURN_OK;
4701}
4702
4703//Set radio ADDBA enable setting
4704INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4705{
4706 return RETURN_ERR;
4707}
4708
4709//Get radio auto block ack enable setting
4710INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4711{
4712 if (NULL == output_bool)
4713 return RETURN_ERR;
4714 *output_bool = TRUE;
4715 return RETURN_OK;
4716}
4717
4718//Set radio auto block ack enable setting
4719INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4720{
4721 return RETURN_ERR;
4722}
4723
4724//Get radio 11n pure mode enable support
4725INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4726{
4727 if (NULL == output_bool)
4728 return RETURN_ERR;
4729 *output_bool = TRUE;
4730 return RETURN_OK;
4731}
4732
4733//Get radio 11n pure mode enable setting
4734INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4735{
4736 if (NULL == output_bool)
4737 return RETURN_ERR;
4738 *output_bool = TRUE;
4739 return RETURN_OK;
4740}
4741
4742//Set radio 11n pure mode enable setting
4743INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4744{
4745 return RETURN_ERR;
4746}
4747
4748//Get radio IGMP snooping enable setting
4749INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4750{
developer81bf2ed2022-09-13 15:31:14 +08004751 char cmd[128]={0};
4752 char buf[4]={0};
4753 bool bridge = FALSE, mac80211 = FALSE;
4754 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4755
4756 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004757 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004758
4759 *output_bool = FALSE;
4760
4761 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4762 _syscmd(cmd, buf, sizeof(buf));
4763 if (strncmp(buf, "1", 1) == 0)
4764 bridge = TRUE;
4765
4766 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4767 _syscmd(cmd, buf, sizeof(buf));
4768 if (strncmp(buf, "1", 1) == 0)
4769 mac80211 = TRUE;
4770
4771 if (bridge && mac80211)
4772 *output_bool = TRUE;
4773
4774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004775 return RETURN_OK;
4776}
4777
4778//Set radio IGMP snooping enable setting
4779INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4780{
developer81bf2ed2022-09-13 15:31:14 +08004781 char cmd[128]={0};
4782 char buf[4]={0};
4783
4784 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4785
4786 // bridge
4787 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4788 _syscmd(cmd, buf, sizeof(buf));
4789
4790 // mac80211
4791 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4792 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4793 _syscmd(cmd, buf, sizeof(buf));
4794 }
4795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4796 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004797}
4798
4799//Get the Reset count of radio
4800INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4801{
4802 if (NULL == output_int)
4803 return RETURN_ERR;
4804 *output_int = (radioIndex==0)? 1: 3;
4805
4806 return RETURN_OK;
4807}
4808
4809
4810//---------------------------------------------------------------------------------------------------
4811//
4812// Additional Wifi AP level APIs used for Access Point devices
4813//
4814//---------------------------------------------------------------------------------------------------
4815
4816// creates a new ap and pushes these parameters to the hardware
4817INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4818{
4819 char buf[1024];
4820 char cmd[128];
4821
4822 if (NULL == essid)
4823 return RETURN_ERR;
4824
4825 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4826 _syscmd(cmd, buf, sizeof(buf));
4827
4828 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4829 _syscmd(cmd, buf, sizeof(buf));
4830
4831 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4832
4833 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4834 _syscmd(cmd, buf, sizeof(buf));
4835
4836 return RETURN_OK;
4837}
4838
4839// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4840INT wifi_deleteAp(INT apIndex)
4841{
4842 char buf[1024];
4843 char cmd[128];
4844
4845 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4846 _syscmd(cmd, buf, sizeof(buf));
4847
4848 wifi_removeApSecVaribles(apIndex);
4849
4850 return RETURN_OK;
4851}
4852
4853// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4854INT wifi_getApName(INT apIndex, CHAR *output_string)
4855{
4856 if(NULL == output_string)
4857 return RETURN_ERR;
4858
4859 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4860 return RETURN_OK;
4861}
4862
4863// Outputs the index number in that corresponds to the SSID string
4864INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4865{
4866 CHAR *pos = NULL;
4867
4868 *output_int = -1;
4869 pos = strstr(inputSsidString, AP_PREFIX);
4870 if(pos)
4871 {
4872 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4873 return RETURN_OK;
4874 }
4875 return RETURN_ERR;
4876}
4877
4878INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4879{
4880 return wifi_getIndexFromName(inputSsidString, output_int);
4881}
4882
4883// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4884INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4885{
4886 char buf[MAX_BUF_SIZE] = {0};
4887 char cmd[MAX_CMD_SIZE] = {0};
4888 char config_file[MAX_BUF_SIZE] = {0};
4889
4890 if(NULL == output_string)
4891 return RETURN_ERR;
4892
4893 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4894 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4895 if((strcmp(buf,"3")==0))
4896 snprintf(output_string, 32, "WPAand11i");
4897 else if((strcmp(buf,"2")==0))
4898 snprintf(output_string, 32, "11i");
4899 else if((strcmp(buf,"1")==0))
4900 snprintf(output_string, 32, "WPA");
4901 else
4902 snprintf(output_string, 32, "None");
4903
4904 return RETURN_OK;
4905}
4906
4907// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4908INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4909{
4910 char config_file[MAX_BUF_SIZE] = {0};
4911 struct params list;
4912
4913 if (NULL == beaconTypeString)
4914 return RETURN_ERR;
4915 list.name = "wpa";
4916 list.value = "0";
4917
4918 if((strcmp(beaconTypeString,"WPAand11i")==0))
4919 list.value="3";
4920 else if((strcmp(beaconTypeString,"11i")==0))
4921 list.value="2";
4922 else if((strcmp(beaconTypeString,"WPA")==0))
4923 list.value="1";
4924
4925 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4926 wifi_hostapdWrite(config_file, &list, 1);
4927 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4928 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4929 return RETURN_OK;
4930}
4931
4932// sets the beacon interval on the hardware for this AP
4933INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4934{
developer5f222492022-09-13 15:21:52 +08004935 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4936 struct params params={'\0'};
4937 char buf[MAX_BUF_SIZE] = {'\0'};
4938 char config_file[MAX_BUF_SIZE] = {'\0'};
4939
4940 params.name = "beacon_int";
4941 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4942 params.value = buf;
4943
4944 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4945 wifi_hostapdWrite(config_file, &params, 1);
4946
4947 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4948 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4949 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004950}
4951
4952INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4953{
4954 //save config and apply instantly
4955 return RETURN_ERR;
4956}
4957
4958// Get the packet size threshold supported.
4959INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4960{
4961 //save config and apply instantly
4962 if (NULL == output_bool)
4963 return RETURN_ERR;
4964 *output_bool = FALSE;
4965 return RETURN_OK;
4966}
4967
4968// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4969INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4970{
4971 char cmd[128];
4972 char buf[512];
4973
4974 if (threshold > 0)
4975 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4976 else
4977 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4978 _syscmd(cmd, buf, sizeof(buf));
4979
4980 return RETURN_OK;
4981}
4982
4983// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4984INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4985{
4986 if (NULL == output_string)
4987 return RETURN_ERR;
4988 snprintf(output_string, 32, "TKIPandAESEncryption");
4989 return RETURN_OK;
4990
4991}
4992
4993// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4994INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4995{
4996 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4997 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4998
4999 if(NULL == output_string)
5000 return RETURN_ERR;
5001
5002 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5003 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5004
5005 if(strcmp(buf,"0")==0)
5006 {
5007 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5008 snprintf(output_string, 32, "None");
5009 return RETURN_OK;
5010 }
5011 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5012 param_name = "rsn_pairwise";
5013 else if((strcmp(buf,"1")==0))
5014 param_name = "wpa_pairwise";
5015 else
5016 return RETURN_ERR;
5017 memset(output_string,'\0',32);
5018 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5019 wifi_hostapdRead(config_file,param_name,output_string,32);
5020 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5021
5022 if(strcmp(output_string,"TKIP") == 0)
5023 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5024 else if(strcmp(output_string,"CCMP") == 0)
5025 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5026 else if(strcmp(output_string,"TKIP CCMP") == 0)
5027 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5028
5029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5030 return RETURN_OK;
5031}
5032
5033// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5034INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5035{
5036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5037 struct params params={'\0'};
5038 char output_string[32];
5039 char config_file[MAX_BUF_SIZE] = {0};
5040
5041 memset(output_string,'\0',32);
5042 wifi_getApWpaEncryptionMode(apIndex,output_string);
5043
5044 if(strcmp(encMode, "TKIPEncryption") == 0)
5045 params.value = "TKIP";
5046 else if(strcmp(encMode,"AESEncryption") == 0)
5047 params.value = "CCMP";
5048 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5049 params.value = "TKIP CCMP";
5050
5051 if((strcmp(output_string,"WPAand11i")==0))
5052 {
5053 params.name = "wpa_pairwise";
5054 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5055 wifi_hostapdWrite(config_file, &params, 1);
5056 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5057
5058 params.name,"rsn_pairwise";
5059 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5060 wifi_hostapdWrite(config_file, &params, 1);
5061 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5062
5063 return RETURN_OK;
5064 }
5065 else if((strcmp(output_string,"11i")==0))
5066 {
5067 params.name = "rsn_pairwise";
5068 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5069 wifi_hostapdWrite(config_file, &params, 1);
5070 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5071 return RETURN_OK;
5072 }
5073 else if((strcmp(output_string,"WPA")==0))
5074 {
5075 params.name = "wpa_pairwise";
5076 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5077 wifi_hostapdWrite(config_file, &params, 1);
5078 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5079 return RETURN_OK;
5080 }
5081
5082 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5083 return RETURN_OK;
5084}
5085
5086// deletes internal security varable settings for this ap
5087INT wifi_removeApSecVaribles(INT apIndex)
5088{
5089 //TODO: remove the entry in hostapd config file
5090 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5091 //_syscmd(cmd, buf, sizeof(buf));
5092
5093 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5094 //_syscmd(cmd, buf, sizeof(buf));
5095 return RETURN_ERR;
5096}
5097
5098// changes the hardware settings to disable encryption on this ap
5099INT wifi_disableApEncryption(INT apIndex)
5100{
5101 //Apply instantly
5102 return RETURN_ERR;
5103}
5104
5105// set the authorization mode on this ap
5106// mode mapping as: 1: open, 2: shared, 4:auto
5107INT wifi_setApAuthMode(INT apIndex, INT mode)
5108{
developeraf95c502022-09-13 16:18:22 +08005109 struct params params={0};
5110 char config_file[64] = {0};
5111 int ret;
5112
5113 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5114
5115 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5116 params.name = "auth_algs";
5117
5118 if (mode & 1 && mode & 2)
5119 params.value = "3";
5120 else if (mode & 2)
5121 params.value = "2";
5122 else if (mode & 1)
5123 params.value = "1";
5124 else
5125 params.value = "0";
5126
5127 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5128 wifi_hostapdWrite(config_file, &params, 1);
5129 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5131
5132 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005133}
5134
5135// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5136INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5137{
5138 //save to wifi config, and wait for wifi restart to apply
5139 struct params params={'\0'};
5140 char config_file[MAX_BUF_SIZE] = {0};
5141 int ret;
5142
5143 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5144 if(authMode == NULL)
5145 return RETURN_ERR;
5146
5147 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5148 params.name = "wpa_key_mgmt";
5149
5150 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5151 params.value = "WPA-PSK";
5152 else if(strcmp(authMode,"EAPAuthentication") == 0)
5153 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005154 else if (strcmp(authMode, "SAEAuthentication") == 0)
5155 params.value = "SAE";
5156 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5157 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005158 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5159 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005160 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5161 return RETURN_OK; //This is taken careof in beaconType
5162
5163 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5164 ret=wifi_hostapdWrite(config_file,&params,1);
5165 if(!ret)
5166 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5167 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5168
5169 return ret;
5170}
5171
5172// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5173INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5174{
5175 //save to wifi config, and wait for wifi restart to apply
5176 char BeaconType[50] = {0};
5177 char config_file[MAX_BUF_SIZE] = {0};
5178
5179 *authMode = 0;
5180 wifi_getApBeaconType(apIndex,BeaconType);
5181 printf("%s____%s \n",__FUNCTION__,BeaconType);
5182
5183 if(strcmp(BeaconType,"None") == 0)
5184 strcpy(authMode,"None");
5185 else
5186 {
5187 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5188 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5189 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5190 if(strcmp(authMode,"WPA-PSK") == 0)
5191 strcpy(authMode,"SharedAuthentication");
5192 else if(strcmp(authMode,"WPA-EAP") == 0)
5193 strcpy(authMode,"EAPAuthentication");
5194 }
5195
5196 return RETURN_OK;
5197}
5198
5199// Outputs the number of stations associated per AP
5200INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5201{
5202 char cmd[128]={0};
5203 char buf[128]={0};
5204 BOOL status = false;
5205
5206 if(apIndex > MAX_APS)
5207 return RETURN_ERR;
5208
5209 wifi_getApEnable(apIndex,&status);
5210 if (!status)
5211 return RETURN_OK;
5212
5213 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5214 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5215 _syscmd(cmd, buf, sizeof(buf));
5216 sscanf(buf,"%lu", output_ulong);
5217
5218 return RETURN_OK;
5219}
5220
5221// manually removes any active wi-fi association with the device specified on this ap
5222INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5223{
5224 char buf[126]={'\0'};
5225
5226 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5227 system(buf);
5228
5229 return RETURN_OK;
5230}
5231
5232// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5233INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5234{
5235 if(NULL == output_int)
5236 return RETURN_ERR;
5237 *output_int = apIndex%2;
5238 return RETURN_OK;
5239}
5240
5241// sets the radio index for the specific ap
5242INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5243{
5244 //set to config only and wait for wifi reset to apply settings
5245 return RETURN_ERR;
5246}
5247
5248// Get the ACL MAC list per AP
5249INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5250{
5251 char cmd[MAX_CMD_SIZE]={'\0'};
5252 int ret = 0;
5253
5254 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5255 ret = _syscmd(cmd,macArray,buf_size);
5256 if (ret != 0)
5257 return RETURN_ERR;
5258
5259 return RETURN_OK;
5260}
5261
developere6aafda2022-09-13 14:59:28 +08005262INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5263{
5264 char cmd[MAX_CMD_SIZE]={'\0'};
5265 int ret = 0;
5266
5267 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5268 ret = _syscmd(cmd,macArray,buf_size);
5269 if (ret != 0)
5270 return RETURN_ERR;
5271
5272 return RETURN_OK;
5273}
5274
5275
developer06a01d92022-09-07 16:32:39 +08005276// Get the list of stations associated per AP
5277INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5278{
5279 char cmd[128];
5280
5281 if(apIndex > 3) //Currently supporting apIndex upto 3
5282 return RETURN_ERR;
5283 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5284 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5285 _syscmd(cmd, macArray, buf_size);
5286
5287 return RETURN_OK;
5288}
5289
5290// adds the mac address to the filter list
5291//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5292INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5293{
5294 char cmd[MAX_CMD_SIZE]={'\0'};
5295 char buf[MAX_BUF_SIZE]={'\0'};
5296
5297#if 0
5298 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5299 if(_syscmd(cmd,buf,sizeof(buf)))
5300 return RETURN_ERR;
5301#endif
5302 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5303 if(_syscmd(cmd,buf,sizeof(buf)))
5304 return RETURN_ERR;
5305
5306 return RETURN_OK;
5307}
5308
5309// deletes the mac address from the filter list
5310//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5311INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5312{
5313 char cmd[MAX_CMD_SIZE]={'\0'};
5314 char buf[MAX_BUF_SIZE]={'\0'};
5315
5316#if 0
5317 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5318 if(_syscmd(cmd,buf,sizeof(buf)))
5319 return RETURN_ERR;
5320
5321#endif
5322 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5323 if(_syscmd(cmd,buf,sizeof(buf)))
5324 return RETURN_ERR;
5325
5326 return RETURN_OK;
5327}
5328
5329// outputs the number of devices in the filter list
5330INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5331{
developere6aafda2022-09-13 14:59:28 +08005332 char cmd[MAX_BUF_SIZE]={0};
5333 char buf[MAX_CMD_SIZE]={0};
5334
5335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5336 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005337 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005338
5339 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5340 _syscmd(cmd, buf, sizeof(buf));
5341
5342 *output_uint = atoi(buf);
5343
5344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5345 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005346}
5347
5348INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5349{
5350 char cmd[128]={'\0'};
5351 char buf[128]={'\0'};
5352
5353 if(strcmp(action,"DENY")==0)
5354 {
5355 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5356 system(buf);
5357 return RETURN_OK;
5358 }
5359
5360 if(strcmp(action,"ALLOW")==0)
5361 {
5362 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5363 system(buf);
5364 return RETURN_OK;
5365 }
5366
5367 return RETURN_ERR;
5368
5369}
5370
5371// enable kick for devices on acl black list
5372INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5373{
5374 char aclArray[512] = {0}, *acl = NULL;
5375 char assocArray[512] = {0}, *asso = NULL;
5376
developere6aafda2022-09-13 14:59:28 +08005377 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005378 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5379
5380 // if there are no devices connected there is nothing to do
5381 if (strlen(assocArray) < 17)
5382 return RETURN_OK;
5383
5384 if (enable == TRUE)
5385 {
5386 //kick off the MAC which is in ACL array (deny list)
5387 acl = strtok(aclArray, "\r\n");
5388 while (acl != NULL) {
5389 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5390 wifi_kickApAssociatedDevice(apIndex, acl);
5391
5392 acl = strtok(NULL, "\r\n");
5393 }
developere6aafda2022-09-13 14:59:28 +08005394 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005395 }
5396 else
5397 {
developere6aafda2022-09-13 14:59:28 +08005398 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005399 }
5400
5401#if 0
5402 //TODO: need to revisit below implementation
5403 char aclArray[512]={0}, *acl=NULL;
5404 char assocArray[512]={0}, *asso=NULL;
5405 char buf[256]={'\0'};
5406 char action[10]={'\0'};
5407 FILE *fr=NULL;
5408 char interface[10]={'\0'};
5409 char config_file[MAX_BUF_SIZE] = {0};
5410
5411 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5412 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5413 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5414 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5415
5416 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5417 system(buf);
5418 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5419 system(buf);
5420 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5421 system(buf);
5422 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5423 system(buf);
5424 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5425 system(buf);
5426
5427 if ( enable == TRUE )
5428 {
5429 int device_count=0;
5430 strcpy(action,"DENY");
5431 //kick off the MAC which is in ACL array (deny list)
5432 acl = strtok (aclArray,",");
5433 while (acl != NULL) {
5434 if(strlen(acl)>=17)
5435 {
5436 apply_rules(apIndex, acl,action,interface);
5437 device_count++;
5438 //Register mac to be blocked ,in syscfg.db persistent storage
5439 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5440 system(buf);
5441 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5442 system(buf);
5443 system("syscfg commit");
5444
5445 wifi_kickApAssociatedDevice(apIndex, acl);
5446 }
5447 acl = strtok (NULL, ",");
5448 }
5449 }
5450 else
5451 {
5452 int device_count=0;
5453 char cmdmac[20]={'\0'};
5454 strcpy(action,"ALLOW");
5455 //kick off the MAC which is not in ACL array (allow list)
5456 acl = strtok (aclArray,",");
5457 while (acl != NULL) {
5458 if(strlen(acl)>=17)
5459 {
5460 apply_rules(apIndex, acl,action,interface);
5461 device_count++;
5462 //Register mac to be Allowed ,in syscfg.db persistent storage
5463 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5464 system(buf);
5465 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5466 system(buf);
5467 sprintf(cmdmac,"%s",acl);
5468 }
5469 acl = strtok (NULL, ",");
5470 }
5471 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5472 system(buf);
5473
5474 //Disconnect the mac which is not in ACL
5475 asso = strtok (assocArray,",");
5476 while (asso != NULL) {
5477 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5478 wifi_kickApAssociatedDevice(apIndex, asso);
5479 asso = strtok (NULL, ",");
5480 }
5481 }
5482#endif
5483 return RETURN_OK;
5484}
5485
5486INT wifi_setPreferPrivateConnection(BOOL enable)
5487{
5488 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5489 char buf[1024] = {0};
5490
5491 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5492 if(enable == TRUE)
5493 {
5494 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5495 sprintf(buf,"ifconfig %s down" ,interface_name);
5496 system(buf);
5497 memset(buf,0,sizeof(buf));
5498 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5499 sprintf(buf,"ifconfig %s down" ,interface_name);
5500 system(buf);
5501 }
5502 else
5503 {
5504 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5505 if(strcmp(ssid_cur_value,"1") == 0)
5506 wifi_RestartPrivateWifi_5G();
5507 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5508 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5509 if(strcmp(ssid_cur_value,"1") == 0)
5510 wifi_RestartHostapd_2G();
5511 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5512 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5513 if(strcmp(ssid_cur_value,"1") == 0)
5514 wifi_RestartHostapd_5G();
5515 }
5516 return RETURN_OK;
5517}
5518
5519// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5520INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5521{
5522 int items = 1;
5523 struct params list[2];
5524 char buf[MAX_BUF_SIZE] = {0};
5525 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005526 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005527
5528 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005529
developer10adcc12022-09-13 14:39:17 +08005530 if (filterMode == 0) {
5531 sprintf(buf, "%d", 0);
5532 list[0].value = buf;
5533
5534 char cmd[128], rtn[128];
5535 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5536 _syscmd(cmd, rtn, sizeof(rtn));
5537 memset(cmd,0,sizeof(cmd));
5538 // Delete deny_mac_file in hostapd configuration
5539 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5540 _syscmd(cmd, rtn, sizeof(rtn));
5541 }
5542 else if (filterMode == 1) {
5543 sprintf(buf, "%d", filterMode);
5544 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005545 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5546 list[1].name = "accept_mac_file";
5547 list[1].value = acl_file;
5548 items = 2;
developer10adcc12022-09-13 14:39:17 +08005549 } else if (filterMode == 2) {
5550 //TODO: deny_mac_file
5551 sprintf(buf, "%d", 0);
5552 list[0].value = buf;
5553 list[1].name = "deny_mac_file";
5554 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5555 list[1].value = deny_file;
5556 items = 2;
5557 } else {
5558 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005559 }
developer10adcc12022-09-13 14:39:17 +08005560
developer06a01d92022-09-07 16:32:39 +08005561 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5562 wifi_hostapdWrite(config_file, list, items);
5563
5564 return RETURN_OK;
5565
5566#if 0
5567 if(apIndex==0 || apIndex==1)
5568 {
5569 //set the filtermode
5570 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5571 system(buf);
5572 system("syscfg commit");
5573
5574 if(filterMode==0)
5575 {
5576 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5577 system(buf);
5578 return RETURN_OK;
5579 }
5580 }
5581 return RETURN_OK;
5582#endif
5583}
5584
5585// 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.
5586INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5587{
5588 return RETURN_ERR;
5589}
5590
5591// gets the vlan ID for this ap from an internal enviornment variable
5592INT wifi_getApVlanID(INT apIndex, INT *output_int)
5593{
5594 if(apIndex=0)
5595 {
5596 *output_int=100;
5597 return RETURN_OK;
5598 }
5599
5600 return RETURN_ERR;
5601}
5602
5603// sets the vlan ID for this ap to an internal enviornment variable
5604INT wifi_setApVlanID(INT apIndex, INT vlanId)
5605{
5606 //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)
5607 return RETURN_ERR;
5608}
5609
5610// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5611INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5612{
5613 snprintf(bridgeName, 32, "brlan0");
5614 snprintf(IP, 32, "10.0.0.1");
5615 snprintf(subnet, 32, "255.255.255.0");
5616
5617 return RETURN_OK;
5618}
5619
5620//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5621INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5622{
5623 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5624 return RETURN_ERR;
5625}
5626
5627// reset the vlan configuration for this ap
5628INT wifi_resetApVlanCfg(INT apIndex)
5629{
developerf5fef612022-09-20 19:38:26 +08005630 char original_config_file[64] = {0};
5631 char current_config_file[64] = {0};
5632 char buf[64] = {0};
5633 char cmd[64] = {0};
5634 char vlan_file[64] = {0};
5635 char vlan_tagged_interface[16] = {0};
5636 char vlan_bridge[16] = {0};
5637 char vlan_naming[16] = {0};
5638 struct params list[4] = {0};
5639 wifi_band band;
5640
5641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5642
5643 band = wifi_index_to_band(apIndex);
5644 if (band == band_2_4)
5645 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5646 else if (band = band_5)
5647 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5648 else if (band = band_6)
5649 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5650
5651 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5652
5653 if (strlen(vlan_file) == 0)
5654 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005655
developerf5fef612022-09-20 19:38:26 +08005656 // The file should exist or this vap would not work.
5657 if (access(vlan_file, F_OK) != 0) {
5658 sprintf(cmd, "touch %s", vlan_file);
5659 _syscmd(cmd, buf, sizeof(buf));
5660 }
5661 list[0].name = "vlan_file";
5662 list[0].value = vlan_file;
5663
5664 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5665 list[1].name = "vlan_tagged_interface";
5666 list[1].value = vlan_tagged_interface;
5667
5668 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5669 list[2].name = "vlan_bridge";
5670 list[2].value = vlan_bridge;
5671
5672 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5673 list[3].name = "vlan_naming";
5674 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005675
developerf5fef612022-09-20 19:38:26 +08005676 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5677 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005678 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005679 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005680
developerf5fef612022-09-20 19:38:26 +08005681 // restart this ap
5682 wifi_setApEnable(apIndex, FALSE);
5683 wifi_setApEnable(apIndex, TRUE);
5684
5685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5686
5687 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005688}
5689
5690// 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.
5691INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5692{
5693 return RETURN_ERR;
5694}
5695
5696// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5697INT wifi_startHostApd()
5698{
5699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5700 system("systemctl start hostapd.service");
5701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5702 return RETURN_OK;
5703 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5704}
5705
5706// stops hostapd
5707INT wifi_stopHostApd()
5708{
5709 char cmd[128] = {0};
5710 char buf[128] = {0};
5711
5712 sprintf(cmd,"systemctl stop hostapd");
5713 _syscmd(cmd, buf, sizeof(buf));
5714
5715 return RETURN_OK;
5716}
5717
5718// restart hostapd dummy function
5719INT wifi_restartHostApd()
5720{
5721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5722 system("systemctl restart hostapd-global");
5723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5724
5725 return RETURN_OK;
5726}
5727
5728static int align_hostapd_config(int index)
5729{
5730 ULONG lval;
5731 wifi_getRadioChannel(index%2, &lval);
5732 wifi_setRadioChannel(index%2, lval);
5733}
5734
5735// sets the AP enable status variable for the specified ap.
5736INT wifi_setApEnable(INT apIndex, BOOL enable)
5737{
5738 char config_file[MAX_BUF_SIZE] = {0};
5739 char cmd[MAX_CMD_SIZE] = {0};
5740 char buf[MAX_BUF_SIZE] = {0};
5741 BOOL status;
5742
5743 wifi_getApEnable(apIndex,&status);
5744 if (enable == status)
5745 return RETURN_OK;
5746
5747 if (enable == TRUE) {
5748 int radioIndex = apIndex % NUMBER_OF_RADIOS;
developer06a01d92022-09-07 16:32:39 +08005749 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5750 //Hostapd will bring up this interface
5751 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5752 _syscmd(cmd, buf, sizeof(buf));
5753 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5754 _syscmd(cmd, buf, sizeof(buf));
5755 }
5756 else {
5757 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5758 _syscmd(cmd, buf, sizeof(buf));
5759 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5760 _syscmd(cmd, buf, sizeof(buf));
5761 }
5762 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5763 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5764 _syscmd(cmd, buf, sizeof(buf));
5765 //Wait for wifi up/down to apply
5766 return RETURN_OK;
5767}
5768
5769// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5770INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5771{
5772 char cmd[MAX_CMD_SIZE] = {'\0'};
5773 char buf[MAX_BUF_SIZE] = {'\0'};
5774
5775 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5776 return RETURN_ERR;
5777
5778 *output_bool = 0;
5779
5780 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5781 {
developer70490032022-09-13 15:45:20 +08005782 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005783 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5784 }
5785
5786 return RETURN_OK;
5787}
5788
5789// Outputs the AP "Enabled" "Disabled" status from driver
5790INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5791{
5792 char cmd[128] = {0};
5793 char buf[128] = {0};
5794 BOOL output_bool;
5795
5796 if ( NULL == output_string)
5797 return RETURN_ERR;
5798 wifi_getApEnable(apIndex,&output_bool);
5799
5800 if(output_bool == 1)
5801 snprintf(output_string, 32, "Up");
5802 else
5803 snprintf(output_string, 32, "Disable");
5804
5805 return RETURN_OK;
5806}
5807
5808//Indicates whether or not beacons include the SSID name.
5809// outputs a 1 if SSID on the AP is enabled, else outputs 0
5810INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5811{
5812 //get the running status
5813 char config_file[MAX_BUF_SIZE] = {0};
5814 char buf[16] = {0};
5815
5816 if (!output)
5817 return RETURN_ERR;
5818
5819 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5820 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005821 // default is enable
5822 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5823 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005824
5825 return RETURN_OK;
5826}
5827
5828// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5829INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5830{
5831 //store the config, apply instantly
5832 char config_file[MAX_BUF_SIZE] = {0};
5833 struct params list;
5834
5835 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5836 list.name = "ignore_broadcast_ssid";
5837 list.value = enable?"0":"1";
5838
5839 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5840 wifi_hostapdWrite(config_file, &list, 1);
5841 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5842 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005843 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005844 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5845
5846 return RETURN_OK;
5847}
5848
5849//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5850INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5851{
5852 //get the running status
5853 if(!output_uint)
5854 return RETURN_ERR;
5855 *output_uint=16;
5856 return RETURN_OK;
5857}
5858
5859INT wifi_setApRetryLimit(INT apIndex, UINT number)
5860{
5861 //apply instantly
5862 return RETURN_ERR;
5863}
5864
5865//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5866INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5867{
5868 if(!output)
5869 return RETURN_ERR;
5870 *output=TRUE;
5871 return RETURN_OK;
5872}
5873
5874//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5875INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5876{
5877 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005878 char cmd[128] = {0};
5879 char buf[128] = {0};
5880 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005881
developer0b246d12022-09-30 15:24:20 +08005882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005883
developer0b246d12022-09-30 15:24:20 +08005884 wifi_getMaxRadioNumber(&max_radio_num);
5885 radioIndex = apIndex % max_radio_num;
5886 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5887 _syscmd(cmd,buf, sizeof(buf));
5888
5889 if (strlen(buf) > 0)
5890 *output = true;
5891
5892 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005893
developer06a01d92022-09-07 16:32:39 +08005894 return RETURN_OK;
5895}
5896
5897//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5898INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5899{
5900 //get the running status from driver
5901 if(!output)
5902 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005903
5904 char config_file[MAX_BUF_SIZE] = {0};
5905 char buf[16] = {0};
5906
5907 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5908 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005909 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08005910 *output = TRUE;
5911 else
5912 *output = FALSE;
5913
developer06a01d92022-09-07 16:32:39 +08005914 return RETURN_OK;
5915}
5916
5917// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5918INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5919{
5920 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005921 char config_file[MAX_BUF_SIZE] = {0};
5922 struct params list;
5923
5924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5925 list.name = "wmm_enabled";
5926 list.value = enable?"1":"0";
5927
5928 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5929 wifi_hostapdWrite(config_file, &list, 1);
5930 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5931 wifi_reloadAp(apIndex);
5932 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5933
5934 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005935}
5936
5937//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.
5938INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5939{
5940 //get the running status from driver
5941 if(!output)
5942 return RETURN_ERR;
5943 *output=TRUE;
5944 return RETURN_OK;
5945}
5946
5947// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5948INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5949{
5950 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005951 char config_file[MAX_BUF_SIZE] = {0};
5952 struct params list;
5953
5954 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5955 list.name = "uapsd_advertisement_enabled";
5956 list.value = enable?"1":"0";
5957
5958 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5959 wifi_hostapdWrite(config_file, &list, 1);
5960 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5961 wifi_reloadAp(apIndex);
5962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5963
5964 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005965}
5966
developer6daeb3f2022-09-30 13:36:39 +08005967// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005968INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5969{
developer6daeb3f2022-09-30 13:36:39 +08005970 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5971 char cmd[128] = {0};
5972 char buf[128] = {0};
5973 char ack_filepath[128] = {0};
5974 uint16_t bitmap = 0;
5975 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5976 FILE *f = NULL;
5977
5978 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5979
5980 // Get current setting
5981 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5982 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5983 _syscmd(cmd, buf, sizeof(buf));
5984 if (strlen(buf) > 0)
5985 bitmap = strtoul(buf, NULL, 10);
5986
5987 bitmap = strtoul(buf, NULL, 10);
5988
5989 if (ackPolicy == TRUE) { // True, unset this class
5990 bitmap &= ~class_map[class];
5991 } else { // False, set this class
5992 bitmap |= class_map[class];
5993 }
5994
5995 f = fopen(ack_filepath, "w");
5996 if (f == NULL) {
5997 fprintf(stderr, "%s: fopen failed\n", __func__);
5998 return RETURN_ERR;
5999 }
6000 fprintf(f, "%hu", bitmap);
6001 fclose(f);
6002
6003 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
6004 _syscmd(cmd, buf, sizeof(buf));
6005
6006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6007 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006008}
6009
6010//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.
6011INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6012{
6013 //get the running status from driver
6014 if(!output_uint)
6015 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006016
6017 char output[16]={'\0'};
6018 char config_file[MAX_BUF_SIZE] = {0};
6019
6020 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6021 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6022 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6023 else {
6024 int device_num = atoi(output);
6025 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6026 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6027 return RETURN_ERR;
6028 }
6029 else {
6030 *output_uint = device_num;
6031 }
6032 }
6033
developer06a01d92022-09-07 16:32:39 +08006034 return RETURN_OK;
6035}
6036
6037INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6038{
6039 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006040 char str[MAX_BUF_SIZE]={'\0'};
6041 char cmd[MAX_CMD_SIZE]={'\0'};
6042 struct params params;
6043 char config_file[MAX_BUF_SIZE] = {0};
6044
6045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6046 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6047 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6048 return RETURN_ERR;
6049 }
6050 sprintf(str, "%d", number);
6051 params.name = "max_num_sta";
6052 params.value = str;
6053
6054 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6055 int ret = wifi_hostapdWrite(config_file, &params, 1);
6056 if (ret) {
6057 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6058 ,__func__, ret);
6059 }
6060
6061 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6062 if (ret) {
6063 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6064 ,__func__, ret);
6065 }
6066 wifi_reloadAp(apIndex);
6067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6068
6069 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006070}
6071
6072//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.
6073INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6074{
6075 //get the current threshold
6076 if(!output_uint)
6077 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006078 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6079 if (*output_uint == 0)
6080 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006081 return RETURN_OK;
6082}
6083
6084INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6085{
6086 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006087 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6088 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006089 return RETURN_ERR;
6090}
6091
6092//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.
6093INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6094{
6095 if(!output_uint)
6096 return RETURN_ERR;
6097 *output_uint = 3;
6098 return RETURN_OK;
6099}
6100
6101//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6102INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6103{
6104 if(!output_uint)
6105 return RETURN_ERR;
6106 *output_uint = 3;
6107 return RETURN_OK;
6108}
6109
6110//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.
6111INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6112{
6113 if(!output_in_seconds)
6114 return RETURN_ERR;
6115 *output_in_seconds = 0;
6116 return RETURN_OK;
6117}
6118
6119//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
6120INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6121{
6122 if(!output || apIndex>=MAX_APS)
6123 return RETURN_ERR;
6124 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006125 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006126 return RETURN_OK;
6127}
6128
6129//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6130INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6131{
developer587c1b62022-09-27 15:58:59 +08006132 char config_file[128] = {0};
6133 char wpa[16] = {0};
6134 char key_mgmt[64] = {0};
6135 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006136 if (!output)
6137 return RETURN_ERR;
6138
6139 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006140 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006141
developer587c1b62022-09-27 15:58:59 +08006142 strcpy(output, "None");//Copying "None" to output string for default case
6143 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006144 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006145 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006146 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006147 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006148 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006149 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006150 snprintf(output, 32, "WPA-WPA2-Personal");
6151
6152 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006153 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006154 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006155 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006156 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006157 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006158 snprintf(output, 32, "WPA-WPA2-Enterprise");
6159 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006160 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006161 snprintf(output, 32, "WPA3-Personal");
6162 else
developer4a359672022-10-13 15:30:46 +08006163 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006164 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6165 snprintf(output, 32, "WPA3-Enterprise");
6166 }
developer06a01d92022-09-07 16:32:39 +08006167
6168 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6169 return RETURN_OK;
6170#if 0
6171 //TODO: need to revisit below implementation
6172 char securityType[32], authMode[32];
6173 int enterpriseMode=0;
6174
6175 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6176 if(!output)
6177 return RETURN_ERR;
6178
6179 wifi_getApBeaconType(apIndex, securityType);
6180 strcpy(output,"None");//By default, copying "None" to output string
6181 if (strncmp(securityType,"None", strlen("None")) == 0)
6182 return RETURN_OK;
6183
6184 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6185 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6186
6187 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6188 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6189 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6190 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6191 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6192 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6193 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6194
6195 return RETURN_OK;
6196#endif
6197}
6198
6199INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6200{
6201 char securityType[32];
6202 char authMode[32];
6203
6204 //store settings and wait for wifi up to apply
6205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6206 if(!encMode)
6207 return RETURN_ERR;
6208
developer06a01d92022-09-07 16:32:39 +08006209 if (strcmp(encMode, "None")==0)
6210 {
6211 strcpy(securityType,"None");
6212 strcpy(authMode,"None");
6213 }
6214 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6215 {
6216 strcpy(securityType,"WPAand11i");
6217 strcpy(authMode,"PSKAuthentication");
6218 }
6219 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6220 {
6221 strcpy(securityType,"WPAand11i");
6222 strcpy(authMode,"EAPAuthentication");
6223 }
6224 else if (strcmp(encMode, "WPA-Personal")==0)
6225 {
6226 strcpy(securityType,"WPA");
6227 strcpy(authMode,"PSKAuthentication");
6228 }
6229 else if (strcmp(encMode, "WPA-Enterprise")==0)
6230 {
6231 strcpy(securityType,"WPA");
6232 strcpy(authMode,"EAPAuthentication");
6233 }
6234 else if (strcmp(encMode, "WPA2-Personal")==0)
6235 {
6236 strcpy(securityType,"11i");
6237 strcpy(authMode,"PSKAuthentication");
6238 }
6239 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6240 {
6241 strcpy(securityType,"11i");
6242 strcpy(authMode,"EAPAuthentication");
6243 }
developer587c1b62022-09-27 15:58:59 +08006244 else if (strcmp(encMode, "WPA3-Personal") == 0)
6245 {
6246 strcpy(securityType,"11i");
6247 strcpy(authMode,"SAEAuthentication");
6248 }
developer4a359672022-10-13 15:30:46 +08006249 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006250 {
6251 strcpy(securityType, "11i");
6252 strcpy(authMode, "PSK-SAEAuthentication");
6253 }
developer587c1b62022-09-27 15:58:59 +08006254 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6255 {
6256 strcpy(securityType,"11i");
6257 strcpy(authMode,"EAP_192-bit_Authentication");
6258 }
developer06a01d92022-09-07 16:32:39 +08006259 else
6260 {
6261 strcpy(securityType,"None");
6262 strcpy(authMode,"None");
6263 }
6264 wifi_setApBeaconType(apIndex, securityType);
6265 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6266 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6267
6268 return RETURN_OK;
6269}
6270
6271
6272//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6273// output_string must be pre-allocated as 64 character string by caller
6274// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6275INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6276{
6277 char buf[16];
6278 char config_file[MAX_BUF_SIZE] = {0};
6279
6280 if(output_string==NULL)
6281 return RETURN_ERR;
6282
6283 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6284 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6285
6286 if(strcmp(buf,"0")==0)
6287 {
6288 printf("wpa_mode is %s ......... \n",buf);
6289 return RETURN_ERR;
6290 }
6291
6292 wifi_dbg_printf("\nFunc=%s\n",__func__);
6293 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6294 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6295 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6296
6297 return RETURN_OK;
6298}
6299
6300// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6301// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6302INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6303{
6304 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6305 struct params params={'\0'};
6306 int ret;
6307 char config_file[MAX_BUF_SIZE] = {0};
6308
6309 if(NULL == preSharedKey)
6310 return RETURN_ERR;
6311
6312 params.name = "wpa_passphrase";
6313
6314 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6315 {
6316 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6317 return RETURN_ERR;
6318 }
6319 params.value = preSharedKey;
6320 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6321 ret = wifi_hostapdWrite(config_file, &params, 1);
6322 if(!ret)
6323 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6324 return ret;
6325 //TODO: call hostapd_cli for dynamic_config_control
6326}
6327
6328//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6329// outputs the passphrase, maximum 63 characters
6330INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6331{
6332 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6333
6334 wifi_dbg_printf("\nFunc=%s\n",__func__);
6335 if (NULL == output_string)
6336 return RETURN_ERR;
6337
6338 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6339 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6340 if(strcmp(buf,"0")==0)
6341 {
6342 printf("wpa_mode is %s ......... \n",buf);
6343 return RETURN_ERR;
6344 }
6345
6346 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6347 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6348
6349 return RETURN_OK;
6350}
6351
6352// sets the passphrase enviornment variable, max 63 characters
6353INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6354{
6355 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6356 struct params params={'\0'};
6357 char config_file[MAX_BUF_SIZE] = {0};
6358 int ret;
6359
6360 if(NULL == passPhrase)
6361 return RETURN_ERR;
6362
6363 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6364 {
6365 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6366 return RETURN_ERR;
6367 }
6368 params.name = "wpa_passphrase";
6369 params.value = passPhrase;
6370 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6371 ret=wifi_hostapdWrite(config_file,&params,1);
6372 if(!ret)
6373 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6374
6375 return ret;
6376}
6377
6378//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.
6379INT wifi_setApSecurityReset(INT apIndex)
6380{
developer8d583982022-09-20 11:28:22 +08006381 char original_config_file[64] = {0};
6382 char current_config_file[64] = {0};
6383 char buf[64] = {0};
6384 char cmd[64] = {0};
6385 char wpa[4] = {0};
6386 char wpa_psk[64] = {0};
6387 char wpa_passphrase[64] = {0};
6388 char wpa_psk_file[128] = {0};
6389 char wpa_key_mgmt[64] = {0};
6390 char wpa_pairwise[32] = {0};
6391 wifi_band band;
6392 struct params list[6];
6393
6394 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6395
6396 band = wifi_index_to_band(apIndex);
6397 if (band == band_2_4)
6398 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6399 else if (band = band_5)
6400 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6401 else if (band = band_6)
6402 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6403 else
6404 return RETURN_ERR;
6405
6406 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6407 list[0].name = "wpa";
6408 list[0].value = wpa;
6409
6410 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6411 list[1].name = "wpa_psk";
6412 list[1].value = wpa_psk;
6413
6414 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6415 list[2].name = "wpa_passphrase";
6416 list[2].value = wpa_passphrase;
6417
6418 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6419
6420 if (strlen(wpa_psk_file) == 0)
6421 strcpy(wpa_psk_file, PSK_FILE);
6422
6423 if (access(wpa_psk_file, F_OK) != 0) {
6424 sprintf(cmd, "touch %s", wpa_psk_file);
6425 _syscmd(cmd, buf, sizeof(buf));
6426 }
6427 list[3].name = "wpa_psk_file";
6428 list[3].value = wpa_psk_file;
6429
6430 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6431 list[4].name = "wpa_key_mgmt";
6432 list[4].value = wpa_key_mgmt;
6433
6434 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6435 list[5].name = "wpa_pairwise";
6436 list[5].value = wpa_pairwise;
6437
6438 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6439 wifi_hostapdWrite(current_config_file, list, 6);
6440
6441 wifi_setApEnable(apIndex, FALSE);
6442 wifi_setApEnable(apIndex, TRUE);
6443
6444 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6445 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006446}
6447
6448//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).
6449INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6450{
developer8f2ddd52022-09-13 15:39:24 +08006451 char config_file[64] = {0};
6452 char buf[64] = {0};
6453 char cmd[256] = {0};
6454
6455 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6456
developer06a01d92022-09-07 16:32:39 +08006457 if(!IP_output || !Port_output || !RadiusSecret_output)
6458 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006459
developer8f2ddd52022-09-13 15:39:24 +08006460 // Read the first matched config
6461 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6462 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6463 _syscmd(cmd, buf, sizeof(buf));
6464 strncpy(IP_output, buf, 64);
6465
6466 memset(buf, 0, sizeof(buf));
6467 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6468 _syscmd(cmd, buf, sizeof(buf));
6469 *Port_output = atoi(buf);
6470
6471 memset(buf, 0, sizeof(buf));
6472 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6473 _syscmd(cmd, buf, sizeof(buf));
6474 strncpy(RadiusSecret_output, buf, 64);
6475
6476 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006477 return RETURN_OK;
6478}
6479
6480INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6481{
developer8f2ddd52022-09-13 15:39:24 +08006482 char config_file[64] = {0};
6483 char port_str[8] = {0};
6484 char cmd[256] = {0};
6485 char buf[128] = {0};
6486
6487 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6488
6489 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6490
6491 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6492 _syscmd(cmd, buf, sizeof(buf));
6493 memset(cmd, 0, sizeof(cmd));
6494
6495 snprintf(port_str, sizeof(port_str), "%d", port);
6496 if (strlen(buf) == 0)
6497 // Append
6498 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6499 "auth_server_addr=%s\\n"
6500 "auth_server_port=%s\\n"
6501 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6502 else {
6503 // Delete the three lines setting after the "# radius 1" comment
6504 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6505 _syscmd(cmd, buf, sizeof(buf));
6506 memset(cmd, 0, sizeof(cmd));
6507 // Use "# radius 1" comment to find the location to insert the radius setting
6508 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6509 "# radius 1\\n"
6510 "auth_server_addr=%s\\n"
6511 "auth_server_port=%s\\n"
6512 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6513 }
6514 if(_syscmd(cmd, buf, sizeof(buf))) {
6515 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6516 return RETURN_ERR;
6517 }
6518
6519 wifi_reloadAp(apIndex);
6520 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6521 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006522}
6523
6524INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6525{
developer8f2ddd52022-09-13 15:39:24 +08006526 char config_file[64] = {0};
6527 char buf[64] = {0};
6528 char cmd[256] = {0};
6529
6530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6531
developer06a01d92022-09-07 16:32:39 +08006532 if(!IP_output || !Port_output || !RadiusSecret_output)
6533 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006534
6535 // Read the second matched config
6536 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6537 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6538 _syscmd(cmd, buf, sizeof(buf));
6539 strncpy(IP_output, buf, 64);
6540
6541 memset(buf, 0, sizeof(buf));
6542 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6543 _syscmd(cmd, buf, sizeof(buf));
6544 *Port_output = atoi(buf);
6545
6546 memset(buf, 0, sizeof(buf));
6547 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6548 _syscmd(cmd, buf, sizeof(buf));
6549 strncpy(RadiusSecret_output, buf, 64);
6550
6551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006552 return RETURN_OK;
6553}
6554
6555INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6556{
developer8f2ddd52022-09-13 15:39:24 +08006557 char config_file[64] = {0};
6558 char port_str[8] = {0};
6559 char cmd[256] = {0};
6560 char buf[128] = {0};
6561
6562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6563
6564 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6565
6566 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6567 _syscmd(cmd, buf, sizeof(buf));
6568 memset(cmd, 0, sizeof(cmd));
6569
6570 snprintf(port_str, sizeof(port_str), "%d", port);
6571 if (strlen(buf) == 0)
6572 // Append
6573 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6574 "auth_server_addr=%s\\n"
6575 "auth_server_port=%s\\n"
6576 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6577 else {
6578 // Delete the three lines setting after the "# radius 2" comment
6579 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6580 _syscmd(cmd, buf, sizeof(buf));
6581 memset(cmd, 0, sizeof(cmd));
6582 // Use "# radius 2" comment to find the location to insert the radius setting
6583 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6584 "# radius 2\\n"
6585 "auth_server_addr=%s\\n"
6586 "auth_server_port=%s\\n"
6587 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6588 }
6589 if(_syscmd(cmd, buf, sizeof(buf))) {
6590 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6591 return RETURN_ERR;
6592 }
6593
6594 wifi_reloadAp(apIndex);
6595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6596 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006597}
6598
6599//RadiusSettings
6600INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6601{
6602 if(!output)
6603 return RETURN_ERR;
6604
6605 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6606 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6607 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6608 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6609 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6610 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.
6611 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6612 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6613 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6614 //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.
6615
6616 return RETURN_OK;
6617}
6618
6619INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6620{
6621 //store the paramters, and apply instantly
6622 return RETURN_ERR;
6623}
6624
6625//Device.WiFi.AccessPoint.{i}.WPS.Enable
6626//Enables or disables WPS functionality for this access point.
6627// outputs the WPS enable state of this ap in output_bool
6628INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6629{
6630 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6631 if(!output_bool || !(apIndex==0 || apIndex==1))
6632 return RETURN_ERR;
6633 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6634 _syscmd(cmd, buf, sizeof(buf));
6635 if(strstr(buf, "configured"))
6636 *output_bool=TRUE;
6637 else
6638 *output_bool=FALSE;
6639
6640 return RETURN_OK;
6641}
6642
6643//Device.WiFi.AccessPoint.{i}.WPS.Enable
6644// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6645INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6646{
6647 char config_file[MAX_BUF_SIZE] = {0};
6648 struct params params;
6649
6650 if(!(apIndex==0 || apIndex==1))
6651 return RETURN_ERR;
6652 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6653 //store the paramters, and wait for wifi up to apply
6654 params.name = "wps_state";
6655 params.value = enable ? "2":"0";
6656
6657 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6658 wifi_hostapdWrite(config_file, &params, 1);
6659 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6660 wifi_reloadAp(apIndex);
6661
6662 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6663 return RETURN_OK;
6664}
6665
6666//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
6667INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6668{
6669 if(!output)
6670 return RETURN_ERR;
6671 snprintf(output, 128, "PushButton,PIN");
6672 return RETURN_OK;
6673}
6674
6675//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6676//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.
6677// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6678INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6679{
6680 if(!output)
6681 return RETURN_ERR;
6682 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6683
6684 return RETURN_OK;
6685}
6686
6687//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6688// 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
6689INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6690{
6691 //apply instantly. No setting need to be stored.
6692 char methods[MAX_BUF_SIZE], *token, *next_token;
6693 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6694 struct params params;
6695
6696 if(!methodString || !(apIndex==0 || apIndex==1))
6697 return RETURN_ERR;
6698 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6699 //store the paramters, and wait for wifi up to apply
6700
6701 snprintf(methods, sizeof(methods), "%s", methodString);
6702 for(token=methods; *token; token=next_token)
6703 {
6704 strtok_r(token, ",", &next_token);
6705 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6706 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6707 else if(*token=='E')
6708 {
6709 if(!strcmp(methods, "Ethernet"))
6710 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6711 else if(!strcmp(methods, "ExternalNFCToken"))
6712 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6713 else
6714 printf("%s: Unknown WpsConfigMethod\n", __func__);
6715 }
6716 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6717 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6718 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6719 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6720 else if(*token=='P' )
6721 {
6722 if(!strcmp(token, "PushButton"))
6723 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6724 else if(!strcmp(token, "PIN"))
6725 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6726 else
6727 printf("%s: Unknown WpsConfigMethod\n", __func__);
6728 }
6729 else
6730 printf("%s: Unknown WpsConfigMethod\n", __func__);
6731 }
6732 params.name = "config_methods";
6733 params.value = config_methods;
6734 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6735 wifi_hostapdWrite(config_file, &params, 1);
6736 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6738
6739 return RETURN_OK;
6740}
6741
6742// outputs the pin value, ulong_pin must be allocated by the caller
6743INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6744{
6745 char buf[MAX_BUF_SIZE] = {0};
6746 char cmd[MAX_CMD_SIZE] = {0};
6747
6748 if(!output_ulong || !(apIndex==0 || apIndex==1))
6749 return RETURN_ERR;
6750 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6751 _syscmd(cmd, buf, sizeof(buf));
6752 if(strlen(buf) > 0)
6753 *output_ulong=strtoul(buf, NULL, 10);
6754
6755 return RETURN_OK;
6756}
6757
6758// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6759INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6760{
6761 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6762 char ap_pin[16] = {0};
6763 char buf[MAX_BUF_SIZE] = {0};
6764 char config_file[MAX_BUF_SIZE] = {0};
6765 ULONG prev_pin = 0;
6766 struct params params;
6767
6768 if(!(apIndex==0 || apIndex==1))
6769 return RETURN_ERR;
6770 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6771 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6772 params.name = "ap_pin";
6773 params.value = ap_pin;
6774 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6775 wifi_hostapdWrite(config_file, &params, 1);
6776 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6777 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6778
6779 return RETURN_OK;
6780}
6781
6782// Output string is either Not configured or Configured, max 32 characters
6783INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6784{
6785 char cmd[MAX_CMD_SIZE];
6786 char buf[MAX_BUF_SIZE]={0};
6787
6788 if(!output_string || !(apIndex==0 || apIndex==1))
6789 return RETURN_ERR;
6790 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6791 snprintf(output_string, 32, "Not configured");
6792 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6793 _syscmd(cmd, buf, sizeof(buf));
6794
developer348e3d92022-09-13 14:48:41 +08006795 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006796 snprintf(output_string, 32, "Configured");
6797 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6798
6799 return RETURN_OK;
6800}
6801
6802// sets the WPS pin for this AP
6803INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6804{
6805 char cmd[MAX_CMD_SIZE];
6806 char buf[MAX_BUF_SIZE]={0};
6807 BOOL enable;
6808
6809 if(!(apIndex==0 || apIndex==1))
6810 return RETURN_ERR;
6811 wifi_getApEnable(apIndex, &enable);
6812 if (!enable)
6813 return RETURN_ERR;
6814 wifi_getApWpsEnable(apIndex, &enable);
6815 if (!enable)
6816 return RETURN_ERR;
6817
6818 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6819 _syscmd(cmd, buf, sizeof(buf));
6820 if((strstr(buf, "OK"))!=NULL)
6821 return RETURN_OK;
6822
6823 return RETURN_ERR;
6824}
6825
6826// This function is called when the WPS push button has been pressed for this AP
6827INT wifi_setApWpsButtonPush(INT apIndex)
6828{
6829 char cmd[MAX_CMD_SIZE];
6830 char buf[MAX_BUF_SIZE]={0};
6831 BOOL enable=FALSE;
6832
6833 if(!(apIndex==0 || apIndex==1))
6834 return RETURN_ERR;
6835 wifi_getApEnable(apIndex, &enable);
6836 if (!enable)
6837 return RETURN_ERR;
6838
6839 wifi_getApWpsEnable(apIndex, &enable);
6840 if (!enable)
6841 return RETURN_ERR;
6842
6843 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6844 _syscmd(cmd, buf, sizeof(buf));
6845
6846 if((strstr(buf, "OK"))!=NULL)
6847 return RETURN_OK;
6848 return RETURN_ERR;
6849}
6850
6851// cancels WPS mode for this AP
6852INT wifi_cancelApWPS(INT apIndex)
6853{
6854 char cmd[MAX_CMD_SIZE];
6855 char buf[MAX_BUF_SIZE]={0};
6856
6857 if(!(apIndex==0 || apIndex==1))
6858 return RETURN_ERR;
6859 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6860 _syscmd(cmd,buf, sizeof(buf));
6861
6862 if((strstr(buf, "OK"))!=NULL)
6863 return RETURN_OK;
6864 return RETURN_ERR;
6865}
6866
6867//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6868//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6869INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6870{
6871 FILE *f;
6872 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6873 char cmd[256], buf[2048];
6874 char *param , *value, *line=NULL;
6875 size_t len = 0;
6876 ssize_t nread;
6877 wifi_associated_dev_t *dev=NULL;
6878
6879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6880 *associated_dev_array = NULL;
6881 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6882 _syscmd(cmd,buf,sizeof(buf));
6883 *output_array_size = atoi(buf);
6884
6885 if (*output_array_size <= 0)
6886 return RETURN_OK;
6887
6888 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6889 *associated_dev_array = dev;
6890 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6891 _syscmd(cmd,buf,sizeof(buf));
6892 f = fopen("/tmp/connected_devices.txt", "r");
6893 if (f==NULL)
6894 {
6895 *output_array_size=0;
6896 return RETURN_ERR;
6897 }
6898 while ((nread = getline(&line, &len, f)) != -1)
6899 {
6900 param = strtok(line,"=");
6901 value = strtok(NULL,"=");
6902
6903 if( strcmp("flags",param) == 0 )
6904 {
6905 value[strlen(value)-1]='\0';
6906 if(strstr (value,"AUTHORIZED") != NULL )
6907 {
6908 dev[auth_temp].cli_AuthenticationState = 1;
6909 dev[auth_temp].cli_Active = 1;
6910 auth_temp++;
6911 read_flag=1;
6912 }
6913 }
6914 if(read_flag==1)
6915 {
6916 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6917 {
6918 value[strlen(value)-1]='\0';
6919 sscanf(value, "%x:%x:%x:%x:%x:%x",
6920 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6921 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6922 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6923 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6924 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6925 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6926 mac_temp++;
6927 read_flag=0;
6928 }
6929 }
6930 }
6931 *output_array_size = auth_temp;
6932 auth_temp=0;
6933 mac_temp=0;
6934 free(line);
6935 fclose(f);
6936 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6937 return RETURN_OK;
6938}
6939
6940#define MACADDRESS_SIZE 6
6941
6942INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6943{
6944 FILE *fp = NULL;
6945 char str[MAX_BUF_SIZE] = {0};
6946 int wificlientindex = 0 ;
6947 int count = 0;
6948 int signalstrength = 0;
6949 int arr[MACADDRESS_SIZE] = {0};
6950 unsigned char mac[MACADDRESS_SIZE] = {0};
6951 UINT wifi_count = 0;
6952 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6953 char pipeCmd[MAX_CMD_SIZE] = {0};
6954
6955 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6956 *output_array_size = 0;
6957 *associated_dev_array = NULL;
6958
6959 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6960 fp = popen(pipeCmd, "r");
6961 if (fp == NULL)
6962 {
6963 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6964 return RETURN_ERR;
6965 }
6966
6967 /* Read the output a line at a time - output it. */
6968 fgets(str, sizeof(str)-1, fp);
6969 wifi_count = (unsigned int) atoi ( str );
6970 *output_array_size = wifi_count;
6971 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6972 pclose(fp);
6973
6974 if(wifi_count == 0)
6975 {
6976 return RETURN_OK;
6977 }
6978 else
6979 {
6980 wifi_associated_dev3_t* temp = NULL;
6981 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6982 if(temp == NULL)
6983 {
6984 printf("Error Statement. Insufficient memory \n");
6985 return RETURN_ERR;
6986 }
6987
6988 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6989 system(pipeCmd);
6990 memset(pipeCmd,0,sizeof(pipeCmd));
6991 if(apIndex == 0)
6992 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6993 else if(apIndex == 1)
6994 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6995 system(pipeCmd);
6996
6997 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6998 if(fp == NULL)
6999 {
7000 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7001 return RETURN_ERR;
7002 }
7003 fclose(fp);
7004
7005 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7006 fp = popen(pipeCmd, "r");
7007 if(fp)
7008 {
7009 for(count =0 ; count < wifi_count; count++)
7010 {
7011 fgets(str, MAX_BUF_SIZE, fp);
7012 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7013 {
7014 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7015 {
7016 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7017
7018 }
7019 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7020 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]);
7021 }
7022 temp[count].cli_AuthenticationState = 1; //TODO
7023 temp[count].cli_Active = 1; //TODO
7024 }
7025 pclose(fp);
7026 }
7027
7028 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7029 fp = popen(pipeCmd, "r");
7030 if(fp)
7031 {
7032 pclose(fp);
7033 }
7034 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7035 if(fp)
7036 {
7037 for(count =0 ; count < wifi_count ;count++)
7038 {
7039 fgets(str, MAX_BUF_SIZE, fp);
7040 signalstrength = atoi(str);
7041 temp[count].cli_SignalStrength = signalstrength;
7042 temp[count].cli_RSSI = signalstrength;
7043 temp[count].cli_SNR = signalstrength + 95;
7044 }
7045 pclose(fp);
7046 }
7047
7048
7049 if((apIndex == 0) || (apIndex == 4))
7050 {
7051 for(count =0 ; count < wifi_count ;count++)
7052 {
7053 strcpy(temp[count].cli_OperatingStandard,"g");
7054 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7055 }
7056
7057 //BytesSent
7058 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7059 fp = popen(pipeCmd, "r");
7060 if(fp)
7061 {
7062 pclose(fp);
7063 }
7064 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7065 if(fp)
7066 {
7067 for (count = 0; count < wifi_count; count++)
7068 {
7069 fgets(str, MAX_BUF_SIZE, fp);
7070 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7071 }
7072 pclose(fp);
7073 }
7074
7075 //BytesReceived
7076 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7077 fp = popen(pipeCmd, "r");
7078 if (fp)
7079 {
7080 pclose(fp);
7081 }
7082 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7083 if (fp)
7084 {
7085 for (count = 0; count < wifi_count; count++)
7086 {
7087 fgets(str, MAX_BUF_SIZE, fp);
7088 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7089 }
7090 pclose(fp);
7091 }
7092
7093 //PacketsSent
7094 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7095 fp = popen(pipeCmd, "r");
7096 if (fp)
7097 {
7098 pclose(fp);
7099 }
7100
7101 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7102 if (fp)
7103 {
7104 for (count = 0; count < wifi_count; count++)
7105 {
7106 fgets(str, MAX_BUF_SIZE, fp);
7107 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7108 }
7109 pclose(fp);
7110 }
7111
7112 //PacketsReceived
7113 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7114 fp = popen(pipeCmd, "r");
7115 if (fp)
7116 {
7117 pclose(fp);
7118 }
7119 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7120 if (fp)
7121 {
7122 for (count = 0; count < wifi_count; count++)
7123 {
7124 fgets(str, MAX_BUF_SIZE, fp);
7125 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7126 }
7127 pclose(fp);
7128 }
7129
7130 //ErrorsSent
7131 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7132 fp = popen(pipeCmd, "r");
7133 if (fp)
7134 {
7135 pclose(fp);
7136 }
7137 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7138 if (fp)
7139 {
7140 for (count = 0; count < wifi_count; count++)
7141 {
7142 fgets(str, MAX_BUF_SIZE, fp);
7143 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7144 }
7145 pclose(fp);
7146 }
7147
7148 //ErrorsSent
7149 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7150 fp = popen(pipeCmd, "r");
7151 if (fp)
7152 {
7153 pclose(fp);
7154 }
7155 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7156 if (fp)
7157 {
7158 for (count = 0; count < wifi_count; count++)
7159 {
7160 fgets(str, MAX_BUF_SIZE, fp);
7161 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7162 }
7163 pclose(fp);
7164 }
7165
7166 //LastDataDownlinkRate
7167 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7168 fp = popen(pipeCmd, "r");
7169 if (fp)
7170 {
7171 pclose(fp);
7172 }
7173 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7174 if (fp)
7175 {
7176 for (count = 0; count < wifi_count; count++)
7177 {
7178 fgets(str, MAX_BUF_SIZE, fp);
7179 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7180 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7181 }
7182 pclose(fp);
7183 }
7184
7185 //LastDataUplinkRate
7186 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7187 fp = popen(pipeCmd, "r");
7188 if (fp)
7189 {
7190 pclose(fp);
7191 }
7192 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7193 if (fp)
7194 {
7195 for (count = 0; count < wifi_count; count++)
7196 {
7197 fgets(str, MAX_BUF_SIZE, fp);
7198 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7199 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7200 }
7201 pclose(fp);
7202 }
7203
7204 }
7205 else if ((apIndex == 1) || (apIndex == 5))
7206 {
7207 for (count = 0; count < wifi_count; count++)
7208 {
7209 strcpy(temp[count].cli_OperatingStandard, "a");
7210 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7211 temp[count].cli_BytesSent = 0;
7212 temp[count].cli_BytesReceived = 0;
7213 temp[count].cli_LastDataUplinkRate = 0;
7214 temp[count].cli_LastDataDownlinkRate = 0;
7215 temp[count].cli_PacketsSent = 0;
7216 temp[count].cli_PacketsReceived = 0;
7217 temp[count].cli_ErrorsSent = 0;
7218 }
7219 }
7220
7221 for (count = 0; count < wifi_count; count++)
7222 {
7223 temp[count].cli_Retransmissions = 0;
7224 temp[count].cli_DataFramesSentAck = 0;
7225 temp[count].cli_DataFramesSentNoAck = 0;
7226 temp[count].cli_MinRSSI = 0;
7227 temp[count].cli_MaxRSSI = 0;
7228 strncpy(temp[count].cli_InterferenceSources, "", 64);
7229 memset(temp[count].cli_IPAddress, 0, 64);
7230 temp[count].cli_RetransCount = 0;
7231 temp[count].cli_FailedRetransCount = 0;
7232 temp[count].cli_RetryCount = 0;
7233 temp[count].cli_MultipleRetryCount = 0;
7234 }
7235 *associated_dev_array = temp;
7236 }
7237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7238 return RETURN_OK;
7239}
7240
7241int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7242{
7243 FILE *fp = NULL;
7244 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7245 char cmd[MAX_CMD_SIZE];
7246 int count = 0;
7247
7248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7249 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7250 fp = popen(cmd,"r");
7251 if(fp == NULL)
7252 {
7253 printf("Failed to run command in Function %s\n",__FUNCTION__);
7254 return 0;
7255 }
7256 if(fgets(path, sizeof(path)-1, fp) != NULL)
7257 {
7258 for(count=0;path[count]!='\n';count++)
7259 status[count]=path[count];
7260 status[count]='\0';
7261 }
7262 strcpy(wifi_status,status);
7263 pclose(fp);
7264 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7265 return RETURN_OK;
7266}
7267
7268/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7269struct hostapd_sta_param {
7270 char key[50];
7271 char value[100];
7272}
7273
7274static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7275 int i = 0;
7276
7277 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7278 if (strncmp(params[i].key,key,50) == 0){
7279 return &params[i].value;
7280 }
7281 i++;
7282 }
7283 return NULL;
7284
7285} */
7286
7287static unsigned int count_occurences(const char *buf, const char *word)
7288{
7289 unsigned int n = 0;
7290 char *ptr = strstr(buf, word);
7291
7292 while (ptr++) {
7293 n++;
7294 ptr = strstr(ptr, word);
7295 }
7296
7297 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7298 return n;
7299}
7300
7301static const char *get_line_from_str_buf(const char *buf, char *line)
7302{
7303 int i;
7304 int n = strlen(buf);
7305
7306 for (i = 0; i < n; i++) {
7307 line[i] = buf[i];
7308 if (buf[i] == '\n') {
7309 line[i] = '\0';
7310 return &buf[i + 1];
7311 }
7312 }
7313
7314 return NULL;
7315}
7316
7317INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7318{
7319 unsigned int assoc_cnt = 0;
7320 char interface_name[50] = {0};
7321 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7322 char cmd[MAX_CMD_SIZE] = {'\0'};
7323 char line[256] = {'\0'};
7324 int i = 0;
7325 int ret = 0;
7326 const char *ptr = NULL;
7327 char *key = NULL;
7328 char *val = NULL;
7329 wifi_associated_dev3_t *temp = NULL;
7330 int rssi;
7331
7332 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7333
7334 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7335 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7336 return RETURN_ERR;
7337 }
7338
7339 // Example filtered output of 'iw dev' command:
7340 // Station 0a:69:72:10:d2:fa (on wifi0)
7341 // signal avg:-67 [-71, -71] dBm
7342 // Station 28:c2:1f:25:5f:99 (on wifi0)
7343 // signal avg:-67 [-71, -70] dBm
7344 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7345 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7346 return RETURN_ERR;
7347 }
7348
7349 ret = _syscmd(cmd, buf, sizeof(buf));
7350 if (ret == RETURN_ERR) {
7351 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7352 return RETURN_ERR;
7353 }
7354
7355 *output_array_size = count_occurences(buf, "Station");
7356 if (*output_array_size == 0) return RETURN_OK;
7357
7358 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7359 if (temp == NULL) {
7360 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7361 return RETURN_ERR;
7362 }
7363 *associated_dev_array = temp;
7364
7365 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7366 ptr = get_line_from_str_buf(buf, line);
7367 i = -1;
7368 while (ptr) {
7369 if (strstr(line, "Station")) {
7370 i++;
7371 key = strtok(line, " ");
7372 val = strtok(NULL, " ");
7373 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7374 &temp[i].cli_MACAddress[0],
7375 &temp[i].cli_MACAddress[1],
7376 &temp[i].cli_MACAddress[2],
7377 &temp[i].cli_MACAddress[3],
7378 &temp[i].cli_MACAddress[4],
7379 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7380 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7381 free(*associated_dev_array);
7382 return RETURN_ERR;
7383 }
7384 }
7385 else if (i < 0) {
7386 ptr = get_line_from_str_buf(ptr, line);
7387 continue; // We didn't detect 'station' entry yet
7388 }
7389 else if (strstr(line, "signal avg")) {
7390 key = strtok(line, ":");
7391 val = strtok(NULL, " ");
7392 if (sscanf(val, "%d", &rssi) <= 0 ) {
7393 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7394 free(*associated_dev_array);
7395 return RETURN_ERR;
7396 }
7397 temp[i].cli_RSSI = rssi;
7398 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7399 }
7400 // Here other fields can be parsed if added to filter of 'iw dev' command
7401
7402 ptr = get_line_from_str_buf(ptr, line);
7403 };
7404
7405 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7406
7407 return RETURN_OK;
7408}
7409
7410#if 0
7411//To-do
7412INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7413{
7414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7415
7416 //Using different approach to get required WiFi Parameters from system available commands
7417#if 0
7418 FILE *f;
7419 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7420 char cmd[256], buf[2048];
7421 char *param , *value, *line=NULL;
7422 size_t len = 0;
7423 ssize_t nread;
7424 wifi_associated_dev3_t *dev=NULL;
7425 *associated_dev_array = NULL;
7426 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7427 _syscmd(cmd,buf,sizeof(buf));
7428 *output_array_size = atoi(buf);
7429
7430 if (*output_array_size <= 0)
7431 return RETURN_OK;
7432
7433 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7434 *associated_dev_array = dev;
7435 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7436 _syscmd(cmd,buf,sizeof(buf));
7437 f = fopen("/tmp/connected_devices.txt", "r");
7438 if (f==NULL)
7439 {
7440 *output_array_size=0;
7441 return RETURN_ERR;
7442 }
7443 while ((nread = getline(&line, &len, f)) != -1)
7444 {
7445 param = strtok(line,"=");
7446 value = strtok(NULL,"=");
7447
7448 if( strcmp("flags",param) == 0 )
7449 {
7450 value[strlen(value)-1]='\0';
7451 if(strstr (value,"AUTHORIZED") != NULL )
7452 {
7453 dev[auth_temp].cli_AuthenticationState = 1;
7454 dev[auth_temp].cli_Active = 1;
7455 auth_temp++;
7456 read_flag=1;
7457 }
7458 }
7459 if(read_flag==1)
7460 {
7461 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7462 {
7463 value[strlen(value)-1]='\0';
7464 sscanf(value, "%x:%x:%x:%x:%x:%x",
7465 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7466 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7467 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7468 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7469 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7470 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7471
7472 }
7473 else if( strcmp("rx_packets",param) == 0 )
7474 {
7475 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7476 }
7477
7478 else if( strcmp("tx_packets",param) == 0 )
7479 {
7480 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7481 }
7482
7483 else if( strcmp("rx_bytes",param) == 0 )
7484 {
7485 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7486 }
7487
7488 else if( strcmp("tx_bytes",param) == 0 )
7489 {
7490 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7491 mac_temp++;
7492 read_flag=0;
7493 }
7494 }
7495 }
7496
7497 *output_array_size = auth_temp;
7498 auth_temp=0;
7499 mac_temp=0;
7500 free(line);
7501 fclose(f);
7502#endif
7503 char interface_name[MAX_BUF_SIZE] = {0};
7504 char wifi_status[MAX_BUF_SIZE] = {0};
7505 char hostapdconf[MAX_BUF_SIZE] = {0};
7506
7507 wifi_associated_dev3_t *dev_array = NULL;
7508 ULONG wifi_count = 0;
7509
7510 *associated_dev_array = NULL;
7511 *output_array_size = 0;
7512
7513 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7514 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7515 {
7516 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7517
7518 GetInterfaceName(interface_name, hostapdconf);
7519
7520 if(strlen(interface_name) > 1)
7521 {
7522 wifihal_interfacestatus(wifi_status,interface_name);
7523 if(strcmp(wifi_status,"RUNNING") == 0)
7524 {
7525 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7526
7527 *associated_dev_array = dev_array;
7528 *output_array_size = wifi_count;
7529 }
7530 else
7531 {
7532 *associated_dev_array = NULL;
7533 }
7534 }
7535 }
7536
7537 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7538 return RETURN_OK;
7539}
7540#endif
7541
7542/* getIPAddress function */
7543/**
7544* @description Returning IpAddress of the Matched String
7545*
7546* @param
7547* @str Having MacAddress
7548* @ipaddr Having ipaddr
7549* @return The status of the operation
7550* @retval RETURN_OK if successful
7551* @retval RETURN_ERR if any error is detected
7552*
7553*/
7554
7555INT getIPAddress(char *str,char *ipaddr)
7556{
7557 FILE *fp = NULL;
7558 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7559 int LeaseTime = 0,ret = 0;
7560 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7561 {
7562 return RETURN_ERR;
7563 }
7564
7565 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7566 {
7567 /*
7568 Sample:sss
7569 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7570 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7571 */
7572 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7573 &(LeaseTime),
7574 phyAddr,
7575 ipAddr,
7576 hostName
7577 );
7578 if(ret != 4)
7579 continue;
7580 if(strcmp(str,phyAddr) == 0)
7581 strcpy(ipaddr,ipAddr);
7582 }
7583 return RETURN_OK;
7584}
7585
7586/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7587/**
7588* @description Returning Inactive wireless connected clients informations
7589*
7590* @param
7591* @filename Holding private_wifi 2g/5g content files
7592* @associated_dev_array Having inactiv wireless clients informations
7593* @output_array_size Returning Inactive wireless counts
7594* @return The status of the operation
7595* @retval RETURN_OK if successful
7596* @retval RETURN_ERR if any error is detected
7597*
7598*/
7599
7600INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7601{
7602 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7603 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7604 FILE *fp = NULL;
7605 int arr[MACADDRESS_SIZE] = {0};
7606 unsigned char mac[MACADDRESS_SIZE] = {0};
7607 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7608 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7609 fp = popen(buf,"r");
7610 if(fp == NULL)
7611 return RETURN_ERR;
7612 else
7613 {
7614 fgets(path,sizeof(path),fp);
7615 maccount = atoi(path);
7616 }
7617 pclose(fp);
7618 *output_array_size = maccount;
7619 wifi_associated_dev3_t* temp = NULL;
7620 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7621 *associated_dev_array = temp;
7622 if(temp == NULL)
7623 {
7624 printf("Error Statement. Insufficient memory \n");
7625 return RETURN_ERR;
7626 }
7627 memset(buf,0,sizeof(buf));
7628 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7629 fp = popen(buf,"r");
7630 for(count = 0; count < maccount ; count++)
7631 {
7632 fgets(path,sizeof(path),fp);
7633 for(i = 0; path[i]!='\n';i++)
7634 str[i]=path[i];
7635 str[i]='\0';
7636 getIPAddress(str,ipaddr);
7637 memset(buf,0,sizeof(buf));
7638 if(strlen(ipaddr) > 0)
7639 {
7640 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7641 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7642 {
7643 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7644 {
7645 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7646 {
7647 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7648
7649 }
7650 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7651 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]);
7652 }
7653 temp[count].cli_AuthenticationState = 0; //TODO
7654 temp[count].cli_Active = 0; //TODO
7655 temp[count].cli_SignalStrength = 0;
7656 }
7657 else //Active wireless clients info
7658 {
7659 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7660 {
7661 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7662 {
7663 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7664
7665 }
7666 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7667 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]);
7668 }
7669 temp[count].cli_Active = 1;
7670 }
7671 }
7672 memset(ipaddr,0,sizeof(ipaddr));
7673 }
7674 pclose(fp);
7675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7676 return RETURN_OK;
7677}
7678//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7679//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7680//To get Band Steering Capability
7681INT wifi_getBandSteeringCapability(BOOL *support)
7682{
7683 *support = FALSE;
7684 return RETURN_OK;
7685}
7686
7687
7688//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7689//To get Band Steering enable status
7690INT wifi_getBandSteeringEnable(BOOL *enable)
7691{
7692 *enable = FALSE;
7693 return RETURN_OK;
7694}
7695
7696//To turn on/off Band steering
7697INT wifi_setBandSteeringEnable(BOOL enable)
7698{
7699 return RETURN_OK;
7700}
7701
7702//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7703//To get Band Steering AP group
7704INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7705{
7706 if (NULL == output_ApGroup)
7707 return RETURN_ERR;
7708
7709 strcpy(output_ApGroup, "1,2");
7710 return RETURN_OK;
7711}
7712
7713//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7714//to set and read the band steering BandUtilizationThreshold parameters
7715INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7716{
7717 return RETURN_ERR;
7718}
7719
7720INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7721{
7722 return RETURN_ERR;
7723}
7724
7725//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7726//to set and read the band steering RSSIThreshold parameters
7727INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7728{
7729 return RETURN_ERR;
7730}
7731
7732INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7733{
7734 return RETURN_ERR;
7735}
7736
7737
7738//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7739//to set and read the band steering physical modulation rate threshold parameters
7740INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7741{
7742 //If chip is not support, return -1
7743 return RETURN_ERR;
7744}
7745
7746INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7747{
7748 //If chip is not support, return -1
7749 return RETURN_ERR;
7750}
7751
7752//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7753//to set and read the inactivity time (in seconds) for steering under overload condition
7754INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7755{
7756 return RETURN_ERR;
7757}
7758
7759INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7760{
7761 return RETURN_ERR;
7762}
7763
7764//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7765//to set and read the inactivity time (in seconds) for steering under Idle condition
7766INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7767{
7768 return RETURN_ERR;
7769}
7770
7771INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7772{
7773 return RETURN_ERR;
7774}
7775
7776//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7777//pClientMAC[64]
7778//pSourceSSIDIndex[64]
7779//pDestSSIDIndex[64]
7780//pSteeringReason[256]
7781INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7782{
7783 //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
7784 *pSteeringTime=time(NULL);
7785 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7786 return RETURN_OK;
7787}
7788
7789INT wifi_ifConfigDown(INT apIndex)
7790{
7791 INT status = RETURN_OK;
7792 char cmd[64];
7793
7794 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7795 printf("%s: %s\n", __func__, cmd);
7796 system(cmd);
7797
7798 return status;
7799}
7800
7801INT wifi_ifConfigUp(INT apIndex)
7802{
7803 char cmd[128];
7804 char buf[1024];
7805
7806 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7807 _syscmd(cmd, buf, sizeof(buf));
7808 return 0;
7809}
7810
7811//>> Deprecated. Replace with wifi_applyRadioSettings
7812INT wifi_pushBridgeInfo(INT apIndex)
7813{
7814 char ip[32];
7815 char subnet[32];
7816 char bridge[32];
7817 int vlanId;
7818 char cmd[128];
7819 char buf[1024];
7820
7821 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7822 wifi_getApVlanID(apIndex,&vlanId);
7823
7824 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7825 _syscmd(cmd,buf, sizeof(buf));
7826
7827 return 0;
7828}
7829
7830INT wifi_pushChannel(INT radioIndex, UINT channel)
7831{
7832 char cmd[128];
7833 char buf[1024];
7834 int apIndex;
7835
7836 apIndex=(radioIndex==0)?0:1;
7837 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7838 _syscmd(cmd,buf, sizeof(buf));
7839
7840 return 0;
7841}
7842
7843INT wifi_pushChannelMode(INT radioIndex)
7844{
7845 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7846 return RETURN_ERR;
7847}
7848
7849INT wifi_pushDefaultValues(INT radioIndex)
7850{
7851 //Apply Comcast specified default radio settings instantly
7852 //AMPDU=1
7853 //AMPDUFrames=32
7854 //AMPDULim=50000
7855 //txqueuelen=1000
7856
7857 return RETURN_ERR;
7858}
7859
7860INT wifi_pushTxChainMask(INT radioIndex)
7861{
7862 //Apply default TxChainMask instantly
7863 return RETURN_ERR;
7864}
7865
7866INT wifi_pushRxChainMask(INT radioIndex)
7867{
7868 //Apply default RxChainMask instantly
7869 return RETURN_ERR;
7870}
7871
7872INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7873{
7874 INT status;
7875
7876 status = wifi_setSSIDName(apIndex,ssid);
7877 wifi_setApEnable(apIndex,FALSE);
7878 wifi_setApEnable(apIndex,TRUE);
7879
7880 return status;
7881}
7882
7883INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7884{
7885 //Apply default Ssid Advertisement instantly
7886 return RETURN_ERR;
7887}
7888
7889INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7890{
7891 INT status = RETURN_ERR;
7892 *output = 0;
7893 return RETURN_ERR;
7894}
7895
7896INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7897{
7898 return RETURN_OK;
7899}
7900
7901INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7902{
7903 return RETURN_OK;
7904}
7905
7906//To-do
7907INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7908{
developereb199ae2022-09-13 14:04:27 +08007909 char output[16]={'\0'};
7910 char config_file[MAX_BUF_SIZE] = {0};
7911
7912 if (!output_string)
7913 return RETURN_ERR;
7914
7915 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7916 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7917
7918 if (strlen(output) == 0)
7919 snprintf(output_string, 64, "Disabled");
7920 else if (strncmp(output, "0", 1) == 0)
7921 snprintf(output_string, 64, "Disabled");
7922 else if (strncmp(output, "1", 1) == 0)
7923 snprintf(output_string, 64, "Optional");
7924 else if (strncmp(output, "2", 1) == 0)
7925 snprintf(output_string, 64, "Required");
7926 else {
7927 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7928 return RETURN_ERR;
7929 }
7930
7931 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007932 return RETURN_OK;
7933}
7934INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7935{
developereb199ae2022-09-13 14:04:27 +08007936 char str[MAX_BUF_SIZE]={'\0'};
7937 char cmd[MAX_CMD_SIZE]={'\0'};
7938 struct params params;
7939 char config_file[MAX_BUF_SIZE] = {0};
7940
7941 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7942 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7943 return RETURN_ERR;
7944
7945 params.name = "ieee80211w";
7946 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7947 params.value = "0";
7948 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7949 params.value = "1";
7950 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7951 params.value = "2";
7952 else{
7953 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7954 return RETURN_ERR;
7955 }
7956 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7957 wifi_hostapdWrite(config_file, &params, 1);
7958 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007959 return RETURN_OK;
7960}
7961INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7962{
7963 char output[16]={'\0'};
7964 char config_file[MAX_BUF_SIZE] = {0};
7965
7966 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7967 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7968 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7969
7970 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7971 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7972
7973 return RETURN_OK;
7974}
7975
7976INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7977{
7978 return RETURN_OK;
7979}
7980
7981INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7982{
7983 return RETURN_OK;
7984}
7985
7986INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7987{
7988 return RETURN_OK;
7989}
7990
7991INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7992{
7993 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7994 char config_file[MAX_BUF_SIZE] = {0};
7995
7996 if (NULL == output)
7997 return RETURN_ERR;
7998 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7999 wifi_hostapdRead(config_file,"hw_mode",output,64);
8000
8001 if(strcmp(output,"b")==0)
8002 sprintf(output, "%s", "1,2,5.5,11");
8003 else if (strcmp(output,"a")==0)
8004 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8005 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8006 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8007
8008 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8009 return RETURN_OK;
8010}
8011
8012INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8013{
8014 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8015 char *temp;
8016 char temp_output[128];
8017 char temp_TransmitRates[128];
8018 char config_file[MAX_BUF_SIZE] = {0};
8019
8020 if (NULL == output)
8021 return RETURN_ERR;
8022
8023 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8024 wifi_hostapdRead(config_file,"supported_rates",output,64);
8025
8026 strcpy(temp_TransmitRates,output);
8027 strcpy(temp_output,"");
8028 temp = strtok(temp_TransmitRates," ");
8029 while(temp!=NULL)
8030 {
8031 temp[strlen(temp)-1]=0;
8032 if((temp[0]=='5') && (temp[1]=='\0'))
8033 {
8034 temp="5.5";
8035 }
8036 strcat(temp_output,temp);
8037 temp = strtok(NULL," ");
8038 if(temp!=NULL)
8039 {
8040 strcat(temp_output,",");
8041 }
8042 }
8043 strcpy(output,temp_output);
8044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8045
8046 return RETURN_OK;
8047}
8048
8049INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8050{
8051 return RETURN_OK;
8052}
8053
8054
8055INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8056{
8057 int i=0;
8058 char *temp;
8059 char temp1[128];
8060 char temp_output[128];
8061 char temp_TransmitRates[128];
8062 struct params params={'\0'};
8063 char config_file[MAX_BUF_SIZE] = {0};
8064
8065 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8066 if(NULL == output)
8067 return RETURN_ERR;
8068
8069 strcpy(temp_TransmitRates,output);
8070
8071 for(i=0;i<strlen(temp_TransmitRates);i++)
8072 {
8073 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
8074 {
8075 continue;
8076 }
8077 else
8078 {
8079 return RETURN_ERR;
8080 }
8081 }
8082 strcpy(temp_output,"");
8083 temp = strtok(temp_TransmitRates," ");
8084 while(temp!=NULL)
8085 {
8086 strcpy(temp1,temp);
8087 if(wlanIndex==1)
8088 {
8089 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8090 {
8091 return RETURN_ERR;
8092 }
8093 }
8094
8095 if(strcmp(temp,"5.5")==0)
8096 {
8097 strcpy(temp1,"55");
8098 }
8099 else
8100 {
8101 strcat(temp1,"0");
8102 }
8103 strcat(temp_output,temp1);
8104 temp = strtok(NULL," ");
8105 if(temp!=NULL)
8106 {
8107 strcat(temp_output," ");
8108 }
8109 }
8110 strcpy(output,temp_output);
8111
8112
8113 params.name = "supported_rates";
8114 params.value = output;
8115
8116 wifi_dbg_printf("\n%s:",__func__);
8117 wifi_dbg_printf("params.value=%s\n",params.value);
8118 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8119 wifi_hostapdWrite(config_file,&params,1);
8120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8121
8122 return RETURN_OK;
8123}
8124
8125
8126static char *sncopy(char *dst, int dst_sz, const char *src)
8127{
8128 if (src && dst && dst_sz > 0) {
8129 strncpy(dst, src, dst_sz);
8130 dst[dst_sz - 1] = '\0';
8131 }
8132 return dst;
8133}
8134
8135static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8136{
8137 if (0 == strcmp(ht_mode, "HT40") ||
8138 0 == strcmp(ht_mode, "HT80") ||
8139 0 == strcmp(ht_mode, "HT160")) {
8140 switch (channel) {
8141 case 1 ... 7:
8142 case 36:
8143 case 44:
8144 case 52:
8145 case 60:
8146 case 100:
8147 case 108:
8148 case 116:
8149 case 124:
8150 case 132:
8151 case 140:
8152 case 149:
8153 case 157:
8154 return 1;
8155 case 8 ... 13:
8156 case 40:
8157 case 48:
8158 case 56:
8159 case 64:
8160 case 104:
8161 case 112:
8162 case 120:
8163 case 128:
8164 case 136:
8165 case 144:
8166 case 153:
8167 case 161:
8168 return -1;
8169 default:
8170 return -EINVAL;
8171 }
8172 }
8173
8174 return -EINVAL;
8175}
8176
developerb7593de2022-10-18 09:51:57 +08008177static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8178{
8179 int idx = channel%8;
8180 if (0 == strcmp(ht_mode, "HT40") ||
8181 0 == strcmp(ht_mode, "HT80") ||
8182 0 == strcmp(ht_mode, "HT160")) {
8183 switch (idx) {
8184 case 1:
8185 return 1;
8186 case 5:
8187 return -1;
8188 default:
8189 return -EINVAL;
8190 }
8191 }
8192
8193 return -EINVAL;
8194}
developer06a01d92022-09-07 16:32:39 +08008195static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8196{
8197 if (NULL == hw_mode) return;
8198
8199 if (0 == strcmp(hw_mode, "ac"))
8200 sncopy(bw_mode, bw_mode_len, "ht vht");
8201
8202 if (0 == strcmp(hw_mode, "n"))
8203 sncopy(bw_mode, bw_mode_len, "ht");
8204
8205 return;
8206}
8207
8208static int util_chan_to_freq(int chan)
8209{
8210 if (chan == 14)
8211 return 2484;
8212 else if (chan < 14)
8213 return 2407 + chan * 5;
8214 else if (chan >= 182 && chan <= 196)
8215 return 4000 + chan * 5;
8216 else
8217 return 5000 + chan * 5;
8218 return 0;
8219}
8220
developerb7593de2022-10-18 09:51:57 +08008221static int util_6G_chan_to_freq(int chan)
8222{
8223 if (chan)
8224 return 5950 + chan * 5;
8225 else
8226 return 0;
8227
8228}
developer06a01d92022-09-07 16:32:39 +08008229const int *util_unii_5g_chan2list(int chan, int width)
8230{
8231 static const int lists[] = {
8232 // <width>, <chan1>, <chan2>..., 0,
8233 20, 36, 0,
8234 20, 40, 0,
8235 20, 44, 0,
8236 20, 48, 0,
8237 20, 52, 0,
8238 20, 56, 0,
8239 20, 60, 0,
8240 20, 64, 0,
8241 20, 100, 0,
8242 20, 104, 0,
8243 20, 108, 0,
8244 20, 112, 0,
8245 20, 116, 0,
8246 20, 120, 0,
8247 20, 124, 0,
8248 20, 128, 0,
8249 20, 132, 0,
8250 20, 136, 0,
8251 20, 140, 0,
8252 20, 144, 0,
8253 20, 149, 0,
8254 20, 153, 0,
8255 20, 157, 0,
8256 20, 161, 0,
8257 20, 165, 0,
8258 40, 36, 40, 0,
8259 40, 44, 48, 0,
8260 40, 52, 56, 0,
8261 40, 60, 64, 0,
8262 40, 100, 104, 0,
8263 40, 108, 112, 0,
8264 40, 116, 120, 0,
8265 40, 124, 128, 0,
8266 40, 132, 136, 0,
8267 40, 140, 144, 0,
8268 40, 149, 153, 0,
8269 40, 157, 161, 0,
8270 80, 36, 40, 44, 48, 0,
8271 80, 52, 56, 60, 64, 0,
8272 80, 100, 104, 108, 112, 0,
8273 80, 116, 120, 124, 128, 0,
8274 80, 132, 136, 140, 144, 0,
8275 80, 149, 153, 157, 161, 0,
8276 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8277 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8278 -1 // final delimiter
8279 };
8280 const int *start;
8281 const int *p;
8282
8283 for (p = lists; *p != -1; p++) {
8284 if (*p == width) {
8285 for (start = ++p; *p != 0; p++) {
8286 if (*p == chan)
8287 return start;
8288 }
8289 }
8290 // move to the end of channel list of given width
8291 while (*p != 0) {
8292 p++;
8293 }
8294 }
8295
8296 return NULL;
8297}
8298
8299static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8300{
8301 if (NULL == ht_mode)
8302 return 0;
8303
8304 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8305 const int *chans = util_unii_5g_chan2list(channel, width);
8306 int sum = 0;
8307 int cnt = 0;
8308
8309 if (NULL == chans)
8310 return 0;
8311
8312 while (*chans) {
8313 sum += *chans;
8314 cnt++;
8315 chans++;
8316 }
8317 return sum / cnt;
8318}
8319
developerb7593de2022-10-18 09:51:57 +08008320static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8321{
8322 if (NULL == ht_mode)
8323 return 0;
8324
8325 int width = strtol((ht_mode + 2), NULL, 10);
8326
8327 int idx = 0 ;
8328 int centerchan = 0;
8329 int chan_ofs = 1;
8330
8331 if (width == 40){
8332 idx = ((channel/4) + chan_ofs)%2;
8333 switch (idx) {
8334 case 0:
8335 centerchan = (channel - 2);
8336 break;
8337 case 1:
8338 centerchan = (channel + 2);
8339 break;
8340 default:
8341 return -EINVAL;
8342 }
8343 }else if (width == 80){
8344 idx = ((channel/4) + chan_ofs)%4;
8345 switch (idx) {
8346 case 0:
8347 centerchan = (channel - 6);
8348 break;
8349 case 1:
8350 centerchan = (channel + 6);
8351 break;
8352 case 2:
8353 centerchan = (channel + 2);
8354 break;
8355 case 3:
8356 centerchan = (channel - 2);
8357 break;
8358 default:
8359 return -EINVAL;
8360 }
8361 }else if (width == 160){
8362 switch (channel) {
8363 case 1 ... 29:
8364 centerchan = 15;
8365 break;
8366 case 33 ... 61:
8367 centerchan = 47;
8368 break;
8369 case 65 ... 93:
8370 centerchan = 79;
8371 break;
8372 case 97 ... 125:
8373 centerchan = 111;
8374 break;
8375 case 129 ... 157:
8376 centerchan = 143;
8377 break;
8378 case 161 ... 189:
8379 centerchan = 175;
8380 break;
8381 case 193 ... 221:
8382 centerchan = 207;
8383 break;
8384 default:
8385 return -EINVAL;
8386 }
8387 }
8388 return centerchan;
8389}
developer06a01d92022-09-07 16:32:39 +08008390static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8391{
8392 BOOL onlyG, onlyN, onlyA;
8393 CHAR tmp[64];
8394 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8395 if (ret == RETURN_OK) {
8396 sncopy(hw_mode, hw_mode_size, tmp);
8397 }
8398 return ret;
8399}
8400
8401INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8402{
8403 // Sample commands:
8404 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8405 // hostapd_cli -i wifi0 chan_switch 30 2437
8406 char cmd[MAX_CMD_SIZE] = {0};
8407 char buf[MAX_BUF_SIZE] = {0};
8408 int freq = 0, ret = 0;
8409 char center_freq1_str[32] = ""; // center_freq1=%d
8410 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8411 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8412 char hw_mode[16] = ""; // n|ac
8413 char bw_mode[16] = ""; // ht|ht vht
8414 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8415 int sec_chan_offset;
8416 int width;
developer4fb0b922022-09-30 14:29:09 +08008417 char config_file[64] = {0};
8418 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008419 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008420 wifi_band band = band_invalid;
8421 int center_chan = 0;
8422 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008423
developer4fb0b922022-09-30 14:29:09 +08008424 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008425
8426 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8427
developerb7593de2022-10-18 09:51:57 +08008428 band = wifi_index_to_band(radioIndex);
8429
developer5884e982022-10-06 10:52:50 +08008430 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008431
8432 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008433 if (channel){
developerb7593de2022-10-18 09:51:57 +08008434 if (band == band_6){
8435 freq = util_6G_chan_to_freq(channel);
8436 }else{
8437 freq = util_chan_to_freq(channel);
8438 }
developer5884e982022-10-06 10:52:50 +08008439 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008440
developer5884e982022-10-06 10:52:50 +08008441 // Provide bandwith if specified
8442 if (channel_width_MHz > 20) {
8443 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8444 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8445 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008446
developer5884e982022-10-06 10:52:50 +08008447 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8448 }else if (channel_width_MHz == 20){
8449 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8450 }
developer06a01d92022-09-07 16:32:39 +08008451
developerb7593de2022-10-18 09:51:57 +08008452
developer5884e982022-10-06 10:52:50 +08008453 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008454 if (band == band_6){
8455 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8456 if(center_chan){
8457 center_freq1 = util_6G_chan_to_freq(center_chan);
8458 }
8459 }else{
8460 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8461 if(center_chan){
8462 center_freq1 = util_chan_to_freq(center_chan);
8463 }
developer5884e982022-10-06 10:52:50 +08008464 }
developerb7593de2022-10-18 09:51:57 +08008465
8466 if (center_freq1)
8467 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8468
8469 }
8470
8471 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8472 if (band == band_6){
8473 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8474 }else{
8475 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008476 }
developerb7593de2022-10-18 09:51:57 +08008477 if (sec_chan_offset != -EINVAL)
8478 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008479
developer5884e982022-10-06 10:52:50 +08008480 // Only the first AP, other are hanging on the same radio
8481 int apIndex = radioIndex;
8482 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8483 AP_PREFIX, apIndex, csa_beacon_count, freq,
8484 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8485 wifi_dbg_printf("execute: '%s'\n", cmd);
8486 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008487
developer5884e982022-10-06 10:52:50 +08008488 ret = wifi_setRadioChannel(radioIndex, channel);
8489 if (ret != RETURN_OK) {
8490 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8491 return RETURN_ERR;
8492 }
8493
8494 if (sec_chan_offset == 1) ext_str = "Above";
8495 else if (sec_chan_offset == -1) ext_str = "Below";
8496
8497 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008498
developer5884e982022-10-06 10:52:50 +08008499 } else {
8500 if (channel_width_MHz > 20)
8501 ext_str = "Above";
8502 }
developer4fb0b922022-09-30 14:29:09 +08008503 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8504 _syscmd(cmd, buf, sizeof(buf));
8505 if (strlen(buf) != 0)
8506 stbcEnable = TRUE;
8507
developer06a01d92022-09-07 16:32:39 +08008508 wifi_setRadioExtChannel(radioIndex, ext_str);
8509
developer4fb0b922022-09-30 14:29:09 +08008510 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8511
developer06a01d92022-09-07 16:32:39 +08008512 char mhz_str[16];
8513 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8514 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8515
8516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8517
8518 return RETURN_OK;
8519}
8520
8521INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8522{
developer615510b2022-09-27 10:14:35 +08008523 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008524 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008525 char cmd[256]={0};
8526 char buf[128]={0};
8527 char file_name[32] = {0};
8528 char filter_SSID[32] = {0};
8529 char line[256] = {0};
8530 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008531 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008532 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008533 size_t len=0;
8534 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008535 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008536 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008537 bool filter_enable = false;
8538 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008539
developer615510b2022-09-27 10:14:35 +08008540 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008541
developer615510b2022-09-27 10:14:35 +08008542 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8543 f = fopen(file_name, "r");
8544 if (f != NULL) {
8545 fgets(filter_SSID, sizeof(file_name), f);
8546 if (strlen(filter_SSID) != 0)
8547 filter_enable = true;
8548 fclose(f);
8549 }
8550
8551 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8552 _syscmd(cmd, buf, sizeof(buf));
8553 channels_num = strtol(buf, NULL, 10);
8554
developer615510b2022-09-27 10:14:35 +08008555 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8556 // 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);
8557 fprintf(stderr, "cmd: %s\n", cmd);
8558 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008559 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8560 return RETURN_ERR;
8561 }
developer5550e242022-09-30 09:59:32 +08008562
8563 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8564 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8565
developer615510b2022-09-27 10:14:35 +08008566 ret = fgets(line, sizeof(line), f);
8567 while (ret != NULL) {
8568 if(strstr(line, "BSS") != NULL) { // new neighbor info
8569 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8570 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8571 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8572
8573 if (!filter_BSS) {
8574 index++;
8575 wifi_neighbor_ap2_t *tmp;
8576 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8577 if (tmp == NULL) { // no more memory to use
8578 index--;
8579 wifi_dbg_printf("%s: realloc failed\n", __func__);
8580 break;
8581 }
8582 scan_array = tmp;
8583 }
8584 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008585
developer615510b2022-09-27 10:14:35 +08008586 filter_BSS = false;
8587 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8588 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8589 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8590 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8591 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008592 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008593 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008594
developer615510b2022-09-27 10:14:35 +08008595 if (freq >= 2412 && freq <= 2484) {
8596 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8597 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8598 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8599 }
8600 else if (freq >= 5160 && freq <= 5805) {
8601 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8602 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8603 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8604 }
developer06a01d92022-09-07 16:32:39 +08008605
developer615510b2022-09-27 10:14:35 +08008606 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008607 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008608 for (int i = 0; i < channels_num; i++) {
8609 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8610 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8611 break;
8612 }
8613 }
developer06a01d92022-09-07 16:32:39 +08008614 }
developer615510b2022-09-27 10:14:35 +08008615 } else if (strstr(line, "beacon interval") != NULL) {
8616 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8617 } else if (strstr(line, "signal") != NULL) {
8618 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8619 } else if (strstr(line,"SSID") != NULL) {
8620 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8621 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8622 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008623 }
developer615510b2022-09-27 10:14:35 +08008624 } else if (strstr(line, "Supported rates") != NULL) {
8625 char SRate[80] = {0}, *tmp = NULL;
8626 memset(buf, 0, sizeof(buf));
8627 strcpy(SRate, line);
8628 tmp = strtok(SRate, ":");
8629 tmp = strtok(NULL, ":");
8630 strcpy(buf, tmp);
8631 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008632
developer615510b2022-09-27 10:14:35 +08008633 tmp = strtok(buf, " \n");
8634 while (tmp != NULL) {
8635 strcat(SRate, tmp);
8636 if (SRate[strlen(SRate) - 1] == '*') {
8637 SRate[strlen(SRate) - 1] = '\0';
8638 }
8639 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008640
developer615510b2022-09-27 10:14:35 +08008641 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008642 }
developer615510b2022-09-27 10:14:35 +08008643 SRate[strlen(SRate) - 1] = '\0';
8644 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8645 } else if (strstr(line, "DTIM") != NULL) {
8646 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8647 } else if (strstr(line, "VHT capabilities") != NULL) {
8648 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8649 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8650 } else if (strstr(line, "HT capabilities") != NULL) {
8651 strcat(scan_array[index].ap_SupportedStandards, ",n");
8652 strcpy(scan_array[index].ap_OperatingStandards, "n");
8653 } else if (strstr(line, "VHT operation") != NULL) {
8654 ret = fgets(line, sizeof(line), f);
8655 sscanf(line," * channel width: %d", &vht_channel_width);
8656 if(vht_channel_width == 1) {
8657 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8658 } else {
8659 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8660 }
8661 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8662 continue;
8663 } else if (strstr(line, "HT operation") != NULL) {
8664 ret = fgets(line, sizeof(line), f);
8665 sscanf(line," * secondary channel offset: %s", &buf);
8666 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008667 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008668 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 +08008669 }
developer615510b2022-09-27 10:14:35 +08008670 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008671 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008672 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8673 } else {
8674 //20Mhz
8675 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 +08008676 }
developer615510b2022-09-27 10:14:35 +08008677 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008678 continue;
developer615510b2022-09-27 10:14:35 +08008679 } else if (strstr(line, "HE capabilities") != NULL) {
8680 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8681 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8682 ret = fgets(line, sizeof(line), f);
8683 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8684 if (strstr(line, "HE40/2.4GHz") != NULL)
8685 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8686 else
8687 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8688 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8689 if (strstr(line, "HE80/5GHz") != NULL) {
8690 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8691 ret = fgets(line, sizeof(line), f);
8692 } else
8693 continue;
8694 if (strstr(line, "HE160/5GHz") != NULL)
8695 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008696 }
developer615510b2022-09-27 10:14:35 +08008697 continue;
8698 } else if (strstr(line, "WPA") != NULL) {
8699 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8700 } else if (strstr(line, "RSN") != NULL) {
8701 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8702 } else if (strstr(line, "Group cipher") != NULL) {
8703 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8704 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8705 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008706 }
developer06a01d92022-09-07 16:32:39 +08008707 }
developer615510b2022-09-27 10:14:35 +08008708 ret = fgets(line, sizeof(line), f);
8709 }
8710
8711 if (!filter_BSS) {
8712 *output_array_size = index + 1;
8713 } else {
8714 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8715 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008716 }
developer06a01d92022-09-07 16:32:39 +08008717 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008718 pclose(f);
developer5550e242022-09-30 09:59:32 +08008719 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008720 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008721 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008722}
developer615510b2022-09-27 10:14:35 +08008723
developer06a01d92022-09-07 16:32:39 +08008724INT wifi_getApAssociatedDeviceStats(
8725 INT apIndex,
8726 mac_address_t *clientMacAddress,
8727 wifi_associated_dev_stats_t *associated_dev_stats,
8728 u64 *handle)
8729{
8730 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8731 char interface_name[50] = {0};
8732 char cmd[1024] = {0};
8733 char mac_str[18] = {0};
8734 char *key = NULL;
8735 char *val = NULL;
8736 FILE *f = NULL;
8737 char *line = NULL;
8738 size_t len = 0;
8739 ssize_t read = 0;
8740
8741 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8742 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8743 return RETURN_ERR;
8744 }
8745
8746 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8747 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8748 if((f = popen(cmd, "r")) == NULL) {
8749 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8750 return RETURN_ERR;
8751 }
8752
8753 while ((read = getline(&line, &len, f)) != -1) {
8754 key = strtok(line,":");
8755 val = strtok(NULL,":");
8756
8757 if(!strncmp(key,"rx bytes",8))
8758 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8759 if(!strncmp(key,"tx bytes",8))
8760 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8761 if(!strncmp(key,"rx packets",10))
8762 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8763 if(!strncmp(key,"tx packets",10))
8764 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8765 if(!strncmp(key,"tx retries",10))
8766 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8767 if(!strncmp(key,"tx failed",9))
8768 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8769 if(!strncmp(key,"rx drop misc",13))
8770 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8771 if(!strncmp(key,"rx bitrate",10)) {
8772 val = strtok(val, " ");
8773 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8774 }
8775 if(!strncmp(key,"tx bitrate",10)) {
8776 val = strtok(val, " ");
8777 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8778 }
8779 }
8780 free(line);
8781 pclose(f);
8782 return RETURN_OK;
8783}
8784
8785INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8786{
8787 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8788
8789 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8790 if (NULL == output_string)
8791 return RETURN_ERR;
8792
8793 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8794 _syscmd(cmd, buf, sizeof(buf));
8795
8796 //size of SSID name restricted to value less than 32 bytes
8797 snprintf(output_string, 32, "%s", buf);
8798 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8799
8800 return RETURN_OK;
8801}
8802
8803INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8804{
8805 //char cmd[MAX_CMD_SIZE] = {0};
8806 char config_file[MAX_BUF_SIZE] = {0};
8807 char buf[32] = {0};
8808
8809 if (!output_filterMode)
8810 return RETURN_ERR;
8811
8812 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8813 //_syscmd(cmd, buf, sizeof(buf));
8814 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8815 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008816 if(strlen(buf) == 0) {
8817 *output_filterMode = 0;
8818 }
8819 else {
8820 int macaddr_acl_mode = strtol(buf, NULL, 10);
8821 if (macaddr_acl_mode == 1) {
8822 *output_filterMode = 1;
8823 } else if (macaddr_acl_mode == 0) {
8824 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8825 if (strlen(buf) == 0) {
8826 *output_filterMode = 0;
8827 } else {
8828 *output_filterMode = 2;
8829 }
8830 } else {
8831 return RETURN_ERR;
8832 }
8833 }
developer06a01d92022-09-07 16:32:39 +08008834
8835 return RETURN_OK;
8836}
8837
8838INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8839{
8840 FILE *fp = NULL;
8841 char str[MAX_BUF_SIZE] = {0};
8842 int wificlientindex = 0 ;
8843 int count = 0;
8844 int signalstrength = 0;
8845 int arr[MACADDRESS_SIZE] = {0};
8846 unsigned char mac[MACADDRESS_SIZE] = {0};
8847 UINT wifi_count = 0;
8848 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8849 char pipeCmd[MAX_CMD_SIZE] = {0};
8850
8851 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8852 *output_array_size = 0;
8853 *associated_dev_array = NULL;
8854 char interface_name[50] = {0};
8855
8856 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8857 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8858 return RETURN_ERR;
8859 }
8860
8861 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8862 fp = popen(pipeCmd, "r");
8863 if (fp == NULL)
8864 {
8865 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8866 return RETURN_ERR;
8867 }
8868
8869 /* Read the output a line at a time - output it. */
8870 fgets(str, sizeof(str)-1, fp);
8871 wifi_count = (unsigned int) atoi ( str );
8872 *output_array_size = wifi_count;
8873 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8874 pclose(fp);
8875
8876 if(wifi_count == 0)
8877 {
8878 return RETURN_OK;
8879 }
8880 else
8881 {
8882 wifi_associated_dev2_t* temp = NULL;
8883 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8884 *associated_dev_array = temp;
8885 if(temp == NULL)
8886 {
8887 printf("Error Statement. Insufficient memory \n");
8888 return RETURN_ERR;
8889 }
8890
8891 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8892 system(pipeCmd);
8893
8894 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8895 if(fp == NULL)
8896 {
8897 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8898 return RETURN_ERR;
8899 }
8900 fclose(fp);
8901
8902 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8903 fp = popen(pipeCmd, "r");
8904 if(fp)
8905 {
8906 for(count =0 ; count < wifi_count; count++)
8907 {
8908 fgets(str, MAX_BUF_SIZE, fp);
8909 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8910 {
8911 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8912 {
8913 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8914
8915 }
8916 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8917 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]);
8918 }
8919 temp[count].cli_AuthenticationState = 1; //TODO
8920 temp[count].cli_Active = 1; //TODO
8921 }
8922 pclose(fp);
8923 }
8924
8925 //Updating RSSI per client
8926 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8927 fp = popen(pipeCmd, "r");
8928 if(fp)
8929 {
8930 pclose(fp);
8931 }
8932 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8933 if(fp)
8934 {
8935 for(count =0 ; count < wifi_count ;count++)
8936 {
8937 fgets(str, MAX_BUF_SIZE, fp);
8938 signalstrength = atoi(str);
8939 temp[count].cli_RSSI = signalstrength;
8940 }
8941 pclose(fp);
8942 }
8943
8944
8945 //LastDataDownlinkRate
8946 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8947 fp = popen(pipeCmd, "r");
8948 if (fp)
8949 {
8950 pclose(fp);
8951 }
8952 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8953 if (fp)
8954 {
8955 for (count = 0; count < wifi_count; count++)
8956 {
8957 fgets(str, MAX_BUF_SIZE, fp);
8958 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8959 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8960 }
8961 pclose(fp);
8962 }
8963
8964 //LastDataUplinkRate
8965 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8966 fp = popen(pipeCmd, "r");
8967 if (fp)
8968 {
8969 pclose(fp);
8970 }
8971 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8972 if (fp)
8973 {
8974 for (count = 0; count < wifi_count; count++)
8975 {
8976 fgets(str, MAX_BUF_SIZE, fp);
8977 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8978 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8979 }
8980 pclose(fp);
8981 }
8982 }
8983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8984 return RETURN_OK;
8985
8986}
8987
8988INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8989{
8990#if 0
8991 /*char buf[1024] = {0};
8992 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8993 _syscmd(cmd, buf, sizeof(buf));*/
8994
8995 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8996 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8997 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8998 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8999
9000 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.
9001 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].
9002 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].
9003 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].
9004 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9005 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9006
9007 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9008 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9009 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9010 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.
9011 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.
9012 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.
9013 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.
9014 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.
9015 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.
9016 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.
9017 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9018#endif
9019
9020 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08009021 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08009022 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009023 char pipeCmd[128] = {0};
9024 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009025 wifi_ssidTrafficStats2_t *out = output_struct;
9026
developerce736392022-09-13 15:24:34 +08009027 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009028 if (!output_struct)
9029 return RETURN_ERR;
9030
developerce736392022-09-13 15:24:34 +08009031 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9032 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
9033 GetInterfaceName(interface_name, HConf_file);
9034 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009035
developer06a01d92022-09-07 16:32:39 +08009036 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009037 if (fp == NULL) {
9038 fprintf(stderr, "%s: popen failed\n", __func__);
9039 return RETURN_ERR;
9040 }
9041 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08009042
developerce736392022-09-13 15:24:34 +08009043 if (strlen(str) == 0) // interface not exist
9044 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009045
developerce736392022-09-13 15:24:34 +08009046 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9047 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009048 pclose(fp);
9049
developerce736392022-09-13 15:24:34 +08009050 memset(str, 0, sizeof(str));
9051 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009052 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009053 if (fp == NULL) {
9054 fprintf(stderr, "%s: popen failed\n", __func__);
9055 return RETURN_ERR;
9056 }
9057 fgets(str, sizeof(str), fp);
9058
9059 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9060 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009061 pclose(fp);
developerce736392022-09-13 15:24:34 +08009062
9063 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9064 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9065
9066 // Not supported
9067 output_struct->ssid_RetransCount = 0;
9068 output_struct->ssid_FailedRetransCount = 0;
9069 output_struct->ssid_RetryCount = 0;
9070 output_struct->ssid_MultipleRetryCount = 0;
9071 output_struct->ssid_ACKFailureCount = 0;
9072 output_struct->ssid_AggregatedPacketCount = 0;
9073
developer06a01d92022-09-07 16:32:39 +08009074 return RETURN_OK;
9075}
9076
9077//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).
9078INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9079{
9080 char output_val[16]={'\0'};
9081 char config_file[MAX_BUF_SIZE] = {0};
9082
9083 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9084 if (!output)
9085 return RETURN_ERR;
9086 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9087 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9088
9089 if( strcmp(output_val,"1") == 0 )
9090 *output = TRUE;
9091 else
9092 *output = FALSE;
9093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9094
9095 return RETURN_OK;
9096}
9097
9098INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9099{
9100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9101 char str[MAX_BUF_SIZE]={'\0'};
9102 char string[MAX_BUF_SIZE]={'\0'};
9103 char cmd[MAX_CMD_SIZE]={'\0'};
9104 char *ch;
9105 char config_file[MAX_BUF_SIZE] = {0};
9106 struct params params;
9107
9108 if(enable == TRUE)
9109 strcpy(string,"1");
9110 else
9111 strcpy(string,"0");
9112
9113 params.name = "ap_isolate";
9114 params.value = string;
9115
9116 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9117 wifi_hostapdWrite(config_file,&params,1);
9118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9119
9120 return RETURN_OK;
9121}
9122
9123INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9124{
9125 if (NULL == output_dBm)
9126 return RETURN_ERR;
9127
9128 *output_dBm = 0;
9129 return RETURN_OK;
9130}
9131
9132INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9133{
9134 return RETURN_OK;
9135}
9136INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9137{
9138 return RETURN_OK;
9139}
9140INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9141{
9142 return RETURN_OK;
9143}
9144INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9145{
9146 return RETURN_OK;
9147}
9148INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9149{
9150 return RETURN_OK;
9151}
9152INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9153{
9154 char config_file[MAX_BUF_SIZE] = {0};
9155 struct params list;
9156
9157 list.name = "bss_transition";
9158 list.value = activate?"1":"0";
9159 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9160 wifi_hostapdWrite(config_file, &list, 1);
9161
9162 return RETURN_OK;
9163}
9164wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9165
9166void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9167{
9168 return;
9169}
9170
9171INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9172{
9173 // TODO Implement me!
9174 return RETURN_OK;
9175}
9176
9177INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9178{
developera3c68b92022-09-13 15:27:29 +08009179 char file_name[128] = {0};
9180 char buf[128] = {0};
9181 FILE *f = NULL;
9182
9183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9184
9185 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9186 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
9187 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9188 f = fopen(file_name, "w");
9189 if (f == NULL)
9190 return RETURN_ERR;
9191 // For mode == 0 is to disable filter, just don't write to the file.
9192 if (mode)
9193 fprintf(f, "%s", essid);
9194
9195 fclose(f);
9196 }
9197 } else { // special case, need to set AP's SSID as filter for each radio.
9198 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9199 f = fopen(file_name, "w");
9200 if (f == NULL)
9201 return RETURN_ERR;
9202
9203 // For mode == 0 is to disable filter, just don't write to the file.
9204 if (mode)
9205 fprintf(f, "%s", essid);
9206
9207 fclose(f);
9208 }
9209
9210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009211 return RETURN_OK;
9212}
9213
9214INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9215{
9216 // TODO Implement me!
9217 //Apply wifi_pushRadioChannel() instantly
9218 return RETURN_ERR;
9219}
9220
9221INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9222{
9223 // TODO Implement me!
9224 return RETURN_OK;
9225}
9226
9227#ifdef HAL_NETLINK_IMPL
9228static int tidStats_callback(struct nl_msg *msg, void *arg) {
9229 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9230 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9231 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9232 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9233 int rem , tid_index = 0;
9234
9235 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9236 wifi_associated_dev_tid_entry_t *stats_entry;
9237
9238 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9239 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9240 };
9241 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9242 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9243 };
9244
9245 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9246 genlmsg_attrlen(gnlh, 0), NULL);
9247
9248
9249 if (!tb[NL80211_ATTR_STA_INFO]) {
9250 fprintf(stderr, "station stats missing!\n");
9251 return NL_SKIP;
9252 }
9253
9254 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9255 tb[NL80211_ATTR_STA_INFO],
9256 stats_policy)) {
9257 fprintf(stderr, "failed to parse nested attributes!\n");
9258 return NL_SKIP;
9259 }
9260
9261 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9262 {
9263 stats_entry = &out->tid_array[tid_index];
9264
9265 stats_entry->tid = tid_index;
9266 stats_entry->ac = _tid_ac_index_get[tid_index];
9267
9268 if(sinfo[NL80211_STA_INFO_TID_STATS])
9269 {
9270 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9271 printf("failed to parse nested stats attributes!");
9272 return NL_SKIP;
9273 }
9274 }
9275 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9276 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9277
9278 if(tid_index < (PS_MAX_TID - 1))
9279 tid_index++;
9280 }
9281 //ToDo: sum_time_ms, ewma_time_ms
9282 return NL_SKIP;
9283}
9284#endif
9285
9286INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9287{
9288#ifdef HAL_NETLINK_IMPL
9289 Netlink nl;
9290 char if_name[10];
9291
9292 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9293
9294 nl.id = initSock80211(&nl);
9295
9296 if (nl.id < 0) {
9297 fprintf(stderr, "Error initializing netlink \n");
9298 return -1;
9299 }
9300
9301 struct nl_msg* msg = nlmsg_alloc();
9302
9303 if (!msg) {
9304 fprintf(stderr, "Failed to allocate netlink message.\n");
9305 nlfree(&nl);
9306 return -2;
9307 }
9308
9309 genlmsg_put(msg,
9310 NL_AUTO_PORT,
9311 NL_AUTO_SEQ,
9312 nl.id,
9313 0,
9314 0,
9315 NL80211_CMD_GET_STATION,
9316 0);
9317
9318 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9319 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9320 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9321 nl_send_auto(nl.socket, msg);
9322 nl_recvmsgs(nl.socket, nl.cb);
9323 nlmsg_free(msg);
9324 nlfree(&nl);
9325 return RETURN_OK;
9326#else
9327//iw implementation
9328#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9329#define TOTAL_MAX_LINES 50
9330
9331 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9332 char if_name[10];
9333 FILE *fp=NULL;
9334 char pipeCmd[1024]= {'\0'};
9335 int lines,tid_index=0;
9336 char mac_addr[20] = {'\0'};
9337
9338 wifi_associated_dev_tid_entry_t *stats_entry;
9339
9340 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9341 strcpy(mac_addr,clientMacAddress);
9342
9343 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9344 fp= popen(pipeCmd,"r");
9345 if(fp == NULL)
9346 {
9347 perror("popen for station dump failed\n");
9348 return RETURN_ERR;
9349 }
9350 pclose(fp);
9351
9352 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9353 fp=popen(pipeCmd,"r");
9354 if(fp == NULL)
9355 {
9356 perror("popen for grep station failed\n");
9357 return RETURN_ERR;
9358 }
9359 else if(fgets(buf,sizeof(buf),fp) != NULL)
9360 lines=atoi(buf);
9361 else
9362 {
9363 pclose(fp);
9364 fprintf(stderr,"No devices are connected \n");
9365 return RETURN_ERR;
9366 }
9367 pclose(fp);
9368
9369 if(lines == 1)
9370 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9371
9372 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9373 {
9374 stats_entry = &tid_stats->tid_array[tid_index];
9375 stats_entry->tid = tid_index;
9376
9377 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);
9378
9379 fp=popen(pipeCmd,"r");
9380 if(fp ==NULL)
9381 {
9382 perror("Failed to read from tid file \n");
9383 return RETURN_ERR;
9384 }
9385 else if(fgets(buf,sizeof(buf),fp) != NULL)
9386 stats_entry->num_msdus = atol(buf);
9387
9388 pclose(fp);
9389 stats_entry->ac = _tid_ac_index_get[tid_index];
9390// TODO:
9391// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9392// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9393 }
9394 return RETURN_OK;
9395#endif
9396}
9397
9398
9399INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9400{
developer615510b2022-09-27 10:14:35 +08009401 char cmd[128]={0};
9402 char buf[128]={0};
9403 int freq = 0;
9404
9405 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9406
9407 // full mode is used to scan all channels.
9408 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9409 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9410 ieee80211_channel_to_frequency(chan_list[0], &freq);
9411
9412 if (freq)
9413 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9414 else
9415 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9416
9417 _syscmd(cmd, buf, sizeof(buf));
9418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9419
developer06a01d92022-09-07 16:32:39 +08009420 return RETURN_OK;
9421}
9422
9423
9424INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9425{
9426 // TODO Implement me!
9427 return RETURN_ERR;
9428}
9429
9430INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9431{
9432 // TODO Implement me!
9433 return RETURN_ERR;
9434}
9435
9436INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9437{
9438 // TODO Implement me!
9439 return RETURN_ERR;
9440}
9441
9442INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9443{
9444 // TODO Implement me!
9445 return RETURN_ERR;
9446}
9447
9448INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9449{
9450 // TODO Implement me!
9451 return RETURN_ERR;
9452}
9453
9454INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9455{
9456 // TODO Implement me!
9457 return RETURN_ERR;
9458}
9459
9460INT wifi_steering_eventUnregister(void)
9461{
9462 // TODO Implement me!
9463 return RETURN_ERR;
9464}
9465
9466INT wifi_delApAclDevices(INT apIndex)
9467{
9468#if 0
9469 char cmd[MAX_BUF_SIZE] = {0};
9470 char buf[MAX_BUF_SIZE] = {0};
9471
9472 /* Not reset proof solution */
9473 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9474 if(_syscmd(cmd,buf,sizeof(buf)))
9475 return RETURN_ERR;
9476#endif
developere6aafda2022-09-13 14:59:28 +08009477 char cmd[MAX_CMD_SIZE]={0};
9478 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009479
developere6aafda2022-09-13 14:59:28 +08009480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9481 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9482 if(_syscmd(cmd, buf, sizeof(buf)))
9483 return RETURN_ERR;
9484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009485
9486 return RETURN_OK;
9487}
9488
9489#ifdef HAL_NETLINK_IMPL
9490static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9491 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9492 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9493 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9494 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9495 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9496 char mac_addr[20],dev[20];
9497
9498 nla_parse(tb,
9499 NL80211_ATTR_MAX,
9500 genlmsg_attrdata(gnlh, 0),
9501 genlmsg_attrlen(gnlh, 0),
9502 NULL);
9503
9504 if(!tb[NL80211_ATTR_STA_INFO]) {
9505 fprintf(stderr, "sta stats missing!\n");
9506 return NL_SKIP;
9507 }
9508
9509 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9510 fprintf(stderr, "failed to parse nested attributes!\n");
9511 return NL_SKIP;
9512 }
9513 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9514
9515 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9516
9517 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9518 fprintf(stderr, "failed to parse nested rate attributes!");
9519 return NL_SKIP;
9520 }
9521
9522 if(sinfo[NL80211_STA_INFO_TID_STATS])
9523 {
9524 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9525 printf("failed to parse nested stats attributes!");
9526 return NL_SKIP;
9527 }
9528 }
9529
9530 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9531 {
9532 printf("Type is VHT\n");
9533 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9534 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9535
9536 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9537 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9538 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9539 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9540 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9541 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9542 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9543 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9544 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9545 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9546 }
9547 else
9548 {
9549 printf(" OFDM or CCK \n");
9550 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9551 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9552 }
9553
9554 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9555 if(rinfo[NL80211_RATE_INFO_MCS])
9556 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9557 }
9558 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9559 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9560 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9561 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9562
9563 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9564 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9565
9566 if (sinfo[NL80211_STA_INFO_SIGNAL])
9567 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9568 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9569 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9570 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9571 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9572 //rssi_array need to be filled
9573 return NL_SKIP;
9574}
9575#endif
9576
9577INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9578{
9579#ifdef HAL_NETLINK_IMPL
9580 Netlink nl;
9581 char if_name[10];
9582
9583 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9584
9585 if (*output_array_size <= 0)
9586 return RETURN_OK;
9587
9588 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9589 nl.id = initSock80211(&nl);
9590
9591 if (nl.id < 0) {
9592 fprintf(stderr, "Error initializing netlink \n");
9593 return 0;
9594 }
9595
9596 struct nl_msg* msg = nlmsg_alloc();
9597
9598 if (!msg) {
9599 fprintf(stderr, "Failed to allocate netlink message.\n");
9600 nlfree(&nl);
9601 return 0;
9602 }
9603
9604 genlmsg_put(msg,
9605 NL_AUTO_PORT,
9606 NL_AUTO_SEQ,
9607 nl.id,
9608 0,
9609 0,
9610 NL80211_CMD_GET_STATION,
9611 0);
9612
9613 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9614 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9615 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9616 nl_send_auto(nl.socket, msg);
9617 nl_recvmsgs(nl.socket, nl.cb);
9618 nlmsg_free(msg);
9619 nlfree(&nl);
9620 return RETURN_OK;
9621#else
9622 //TODO Implement me
9623 return RETURN_OK;
9624#endif
9625}
9626
9627#ifdef HAL_NETLINK_IMPL
9628static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9629 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9630 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9631 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9632 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9633 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9634 char mac_addr[20],dev[20];
9635
9636 nla_parse(tb,
9637 NL80211_ATTR_MAX,
9638 genlmsg_attrdata(gnlh, 0),
9639 genlmsg_attrlen(gnlh, 0),
9640 NULL);
9641
9642 if(!tb[NL80211_ATTR_STA_INFO]) {
9643 fprintf(stderr, "sta stats missing!\n");
9644 return NL_SKIP;
9645 }
9646
9647 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9648 fprintf(stderr, "failed to parse nested attributes!\n");
9649 return NL_SKIP;
9650 }
9651
9652 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9653
9654 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9655
9656 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9657 fprintf(stderr, "failed to parse nested rate attributes!");
9658 return NL_SKIP;
9659 }
9660
9661 if(sinfo[NL80211_STA_INFO_TID_STATS])
9662 {
9663 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9664 printf("failed to parse nested stats attributes!");
9665 return NL_SKIP;
9666 }
9667 }
9668 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9669 {
9670 printf("Type is VHT\n");
9671 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9672 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9673
9674 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9675 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9676 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9677 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9678 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9679 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9680 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9681 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9682 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9683 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9684 }
9685 else
9686 {
9687 printf(" OFDM or CCK \n");
9688 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9689 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9690 }
9691
9692 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9693 if(rinfo[NL80211_RATE_INFO_MCS])
9694 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9695 }
9696
9697 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9698 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9699 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9700 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9701
9702 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9703 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9704 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9705
9706 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9707 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9708
9709 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9710 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9711
9712 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9713 ((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]);
9714
9715 return NL_SKIP;
9716}
9717#endif
9718
9719INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9720{
9721#ifdef HAL_NETLINK_IMPL
9722 Netlink nl;
9723 char if_name[10];
9724
9725 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9726
9727 if (*output_array_size <= 0)
9728 return RETURN_OK;
9729
9730 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9731
9732 nl.id = initSock80211(&nl);
9733
9734 if(nl.id < 0) {
9735 fprintf(stderr, "Error initializing netlink \n");
9736 return 0;
9737 }
9738
9739 struct nl_msg* msg = nlmsg_alloc();
9740
9741 if(!msg) {
9742 fprintf(stderr, "Failed to allocate netlink message.\n");
9743 nlfree(&nl);
9744 return 0;
9745 }
9746
9747 genlmsg_put(msg,
9748 NL_AUTO_PORT,
9749 NL_AUTO_SEQ,
9750 nl.id,
9751 0,
9752 0,
9753 NL80211_CMD_GET_STATION,
9754 0);
9755
9756 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9757 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9758 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9759 nl_send_auto(nl.socket, msg);
9760 nl_recvmsgs(nl.socket, nl.cb);
9761 nlmsg_free(msg);
9762 nlfree(&nl);
9763 return RETURN_OK;
9764#else
9765 //TODO Implement me
9766 return RETURN_OK;
9767#endif
9768}
9769
9770INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9771{
9772 // TODO Implement me!
9773 char buf[MAX_BUF_SIZE] = {0};
9774 char config_file[MAX_BUF_SIZE] = {0};
9775
9776 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9777 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9778 *activate = (strncmp("1",buf,1) == 0);
9779
9780 return RETURN_OK;
9781}
9782
9783INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9784{
9785 char config_file[MAX_BUF_SIZE] = {0};
9786 struct params list;
9787
9788 list.name = "rrm_neighbor_report";
9789 list.value = activate?"1":"0";
9790 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9791 wifi_hostapdWrite(config_file, &list, 1);
9792
9793 return RETURN_OK;
9794}
9795
9796INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9797{
9798 char buf[32] = {0};
9799 char config_file[MAX_BUF_SIZE] = {0};
9800
9801 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9802 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9803 *activate = (strncmp("1",buf,1) == 0);
9804
9805 return RETURN_OK;
9806}
9807#undef HAL_NETLINK_IMPL
9808#ifdef HAL_NETLINK_IMPL
9809static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9810 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9811 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9812 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9813 char dev[20];
9814 int freq =0 ;
9815 static int i=0;
9816
9817 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9818
9819 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9820 };
9821
9822 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9823
9824 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9825
9826 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9827 fprintf(stderr, "survey data missing!\n");
9828 return NL_SKIP;
9829 }
9830
9831 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9832 {
9833 fprintf(stderr, "failed to parse nested attributes!\n");
9834 return NL_SKIP;
9835 }
9836
9837
9838 if(out[0].array_size == 1 )
9839 {
9840 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9841 {
9842 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9843 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9844 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9845
9846 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9847 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9848 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9849 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9850 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9851 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9852 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9853 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9854 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9855 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9856 if (sinfo[NL80211_SURVEY_INFO_TIME])
9857 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9858 return NL_STOP;
9859 }
9860 }
9861 else
9862 {
9863 if ( i <= out[0].array_size )
9864 {
9865 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9866 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9867 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9868
9869 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9870 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9871 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9872 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9873 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9874 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9875 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9876 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9877 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9878 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9879 if (sinfo[NL80211_SURVEY_INFO_TIME])
9880 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9881 }
9882 }
9883
9884 i++;
9885 return NL_SKIP;
9886}
9887#endif
9888
9889static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9890{
9891 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9892 FILE *fp;
9893
9894 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9895 {
9896 printf("Creating Frequency-Channel Map\n");
9897 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9898 }
9899 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9900 if((fp = popen(command, "r")))
9901 {
9902 fgets(output, sizeof(output), fp);
9903 *freqMHz = atoi(output);
9904 fclose(fp);
9905 }
9906
9907 return 0;
9908}
9909
9910static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9911{
9912 int freqMHz = -1;
9913 char cmd[MAX_CMD_SIZE] = {'\0'};
9914
9915 ieee80211_channel_to_frequency(channel, &freqMHz);
9916 if (freqMHz == -1) {
9917 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9918 return -1;
9919 }
9920
9921 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9922 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9923 radioIndex, freqMHz);
9924 return -1;
9925 }
9926
9927 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9928 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9929 return -1;
9930 }
9931
9932 return 0;
9933}
9934
9935static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9936{
9937 const char *ptr = buf;
9938 char *key = NULL;
9939 char *val = NULL;
9940 char line[256] = { '\0' };
9941
9942 while (ptr = get_line_from_str_buf(ptr, line)) {
9943 if (strstr(line, "Frequency")) continue;
9944
9945 key = strtok(line, ":");
9946 val = strtok(NULL, " ");
9947 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9948
9949 if (!strcmp(key, "noise")) {
9950 sscanf(val, "%d", &stats->ch_noise);
9951 if (stats->ch_noise == 0) {
9952 // Workaround for missing noise information.
9953 // Assume -95 for 2.4G and -103 for 5G
9954 if (radioIndex == 0) stats->ch_noise = -95;
9955 if (radioIndex == 1) stats->ch_noise = -103;
9956 }
9957 }
9958 else if (!strcmp(key, "channel active time")) {
9959 sscanf(val, "%llu", &stats->ch_utilization_total);
9960 }
9961 else if (!strcmp(key, "channel busy time")) {
9962 sscanf(val, "%llu", &stats->ch_utilization_busy);
9963 }
9964 else if (!strcmp(key, "channel receive time")) {
9965 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9966 }
9967 else if (!strcmp(key, "channel transmit time")) {
9968 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9969 }
9970 };
9971
9972 return 0;
9973}
9974
9975INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9976{
9977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9978#ifdef HAL_NETLINK_IMPL
9979 Netlink nl;
9980 wifi_channelStats_t_loc local[array_size];
9981 char if_name[10];
9982
9983 local[0].array_size = array_size;
9984
9985 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9986
9987 nl.id = initSock80211(&nl);
9988
9989 if (nl.id < 0) {
9990 fprintf(stderr, "Error initializing netlink \n");
9991 return -1;
9992 }
9993
9994 struct nl_msg* msg = nlmsg_alloc();
9995
9996 if (!msg) {
9997 fprintf(stderr, "Failed to allocate netlink message.\n");
9998 nlfree(&nl);
9999 return -2;
10000 }
10001
10002 genlmsg_put(msg,
10003 NL_AUTO_PORT,
10004 NL_AUTO_SEQ,
10005 nl.id,
10006 0,
10007 NLM_F_DUMP,
10008 NL80211_CMD_GET_SURVEY,
10009 0);
10010
10011 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10012 nl_send_auto(nl.socket, msg);
10013 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10014 nl_recvmsgs(nl.socket, nl.cb);
10015 nlmsg_free(msg);
10016 nlfree(&nl);
10017 //Copying the Values
10018 for(int i=0;i<array_size;i++)
10019 {
10020 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10021 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10022 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10023 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10024 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10025 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10026 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10027 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10028 }
10029#else
10030 ULONG channel = 0;
10031 int i;
10032 int number_of_channels = array_size;
10033 char buf[512];
10034 INT ret;
10035 wifi_channelStats_t tmp_stats;
10036
10037 if (number_of_channels == 0) {
10038 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10039 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10040 return RETURN_ERR;
10041 }
10042 number_of_channels = 1;
10043 input_output_channelStats_array[0].ch_number = channel;
10044 }
10045
10046 for (i = 0; i < number_of_channels; i++) {
10047
10048 input_output_channelStats_array[i].ch_noise = 0;
10049 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10050 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10051 input_output_channelStats_array[i].ch_utilization_busy = 0;
10052 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10053 input_output_channelStats_array[i].ch_utilization_total = 0;
10054
10055 memset(buf, 0, sizeof(buf));
10056 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10057 return RETURN_ERR;
10058 }
10059 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10060 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10061 return RETURN_ERR;
10062 }
10063
10064 // XXX: fake missing 'self' counter which is not available in iw survey output
10065 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10066 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10067
10068 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10069 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10070 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10071 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10072 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10073
10074 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",
10075 __func__,
10076 input_output_channelStats_array[i].ch_number,
10077 input_output_channelStats_array[i].ch_noise,
10078 input_output_channelStats_array[i].ch_utilization_total,
10079 input_output_channelStats_array[i].ch_utilization_busy,
10080 input_output_channelStats_array[i].ch_utilization_busy_rx,
10081 input_output_channelStats_array[i].ch_utilization_busy_tx,
10082 input_output_channelStats_array[i].ch_utilization_busy_self,
10083 input_output_channelStats_array[i].ch_utilization_busy_ext);
10084 }
10085#endif
10086 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10087 return RETURN_OK;
10088}
10089#define HAL_NETLINK_IMPL
10090
10091/* Hostapd events */
10092
10093#ifndef container_of
10094#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10095#define container_of(ptr, type, member) \
10096 ((type *)((char *)ptr - offset_of(type, member)))
10097#endif /* container_of */
10098
10099struct ctrl {
10100 char sockpath[128];
10101 char sockdir[128];
10102 char bss[IFNAMSIZ];
10103 char reply[4096];
10104 int ssid_index;
10105 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10106 void (*overrun)(struct ctrl *ctrl);
10107 struct wpa_ctrl *wpa;
10108 unsigned int ovfl;
10109 size_t reply_len;
10110 int initialized;
10111 ev_timer retry;
10112 ev_timer watchdog;
10113 ev_stat stat;
10114 ev_io io;
10115};
10116static wifi_newApAssociatedDevice_callback clients_connect_cb;
10117static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10118static struct ctrl wpa_ctrl[MAX_APS];
10119static int initialized;
10120
10121static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10122{
10123 char cbuf[256] = {};
10124 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10125 struct cmsghdr *cmsg;
10126 unsigned int ovfl = ctrl->ovfl;
10127 unsigned int drop;
10128
10129 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10130 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10131 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10132 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10133
10134 drop = ovfl - ctrl->ovfl;
10135 ctrl->ovfl = ovfl;
10136
10137 return drop;
10138}
10139
10140static void ctrl_close(struct ctrl *ctrl)
10141{
10142 if (ctrl->io.cb)
10143 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10144 if (ctrl->retry.cb)
10145 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10146 if (!ctrl->wpa)
10147 return;
10148
10149 wpa_ctrl_detach(ctrl->wpa);
10150 wpa_ctrl_close(ctrl->wpa);
10151 ctrl->wpa = NULL;
10152 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10153}
10154
10155static void ctrl_process(struct ctrl *ctrl)
10156{
10157 const char *str;
10158 int drops;
10159 int level;
10160 int err;
10161
10162 /* Example events:
10163 *
10164 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10165 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10166 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10167 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10168 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10169 */
10170 if (!(str = index(ctrl->reply, '>')))
10171 return;
10172 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10173 return;
10174
10175 str++;
10176
10177 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10178 if (!(str = index(ctrl->reply, ' ')))
10179 return;
10180 wifi_associated_dev_t sta;
10181 memset(&sta, 0, sizeof(sta));
10182
10183 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10184 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10185 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10186
10187 sta.cli_Active=true;
10188
10189 (clients_connect_cb)(ctrl->ssid_index, &sta);
10190 goto handled;
10191 }
10192
10193 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10194 if (!(str = index(ctrl->reply, ' ')))
10195 return;
10196
10197 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10198 goto handled;
10199 }
10200
10201 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10202 printf("CTRL_WPA: handle TERMINATING event\n");
10203 goto retry;
10204 }
10205
10206 if (strncmp("AP-DISABLED", str, 11) == 0) {
10207 printf("CTRL_WPA: handle AP-DISABLED\n");
10208 goto retry;
10209 }
10210
10211 printf("Event not supported!!\n");
10212
10213handled:
10214
10215 if ((drops = ctrl_get_drops(ctrl))) {
10216 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10217 if (ctrl->overrun)
10218 ctrl->overrun(ctrl);
10219 }
10220
10221 return;
10222
10223retry:
10224 printf("WPA_CTRL: closing\n");
10225 ctrl_close(ctrl);
10226 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10227 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10228}
10229
10230static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10231{
10232 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10233 int err;
10234
10235 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10236 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10237 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10238 ctrl->reply[ctrl->reply_len] = 0;
10239 if (err < 0) {
10240 if (errno == EAGAIN || errno == EWOULDBLOCK)
10241 return;
10242 ctrl_close(ctrl);
10243 ev_timer_again(EV_A_ &ctrl->retry);
10244 return;
10245 }
10246
10247 ctrl_process(ctrl);
10248}
10249
10250static int ctrl_open(struct ctrl *ctrl)
10251{
10252 int fd;
10253
10254 if (ctrl->wpa)
10255 return 0;
10256
10257 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10258 if (!ctrl->wpa)
10259 goto err;
10260
10261 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10262 goto err_close;
10263
10264 fd = wpa_ctrl_get_fd(ctrl->wpa);
10265 if (fd < 0)
10266 goto err_detach;
10267
10268 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10269 goto err_detach;
10270
10271 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10272 ev_io_start(EV_DEFAULT_ &ctrl->io);
10273
10274 return 0;
10275
10276err_detach:
10277 wpa_ctrl_detach(ctrl->wpa);
10278err_close:
10279 wpa_ctrl_close(ctrl->wpa);
10280err:
10281 ctrl->wpa = NULL;
10282 return -1;
10283}
10284
10285static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10286{
10287 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10288
10289 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10290 ctrl_open(ctrl);
10291}
10292
10293static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10294{
10295 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10296
10297 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10298 if (ctrl_open(ctrl) == 0) {
10299 printf("WPA_CTRL: retry successful\n");
10300 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10301 }
10302}
10303
10304int ctrl_enable(struct ctrl *ctrl)
10305{
10306 if (ctrl->wpa)
10307 return 0;
10308
10309 if (!ctrl->stat.cb) {
10310 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10311 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10312 }
10313
10314 if (!ctrl->retry.cb) {
10315 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10316 }
10317
10318 return ctrl_open(ctrl);
10319}
10320
10321static void
10322ctrl_msg_cb(char *buf, size_t len)
10323{
10324 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10325
10326 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10327 ctrl_process(ctrl);
10328}
10329
10330static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10331{
10332 int err;
10333
10334 if (!ctrl->wpa)
10335 return -1;
10336 if (*reply_len < 2)
10337 return -1;
10338
10339 (*reply_len)--;
10340 ctrl->reply_len = sizeof(ctrl->reply);
10341 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10342 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10343 if (err < 0)
10344 return err;
10345
10346 if (ctrl->reply_len > *reply_len)
10347 ctrl->reply_len = *reply_len;
10348
10349 *reply_len = ctrl->reply_len;
10350 memcpy(reply, ctrl->reply, *reply_len);
10351 reply[*reply_len - 1] = 0;
10352 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10353 return 0;
10354}
10355
10356static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10357{
10358 const char *pong = "PONG";
10359 const char *ping = "PING";
10360 char reply[1024];
10361 size_t len = sizeof(reply);
10362 int err;
10363 ULONG s, snum;
10364 INT ret;
10365 BOOL status;
10366
10367 printf("WPA_CTRL: watchdog cb\n");
10368
10369 ret = wifi_getSSIDNumberOfEntries(&snum);
10370 if (ret != RETURN_OK) {
10371 printf("%s: failed to get SSID count", __func__);
10372 return;
10373 }
10374
10375 if (snum > MAX_APS) {
10376 printf("more ssid than supported! %lu\n", snum);
10377 return;
10378 }
10379
10380 for (s = 0; s < snum; s++) {
10381 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10382 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10383 continue;
10384 }
10385 if (status == false) continue;
10386
10387 memset(reply, 0, sizeof(reply));
10388 len = sizeof(reply);
10389 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10390 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10391 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10392 continue;
10393
10394 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10395 ctrl_close(&wpa_ctrl[s]);
10396 printf("WPA_CTRL: ev_timer_again %d\n", s);
10397 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10398 }
10399}
10400
10401static int init_wpa()
10402{
10403 int ret = 0, i = 0;
10404 ULONG s, snum;
10405
10406 ret = wifi_getSSIDNumberOfEntries(&snum);
10407 if (ret != RETURN_OK) {
10408 printf("%s: failed to get SSID count", __func__);
10409 return RETURN_ERR;
10410 }
10411
10412 if (snum > MAX_APS) {
10413 printf("more ssid than supported! %lu\n", snum);
10414 return RETURN_ERR;
10415 }
10416
10417 for (s = 0; s < snum; s++) {
10418 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10419 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10420 wpa_ctrl[s].ssid_index = s;
10421 ctrl_enable(&wpa_ctrl[s]);
10422 }
10423
10424 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10425 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10426
10427 initialized = 1;
10428 printf("WPA_CTRL: initialized\n");
10429
10430 return RETURN_OK;
10431}
10432
10433void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10434{
10435 clients_connect_cb = callback_proc;
10436 if (!initialized)
10437 init_wpa();
10438}
10439
10440void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10441{
10442 clients_disconnect_cb = callback_proc;
10443 if (!initialized)
10444 init_wpa();
10445}
10446
10447INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10448{
10449 // TODO Implement me!
10450 return RETURN_ERR;
10451}
10452
10453INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10454{
10455 // TODO Implement me!
10456 return RETURN_ERR;
10457}
10458
10459INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10460{
10461 int i;
10462 char cmd[256];
10463 char channel_numbers_buf[256];
10464 char dfs_state_buf[256];
10465 char line[256];
10466 const char *ptr;
10467
10468 memset(cmd, 0, sizeof(cmd));
10469 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10470 memset(line, 0, sizeof(line));
10471 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10472 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10473
10474 if (radioIndex == 0) { // 2.4G - all allowed
10475 if (outputMapSize < 11) {
10476 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10477 return RETURN_ERR;
10478 }
10479
10480 for (i = 0; i < 11; i++) {
10481 outputMap[i].ch_number = i + 1;
10482 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10483 }
10484
10485 return RETURN_OK;
10486 }
10487
10488 if (radioIndex == 1) { // 5G
10489// Example output of iw list:
10490//
10491// Frequencies:
10492// * 5180 MHz [36] (17.0 dBm)
10493// * 5200 MHz [40] (17.0 dBm)
10494// * 5220 MHz [44] (17.0 dBm)
10495// * 5240 MHz [48] (17.0 dBm)
10496// * 5260 MHz [52] (23.0 dBm) (radar detection)
10497// DFS state: usable (for 78930 sec)
10498// DFS CAC time: 60000 ms
10499// * 5280 MHz [56] (23.0 dBm) (radar detection)
10500// DFS state: usable (for 78930 sec)
10501// DFS CAC time: 60000 ms
10502// * 5300 MHz [60] (23.0 dBm) (radar detection)
10503// DFS state: usable (for 78930 sec)
10504// DFS CAC time: 60000 ms
10505// * 5320 MHz [64] (23.0 dBm) (radar detection)
10506// DFS state: usable (for 78930 sec)
10507// DFS CAC time: 60000 ms
10508// * 5500 MHz [100] (disabled)
10509// * 5520 MHz [104] (disabled)
10510// * 5540 MHz [108] (disabled)
10511// * 5560 MHz [112] (disabled)
10512//
10513// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10514 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10515 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10516 return RETURN_ERR;
10517 }
10518
10519 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10520 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10521 return RETURN_ERR;
10522 }
10523
10524 ptr = channel_numbers_buf;
10525 i = 0;
10526 while (ptr = get_line_from_str_buf(ptr, line)) {
10527 if (i >= outputMapSize) {
10528 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10529 return RETURN_ERR;
10530 }
10531 sscanf(line, "%d", &outputMap[i].ch_number);
10532
10533 memset(cmd, 0, sizeof(cmd));
10534 // Below command should fetch string for DFS state (usable, available or unavailable)
10535 // Example line: "DFS state: usable (for 78930 sec)"
10536 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) {
10537 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10538 return RETURN_ERR;
10539 }
10540
10541 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10542 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10543 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10544 return RETURN_ERR;
10545 }
10546
10547 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10548
10549 if (!strcmp(dfs_state_buf, "usable")) {
10550 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10551 } else if (!strcmp(dfs_state_buf, "available")) {
10552 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10553 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10554 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10555 } else {
10556 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10557 }
10558 i++;
10559 }
10560
10561 return RETURN_OK;
10562 }
10563
10564 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10565 return RETURN_ERR;
10566}
10567
10568INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10569{
10570 // TODO Implement me!
10571 return RETURN_ERR;
10572}
10573
10574INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10575{
10576 return RETURN_OK;
10577}
10578
10579INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10580{
10581 // TODO Implement me!
10582 return RETURN_ERR;
10583}
10584
10585INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10586{
10587 // TODO API refrence Implementaion is present on RPI hal
10588 return RETURN_ERR;
10589}
10590
10591INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10592{
developera5005b62022-09-13 15:43:35 +080010593 char cmd[128]={'\0'};
10594 char buf[128]={'\0'};
10595 char *support;
10596 int maximum_tx = 0, current_tx = 0;
10597
10598 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10599 if(txpwr_pcntg == NULL)
10600 return RETURN_ERR;
10601
10602 // Get the maximum tx power of the device
10603 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10604 _syscmd(cmd, buf, sizeof(buf));
10605 maximum_tx = strtol(buf, NULL, 10);
10606
10607 // Get the current tx power
10608 memset(cmd, 0, sizeof(cmd));
10609 memset(buf, 0, sizeof(buf));
10610 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10611 _syscmd(cmd, buf, sizeof(buf));
10612 current_tx = strtol(buf, NULL, 10);
10613
10614 // Get the power supported list and find the current power percentage in supported list
10615 memset(buf, 0, sizeof(buf));
10616 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10617 support = strtok(buf, ",");
10618 while(true)
10619 {
10620 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10621 *txpwr_pcntg = 0;
10622 wifi_dbg_printf("current power is not in supported list\n");
10623 return RETURN_ERR;
10624 }
10625 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10626 if (tmp == current_tx) {
10627 *txpwr_pcntg = strtol(support, NULL, 10);
10628 break;
10629 }
10630 support = strtok(NULL, ",");
10631 }
10632 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010633 return RETURN_OK;
10634}
10635
10636INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10637{
developer58599c22022-09-13 16:40:34 +080010638 // TODO precac feature.
10639 struct params params = {0};
10640 char config_file[128] = {0};
10641
10642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10643
10644 params.name = "enable_background_radar";
10645 params.value = enable?"1":"0";
10646 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10647 wifi_hostapdWrite(config_file, &params, 1);
10648 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10649
10650 /* TODO precac feature */
10651
10652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10653 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010654}
10655
10656INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10657{
developer58599c22022-09-13 16:40:34 +080010658 char config_file[128] = {0};
10659 char buf[64] = {0};
10660
10661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10662 if (NULL == enable || NULL == precac)
10663 return RETURN_ERR;
10664
10665 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10666 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10667 if (strncmp(enable, "1", 1) == 0)
10668 *enable = true;
10669 else
10670 *enable = false;
10671
10672 /* TODO precac feature */
10673
10674 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10675 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010676}
10677
10678INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10679{
developer58599c22022-09-13 16:40:34 +080010680 *supported = TRUE;
10681 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010682}
10683
developer3e6b1692022-09-30 18:04:05 +080010684INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10685{
10686 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10687 struct params params = {0};
10688 char config_file[64] = {0};
10689 char buf[64] = {0};
10690 unsigned int set_mu_type = 0;
10691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10692
10693 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10694 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10695
10696 if (strlen(buf) > 0)
10697 set_mu_type = strtol(buf, NULL, 10);
10698
10699 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10700 set_mu_type &= ~0x05; // unset bit 0, 2
10701 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10702 set_mu_type |= 0x01;
10703 set_mu_type &= ~0x04;
10704 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10705 set_mu_type &= ~0x01;
10706 set_mu_type |= 0x04;
10707 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10708 set_mu_type |= 0x05; // set bit 0, 2
10709 }
10710
10711 params.name = "hemu_onoff";
10712 sprintf(buf, "%u", set_mu_type);
10713 params.value = buf;
10714 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10715 wifi_hostapdWrite(config_file, &params, 1);
10716 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10717
10718 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10719 return RETURN_OK;
10720}
10721
10722INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10723{
10724 struct params params={0};
10725 char config_file[64] = {0};
10726 char buf[64] = {0};
10727 unsigned int get_mu_type = 0;
10728
10729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10730
10731 if (mu_type == NULL)
10732 return RETURN_ERR;
10733
10734 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10735 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10736 get_mu_type = strtol(buf, NULL, 10);
10737
10738 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10739 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10740 else if (get_mu_type & 0x04)
10741 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10742 else if (get_mu_type & 0x01)
10743 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10744 else
10745 *mu_type = WIFI_DL_MU_TYPE_NONE;
10746
10747 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10748 return RETURN_OK;
10749}
10750
10751INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10752{
10753 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10754 struct params params={0};
10755 char config_file[64] = {0};
10756 char buf[64] = {0};
10757 unsigned int set_mu_type = 0;
10758 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10759
10760 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10761 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10762
10763 if (strlen(buf) > 0)
10764 set_mu_type = strtol(buf, NULL, 10);
10765
10766 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10767 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10768 set_mu_type &= ~0x0a;
10769 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10770 set_mu_type |= 0x02;
10771 set_mu_type &= ~0x08;
10772 }
10773
10774 params.name = "hemu_onoff";
10775 sprintf(buf, "%u", set_mu_type);
10776 params.value = buf;
10777 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10778 wifi_hostapdWrite(config_file, &params, 1);
10779 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10780
10781 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10782 return RETURN_OK;
10783}
10784
10785INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10786{
10787 struct params params={0};
10788 char config_file[64] = {0};
10789 char buf[64] = {0};
10790 unsigned int get_mu_type = 0;
10791
10792 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10793
10794 if (mu_type == NULL)
10795 return RETURN_ERR;
10796
10797 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10798 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10799
10800 get_mu_type = strtol(buf, NULL, 10);
10801 if (get_mu_type & 0x02)
10802 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10803 else
10804 *mu_type = WIFI_DL_MU_TYPE_NONE;
10805
10806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10807 return RETURN_OK;
10808}
10809
10810
developer454b9462022-09-13 15:29:16 +080010811INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10812{
10813 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010814 char buf[256] = {0};
10815 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010816 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010817 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010818 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010819 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010820
10821 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10822
developer254882b2022-09-30 17:12:31 +080010823 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010824 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10825 return RETURN_ERR;
10826 }
developer454b9462022-09-13 15:29:16 +080010827
developer254882b2022-09-30 17:12:31 +080010828 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010829 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010830
developer254882b2022-09-30 17:12:31 +080010831 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10832 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
10833 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
10834 _syscmd(cmd, buf, sizeof(buf));
10835 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10836 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10837 if (strstr(buf, "[SHORT-GI-") == NULL) {
10838 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
10839 _syscmd(cmd, buf, sizeof(buf));
10840 }
10841 if (band == band_5) {
10842 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10843 if (strstr(buf, "[SHORT-GI-") == NULL) {
10844 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
10845 _syscmd(cmd, buf, sizeof(buf));
10846 }
10847 }
10848 }
10849 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010850
developer254882b2022-09-30 17:12:31 +080010851 if (guard_interval == wifi_guard_interval_400)
10852 strcpy(GI, "0.4");
10853 else if (guard_interval == wifi_guard_interval_800)
10854 strcpy(GI, "0.8");
10855 else if (guard_interval == wifi_guard_interval_1600)
10856 strcpy(GI, "1.6");
10857 else if (guard_interval == wifi_guard_interval_3200)
10858 strcpy(GI, "3.2");
10859 else if (guard_interval == wifi_guard_interval_auto)
10860 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010861 // Record GI for get GI function
10862 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10863 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010864 if (f == NULL)
10865 return RETURN_ERR;
10866 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010867 fclose(f);
10868 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10869 return RETURN_OK;
10870}
10871
10872INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10873{
10874 char buf[32] = {0};
10875 char cmd[64] = {0};
10876
10877 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10878
10879 if (guard_interval == NULL)
10880 return RETURN_ERR;
10881
10882 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10883 _syscmd(cmd, buf, sizeof(buf));
10884
10885 if (strncmp(buf, "0.4", 3) == 0)
10886 *guard_interval = wifi_guard_interval_400;
10887 else if (strncmp(buf, "0.8", 3) == 0)
10888 *guard_interval = wifi_guard_interval_800;
10889 else if (strncmp(buf, "1.6", 3) == 0)
10890 *guard_interval = wifi_guard_interval_1600;
10891 else if (strncmp(buf, "3.2", 3) == 0)
10892 *guard_interval = wifi_guard_interval_3200;
10893 else
10894 *guard_interval = wifi_guard_interval_auto;
10895
10896 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10897 return RETURN_OK;
10898}
10899
developer3cc61d12022-09-13 16:36:05 +080010900INT wifi_setBSSColor(INT radio_index, UCHAR color)
10901{
10902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10903 struct params params = {0};
10904 char config_file[128] = {0};
10905 char bss_color[4] ={0};
10906
10907 params.name = "he_bss_color";
10908 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10909 params.value = bss_color;
10910 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10911 wifi_hostapdWrite(config_file, &params, 1);
10912 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10913
10914 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10915 return RETURN_OK;
10916}
10917
10918INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10919{
10920 char config_file[128] = {0};
10921 char buf[64] = {0};
10922 char temp_output[128] = {'\0'};
10923
10924 wifi_dbg_printf("\nFunc=%s\n", __func__);
10925 if (NULL == color)
10926 return RETURN_ERR;
10927
10928 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10929 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10930
10931 if(strlen(buf) > 0) {
10932 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10933 } else {
10934 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10935 }
10936
10937 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10938 wifi_dbg_printf("\noutput_string=%s\n", color);
10939
10940 return RETURN_OK;
10941}
10942
developer06a01d92022-09-07 16:32:39 +080010943/* multi-psk support */
10944INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10945{
10946 char cmd[256];
10947
10948 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10949 AP_PREFIX,
10950 apIndex,
10951 mac[0],
10952 mac[1],
10953 mac[2],
10954 mac[3],
10955 mac[4],
10956 mac[5]
10957 );
10958 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10959 _syscmd(cmd, key->wifi_keyId, 64);
10960
10961
10962 return RETURN_OK;
10963}
10964
10965INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10966{
10967 FILE *fd = NULL;
10968 char fname[100];
10969 char cmd[128] = {0};
10970 char out[64] = {0};
10971 wifi_key_multi_psk_t * key = NULL;
10972 if(keysNumber < 0)
10973 return RETURN_ERR;
10974
10975 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10976 fd = fopen(fname, "w");
10977 if (!fd) {
10978 return RETURN_ERR;
10979 }
10980 key= (wifi_key_multi_psk_t *) keys;
10981 for(int i=0; i<keysNumber; ++i, key++) {
10982 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10983 }
10984 fclose(fd);
10985
10986 //reload file
10987 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10988 _syscmd(cmd, out, 64);
10989 return RETURN_OK;
10990}
10991
10992INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10993{
10994 FILE *fd = NULL;
10995 char fname[100];
10996 char * line = NULL;
10997 char * pos = NULL;
10998 size_t len = 0;
10999 ssize_t read = 0;
11000 INT ret = RETURN_OK;
11001 wifi_key_multi_psk_t *keys_it = NULL;
11002
11003 if (keysNumber < 1) {
11004 return RETURN_ERR;
11005 }
11006
11007 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11008 fd = fopen(fname, "r");
11009 if (!fd) {
11010 return RETURN_ERR;
11011 }
11012
11013 if (keys == NULL) {
11014 ret = RETURN_ERR;
11015 goto close;
11016 }
11017
11018 keys_it = keys;
11019 while ((read = getline(&line, &len, fd)) != -1) {
11020 //Strip trailing new line if present
11021 if (read > 0 && line[read-1] == '\n') {
11022 line[read-1] = '\0';
11023 }
11024
11025 if(strcmp(line,"keyid=")) {
11026 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11027 if (!(pos = index(line, ' '))) {
11028 ret = RETURN_ERR;
11029 goto close;
11030 }
11031 pos++;
11032 //Here should be 00:00:00:00:00:00
11033 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11034 printf("Not supported MAC: %s\n", pos);
11035 }
11036 if (!(pos = index(pos, ' '))) {
11037 ret = RETURN_ERR;
11038 goto close;
11039 }
11040 pos++;
11041
11042 //The rest is PSK
11043 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11044 keys_it++;
11045
11046 if(--keysNumber <= 0)
11047 break;
11048 }
11049 }
11050
11051close:
11052 free(line);
11053 fclose(fd);
11054 return ret;
11055}
11056/* end of multi-psk support */
11057
11058INT wifi_setNeighborReports(UINT apIndex,
11059 UINT numNeighborReports,
11060 wifi_NeighborReport_t *neighborReports)
11061{
11062 char cmd[256] = { 0 };
11063 char hex_bssid[13] = { 0 };
11064 char bssid[18] = { 0 };
11065 char nr[256] = { 0 };
11066 char ssid[256];
11067 char hex_ssid[256];
11068 INT ret;
11069
11070 /*rmeove all neighbors*/
11071 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
11072 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);
11073 system(cmd);
11074
11075 for(unsigned int i = 0; i < numNeighborReports; i++)
11076 {
11077 memset(ssid, 0, sizeof(ssid));
11078 ret = wifi_getSSIDName(apIndex, ssid);
11079 if (ret != RETURN_OK)
11080 return RETURN_ERR;
11081
11082 memset(hex_ssid, 0, sizeof(hex_ssid));
11083 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11084 sprintf(hex_ssid + k,"%02x", ssid[j]);
11085
11086 snprintf(hex_bssid, sizeof(hex_bssid),
11087 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11088 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11089 snprintf(bssid, sizeof(bssid),
11090 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11091 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11092
11093 snprintf(nr, sizeof(nr),
11094 "%s" // bssid
11095 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11096 "%02hhx" // operclass
11097 "%02hhx" // channel
11098 "%02hhx", // phy_mode
11099 hex_bssid,
11100 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11101 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11102 neighborReports[i].opClass,
11103 neighborReports[i].channel,
11104 neighborReports[i].phyTable);
11105
11106 snprintf(cmd, sizeof(cmd),
11107 "hostapd_cli set_neighbor "
11108 "%s " // bssid
11109 "ssid=%s " // ssid
11110 "nr=%s " // nr
11111 "-i %s%d",
11112 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
11113
11114 if (WEXITSTATUS(system(cmd)) != 0)
11115 {
11116 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11117 }
11118 }
11119
11120 return RETURN_OK;
11121}
11122
11123INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11124{
11125 return RETURN_OK;
11126}
11127
11128#ifdef _WIFI_HAL_TEST_
11129int main(int argc,char **argv)
11130{
11131 int index;
11132 INT ret=0;
11133 char buf[1024]="";
11134
11135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11136 if(argc<3)
11137 {
11138 if(argc==2)
11139 {
11140 if(!strcmp(argv[1], "init"))
11141 return wifi_init();
11142 if(!strcmp(argv[1], "reset"))
11143 return wifi_reset();
11144 if(!strcmp(argv[1], "wifi_getHalVersion"))
11145 {
11146 char buffer[64];
11147 if(wifi_getHalVersion(buffer)==RETURN_OK)
11148 printf("Version: %s\n", buffer);
11149 else
11150 printf("Error in wifi_getHalVersion\n");
11151 return RETURN_OK;
11152 }
11153 }
11154 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11155 exit(-1);
11156 }
11157
11158 index = atoi(argv[2]);
11159 if(strstr(argv[1], "wifi_getApName")!=NULL)
11160 {
11161 wifi_getApName(index,buf);
11162 printf("Ap name is %s \n",buf);
11163 return 0;
11164 }
11165 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11166 {
11167 BOOL b = FALSE;
11168 BOOL *output_bool = &b;
11169 wifi_getRadioAutoChannelEnable(index,output_bool);
11170 printf("Channel enabled = %d \n",b);
11171 return 0;
11172 }
11173 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11174 {
11175 wifi_getApWpaEncryptionMode(index,buf);
11176 printf("encryption enabled = %s\n",buf);
11177 return 0;
11178 }
11179 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11180 {
11181 BOOL b = FALSE;
11182 BOOL *output_bool = &b;
11183 wifi_getApSsidAdvertisementEnable(index,output_bool);
11184 printf("advertisment enabled = %d\n",b);
11185 return 0;
11186 }
11187 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11188 {
11189 if(argc <= 3 )
11190 {
11191 printf("Insufficient arguments \n");
11192 exit(-1);
11193 }
11194
11195 char sta[20] = {'\0'};
11196 ULLONG handle= 0;
11197 strcpy(sta,argv[3]);
11198 mac_address_t st;
11199 mac_addr_aton(st,sta);
11200
11201 wifi_associated_dev_tid_stats_t tid_stats;
11202 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11203 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11204 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);
11205 }
11206
11207 if(strstr(argv[1], "getApEnable")!=NULL) {
11208 BOOL enable;
11209 ret=wifi_getApEnable(index, &enable);
11210 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11211 }
11212 else if(strstr(argv[1], "setApEnable")!=NULL) {
11213 BOOL enable = atoi(argv[3]);
11214 ret=wifi_setApEnable(index, enable);
11215 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11216 }
11217 else if(strstr(argv[1], "getApStatus")!=NULL) {
11218 char status[64];
11219 ret=wifi_getApStatus(index, status);
11220 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11221 }
11222 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11223 {
11224 wifi_getSSIDNameStatus(index,buf);
11225 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11226 return 0;
11227 }
11228 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11229 wifi_ssidTrafficStats2_t stats={0};
11230 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11231 printf("%s %d: returns %d\n", argv[1], index, ret);
11232 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11233 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11234 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11235 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11236 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11237 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11238 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11239 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11240 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11241 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11242 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11243 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11244 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11245 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11246 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11247 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11248 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11249 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11250 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11251 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11252 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11253 }
11254 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11255 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11256 UINT array_size=0;
11257 UINT i=0;
11258 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11259 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11260 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11261 printf(" neighbor %d:\n", i);
11262 printf(" ap_SSID =%s\n", pt->ap_SSID);
11263 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11264 printf(" ap_Mode =%s\n", pt->ap_Mode);
11265 printf(" ap_Channel =%d\n", pt->ap_Channel);
11266 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11267 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11268 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11269 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11270 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11271 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11272 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11273 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11274 printf(" ap_Noise =%d\n", pt->ap_Noise);
11275 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11276 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11277 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11278 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11279 }
11280 if(neighbor_ap_array)
11281 free(neighbor_ap_array); //make sure to free the list
11282 }
11283 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11284 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11285 UINT array_size=0;
11286 UINT i=0;
11287 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11288 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11289 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11290 printf(" associated_dev %d:\n", i);
11291 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11292 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11293 printf(" cli_SNR =%d\n", pt->cli_SNR);
11294 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11295 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11296 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11297 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11298 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11299 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11300 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11301 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11302 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11303 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11304 }
11305 if(associated_dev_array)
11306 free(associated_dev_array); //make sure to free the list
11307 }
11308
11309 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11310 {
11311#define MAX_ARRAY_SIZE 64
11312 int i, array_size;
11313 char *p, *ch_str;
11314 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11315
11316 if(argc != 5)
11317 {
11318 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11319 exit(-1);
11320 }
11321 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11322
11323 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11324 {
11325 strtok_r(ch_str, ",", &p);
11326 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11327 }
11328 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11329 if(!array_size)
11330 array_size=1;//Need to print current channel statistics
11331 for(i=0; i<array_size; i++)
11332 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11333 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11334 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11335 input_output_channelStats_array[i].ch_number,\
11336 input_output_channelStats_array[i].ch_noise,\
11337 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11338 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11339 input_output_channelStats_array[i].ch_utilization_busy,\
11340 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11341 input_output_channelStats_array[i].ch_utilization_total);
11342 }
11343
11344 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11345 {
11346 if(argc <= 3 )
11347 {
11348 printf("Insufficient arguments \n");
11349 exit(-1);
11350 }
11351 char mac_addr[20] = {'\0'};
11352 wifi_device_t output_struct;
11353 int dev_index = atoi(argv[3]);
11354
11355 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11356 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11357 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);
11358 }
11359
11360 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11361 {
11362 if (argc <= 3)
11363 {
11364 printf("Insufficient arguments\n");
11365 exit(-1);
11366 }
11367 char args[256];
11368 wifi_NeighborReport_t *neighborReports;
11369
11370 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11371 if (!neighborReports)
11372 {
11373 printf("Failed to allocate memory");
11374 exit(-1);
11375 }
11376
11377 for (int i = 3; i < argc; ++i)
11378 {
11379 char *val;
11380 int j = 0;
11381 memset(args, 0, sizeof(args));
11382 strncpy(args, argv[i], sizeof(args));
11383 val = strtok(args, ";");
11384 while (val != NULL)
11385 {
11386 if (j == 0)
11387 {
11388 mac_addr_aton(neighborReports[i - 3].bssid, val);
11389 } else if (j == 1)
11390 {
11391 neighborReports[i - 3].info = strtol(val, NULL, 16);
11392 } else if (j == 2)
11393 {
11394 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11395 } else if (j == 3)
11396 {
11397 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11398 } else if (j == 4)
11399 {
11400 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11401 } else {
11402 printf("Insufficient arguments]n\n");
11403 exit(-1);
11404 }
11405 val = strtok(NULL, ";");
11406 j++;
11407 }
11408 }
11409
11410 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11411 if (ret != RETURN_OK)
11412 {
11413 printf("wifi_setNeighborReports ret = %d", ret);
11414 exit(-1);
11415 }
11416 }
11417 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11418 {
11419 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11420 printf("%s.\n", buf);
11421 else
11422 printf("Error returned\n");
11423 }
11424 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11425 {
11426 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11427 printf("%s.\n", buf);
11428 else
11429 printf("Error returned\n");
11430 }
11431 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11432 {
11433 if (argc <= 2)
11434 {
11435 printf("Insufficient arguments\n");
11436 exit(-1);
11437 }
11438 char buf[64]= {'\0'};
11439 wifi_getRadioOperatingChannelBandwidth(index,buf);
11440 printf("Current bandwidth is %s \n",buf);
11441 return 0;
11442 }
11443 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11444 {
11445 if (argc <= 5)
11446 {
11447 printf("Insufficient arguments\n");
11448 exit(-1);
11449 }
11450 UINT channel = atoi(argv[3]);
11451 UINT width = atoi(argv[4]);
11452 UINT beacon = atoi(argv[5]);
11453 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11454 printf("Result = %d", ret);
11455 }
11456
11457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11458 return 0;
11459}
11460
11461#endif
11462
11463#ifdef WIFI_HAL_VERSION_3
11464
developer1e5aa162022-09-13 16:06:24 +080011465INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11466{
11467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11468 if (bitMap & WIFI_BITRATE_1MBPS)
11469 strcat(BasicRate, "1,");
11470 if (bitMap & WIFI_BITRATE_2MBPS)
11471 strcat(BasicRate, "2,");
11472 if (bitMap & WIFI_BITRATE_5_5MBPS)
11473 strcat(BasicRate, "5.5,");
11474 if (bitMap & WIFI_BITRATE_6MBPS)
11475 strcat(BasicRate, "6,");
11476 if (bitMap & WIFI_BITRATE_9MBPS)
11477 strcat(BasicRate, "9,");
11478 if (bitMap & WIFI_BITRATE_11MBPS)
11479 strcat(BasicRate, "11,");
11480 if (bitMap & WIFI_BITRATE_12MBPS)
11481 strcat(BasicRate, "12,");
11482 if (bitMap & WIFI_BITRATE_18MBPS)
11483 strcat(BasicRate, "18,");
11484 if (bitMap & WIFI_BITRATE_24MBPS)
11485 strcat(BasicRate, "24,");
11486 if (bitMap & WIFI_BITRATE_36MBPS)
11487 strcat(BasicRate, "36,");
11488 if (bitMap & WIFI_BITRATE_48MBPS)
11489 strcat(BasicRate, "48,");
11490 if (bitMap & WIFI_BITRATE_54MBPS)
11491 strcat(BasicRate, "54,");
11492 if (strlen(BasicRate) != 0) // remove last comma
11493 BasicRate[strlen(BasicRate) - 1] = '\0';
11494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11495 return RETURN_OK;
11496}
11497
11498INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11499{
11500 UINT BitMap = 0;
11501 char *rate;
11502
11503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11504 rate = strtok(BasicRatesList, ",");
11505 while(rate != NULL)
11506 {
11507 if (strcmp(rate, "1") == 0)
11508 BitMap |= WIFI_BITRATE_1MBPS;
11509 else if (strcmp(rate, "2") == 0)
11510 BitMap |= WIFI_BITRATE_2MBPS;
11511 else if (strcmp(rate, "5.5") == 0)
11512 BitMap |= WIFI_BITRATE_5_5MBPS;
11513 else if (strcmp(rate, "6") == 0)
11514 BitMap |= WIFI_BITRATE_6MBPS;
11515 else if (strcmp(rate, "9") == 0)
11516 BitMap |= WIFI_BITRATE_9MBPS;
11517 else if (strcmp(rate, "11") == 0)
11518 BitMap |= WIFI_BITRATE_11MBPS;
11519 else if (strcmp(rate, "12") == 0)
11520 BitMap |= WIFI_BITRATE_12MBPS;
11521 else if (strcmp(rate, "18") == 0)
11522 BitMap |= WIFI_BITRATE_18MBPS;
11523 else if (strcmp(rate, "24") == 0)
11524 BitMap |= WIFI_BITRATE_24MBPS;
11525 else if (strcmp(rate, "36") == 0)
11526 BitMap |= WIFI_BITRATE_36MBPS;
11527 else if (strcmp(rate, "48") == 0)
11528 BitMap |= WIFI_BITRATE_48MBPS;
11529 else if (strcmp(rate, "54") == 0)
11530 BitMap |= WIFI_BITRATE_54MBPS;
11531 rate = strtok(NULL, ",");
11532 }
11533 *basicRateBitMap = BitMap;
11534 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11535 return RETURN_OK;
11536}
11537
11538// 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 +080011539INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11540{
developer1e5aa162022-09-13 16:06:24 +080011541 char buf[128] = {0};
11542 char cmd[128] = {0};
11543 char config_file[64] = {0};
11544 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011545 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011546 wifi_radio_operationParam_t current_param;
11547
11548 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11549
11550 multiple_set = TRUE;
11551 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11552 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11553 return RETURN_ERR;
11554 }
11555 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11556 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11557 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11558 return RETURN_ERR;
11559 }
11560 }
developer5884e982022-10-06 10:52:50 +080011561
11562 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11563 bandwidth = 20;
11564 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11565 bandwidth = 40;
11566 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11567 bandwidth = 80;
11568 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11569 bandwidth = 160;
11570 if (operationParam->autoChannelEnabled){
11571 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11572 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11573 return RETURN_ERR;
11574 }
11575 }else{
developer1e5aa162022-09-13 16:06:24 +080011576 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11577 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11578 return RETURN_ERR;
11579 }
11580 }
developer5884e982022-10-06 10:52:50 +080011581
developer1e5aa162022-09-13 16:06:24 +080011582 if (current_param.variant != operationParam->variant) {
11583 // Two different definition bit map, so need to check every bit.
11584 if (operationParam->variant & WIFI_80211_VARIANT_A)
11585 set_mode |= WIFI_MODE_A;
11586 if (operationParam->variant & WIFI_80211_VARIANT_B)
11587 set_mode |= WIFI_MODE_B;
11588 if (operationParam->variant & WIFI_80211_VARIANT_G)
11589 set_mode |= WIFI_MODE_G;
11590 if (operationParam->variant & WIFI_80211_VARIANT_N)
11591 set_mode |= WIFI_MODE_N;
11592 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11593 set_mode |= WIFI_MODE_AC;
11594 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11595 set_mode |= WIFI_MODE_AX;
11596 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11597 memset(buf, 0, sizeof(buf));
11598 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11599 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11600 return RETURN_ERR;
11601 }
11602 }
11603 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11604 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11605 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11606 return RETURN_ERR;
11607 }
11608 }
11609 if (current_param.beaconInterval != operationParam->beaconInterval) {
11610 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11611 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11612 return RETURN_ERR;
11613 }
11614 }
11615 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11616 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11617 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11618 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11619 return RETURN_ERR;
11620 }
11621 }
11622 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11623 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11624 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11625 return RETURN_ERR;
11626 }
11627 }
11628 if (current_param.guardInterval != operationParam->guardInterval) {
11629 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11630 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11631 return RETURN_ERR;
11632 }
11633 }
11634 if (current_param.transmitPower != operationParam->transmitPower) {
11635 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11636 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11637 return RETURN_ERR;
11638 }
11639 }
11640 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11641 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11642 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11643 return RETURN_ERR;
11644 }
11645 }
11646 if (current_param.obssCoex != operationParam->obssCoex) {
11647 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11648 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11649 return RETURN_ERR;
11650 }
11651 }
11652 if (current_param.stbcEnable != operationParam->stbcEnable) {
11653 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11654 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11655 return RETURN_ERR;
11656 }
11657 }
11658 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11659 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11660 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11661 return RETURN_ERR;
11662 }
11663 }
11664
11665 // if enable is true, then restart the radio
11666 wifi_setRadioEnable(index, FALSE);
11667 if (operationParam->enable == TRUE)
11668 wifi_setRadioEnable(index, TRUE);
11669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11670
developer06a01d92022-09-07 16:32:39 +080011671 return RETURN_OK;
11672}
11673
11674INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11675{
developer1e5aa162022-09-13 16:06:24 +080011676 char band[64] = {0};
11677 char buf[256] = {0};
11678 char config_file[64] = {0};
11679 char cmd[128] = {0};
11680 int ret = RETURN_ERR;
11681 int mode = 0;
11682 ULONG channel = 0;
11683 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011684
11685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11686 printf("Entering %s index = %d\n", __func__, (int)index);
11687
developer1e5aa162022-09-13 16:06:24 +080011688 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11689 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11690 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011691 {
developer1e5aa162022-09-13 16:06:24 +080011692 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011693 return RETURN_ERR;
11694 }
11695 operationParam->enable = enabled;
11696
11697 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011698 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011699 {
developer1e5aa162022-09-13 16:06:24 +080011700 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011701 return RETURN_ERR;
11702 }
11703
11704 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011705 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011706 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011707 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011708 else if (!strcmp(band, "6GHz"))
11709 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011710 else
11711 {
developer1e5aa162022-09-13 16:06:24 +080011712 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011713 band);
11714 }
11715
developer1e5aa162022-09-13 16:06:24 +080011716 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11717 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11718 operationParam->channel = 0;
11719 operationParam->autoChannelEnabled = TRUE;
11720 } else {
11721 operationParam->channel = strtol(buf, NULL, 10);
11722 operationParam->autoChannelEnabled = FALSE;
11723 }
11724
developer06a01d92022-09-07 16:32:39 +080011725 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011726 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11727 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11728 return RETURN_ERR;
11729 }
developer06a01d92022-09-07 16:32:39 +080011730 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11731 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11732 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011733 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11734 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011735 else
11736 {
developer1e5aa162022-09-13 16:06:24 +080011737 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11738 return false;
developer06a01d92022-09-07 16:32:39 +080011739 }
11740
developer1e5aa162022-09-13 16:06:24 +080011741 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11742 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11743 return RETURN_ERR;
11744 }
11745 // Two different definition bit map, so need to check every bit.
11746 if (mode & WIFI_MODE_A)
11747 operationParam->variant |= WIFI_80211_VARIANT_A;
11748 if (mode & WIFI_MODE_B)
11749 operationParam->variant |= WIFI_80211_VARIANT_B;
11750 if (mode & WIFI_MODE_G)
11751 operationParam->variant |= WIFI_80211_VARIANT_G;
11752 if (mode & WIFI_MODE_N)
11753 operationParam->variant |= WIFI_80211_VARIANT_N;
11754 if (mode & WIFI_MODE_AC)
11755 operationParam->variant |= WIFI_80211_VARIANT_AC;
11756 if (mode & WIFI_MODE_AX)
11757 operationParam->variant |= WIFI_80211_VARIANT_AX;
11758 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11759 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11760 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011761 }
developer1e5aa162022-09-13 16:06:24 +080011762 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11763 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11764 return RETURN_ERR;
11765 }
11766 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11767 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11768 return RETURN_ERR;
11769 }
developer06a01d92022-09-07 16:32:39 +080011770
developer1e5aa162022-09-13 16:06:24 +080011771 memset(buf, 0, sizeof(buf));
11772 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11773 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11774 return RETURN_ERR;
11775 }
11776 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11777
11778 memset(buf, 0, sizeof(buf));
11779 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11780 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11781 return RETURN_ERR;
11782 }
11783 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11784
11785 memset(buf, 0, sizeof(buf));
11786 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11787 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11788
11789 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11790 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11791 return RETURN_ERR;
11792 }
11793 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11794 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11795 return RETURN_ERR;
11796 }
11797
11798 memset(buf, 0, sizeof(buf));
11799 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11800 if (strcmp(buf, "-1") == 0) {
11801 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11802 operationParam->ctsProtection = FALSE;
11803 } else {
11804 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11805 operationParam->ctsProtection = TRUE;
11806 }
11807
11808 memset(buf, 0, sizeof(buf));
11809 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11810 if (strcmp(buf, "0") == 0)
11811 operationParam->obssCoex = FALSE;
11812 else
11813 operationParam->obssCoex = TRUE;
11814
11815 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11816 _syscmd(cmd, buf, sizeof(buf));
11817 if (strlen(buf) != 0)
11818 operationParam->stbcEnable = TRUE;
11819 else
11820 operationParam->stbcEnable = FALSE;
11821
11822 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11823 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11824 return RETURN_ERR;
11825 }
11826
11827 // Below value is hardcoded
11828
11829 operationParam->numSecondaryChannels = 0;
11830 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11831 operationParam->channelSecondary[i] = 0;
11832 }
11833 operationParam->csa_beacon_count = 15;
11834 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011835
11836 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11837 return RETURN_OK;
11838}
11839
11840static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11841{
developerc086fb72022-10-04 10:18:22 +080011842 int max_radio_num = 0;
11843
11844 wifi_getMaxRadioNumber(&max_radio_num);
11845 if (radioIndex >= max_radio_num || radioIndex < 0) {
11846 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11847 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011848 }
11849
developerc086fb72022-10-04 10:18:22 +080011850 return (arrayIndex * max_radio_num) + radioIndex;
11851}
developer06a01d92022-09-07 16:32:39 +080011852
developerc086fb72022-10-04 10:18:22 +080011853wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11854 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11855 return WIFI_BITRATE_1MBPS;
11856 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11857 return WIFI_BITRATE_2MBPS;
11858 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11859 return WIFI_BITRATE_5_5MBPS;
11860 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11861 return WIFI_BITRATE_6MBPS;
11862 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11863 return WIFI_BITRATE_9MBPS;
11864 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11865 return WIFI_BITRATE_11MBPS;
11866 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11867 return WIFI_BITRATE_12MBPS;
11868 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11869 return WIFI_BITRATE_18MBPS;
11870 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11871 return WIFI_BITRATE_24MBPS;
11872 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11873 return WIFI_BITRATE_36MBPS;
11874 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11875 return WIFI_BITRATE_48MBPS;
11876 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11877 return WIFI_BITRATE_54MBPS;
11878 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011879}
11880
developer1d57d002022-10-12 18:03:15 +080011881INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
11882{
11883 if (beacon == WIFI_BITRATE_1MBPS)
11884 strcpy(beacon_str, "1Mbps");
11885 else if (beacon == WIFI_BITRATE_2MBPS)
11886 strcpy(beacon_str, "2Mbps");
11887 else if (beacon == WIFI_BITRATE_5_5MBPS)
11888 strcpy(beacon_str, "5.5Mbps");
11889 else if (beacon == WIFI_BITRATE_6MBPS)
11890 strcpy(beacon_str, "6Mbps");
11891 else if (beacon == WIFI_BITRATE_9MBPS)
11892 strcpy(beacon_str, "9Mbps");
11893 else if (beacon == WIFI_BITRATE_11MBPS)
11894 strcpy(beacon_str, "11Mbps");
11895 else if (beacon == WIFI_BITRATE_12MBPS)
11896 strcpy(beacon_str, "12Mbps");
11897 else if (beacon == WIFI_BITRATE_18MBPS)
11898 strcpy(beacon_str, "18Mbps");
11899 else if (beacon == WIFI_BITRATE_24MBPS)
11900 strcpy(beacon_str, "24Mbps");
11901 else if (beacon == WIFI_BITRATE_36MBPS)
11902 strcpy(beacon_str, "36Mbps");
11903 else if (beacon == WIFI_BITRATE_48MBPS)
11904 strcpy(beacon_str, "48Mbps");
11905 else if (beacon == WIFI_BITRATE_54MBPS)
11906 strcpy(beacon_str, "54Mbps");
11907 return RETURN_OK;
11908}
11909
developer06a01d92022-09-07 16:32:39 +080011910INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11911{
developerc086fb72022-10-04 10:18:22 +080011912 INT mode = 0;
11913 INT ret = -1;
11914 INT output = 0;
11915 int i = 0;
11916 int vap_index = 0;
11917 BOOL enabled = FALSE;
11918 char buf[256] = {0};
11919 wifi_vap_security_t security;
11920 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011921
11922 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11923 printf("Entering %s index = %d\n", __func__, (int)index);
11924
developer06a01d92022-09-07 16:32:39 +080011925 for (i = 0; i < 5; i++)
11926 {
developerc086fb72022-10-04 10:18:22 +080011927 map->vap_array[i].radio_index = index;
11928
developer06a01d92022-09-07 16:32:39 +080011929 vap_index = array_index_to_vap_index(index, i);
11930 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011931 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011932
developerc086fb72022-10-04 10:18:22 +080011933 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011934
11935 map->vap_array[i].vap_index = vap_index;
11936
11937 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011938 ret = wifi_getApName(vap_index, buf);
11939 if (ret != RETURN_OK) {
11940 printf("%s: wifi_getApName return error\n", __func__);
11941 return RETURN_ERR;
11942 }
11943 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
11944
11945 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080011946 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080011947 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080011948 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080011949 return RETURN_ERR;
11950 }
11951 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 +080011952
11953 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080011954 if (ret != RETURN_OK) {
11955 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011956 return RETURN_ERR;
11957 }
11958 map->vap_array[i].u.bss_info.enabled = enabled;
11959
developerc086fb72022-10-04 10:18:22 +080011960 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
11961 if (ret != RETURN_OK) {
11962 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
11963 return RETURN_ERR;
11964 }
developer06a01d92022-09-07 16:32:39 +080011965 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080011966
11967 ret = wifi_getApIsolationEnable(vap_index, &enabled);
11968 if (ret != RETURN_OK) {
11969 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
11970 return RETURN_ERR;
11971 }
11972 map->vap_array[i].u.bss_info.isolation = enabled;
11973
11974 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
11975 if (ret != RETURN_OK) {
11976 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
11977 return RETURN_ERR;
11978 }
11979 map->vap_array[i].u.bss_info.bssMaxSta = output;
11980
11981 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
11982 if (ret != RETURN_OK) {
11983 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
11984 return RETURN_ERR;
11985 }
11986 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011987
developerc086fb72022-10-04 10:18:22 +080011988 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
11989 if (ret != RETURN_OK) {
11990 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
11991 return RETURN_ERR;
11992 }
11993 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011994
developerc086fb72022-10-04 10:18:22 +080011995 ret = wifi_getApSecurity(vap_index, &security);
11996 if (ret != RETURN_OK) {
11997 printf("%s: wifi_getApSecurity return error\n", __func__);
11998 return RETURN_ERR;
11999 }
12000 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012001
developerc086fb72022-10-04 10:18:22 +080012002 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12003 if (ret != RETURN_OK) {
12004 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12005 return RETURN_ERR;
12006 }
12007 if (mode == 0)
12008 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12009 else
12010 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12011 if (mode == 1)
12012 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12013 else if (mode == 2)
12014 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012015
developerc086fb72022-10-04 10:18:22 +080012016 ret = wifi_getApWmmEnable(vap_index, &enabled);
12017 if (ret != RETURN_OK) {
12018 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12019 return RETURN_ERR;
12020 }
12021 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012022
developerc086fb72022-10-04 10:18:22 +080012023 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12024 if (ret != RETURN_OK) {
12025 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012026 return RETURN_ERR;
12027 }
developerc086fb72022-10-04 10:18:22 +080012028 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012029
12030 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012031 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012032 if (ret != RETURN_OK) {
12033 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12034 return RETURN_ERR;
12035 }
12036 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012037
developerc086fb72022-10-04 10:18:22 +080012038 memset(buf, 0, sizeof(buf));
12039 ret = wifi_getBaseBSSID(vap_index, buf);
12040 if (ret != RETURN_OK) {
12041 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12042 return RETURN_ERR;
12043 }
12044 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12045 &map->vap_array[i].u.bss_info.bssid[0],
12046 &map->vap_array[i].u.bss_info.bssid[1],
12047 &map->vap_array[i].u.bss_info.bssid[2],
12048 &map->vap_array[i].u.bss_info.bssid[3],
12049 &map->vap_array[i].u.bss_info.bssid[4],
12050 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012051 // fprintf(stderr, "%s index %d: mac: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", __func__, vap_index, map->vap_array[i].u.bss_info.bssid[0], map->vap_array[i].u.bss_info.bssid[1], map->vap_array[i].u.bss_info.bssid[2], map->vap_array[i].u.bss_info.bssid[3], map->vap_array[i].u.bss_info.bssid[4], map->vap_array[i].u.bss_info.bssid[5]);
12052
12053 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12054 if (ret != RETURN_OK) {
12055 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12056 return RETURN_ERR;
12057 }
12058 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012059
developerc086fb72022-10-04 10:18:22 +080012060 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012061 }
12062 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12063 return RETURN_OK;
12064}
12065
12066INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12067{
12068 unsigned int i;
12069 wifi_vap_info_t *vap_info = NULL;
12070 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012071 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012072 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012073 char buf[256] = {0};
12074 char cmd[128] = {0};
12075 char config_file[64] = {0};
12076 char bssid[32] = {0};
12077 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012078
12079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12080 printf("Entering %s index = %d\n", __func__, (int)index);
12081 for (i = 0; i < map->num_vaps; i++)
12082 {
developer1d57d002022-10-12 18:03:15 +080012083 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012084 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012085 if (vap_info->u.bss_info.enabled == FALSE)
12086 continue;
developer06a01d92022-09-07 16:32:39 +080012087
developer1d57d002022-10-12 18:03:15 +080012088 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12089
12090 // multi-ap need to copy current radio config
12091 if (vap_info->radio_index != vap_info->vap_index) {
12092 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12093 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012094 }
developer06a01d92022-09-07 16:32:39 +080012095
developer1d57d002022-10-12 18:03:15 +080012096 struct params params[3];
12097 snprintf(vap_info->vap_name, 64, "%s%d", AP_PREFIX, vap_info->vap_index);
12098 params[0].name = "interface";
12099 params[0].value = vap_info->vap_name;
12100 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12101 params[1].name = "bssid";
12102 params[1].value = bssid;
12103 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12104 params[2].name = "wpa_psk_file";
12105 params[2].value = psk_file;
12106
12107 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12108 wifi_hostapdWrite(config_file, params, 3);
12109
12110 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12111 _syscmd(cmd, buf, sizeof(buf));
12112
12113 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12114 if (ret != RETURN_OK) {
12115 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12116 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012117 }
developer1d57d002022-10-12 18:03:15 +080012118
12119 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12120 if (ret != RETURN_OK) {
12121 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12122 return RETURN_ERR;
12123 }
12124
12125 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12126 if (ret != RETURN_OK) {
12127 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12128 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012129 }
12130
developer1d57d002022-10-12 18:03:15 +080012131 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12132 if (ret != RETURN_OK) {
12133 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12134 return RETURN_ERR;
12135 }
developer06a01d92022-09-07 16:32:39 +080012136
developer1d57d002022-10-12 18:03:15 +080012137 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12138 if (ret != RETURN_OK) {
12139 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12140 return RETURN_ERR;
12141 }
developer06a01d92022-09-07 16:32:39 +080012142
developer1d57d002022-10-12 18:03:15 +080012143 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12144 if (ret != RETURN_OK) {
12145 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12146 return RETURN_ERR;
12147 }
12148
12149 if (vap_info->u.bss_info.mac_filter_enable == false)
12150 acl_mode = 0;
12151 else {
12152 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list)
12153 acl_mode = 2;
12154 else
12155 acl_mode = 1;
12156 }
12157
12158 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12159 if (ret != RETURN_OK) {
12160 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12161 return RETURN_ERR;
12162 }
12163
12164 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12165 if (ret != RETURN_OK) {
12166 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12167 return RETURN_ERR;
12168 }
12169
12170 memset(buf, 0, sizeof(buf));
12171 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12172 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12173 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12174 if (ret != RETURN_OK) {
12175 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12176 return RETURN_ERR;
12177 }
12178
12179 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12180 if (ret != RETURN_OK) {
12181 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12182 return RETURN_ERR;
12183 }
12184
12185 wifi_setApEnable(vap_info->vap_index, TRUE);
12186 multiple_set = FALSE;
12187
12188 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12189 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12190 if (ret != RETURN_OK) {
12191 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12192 return RETURN_ERR;
12193 }
12194
12195 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12196 if (ret != RETURN_OK) {
12197 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12198 return RETURN_ERR;
12199 }
developer06a01d92022-09-07 16:32:39 +080012200
developer1d57d002022-10-12 18:03:15 +080012201 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012202 }
12203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12204 return RETURN_OK;
12205}
12206
12207int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12208{
12209 char *token, *next;
12210 const char s[2] = ",";
12211 int count =0;
12212
12213 /* get the first token */
12214 token = strtok_r(pchannels, s, &next);
12215
12216 /* walk through other tokens */
12217 while( token != NULL && count < MAX_CHANNELS) {
12218 chlistptr->channels_list[count++] = atoi(token);
12219 token = strtok_r(NULL, s, &next);
12220 }
12221
12222 return count;
12223}
12224
12225static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12226{
12227 INT status;
12228 wifi_channels_list_t *chlistp;
12229 CHAR output_string[64];
12230 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012231 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080012232
12233 if(rcap == NULL)
12234 {
12235 return RETURN_ERR;
12236 }
12237
12238 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012239 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012240
developer1e5aa162022-09-13 16:06:24 +080012241 if (band == band_2_4)
12242 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12243 else if (band == band_5)
12244 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12245 else if (band == band_6)
12246 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012247
12248 chlistp = &(rcap->channel_list[0]);
12249 memset(pchannels, 0, sizeof(pchannels));
12250
12251 /* possible number of radio channels */
12252 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12253 {
12254 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12255 }
12256 /* Number of channels and list*/
12257 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12258
12259 /* autoChannelSupported */
12260 /* always ON with wifi_getRadioAutoChannelSupported */
12261 rcap->autoChannelSupported = TRUE;
12262
12263 /* DCSSupported */
12264 /* always ON with wifi_getRadioDCSSupported */
12265 rcap->DCSSupported = TRUE;
12266
12267 /* zeroDFSSupported - TBD */
12268 rcap->zeroDFSSupported = FALSE;
12269
12270 /* Supported Country List*/
12271 memset(output_string, 0, sizeof(output_string));
12272 status = wifi_getRadioCountryCode(radioIndex, output_string);
12273 if( status != 0 ) {
12274 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12275 return RETURN_ERR;
12276 } else {
12277 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12278 }
12279 if(!strcmp(output_string,"US")){
12280 rcap->countrySupported[0] = wifi_countrycode_US;
12281 rcap->countrySupported[1] = wifi_countrycode_CA;
12282 } else if (!strcmp(output_string,"CA")) {
12283 rcap->countrySupported[0] = wifi_countrycode_CA;
12284 rcap->countrySupported[1] = wifi_countrycode_US;
12285 } else {
12286 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12287 }
12288
12289 rcap->numcountrySupported = 2;
12290
12291 /* csi */
12292 rcap->csi.maxDevices = 8;
12293 rcap->csi.soudingFrameSupported = TRUE;
12294
12295 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
12296
12297 /* channelWidth - all supported bandwidths */
12298 int i=0;
12299 rcap->channelWidth[i] = 0;
12300 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12301 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12302 WIFI_CHANNELBANDWIDTH_40MHZ);
12303
12304 }
developer1e5aa162022-09-13 16:06:24 +080012305 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012306 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12307 WIFI_CHANNELBANDWIDTH_40MHZ |
12308 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12309 }
12310
12311
12312 /* mode - all supported variants */
12313 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12314 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012315 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 +080012316 }
12317 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012318 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12319 }
12320 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12321 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012322 }
12323 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12324 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12325
12326 /* supportedBitRate - all supported bitrates */
12327 rcap->supportedBitRate[i] = 0;
12328 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12329 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12330 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12331 }
developer1e5aa162022-09-13 16:06:24 +080012332 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012333 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12334 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12335 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12336 }
12337
12338
12339 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12340 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12341 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12342 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12343 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12344 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12345 rcap->cipherSupported = 0;
12346 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12347 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12348
12349 return RETURN_OK;
12350}
12351
12352INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12353{
12354 INT status, radioIndex;
12355 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12356 int iter = 0;
12357 unsigned int j;
12358 wifi_interface_name_idex_map_t *iface_info;
12359
12360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12361
12362 memset(cap, 0, sizeof(wifi_hal_capability_t));
12363
12364 /* version */
12365 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12366 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12367
12368 /* number of radios platform property */
12369 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12370 _syscmd(cmd, output, sizeof(output));
12371 cap->wifi_prop.numRadios = atoi(output);
12372
12373 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12374 {
12375 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12376 if (status != 0) {
12377 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12378 return RETURN_ERR;
12379 }
12380
12381 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12382 {
12383 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12384 {
12385 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12386 return RETURN_ERR;
12387 }
12388 iface_info = &cap->wifi_prop.interface_map[iter];
12389 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12390 iface_info->rdk_radio_index = radioIndex;
12391 memset(output, 0, sizeof(output));
12392 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12393 {
12394 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12395 }
12396 // TODO: bridge name
12397 // TODO: vlan id
12398 // TODO: primary
12399 iface_info->index = array_index_to_vap_index(radioIndex, j);
12400 memset(output, 0, sizeof(output));
12401 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12402 {
12403 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12404 }
12405 iter++;
12406 }
12407 }
12408
12409 cap->BandSteeringSupported = FALSE;
12410 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12411 return RETURN_OK;
12412}
12413
developer9df4e652022-10-11 11:27:38 +080012414INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12415{
12416 struct params h_config={0};
12417 char config_file[64] = {0};
12418
12419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12420
12421 h_config.name = "okc";
12422 h_config.value = okc_enable?"1":"0";
12423
12424 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12425 wifi_hostapdWrite(config_file, &h_config, 1);
12426 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12427
12428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12429 return RETURN_OK;
12430}
12431
12432INT wifi_setSAEMFP(int ap_index, BOOL enable)
12433{
12434 struct params h_config={0};
12435 char config_file[64] = {0};
12436 char buf[128] = {0};
12437
12438 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12439
12440 h_config.name = "sae_require_mfp";
12441 h_config.value = enable?"1":"0";
12442
12443 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12444 wifi_hostapdWrite(config_file, &h_config, 1);
12445 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12446
12447 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12448 return RETURN_OK;
12449}
12450
12451INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12452{
12453 struct params h_config={0};
12454 char config_file[64] = {0};
12455 char buf[128] = {0};
12456
12457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12458
12459 h_config.name = "sae_pwe";
12460 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12461 h_config.value = buf;
12462
12463 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12464 wifi_hostapdWrite(config_file, &h_config, 1);
12465 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12466
12467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12468 return RETURN_OK;
12469}
12470
12471INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12472{
12473 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12474 struct params h_config={0};
12475 char config_file[64] = {0};
12476
12477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12478
12479 h_config.name = "wpa_disable_eapol_key_retries";
12480 h_config.value = disable_EAPOL_retries?"1":"0";
12481
12482 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12483 wifi_hostapdWrite(config_file, &h_config, 1);
12484 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12485
12486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12487 return RETURN_OK;
12488}
12489
developer06a01d92022-09-07 16:32:39 +080012490INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12491{
developer587c1b62022-09-27 15:58:59 +080012492 char buf[128] = {0};
12493 char config_file[128] = {0};
12494 char password[64] = {0};
12495 char mfp[32] = {0};
12496 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012497 BOOL okc_enable = FALSE;
12498 BOOL sae_MFP = FALSE;
12499 BOOL disable_EAPOL_retries = TRUE;
12500 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012501 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012502 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012503
12504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12505
12506 multiple_set = TRUE;
12507 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12508 if (security->mode == wifi_security_mode_none) {
12509 strcpy(wpa_mode, "None");
12510 } else if (security->mode == wifi_security_mode_wpa_personal)
12511 strcpy(wpa_mode, "WPA-Personal");
12512 else if (security->mode == wifi_security_mode_wpa2_personal)
12513 strcpy(wpa_mode, "WPA2-Personal");
12514 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12515 strcpy(wpa_mode, "WPA-WPA2-Personal");
12516 else if (security->mode == wifi_security_mode_wpa_enterprise)
12517 strcpy(wpa_mode, "WPA-Enterprise");
12518 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12519 strcpy(wpa_mode, "WPA2-Enterprise");
12520 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12521 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012522 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012523 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012524 okc_enable = TRUE;
12525 sae_MFP = TRUE;
12526 sae_pwe = 2;
12527 disable_EAPOL_retries = FALSE;
12528 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012529 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012530 okc_enable = TRUE;
12531 sae_MFP = TRUE;
12532 sae_pwe = 2;
12533 disable_EAPOL_retries = FALSE;
12534 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012535 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012536 sae_MFP = TRUE;
12537 sae_pwe = 2;
12538 disable_EAPOL_retries = FALSE;
12539 }
12540
12541 band = wifi_index_to_band(ap_index);
12542 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12543 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12544 return RETURN_ERR;
12545 }
developer587c1b62022-09-27 15:58:59 +080012546
12547 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012548 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012549 wifi_setSAEMFP(ap_index, sae_MFP);
12550 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012551 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012552
developer9df4e652022-10-11 11:27:38 +080012553 if (security->mode != wifi_security_mode_none) {
12554 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12555 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12556 password[63] = '\0';
12557 wifi_setApSecurityKeyPassphrase(ap_index, password);
12558 }
12559 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12560 params.name = "sae_password";
12561 params.value = security->u.key.key;
12562 wifi_hostapdWrite(config_file, &params, 1);
12563 }
12564 }
developer587c1b62022-09-27 15:58:59 +080012565
12566 if (security->mode != wifi_security_mode_none) {
12567 memset(&params, 0, sizeof(params));
12568 params.name = "wpa_pairwise";
12569 if (security->encr == wifi_encryption_tkip)
12570 params.value = "TKIP";
12571 else if (security->encr == wifi_encryption_aes)
12572 params.value = "CCMP";
12573 else if (security->encr == wifi_encryption_aes_tkip)
12574 params.value = "TKIP CCMP";
12575 wifi_hostapdWrite(config_file, &params, 1);
12576 }
12577
12578 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012579 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012580 else if (security->mfp == wifi_mfp_cfg_optional)
12581 strcpy(mfp, "Optional");
12582 else if (security->mfp == wifi_mfp_cfg_required)
12583 strcpy(mfp, "Required");
12584 wifi_setApSecurityMFPConfig(ap_index, mfp);
12585
12586 memset(&params, 0, sizeof(params));
12587 params.name = "transition_disable";
12588 if (security->wpa3_transition_disable == TRUE)
12589 params.value = "0x01";
12590 else
12591 params.value = "0x00";
12592 wifi_hostapdWrite(config_file, &params, 1);
12593
12594 memset(&params, 0, sizeof(params));
12595 params.name = "wpa_group_rekey";
12596 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12597 params.value = buf;
12598 wifi_hostapdWrite(config_file, &params, 1);
12599
12600 memset(&params, 0, sizeof(params));
12601 params.name = "wpa_strict_rekey";
12602 params.value = security->strict_rekey?"1":"0";
12603 wifi_hostapdWrite(config_file, &params, 1);
12604
12605 memset(&params, 0, sizeof(params));
12606 params.name = "wpa_pairwise_update_count";
12607 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12608 params.value = buf;
12609 wifi_hostapdWrite(config_file, &params, 1);
12610
12611 memset(&params, 0, sizeof(params));
12612 params.name = "disable_pmksa_caching";
12613 params.value = security->disable_pmksa_caching?"1":"0";
12614 wifi_hostapdWrite(config_file, &params, 1);
12615
12616 wifi_setApEnable(ap_index, FALSE);
12617 wifi_setApEnable(ap_index, TRUE);
12618
12619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12620
developer06a01d92022-09-07 16:32:39 +080012621 return RETURN_OK;
12622}
12623
12624INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12625{
developer9df4e652022-10-11 11:27:38 +080012626 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012627 char config_file[128] = {0};
12628 int disable = 0;
12629 // struct params params = {0};
12630
12631 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12632 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12633 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12634 security->mode = wifi_security_mode_none;
12635 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012636 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012637 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012638 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012639 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012640 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012641 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012642 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012643 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012644 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012645 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012646 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012647 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012648 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012649 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012650 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012651 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012652 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012653 security->mode = wifi_security_mode_wpa3_enterprise;
12654 }
12655
12656 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12657 if (security->mode == wifi_security_mode_none)
12658 security->encr = wifi_encryption_none;
12659 else {
12660 if (strcmp(buf, "TKIP") == 0)
12661 security->encr = wifi_encryption_tkip;
12662 else if (strcmp(buf, "CCMP") == 0)
12663 security->encr = wifi_encryption_aes;
12664 else
12665 security->encr = wifi_encryption_aes_tkip;
12666 }
12667
developer9df4e652022-10-11 11:27:38 +080012668 if (security->mode != wifi_encryption_none) {
12669 memset(buf, 0, sizeof(buf));
12670 // wpa3 can use one or both configs as password, so we check sae_password first.
12671 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12672 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12673 security->u.key.type = wifi_security_key_type_sae;
12674 } else {
12675 security->u.key.type = wifi_security_key_type_psk;
12676 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12677 }
12678 strncpy(security->u.key.key, buf, sizeof(buf));
12679 security->u.key.key[255] = '\0';
12680 }
12681
developer587c1b62022-09-27 15:58:59 +080012682 memset(buf, 0, sizeof(buf));
12683 wifi_getApSecurityMFPConfig(ap_index, buf);
12684 if (strcmp(buf, "Disabled") == 0)
12685 security->mfp = wifi_mfp_cfg_disabled;
12686 else if (strcmp(buf, "Optional") == 0)
12687 security->mfp = wifi_mfp_cfg_optional;
12688 else if (strcmp(buf, "Required") == 0)
12689 security->mfp = wifi_mfp_cfg_required;
12690
12691 memset(buf, 0, sizeof(buf));
12692 security->wpa3_transition_disable = FALSE;
12693 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12694 disable = strtol(buf, NULL, 16);
12695 if (disable != 0)
12696 security->wpa3_transition_disable = TRUE;
12697
12698 memset(buf, 0, sizeof(buf));
12699 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12700 if (strlen(buf) == 0)
12701 security->rekey_interval = 86400;
12702 else
12703 security->rekey_interval = strtol(buf, NULL, 10);
12704
12705 memset(buf, 0, sizeof(buf));
12706 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12707 if (strlen(buf) == 0)
12708 security->strict_rekey = 1;
12709 else
12710 security->strict_rekey = strtol(buf, NULL, 10);
12711
12712 memset(buf, 0, sizeof(buf));
12713 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12714 if (strlen(buf) == 0)
12715 security->eapol_key_retries = 4;
12716 else
12717 security->eapol_key_retries = strtol(buf, NULL, 10);
12718
12719 memset(buf, 0, sizeof(buf));
12720 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12721 if (strlen(buf) == 0)
12722 security->disable_pmksa_caching = FALSE;
12723 else
12724 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12725
12726 /* TODO
12727 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12728 */
12729 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12730 security->eap_identity_req_timeout = 0;
12731 security->eap_identity_req_retries = 0;
12732 security->eap_req_timeout = 0;
12733 security->eap_req_retries = 0;
12734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012735 return RETURN_OK;
12736}
12737
12738#endif /* WIFI_HAL_VERSION_3 */
12739
12740#ifdef WIFI_HAL_VERSION_3_PHASE2
12741INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12742{
developer13df9332022-09-27 16:53:22 +080012743 char cmd[128] = {0};
12744 char buf[128] = {0};
12745 char *mac_addr = NULL;
12746 BOOL status = FALSE;
12747 size_t len = 0;
12748
12749 if(ap_index > MAX_APS)
12750 return RETURN_ERR;
12751
12752 *output_numDevices = 0;
12753 wifi_getApEnable(ap_index, &status);
12754 if (status == FALSE)
12755 return RETURN_OK;
12756
12757 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12758 _syscmd(cmd, buf, sizeof(buf));
12759
12760 mac_addr = strtok(buf, "\n");
12761 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12762 *output_numDevices = i + 1;
12763 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12764 addr_ptr = output_deviceMacAddressArray[i];
12765 mac_addr_aton(addr_ptr, mac_addr);
12766 mac_addr = strtok(NULL, "\n");
12767 }
12768
12769 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012770}
12771#else
12772INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12773{
12774 char cmd[128];
12775 BOOL status = false;
12776
12777 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12778 return RETURN_ERR;
12779
12780 output_buf[0] = '\0';
12781
12782 wifi_getApEnable(ap_index,&status);
12783 if (!status)
12784 return RETURN_OK;
12785
12786 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12787 _syscmd(cmd, output_buf, output_buf_size);
12788
12789 return RETURN_OK;
12790}
12791#endif
developer2f513ab2022-09-13 14:26:06 +080012792
12793INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12794{
12795 char output[16]={'\0'};
12796 char config_file[MAX_BUF_SIZE] = {0};
12797
12798 if (!enable)
12799 return RETURN_ERR;
12800
12801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12802 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12803
12804 if (strlen(output) == 0)
12805 *enable = FALSE;
12806 else if (strncmp(output, "1", 1) == 0)
12807 *enable = TRUE;
12808 else
12809 *enable = FALSE;
12810
12811 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12812 return RETURN_OK;
12813}
developer2d9c30f2022-09-13 15:06:14 +080012814
12815INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12816{
12817 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12818 return RETURN_ERR;
12819 *output_enable=TRUE;
12820 return RETURN_OK;
12821}
developerfd7d2892022-09-13 16:44:53 +080012822
12823INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12824{
12825 char cmd[128] = {0};
12826 char buf[128] = {0};
12827 char line[128] = {0};
12828 size_t len = 0;
12829 ssize_t read = 0;
12830 FILE *f = NULL;
12831 int index = 0;
12832 int exp = 0;
12833 int mantissa = 0;
12834 int duration = 0;
12835 int radio_index = 0;
12836 int max_radio_num = 0;
12837 uint twt_wake_interval = 0;
12838
12839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12840
12841 wifi_getMaxRadioNumber(&max_radio_num);
12842 radio_index = ap_index % max_radio_num;
12843 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12844 _syscmd(cmd, buf, sizeof(buf));
12845 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12846 if (*numSessionReturned > maxNumberSessions)
12847 *numSessionReturned = maxNumberSessions;
12848 else if (*numSessionReturned < 1) {
12849 *numSessionReturned = 0;
12850 return RETURN_OK;
12851 }
12852
12853 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12854 if ((f = popen(cmd, "r")) == NULL) {
12855 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12856 return RETURN_ERR;
12857 }
12858
12859 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12860 while((read = fgets(line, sizeof(line), f)) != NULL) {
12861 char *tmp = NULL;
12862 strcpy(buf, line);
12863 tmp = strtok(buf, " ");
12864 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12865 tmp = strtok(NULL, " ");
12866 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12867 tmp = strtok(NULL, " ");
12868 if (strstr(tmp, "t")) {
12869 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12870 }
12871 if (strstr(tmp, "a")) {
12872 twtSessions[index].twtParameters.operation.announced = TRUE;
12873 }
12874 tmp = strtok(NULL, " ");
12875 exp = strtol(tmp, NULL, 10);
12876 tmp = strtok(NULL, " ");
12877 mantissa = strtol(tmp, NULL, 10);
12878 tmp = strtok(NULL, " ");
12879 duration = strtol(tmp, NULL, 10);
12880
12881 // only implicit supported
12882 twtSessions[index].twtParameters.operation.implicit = TRUE;
12883 // only individual agreement supported
12884 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12885
12886 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12887 twt_wake_interval = mantissa * (1 << exp);
12888 if (twt_wake_interval/mantissa != (1 << exp)) {
12889 // Overflow handling
12890 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12891 } else {
12892 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12893 }
12894 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12895 index++;
12896 }
12897
12898 pclose(f);
12899 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12900 return RETURN_OK;
12901}