blob: 6eb056e79cfcd2dabb0b3191b5d34d241a74fa73 [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
developer06a01d92022-09-07 16:32:39 +08002067//Get the list of supported channel. eg: "1-11"
2068//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.
2069INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2070{
developer6318ed52022-09-13 15:17:58 +08002071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002072 if (NULL == output_string)
2073 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002074 char cmd[256] = {0};
2075 char buf[128] = {0};
2076 BOOL dfs_enable = false;
2077 // Parse possible channel number and separate them with commas.
2078 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer76989232022-10-04 14:13:19 +08002079 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002080 if (dfs_enable)
developer76989232022-10-04 14:13:19 +08002081 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 +08002082 else
developer76989232022-10-04 14:13:19 +08002083 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 +08002084
2085 _syscmd(cmd,buf,sizeof(buf));
2086 strncpy(output_string, buf, sizeof(buf));
2087
2088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2089 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002090}
2091
2092//Get the list for used channel. eg: "1,6,9,11"
2093//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.
2094INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2095{
developerf5745ee2022-10-05 16:09:53 +08002096 char cmd[128] = {0};
2097 char buf[128] = {0};
2098 char config_file[64] = {0};
2099 int channel = 0;
2100 int freq = 0;
2101 int bandwidth = 0;
2102 int center_freq = 0;
2103 int center_channel = 0;
2104 int channel_delta = 0;
2105 wifi_band band = band_invalid;
2106
2107 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2108
developer06a01d92022-09-07 16:32:39 +08002109 if (NULL == output_string)
2110 return RETURN_ERR;
2111
developerf5745ee2022-10-05 16:09:53 +08002112 sprintf(cmd, "iw %s%d info | grep channel | sed -e 's/[^0-9 ]//g'", AP_PREFIX, radioIndex);
2113 _syscmd(cmd, buf, sizeof(buf));
2114 if (strlen(buf) == 0) {
2115 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2116 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002117 }
developerf5745ee2022-10-05 16:09:53 +08002118 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2119
2120 if (bandwidth == 20) {
2121 snprintf(output_string, 256, "%d", channel);
2122 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002123 }
developerf5745ee2022-10-05 16:09:53 +08002124
2125 center_channel = ieee80211_frequency_to_channel(center_freq);
2126
2127 band = wifi_index_to_band(radioIndex);
2128 if (band == band_2_4 && bandwidth == 40) {
2129 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2130 memset(buf, 0, sizeof(buf));
2131 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2132
2133 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2134 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2135 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2136 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2137 } else {
2138 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2139 return RETURN_ERR;
2140 }
2141 } else if (band == band_5 || band == band_6){
2142 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2143 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2144 channel_delta = (bandwidth-20)/10;
2145 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2146 } else
2147 return RETURN_ERR;
2148
2149 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002150 return RETURN_OK;
2151}
2152
2153//Get the running channel number
2154INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2155{
developerda1ed692022-09-13 13:59:20 +08002156#ifdef MTK_IMPL
2157 if(!wifi_getApChannel(radioIndex, output_ulong))
2158 return RETURN_OK;
2159 else
2160 return RETURN_ERR;
2161#else
developer06a01d92022-09-07 16:32:39 +08002162 char cmd[1024] = {0}, buf[5] = {0};
2163
2164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2165 if (NULL == output_ulong)
2166 return RETURN_ERR;
2167
2168 snprintf(cmd, sizeof(cmd),
2169 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2170 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2171 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2172 _syscmd(cmd, buf, sizeof(buf));
2173
2174 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2175 if (*output_ulong <= 0) {
2176 *output_ulong = 0;
2177 return RETURN_ERR;
2178 }
2179
2180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2181 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002182#endif
developer06a01d92022-09-07 16:32:39 +08002183}
2184
2185
2186INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2187{
2188 char cmd[1024] = {0}, buf[5] = {0};
2189 char interface_name[50] = {0};
2190
2191 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2192 if (NULL == output_ulong)
2193 return RETURN_ERR;
2194
2195 wifi_getApName(apIndex,interface_name);
2196 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2197 _syscmd(cmd,buf,sizeof(buf));
2198 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2199 if (*output_ulong == 0) {
2200 return RETURN_ERR;
2201 }
2202
2203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2204 return RETURN_OK;
2205}
2206
2207//Storing the previous channel value
2208INT wifi_storeprevchanval(INT radioIndex)
2209{
2210 char buf[256] = {0};
2211 char output[4]={'\0'};
2212 char config_file[MAX_BUF_SIZE] = {0};
2213 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2214 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2215 if(radioIndex == 0)
2216 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2217 else if(radioIndex == 1)
2218 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2219 system(buf);
2220 Radio_flag = FALSE;
2221 return RETURN_OK;
2222}
2223
2224//Set the running channel number
2225INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2226{
developer76989232022-10-04 14:13:19 +08002227 // We only write hostapd config here
2228 char str_channel[8]={0};
2229 char *list_channel;
2230 char config_file[128] = {0};
2231 char possible_channels[256] = {0};
2232 int max_radio_num = 0;
2233 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002234
developer76989232022-10-04 14:13:19 +08002235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002236
developer76989232022-10-04 14:13:19 +08002237 // Check valid
2238 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002239
developer76989232022-10-04 14:13:19 +08002240 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2241 list_channel = strtok(possible_channels, ",");
2242 while(true)
developer06a01d92022-09-07 16:32:39 +08002243 {
developer76989232022-10-04 14:13:19 +08002244 if(list_channel == NULL) { // input not in the list
2245 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2246 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002247 }
developer76989232022-10-04 14:13:19 +08002248 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2249 break;
2250 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002251 }
2252
developer76989232022-10-04 14:13:19 +08002253 list.name = "channel";
2254 list.value = str_channel;
2255 wifi_getMaxRadioNumber(&max_radio_num);
2256 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002257 {
developer76989232022-10-04 14:13:19 +08002258 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2259 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002260 }
2261
developer76989232022-10-04 14:13:19 +08002262 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002263 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002264}
developer06a01d92022-09-07 16:32:39 +08002265
2266INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2267{
developer76989232022-10-04 14:13:19 +08002268 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002269 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002270 char config_file[64];
2271 int max_num_radios = 0;
2272 wifi_band band = band_invalid;
2273
2274 band = wifi_index_to_band(radioIndex);
2275 if (band == band_2_4)
2276 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002277
developer06a01d92022-09-07 16:32:39 +08002278 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002279 list[0].name = "vht_oper_centr_freq_seg0_idx";
2280 list[0].value = str_idx;
2281 list[1].name = "he_oper_centr_freq_seg0_idx";
2282 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002283
developer76989232022-10-04 14:13:19 +08002284 wifi_getMaxRadioNumber(&max_num_radios);
2285 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002286 {
developer76989232022-10-04 14:13:19 +08002287 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2288 if (band == band_6)
2289 wifi_hostapdWrite(config_file, &list[1], 1);
2290 else
2291 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002292 }
2293
2294 return RETURN_OK;
2295}
2296
2297//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2298//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2299INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2300{
2301 //Set to wifi config only. Wait for wifi reset to apply.
2302 char buf[256] = {0};
2303 char str_channel[256] = {0};
2304 int count = 0;
2305 ULONG Value = 0;
2306 FILE *fp = NULL;
2307 if(enable == TRUE)
2308 {
developer06a01d92022-09-07 16:32:39 +08002309 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002310 }
developer5884e982022-10-06 10:52:50 +08002311 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002312}
2313
developer0b246d12022-09-30 15:24:20 +08002314INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2315{
2316 if (output_bool == NULL)
2317 return RETURN_ERR;
2318
2319 *output_bool = TRUE;
2320
2321 return RETURN_OK;
2322}
2323
developer06a01d92022-09-07 16:32:39 +08002324INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2325{
2326 if (NULL == output_bool)
2327 return RETURN_ERR;
2328 *output_bool=FALSE;
2329 return RETURN_OK;
2330}
2331
2332INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2333{
2334 if (NULL == output_bool)
2335 return RETURN_ERR;
2336 *output_bool=FALSE;
2337 return RETURN_OK;
2338}
2339
2340INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2341{
2342 //Set to wifi config only. Wait for wifi reset to apply.
2343 return RETURN_OK;
2344}
2345
2346INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2347{
2348 return RETURN_OK;
2349}
2350
2351INT wifi_factoryResetAP(int apIndex)
2352{
developer838cca92022-10-03 13:19:57 +08002353 char ap_config_file[64] = {0};
2354 char cmd[128] = {0};
2355
developer06a01d92022-09-07 16:32:39 +08002356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002357
2358 wifi_setApEnable(apIndex, FALSE);
2359 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2360 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2361 wifi_setApEnable(apIndex, TRUE);
2362
developer06a01d92022-09-07 16:32:39 +08002363 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002364
developer06a01d92022-09-07 16:32:39 +08002365 return RETURN_OK;
2366}
2367
2368//To set Band Steering AP group
2369//To-do
2370INT wifi_setBandSteeringApGroup(char *ApGroup)
2371{
2372 return RETURN_OK;
2373}
2374
developer1e5aa162022-09-13 16:06:24 +08002375INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2376{
2377 char config_file[128] = {'\0'};
2378 char buf[128] = {'\0'};
2379
2380 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2381 if (dtimInterval == NULL)
2382 return RETURN_ERR;
2383
2384 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2385 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2386
2387 if (strlen(buf) == 0) {
2388 *dtimInterval = 2;
2389 } else {
2390 *dtimInterval = strtoul(buf, NULL, 10);
2391 }
2392
2393 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2394 return RETURN_OK;
2395}
2396
developer06a01d92022-09-07 16:32:39 +08002397INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2398{
developer5f222492022-09-13 15:21:52 +08002399 struct params params={0};
2400 char config_file[MAX_BUF_SIZE] = {'\0'};
2401 char buf[MAX_BUF_SIZE] = {'\0'};
2402
2403 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2404 if (dtimInterval < 1 || dtimInterval > 255) {
2405 return RETURN_ERR;
2406 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2407 }
2408
2409 params.name = "dtim_period";
2410 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2411 params.value = buf;
2412
2413 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2414 wifi_hostapdWrite(config_file, &params, 1);
2415 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2416
2417 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2418 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002419}
2420
2421//Check if the driver support the Dfs
2422INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2423{
2424 if (NULL == output_bool)
2425 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002426 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002427 return RETURN_OK;
2428}
2429
2430//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.
2431//The value of this parameter is a comma seperated list of channel number
2432INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2433{
2434 if (NULL == output_pool)
2435 return RETURN_ERR;
2436 if (radioIndex==1)
2437 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2438 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2439
2440 return RETURN_OK;
2441}
2442
2443INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2444{
2445 //Set to wifi config. And apply instantly.
2446 return RETURN_OK;
2447}
2448
2449INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2450{
2451 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2452 return RETURN_ERR;
2453 *output_interval_seconds=1800;
2454 *output_dwell_milliseconds=40;
2455
2456 return RETURN_OK;
2457}
2458
2459INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2460{
2461 //Set to wifi config. And apply instantly.
2462 return RETURN_OK;
2463}
2464
developerbfc18512022-10-05 17:54:28 +08002465INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2466{
2467 if (output_bool == NULL)
2468 return RETURN_ERR;
2469 *output_bool = true;
2470 return RETURN_OK;
2471}
2472
2473INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2474{
2475 return RETURN_OK;
2476}
2477
developer06a01d92022-09-07 16:32:39 +08002478//Get the Dfs enable status
2479INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2480{
developer9964b5b2022-09-13 15:59:34 +08002481 char buf[16] = {0};
2482 FILE *f = NULL;
2483 wifi_band band;
2484
2485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2486
2487 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002488 if (NULL == output_bool)
2489 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002490
2491 band = wifi_index_to_band(radioIndex);
2492 if (band != band_5)
2493 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002494
developer9964b5b2022-09-13 15:59:34 +08002495 f = fopen(DFS_ENABLE_FILE, "r");
2496 if (f != NULL) {
2497 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002498 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002499 *output_bool = FALSE;
2500 fclose(f);
2501 }
2502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002503 return RETURN_OK;
2504}
2505
2506//Set the Dfs enable status
2507INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2508{
developer9964b5b2022-09-13 15:59:34 +08002509 char config_file[128] = {0};
2510 FILE *f = NULL;
2511 struct params params={0};
2512 wifi_band band;
2513
2514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2515
2516 band = wifi_index_to_band(radioIndex);
2517 if (band != band_5)
2518 return RETURN_OK;
2519
2520 f = fopen(DFS_ENABLE_FILE, "w");
2521 if (f == NULL)
2522 return RETURN_ERR;
2523 fprintf(f, "%d", enable);
2524 fclose(f);
2525
2526 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002527 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002528 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2529 wifi_hostapdWrite(config_file, &params, 1);
2530 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2531
2532 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2533
developer9964b5b2022-09-13 15:59:34 +08002534 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002535 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002536}
2537
2538//Check if the driver support the AutoChannelRefreshPeriod
2539INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2540{
2541 if (NULL == output_bool)
2542 return RETURN_ERR;
2543 *output_bool=FALSE; //not support
2544
2545 return RETURN_OK;
2546}
2547
2548//Get the ACS refresh period in seconds
2549INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2550{
2551 if (NULL == output_ulong)
2552 return RETURN_ERR;
2553 *output_ulong=300;
2554
2555 return RETURN_OK;
2556}
2557
2558//Set the ACS refresh period in seconds
2559INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2560{
2561 return RETURN_ERR;
2562}
2563
2564//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2565//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.
2566INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2567{
developer70490032022-09-13 15:45:20 +08002568 char cmd[128] = {0}, buf[64] = {0};
2569 char interface_name[64] = {0};
2570 int ret = 0, len=0;
2571 BOOL radio_enable = FALSE;
2572
2573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2574
developer06a01d92022-09-07 16:32:39 +08002575 if (NULL == output_string)
2576 return RETURN_ERR;
2577
developer70490032022-09-13 15:45:20 +08002578 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2579 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002580
developer70490032022-09-13 15:45:20 +08002581 if (radio_enable != TRUE)
2582 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002583
developer70490032022-09-13 15:45:20 +08002584 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002585 ret = _syscmd(cmd, buf, sizeof(buf));
2586 len = strlen(buf);
2587 if((ret != 0) || (len == 0))
2588 {
2589 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2590 return RETURN_ERR;
2591 }
2592
2593 buf[len-1] = '\0';
2594 snprintf(output_string, 64, "%sMHz", buf);
2595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2596
2597#if 0
2598 //TODO: revisit below implementation
2599 char output_buf[8]={0};
2600 char bw_value[10];
2601 char config_file[MAX_BUF_SIZE] = {0};
2602
2603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2604 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2605 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2606 readBandWidth(radioIndex,bw_value);
2607
2608 if(strstr (output_buf,"0") != NULL )
2609 {
2610 strcpy(output_string,bw_value);
2611 }
2612 else if (strstr (output_buf,"1") != NULL)
2613 {
2614 strcpy(output_string,"80MHz");
2615 }
2616 else if (strstr (output_buf,"2") != NULL)
2617 {
2618 strcpy(output_string,"160MHz");
2619 }
2620 else if (strstr (output_buf,"3") != NULL)
2621 {
2622 strcpy(output_string,"80+80");
2623 }
2624 else
2625 {
2626 strcpy(output_string,"Auto");
2627 }
2628 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2629#endif
2630
2631 return RETURN_OK;
2632}
2633
2634//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002635INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002636{
developerf7a466e2022-09-29 11:55:56 +08002637 char config_file[128];
2638 char set_value[16];
2639 struct params params[2];
2640 int max_radio_num = 0;
2641
developer06a01d92022-09-07 16:32:39 +08002642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002643
developerf7a466e2022-09-29 11:55:56 +08002644 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002645 return RETURN_ERR;
2646
developerf7a466e2022-09-29 11:55:56 +08002647 if(strstr(bandwidth,"80+80") != NULL)
2648 strcpy(set_value, "3");
2649 else if(strstr(bandwidth,"160") != NULL)
2650 strcpy(set_value, "2");
2651 else if(strstr(bandwidth,"80") != NULL)
2652 strcpy(set_value, "1");
2653 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2654 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002655 else
2656 {
developerf7a466e2022-09-29 11:55:56 +08002657 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002658 return RETURN_ERR;
2659 }
2660
developerf7a466e2022-09-29 11:55:56 +08002661 params[0].name = "vht_oper_chwidth";
2662 params[0].value = set_value;
2663 params[1].name = "he_oper_chwidth";
2664 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002665
developerf7a466e2022-09-29 11:55:56 +08002666 wifi_getMaxRadioNumber(&max_radio_num);
2667 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002668 {
developerf7a466e2022-09-29 11:55:56 +08002669 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2670 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002671 }
2672
2673 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2674 return RETURN_OK;
2675}
2676
2677//Getting current radio extension channel
2678INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2679{
2680 CHAR buf[150] = {0};
2681 CHAR cmd[150] = {0};
2682 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2683 _syscmd(cmd, buf, sizeof(buf));
2684 if(NULL != strstr(buf,"HT40+"))
2685 strcpy(Value,"AboveControlChannel");
2686 else if(NULL != strstr(buf,"HT40-"))
2687 strcpy(Value,"BelowControlChannel");
2688 return RETURN_OK;
2689}
2690
2691//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2692//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.
2693INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2694{
2695 if (NULL == output_string)
2696 return RETURN_ERR;
2697
2698 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2699#if 0
2700 CHAR Value[100] = {0};
2701 if (NULL == output_string)
2702 return RETURN_ERR;
2703 if(radioIndex == 0)
2704 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2705 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2706 {
2707 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2708 if(strcmp(Value,"40MHz") == 0)
2709 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2710 else
2711 strcpy(Value,"Auto");
2712 }
2713 strcpy(output_string,Value);
2714#endif
2715
2716 return RETURN_OK;
2717}
2718
2719//Set the extension channel.
2720INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2721{
2722 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2723 struct params params={'\0'};
2724 char config_file[MAX_BUF_SIZE] = {0};
2725 char ext_channel[127]={'\0'};
2726
2727 params.name = "ht_capab";
2728
2729 if(radioIndex == 0)
2730 {
2731 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002732 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002733 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002734 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002735 else
developer3cc0f2e2022-09-15 18:25:39 +08002736 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002737 }
2738 else if(radioIndex == 1)
2739 {
2740 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002741 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002742 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002743 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002744 else
developer3cc0f2e2022-09-15 18:25:39 +08002745 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002746 }
2747
2748 params.value = ext_channel;
2749 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2750 {
2751 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2752 wifi_hostapdWrite(config_file, &params, 1);
2753 }
2754
2755 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2757 return RETURN_OK;
2758}
2759
2760//Get the guard interval value. eg "400nsec" or "800nsec"
2761//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.
2762INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2763{
developer454b9462022-09-13 15:29:16 +08002764 wifi_guard_interval_t GI;
2765
2766 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2767
2768 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002769 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002770
2771 if (GI == wifi_guard_interval_400)
2772 strcpy(output_string, "400nsec");
2773 else if (GI == wifi_guard_interval_800)
2774 strcpy(output_string, "800nsec");
2775 else if (GI == wifi_guard_interval_1600)
2776 strcpy(output_string, "1600nsec");
2777 else if (GI == wifi_guard_interval_3200)
2778 strcpy(output_string, "3200nsec");
2779 else
2780 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002781
developer454b9462022-09-13 15:29:16 +08002782 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002783 return RETURN_OK;
2784}
2785
2786//Set the guard interval value.
2787INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2788{
developer454b9462022-09-13 15:29:16 +08002789 wifi_guard_interval_t GI;
2790 int ret = 0;
2791
2792 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2793
2794 if (strcmp(string, "400nsec") == 0)
2795 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002796 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002797 GI = wifi_guard_interval_800;
2798 else if (strcmp(string , "1600nsec") == 0)
2799 GI = wifi_guard_interval_1600;
2800 else if (strcmp(string , "3200nsec") == 0)
2801 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002802 else
2803 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002804
2805 ret = wifi_setGuardInterval(radioIndex, GI);
2806
2807 if (ret == RETURN_ERR) {
2808 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2809 return RETURN_ERR;
2810 }
2811
2812 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2813 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002814}
2815
2816//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2817INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2818{
developerf49437e2022-09-29 19:58:21 +08002819 char buf[32]={0};
2820 char mcs_file[64] = {0};
2821 char cmd[64] = {0};
2822 int mode_bitmap = 0;
2823
2824 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2825 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002826 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002827 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2828
2829 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2830 _syscmd(cmd, buf, sizeof(buf));
2831 if (strlen(buf) > 0)
2832 *output_int = strtol(buf, NULL, 10);
2833 else {
2834 // output the max MCS for the current radio mode
2835 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2836 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2837 return RETURN_ERR;
2838 }
2839 if (mode_bitmap & WIFI_MODE_AX) {
2840 *output_int = 11;
2841 } else if (mode_bitmap & WIFI_MODE_AC) {
2842 *output_int = 9;
2843 } else if (mode_bitmap & WIFI_MODE_N) {
2844 *output_int = 7;
2845 }
2846 }
2847 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002848
2849 return RETURN_OK;
2850}
2851
2852//Set the Modulation Coding Scheme index
2853INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2854{
developerf49437e2022-09-29 19:58:21 +08002855 // 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).
2856 char config_file[64] = {0};
2857 char set_value[16] = {0};
2858 char mcs_file[32] = {0};
2859 wifi_band band = band_invalid;
2860 struct params set_config = {0};
2861 FILE *f = NULL;
2862
2863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2864
2865 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2866
2867 if (MCS > 11 || MCS < 0) {
2868 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2869 return RETURN_ERR;
2870 }
2871
2872 if (MCS <= 7)
2873 strcpy(set_value, "0");
2874 else if (MCS <= 9)
2875 strcpy(set_value, "1");
2876 else
2877 strcpy(set_value, "2");
2878
2879 set_config.name = "he_basic_mcs_nss_set";
2880 set_config.value = set_value;
2881
2882 wifi_hostapdWrite(config_file, &set_config, 1);
2883 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2884
2885 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2886 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2887 f = fopen(mcs_file, "w");
2888 if (f == NULL) {
2889 fprintf(stderr, "%s: fopen failed\n", __func__);
2890 return RETURN_ERR;
2891 }
2892 fprintf(f, "%d", MCS);
2893 fclose(f);
2894
2895 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2896 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002897}
2898
2899//Get supported Transmit Power list, eg : "0,25,50,75,100"
2900//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.
2901INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2902{
2903 if (NULL == output_list)
2904 return RETURN_ERR;
2905 snprintf(output_list, 64,"0,25,50,75,100");
2906 return RETURN_OK;
2907}
2908
developera5005b62022-09-13 15:43:35 +08002909//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002910//The transmite power level is in units of full power for this radio.
2911INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2912{
2913 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002914 char buf[16]={0};
2915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002916
developera5005b62022-09-13 15:43:35 +08002917 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002918 return RETURN_ERR;
2919
developera5005b62022-09-13 15:43:35 +08002920 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 +08002921 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002922
developera5005b62022-09-13 15:43:35 +08002923 *output_ulong = strtol(buf, NULL, 10);
2924
2925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002926 return RETURN_OK;
2927}
2928
2929//Set Transmit Power
2930//The transmite power level is in units of full power for this radio.
2931INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2932{
developera5005b62022-09-13 15:43:35 +08002933 char *support;
developer06a01d92022-09-07 16:32:39 +08002934 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002935 char buf[128]={0};
2936 char txpower_str[64] = {0};
2937 int txpower = 0;
2938 int maximum_tx = 0;
2939
2940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002941
developera5005b62022-09-13 15:43:35 +08002942 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 +08002943 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002944 maximum_tx = strtol(buf, NULL, 10);
2945
2946 // Get the Tx power supported list and check that is the input in the list
2947 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2948 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2949 support = strtok(buf, ",");
2950 while(true)
2951 {
2952 if(support == NULL) { // input not in the list
2953 wifi_dbg_printf("Input value is invalid.\n");
2954 return RETURN_ERR;
2955 }
2956 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2957 break;
2958 }
2959 support = strtok(NULL, ",");
2960 }
2961 txpower = TransmitPower*maximum_tx/100;
2962 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2963 _syscmd(cmd, buf, sizeof(buf));
2964 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002965
2966 return RETURN_OK;
2967}
2968
2969//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2970INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2971{
2972 if (NULL == Supported)
2973 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002974 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002975
2976 return RETURN_OK;
2977}
2978
2979//Get 80211h feature enable
2980INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2981{
developer3885fec2022-09-13 15:13:47 +08002982 char buf[64]={'\0'};
2983 char config_file[64] = {'\0'};
2984
2985 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2986 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002987 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002988
2989 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2990 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002991
developer3885fec2022-09-13 15:13:47 +08002992 if (strncmp(buf, "1", 1) == 0)
2993 *enable = TRUE;
2994 else
2995 *enable = FALSE;
2996
2997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002998 return RETURN_OK;
2999}
3000
3001//Set 80211h feature enable
3002INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3003{
developer3885fec2022-09-13 15:13:47 +08003004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3005 struct params params={'\0'};
3006 char config_file[MAX_BUF_SIZE] = {0};
3007
3008 params.name = "ieee80211h";
3009
3010 if (enable) {
3011 params.value = "1";
3012 } else {
3013 params.value = "0";
3014 }
3015
3016 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3017 wifi_hostapdWrite(config_file, &params, 1);
3018
3019 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3021 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003022}
3023
3024//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.
3025INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3026{
3027 if (NULL == output)
3028 return RETURN_ERR;
3029 *output=100;
3030
3031 return RETURN_OK;
3032}
3033
3034//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.
3035INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3036{
3037 if (NULL == output)
3038 return RETURN_ERR;
3039 *output = -99;
3040
3041 return RETURN_OK;
3042}
3043
3044INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3045{
3046 return RETURN_ERR;
3047}
3048
3049
3050//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3051INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3052{
developer5f222492022-09-13 15:21:52 +08003053 char cmd[MAX_BUF_SIZE]={'\0'};
3054 char buf[MAX_CMD_SIZE]={'\0'};
3055
3056 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3057 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003058 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003059
3060 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3061 _syscmd(cmd, buf, sizeof(buf));
3062 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003063
developer5f222492022-09-13 15:21:52 +08003064 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003065 return RETURN_OK;
3066}
3067
3068INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3069{
developer5f222492022-09-13 15:21:52 +08003070 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3071 struct params params={'\0'};
3072 char buf[MAX_BUF_SIZE] = {'\0'};
3073 char config_file[MAX_BUF_SIZE] = {'\0'};
3074
3075 params.name = "beacon_int";
3076 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3077 params.value = buf;
3078
3079 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3080 wifi_hostapdWrite(config_file, &params, 1);
3081
3082 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3083 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3084 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003085}
3086
3087//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.
3088INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3089{
developer06a01d92022-09-07 16:32:39 +08003090 //TODO: need to revisit below implementation
3091 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003092 char temp_output[128] = {0};
3093 char temp_TransmitRates[64] = {0};
3094 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003095
3096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3097 if (NULL == output)
3098 return RETURN_ERR;
3099 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003100 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3101
3102 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3103 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3104 } else {
3105 temp = strtok(temp_TransmitRates," ");
3106 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003107 {
developere9d0abd2022-09-13 15:40:57 +08003108 // Convert 100 kbps to Mbps
3109 temp[strlen(temp)-1]=0;
3110 if((temp[0]=='5') && (temp[1]=='\0'))
3111 {
3112 temp="5.5";
3113 }
3114 strcat(temp_output,temp);
3115 temp = strtok(NULL," ");
3116 if(temp!=NULL)
3117 {
3118 strcat(temp_output,",");
3119 }
developer06a01d92022-09-07 16:32:39 +08003120 }
developere9d0abd2022-09-13 15:40:57 +08003121 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003122 }
developer06a01d92022-09-07 16:32:39 +08003123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003124 return RETURN_OK;
3125}
3126
3127INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3128{
3129 char *temp;
3130 char temp1[128];
3131 char temp_output[128];
3132 char temp_TransmitRates[128];
3133 char set[128];
3134 char sub_set[128];
3135 int set_count=0,subset_count=0;
3136 int set_index=0,subset_index=0;
3137 char *token;
3138 int flag=0, i=0;
3139 struct params params={'\0'};
3140 char config_file[MAX_BUF_SIZE] = {0};
3141
3142 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3143 if(NULL == TransmitRates)
3144 return RETURN_ERR;
3145 strcpy(sub_set,TransmitRates);
3146
3147 //Allow only supported Data transmit rate to be set
3148 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3149 token = strtok(sub_set,",");
3150 while( token != NULL ) /* split the basic rate to be set, by comma */
3151 {
3152 sub_set[subset_count]=atoi(token);
3153 subset_count++;
3154 token=strtok(NULL,",");
3155 }
3156 token=strtok(set,",");
3157 while(token!=NULL) /* split the supported rate by comma */
3158 {
3159 set[set_count]=atoi(token);
3160 set_count++;
3161 token=strtok(NULL,",");
3162 }
3163 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3164 {
3165 for(set_index=0;set_index < set_count;set_index++)
3166 {
3167 flag=0;
3168 if(sub_set[subset_index]==set[set_index])
3169 break;
3170 else
3171 flag=1; /* No match found */
3172 }
3173 if(flag==1)
3174 return RETURN_ERR; //If value not found return Error
3175 }
3176 strcpy(temp_TransmitRates,TransmitRates);
3177
3178 for(i=0;i<strlen(temp_TransmitRates);i++)
3179 {
3180 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3181 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3182 {
3183 continue;
3184 }
3185 else
3186 {
3187 return RETURN_ERR;
3188 }
3189 }
3190 strcpy(temp_output,"");
3191 temp = strtok(temp_TransmitRates,",");
3192 while(temp!=NULL)
3193 {
3194 strcpy(temp1,temp);
3195 if(radioIndex==1)
3196 {
3197 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3198 {
3199 return RETURN_ERR;
3200 }
3201 }
3202
3203 if(strcmp(temp,"5.5")==0)
3204 {
3205 strcpy(temp1,"55");
3206 }
3207 else
3208 {
3209 strcat(temp1,"0");
3210 }
3211 strcat(temp_output,temp1);
3212 temp = strtok(NULL,",");
3213 if(temp!=NULL)
3214 {
3215 strcat(temp_output," ");
3216 }
3217 }
3218 strcpy(TransmitRates,temp_output);
3219
3220 params.name= "basic_rates";
3221 params.value =TransmitRates;
3222
3223 wifi_dbg_printf("\n%s:",__func__);
3224 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3225 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3226 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3227 wifi_hostapdWrite(config_file,&params,1);
3228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3229 return RETURN_OK;
3230}
3231
3232//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3233INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3234{
3235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3236 FILE *fp = NULL;
3237 char path[256] = {0}, output_string[256] = {0};
3238 int count = 0;
3239 char *interface = NULL;
3240
3241 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3242 if (fp == NULL)
3243 {
3244 printf("Failed to run command in Function %s\n", __FUNCTION__);
3245 return RETURN_ERR;
3246 }
3247 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3248 {
3249 interface = strchr(path, '=');
3250
3251 if (interface != NULL)
3252 {
3253 strcpy(output_string, interface + 1);
3254 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3255 interface_name[count] = output_string[count];
3256
3257 interface_name[count] = '\0';
3258 }
3259 }
3260 pclose(fp);
3261 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3262 return RETURN_OK;
3263}
3264
3265INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3266{
3267 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3268 output_struct->radio_BytesSent = 0;
3269 output_struct->radio_BytesReceived = 0;
3270 output_struct->radio_PacketsSent = 0;
3271 output_struct->radio_PacketsReceived = 0;
3272 output_struct->radio_ErrorsSent = 0;
3273 output_struct->radio_ErrorsReceived = 0;
3274 output_struct->radio_DiscardPacketsSent = 0;
3275 output_struct->radio_DiscardPacketsReceived = 0;
3276 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3277 return RETURN_OK;
3278}
3279
3280
3281INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3282{
3283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3284 CHAR buf[MAX_CMD_SIZE] = {0};
3285 CHAR Value[MAX_BUF_SIZE] = {0};
3286 FILE *fp = NULL;
3287
3288 if (ifname == NULL || strlen(ifname) <= 1)
3289 return RETURN_OK;
3290
3291 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3292 system(buf);
3293
3294 fp = fopen("/tmp/Radio_Stats.txt", "r");
3295 if(fp == NULL)
3296 {
3297 printf("/tmp/Radio_Stats.txt not exists \n");
3298 return RETURN_ERR;
3299 }
3300 fclose(fp);
3301
3302 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3303 File_Reading(buf, Value);
3304 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3305
3306 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3307 File_Reading(buf, Value);
3308 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3309
3310 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3311 File_Reading(buf, Value);
3312 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3313
3314 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3315 File_Reading(buf, Value);
3316 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3317
3318 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3319 File_Reading(buf, Value);
3320 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3321
3322 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3323 File_Reading(buf, Value);
3324 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3325
3326 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3327 File_Reading(buf, Value);
3328 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3329
3330 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3331 File_Reading(buf, Value);
3332 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3333
3334 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3335 return RETURN_OK;
3336}
3337
3338INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3339{
3340 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3341 CHAR buf[MAX_CMD_SIZE] = {0};
3342 FILE *fp = NULL;
3343 INT count = 0;
3344
3345 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3346 {
3347 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3348 File_Reading(buf, status);
3349 }
3350 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3351 return RETURN_OK;
3352}
3353
3354//Get detail radio traffic static info
3355INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3356{
3357
3358#if 0
3359 //ifconfig radio_x
3360 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3361 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3362 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3363 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3364
3365 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3366 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3367 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.
3368 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.
3369
3370 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3371 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].
3372 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3373 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.
3374 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
3375 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
3376 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
3377 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
3378 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
3379
3380 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
3381 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
3382 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
3383 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.
3384
3385 return RETURN_OK;
3386#endif
3387
developera91d99f2022-09-29 15:59:10 +08003388 CHAR interface_name[64] = {0};
3389 CHAR config_path[64] = {0};
3390 BOOL iface_status = FALSE;
3391 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003392
3393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3394 if (NULL == output_struct)
3395 return RETURN_ERR;
3396
developera91d99f2022-09-29 15:59:10 +08003397 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3398 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003399
developera91d99f2022-09-29 15:59:10 +08003400 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003401
developera91d99f2022-09-29 15:59:10 +08003402 if (iface_status == TRUE)
3403 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3404 else
3405 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003406
developera91d99f2022-09-29 15:59:10 +08003407 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3408 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3409 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3410 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3411 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3412 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3413 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3414 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003415
3416 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3417 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].
3418 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3419 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.
3420 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
3421 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
3422 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
3423 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
3424 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
3425
3426 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
3427 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
3428 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
3429 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.
3430
3431 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3432
3433 return RETURN_OK;
3434}
3435
3436//Set radio traffic static Measureing rules
3437INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3438{
3439 //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
3440 // Else, save the MeasuringRate and MeasuringInterval for future usage
3441
3442 return RETURN_OK;
3443}
3444
3445//To start or stop RadioTrafficStats
3446INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3447{
3448 //zqiu: If the RadioTrafficStats process running
3449 // if(enable)
3450 // return RETURN_OK.
3451 // else
3452 // Stop RadioTrafficStats process
3453 // Else
3454 // if(enable)
3455 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3456 // else
3457 // return RETURN_OK.
3458
3459 return RETURN_OK;
3460}
3461
3462//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
3463INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3464{
3465 //zqiu: Please ignor signalIndex.
3466 if (NULL == SignalLevel)
3467 return RETURN_ERR;
3468 *SignalLevel=(radioIndex==0)?-19:-19;
3469
3470 return RETURN_OK;
3471}
3472
3473//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3474INT wifi_applyRadioSettings(INT radioIndex)
3475{
3476 return RETURN_OK;
3477}
3478
3479//Get the radio index assocated with this SSID entry
3480INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3481{
3482 if (NULL == radioIndex)
3483 return RETURN_ERR;
3484 *radioIndex=ssidIndex%2;
3485
3486 return RETURN_OK;
3487}
3488
3489//Device.WiFi.SSID.{i}.Enable
3490//Get SSID enable configuration parameters (not the SSID enable status)
3491INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3492{
3493 if (NULL == output_bool)
3494 return RETURN_ERR;
3495
3496 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3497 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3498 return wifi_getApEnable(ssidIndex, output_bool);
3499}
3500
3501//Device.WiFi.SSID.{i}.Enable
3502//Set SSID enable configuration parameters
3503INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3504{
3505 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3506 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3507 return wifi_setApEnable(ssidIndex, enable);
3508}
3509
3510//Device.WiFi.SSID.{i}.Status
3511//Get the SSID enable status
3512INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3513{
3514 char cmd[MAX_CMD_SIZE]={0};
3515 char buf[MAX_BUF_SIZE]={0};
3516 BOOL output_bool;
3517
3518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3519 if (NULL == output_string)
3520 return RETURN_ERR;
3521 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3522 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3523
3524 wifi_getApEnable(ssidIndex,&output_bool);
3525 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3526
3527 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3528 return RETURN_OK;
3529}
3530
3531// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3532INT wifi_getSSIDName(INT apIndex, CHAR *output)
3533{
3534 char config_file[MAX_BUF_SIZE] = {0};
3535
3536 if (NULL == output)
3537 return RETURN_ERR;
3538
3539 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3540 wifi_hostapdRead(config_file,"ssid",output,32);
3541
3542 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3543 return RETURN_OK;
3544}
3545
3546// Set a max 32 byte string and sets an internal variable to the SSID name
3547INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3548{
3549 char str[MAX_BUF_SIZE]={'\0'};
3550 char cmd[MAX_CMD_SIZE]={'\0'};
3551 struct params params;
3552 char config_file[MAX_BUF_SIZE] = {0};
3553
3554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3555 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3556 return RETURN_ERR;
3557
3558 params.name = "ssid";
3559 params.value = ssid_string;
3560 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3561 wifi_hostapdWrite(config_file, &params, 1);
3562 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3564
3565 return RETURN_OK;
3566}
3567
3568//Get the BSSID
3569INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3570{
3571 char cmd[MAX_CMD_SIZE]="";
3572
3573 if (NULL == output_string)
3574 return RETURN_ERR;
3575
3576 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3577 {
developer1d57d002022-10-12 18:03:15 +08003578 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 +08003579 _syscmd(cmd, output_string, 64);
3580 return RETURN_OK;
3581 }
3582 strncpy(output_string, "\0", 1);
3583
3584 return RETURN_ERR;
3585}
3586
3587//Get the MAC address associated with this Wifi SSID
3588INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3589{
3590 wifi_getBaseBSSID(ssidIndex,output_string);
3591 return RETURN_OK;
3592}
3593
3594//Get the basic SSID traffic static info
3595//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3596//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3597INT wifi_applySSIDSettings(INT ssidIndex)
3598{
3599 BOOL status = false;
3600 char cmd[MAX_CMD_SIZE] = {0};
3601 char buf[MAX_CMD_SIZE] = {0};
3602 int apIndex, ret;
3603 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3604
3605 wifi_getApEnable(ssidIndex,&status);
3606 // Do not apply when ssid index is disabled
3607 if (status == false)
3608 return RETURN_OK;
3609
3610 /* Doing full remove and add for ssid Index
3611 * Not all hostapd options are supported with reload
3612 * for example macaddr_acl
3613 */
3614 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3615 return RETURN_ERR;
3616
3617 ret = wifi_setApEnable(ssidIndex,true);
3618
3619 /* Workaround for hostapd issue with multiple bss definitions
3620 * when first created interface will be removed
3621 * then all vaps other vaps on same phy are removed
3622 * after calling setApEnable to false readd all enabled vaps */
3623 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3624 apIndex = 2*i+radioIndex;
3625 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3626 _syscmd(cmd, buf, sizeof(buf));
3627 if(*buf == '1')
3628 wifi_setApEnable(apIndex, true);
3629 }
3630
3631 return ret;
3632}
3633
developera3c68b92022-09-13 15:27:29 +08003634struct channels_noise {
3635 int channel;
3636 int noise;
3637};
3638
3639// Return noise array for each channel
3640int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3641{
3642 FILE *f = NULL;
3643 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003644 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003645 size_t len = 0;
3646 ssize_t read = 0;
3647 int tmp = 0, arr_index = -1;
3648
3649 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3650
3651 if ((f = popen(cmd, "r")) == NULL) {
3652 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3653 return RETURN_ERR;
3654 }
developer5550e242022-09-30 09:59:32 +08003655
3656 while(fgets(line, sizeof(line), f) != NULL) {
3657 if(arr_index < channels_num){
3658 sscanf(line, "%d", &tmp);
3659 if (tmp > 0) { // channel frequency, the first line must be frequency
3660 arr_index++;
3661 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3662 } else { // noise
3663 channels_noise_arr[arr_index].noise = tmp;
3664 }
3665 }else{
3666 break;
developera3c68b92022-09-13 15:27:29 +08003667 }
3668 }
developera3c68b92022-09-13 15:27:29 +08003669 pclose(f);
3670 return RETURN_OK;
3671}
3672
developer06a01d92022-09-07 16:32:39 +08003673//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3674//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3675INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3676{
developera3c68b92022-09-13 15:27:29 +08003677 int index = -1;
3678 wifi_neighbor_ap2_t *scan_array = NULL;
3679 char cmd[256]={0};
3680 char buf[128]={0};
3681 char file_name[32] = {0};
3682 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003683 char line[256] = {0};
3684 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003685 int freq=0;
3686 FILE *f = NULL;
3687 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003688 int channels_num = 0;
3689 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003690 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003691 bool filter_enable = false;
3692 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003693
developer615510b2022-09-27 10:14:35 +08003694 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003695
3696 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3697 f = fopen(file_name, "r");
3698 if (f != NULL) {
3699 fgets(filter_SSID, sizeof(file_name), f);
3700 if (strlen(filter_SSID) != 0)
3701 filter_enable = true;
3702 fclose(f);
3703 }
3704
3705 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003706 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003707 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003708
developer5550e242022-09-30 09:59:32 +08003709
developer06a01d92022-09-07 16:32:39 +08003710
developera3c68b92022-09-13 15:27:29 +08003711 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 +08003712 // 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 +08003713 fprintf(stderr, "cmd: %s\n", cmd);
3714 if ((f = popen(cmd, "r")) == NULL) {
3715 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3716 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003717 }
developer5550e242022-09-30 09:59:32 +08003718
3719 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3720 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3721
developer615510b2022-09-27 10:14:35 +08003722 ret = fgets(line, sizeof(line), f);
3723 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003724 if(strstr(line, "BSS") != NULL) { // new neighbor info
3725 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3726 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3727 // 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 +08003728
developera3c68b92022-09-13 15:27:29 +08003729 if (!filter_BSS) {
3730 index++;
3731 wifi_neighbor_ap2_t *tmp;
3732 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3733 if (tmp == NULL) { // no more memory to use
3734 index--;
3735 wifi_dbg_printf("%s: realloc failed\n", __func__);
3736 break;
3737 }
3738 scan_array = tmp;
3739 }
3740 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3741
3742 filter_BSS = false;
3743 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3744 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3745 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3746 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3747 } else if (strstr(line, "freq") != NULL) {
3748 sscanf(line," freq: %d", &freq);
3749 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3750
3751 if (freq >= 2412 && freq <= 2484) {
3752 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3753 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3754 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3755 }
3756 else if (freq >= 5160 && freq <= 5805) {
3757 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3758 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3759 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3760 }
3761
3762 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003763 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003764 for (int i = 0; i < channels_num; i++) {
3765 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3766 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3767 break;
3768 }
3769 }
3770 }
3771 } else if (strstr(line, "beacon interval") != NULL) {
3772 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3773 } else if (strstr(line, "signal") != NULL) {
3774 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3775 } else if (strstr(line,"SSID") != NULL) {
3776 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3777 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3778 filter_BSS = true;
3779 }
3780 } else if (strstr(line, "Supported rates") != NULL) {
3781 char SRate[80] = {0}, *tmp = NULL;
3782 memset(buf, 0, sizeof(buf));
3783 strcpy(SRate, line);
3784 tmp = strtok(SRate, ":");
3785 tmp = strtok(NULL, ":");
3786 strcpy(buf, tmp);
3787 memset(SRate, 0, sizeof(SRate));
3788
3789 tmp = strtok(buf, " \n");
3790 while (tmp != NULL) {
3791 strcat(SRate, tmp);
3792 if (SRate[strlen(SRate) - 1] == '*') {
3793 SRate[strlen(SRate) - 1] = '\0';
3794 }
3795 strcat(SRate, ",");
3796
3797 tmp = strtok(NULL, " \n");
3798 }
3799 SRate[strlen(SRate) - 1] = '\0';
3800 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3801 } else if (strstr(line, "DTIM") != NULL) {
3802 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3803 } else if (strstr(line, "VHT capabilities") != NULL) {
3804 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3805 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3806 } else if (strstr(line, "HT capabilities") != NULL) {
3807 strcat(scan_array[index].ap_SupportedStandards, ",n");
3808 strcpy(scan_array[index].ap_OperatingStandards, "n");
3809 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003810 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003811 sscanf(line," * channel width: %d", &vht_channel_width);
3812 if(vht_channel_width == 1) {
3813 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3814 } else {
3815 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3816 }
3817 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3818 continue;
3819 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003820 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003821 sscanf(line," * secondary channel offset: %s", &buf);
3822 if (!strcmp(buf, "above")) {
3823 //40Mhz +
3824 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3825 }
3826 else if (!strcmp(buf, "below")) {
3827 //40Mhz -
3828 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3829 } else {
3830 //20Mhz
3831 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3832 }
3833 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3834 continue;
3835 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003836 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3837 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3838 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003839 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3840 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003841 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003842 else
developer615510b2022-09-27 10:14:35 +08003843 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003844 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003845 if (strstr(line, "HE80/5GHz") != NULL) {
3846 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3847 ret = fgets(line, sizeof(line), f);
3848 } else
3849 continue;
developera3c68b92022-09-13 15:27:29 +08003850 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003851 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003852 }
developer615510b2022-09-27 10:14:35 +08003853 continue;
developera3c68b92022-09-13 15:27:29 +08003854 } else if (strstr(line, "WPA") != NULL) {
3855 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3856 } else if (strstr(line, "RSN") != NULL) {
3857 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3858 } else if (strstr(line, "Group cipher") != NULL) {
3859 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3860 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3861 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3862 }
3863 }
developer615510b2022-09-27 10:14:35 +08003864 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003865 }
3866
3867 if (!filter_BSS) {
3868 *output_array_size = index + 1;
3869 } else {
3870 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3871 *output_array_size = index;
3872 }
3873 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003874 pclose(f);
developer5550e242022-09-30 09:59:32 +08003875 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003876 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003877 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003878}
3879
3880//>> Deprecated: used for old RDKB code.
3881INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3882{
3883 INT status = RETURN_ERR;
3884
3885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3886 output_struct->wifi_PLCPErrorCount = 0;
3887 output_struct->wifi_FCSErrorCount = 0;
3888 output_struct->wifi_InvalidMACCount = 0;
3889 output_struct->wifi_PacketsOtherReceived = 0;
3890 output_struct->wifi_Noise = 0;
3891 status = RETURN_OK;
3892 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3893 return status;
3894}
3895
3896INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3897{
3898 char cmd[128];
3899 char buf[1280];
3900 char *pos = NULL;
3901
3902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3903 if (NULL == output_struct)
3904 return RETURN_ERR;
3905
3906 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3907
3908 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3909 _syscmd(cmd, buf, sizeof(buf));
3910
3911 pos = buf;
3912 if ((pos = strstr(pos, "RX packets:")) == NULL)
3913 return RETURN_ERR;
3914 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3915
3916 if ((pos = strstr(pos, "TX packets:")) == NULL)
3917 return RETURN_ERR;
3918 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3919
3920 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3921 return RETURN_ERR;
3922 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3923
3924 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3925 return RETURN_ERR;
3926 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3927
3928 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3929 _syscmd(cmd, buf, sizeof(buf));
3930 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3931
3932#if 0
3933 //TODO: need to revisit below implementation
3934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3935 char interface_name[MAX_BUF_SIZE] = {0};
3936 char interface_status[MAX_BUF_SIZE] = {0};
3937 char Value[MAX_BUF_SIZE] = {0};
3938 char buf[MAX_CMD_SIZE] = {0};
3939 char cmd[MAX_CMD_SIZE] = {0};
3940 FILE *fp = NULL;
3941
3942 if (NULL == output_struct) {
3943 return RETURN_ERR;
3944 }
3945
3946 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3947
3948 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3949 {
3950 if(apIndex == 0) //private_wifi for 2.4G
3951 {
3952 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3953 }
3954 else if(apIndex == 1) //private_wifi for 5G
3955 {
3956 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3957 }
3958 else if(apIndex == 4) //public_wifi for 2.4G
3959 {
3960 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3961 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3962 {
3963 return RETURN_ERR;
3964 }
3965 if(buf[0] == '#')//tp-link
3966 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3967 else//tenda
3968 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3969 }
3970 else if(apIndex == 5) //public_wifi for 5G
3971 {
3972 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3973 }
3974
3975 GetIfacestatus(interface_name, interface_status);
3976
3977 if(0 != strcmp(interface_status, "1"))
3978 return RETURN_ERR;
3979
3980 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3981 system(cmd);
3982
3983 fp = fopen("/tmp/SSID_Stats.txt", "r");
3984 if(fp == NULL)
3985 {
3986 printf("/tmp/SSID_Stats.txt not exists \n");
3987 return RETURN_ERR;
3988 }
3989 fclose(fp);
3990
3991 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3992 File_Reading(buf, Value);
3993 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3994
3995 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3996 File_Reading(buf, Value);
3997 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3998
3999 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4000 File_Reading(buf, Value);
4001 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4002
4003 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4004 File_Reading(buf, Value);
4005 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4006
4007 /* There is no specific parameter from caller to associate the value wifi_Associations */
4008 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4009 //_syscmd(cmd, buf, sizeof(buf));
4010 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4011 }
4012#endif
4013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4014 return RETURN_OK;
4015}
4016
4017INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4018{
4019 char interface_name[MAX_BUF_SIZE] = {0};
4020 char interface_status[MAX_BUF_SIZE] = {0};
4021 char Value[MAX_BUF_SIZE] = {0};
4022 char buf[MAX_CMD_SIZE] = {0};
4023 char cmd[MAX_CMD_SIZE] = {0};
4024 FILE *fp = NULL;
4025
4026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4027 if (NULL == output_struct)
4028 return RETURN_ERR;
4029
4030 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4031
4032 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4033 {
4034 if(apIndex == 0) //private_wifi for 2.4G
4035 {
4036 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4037 }
4038 else if(apIndex == 1) //private_wifi for 5G
4039 {
4040 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4041 }
4042 else if(apIndex == 4) //public_wifi for 2.4G
4043 {
4044 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4045 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4046 {
4047 return RETURN_ERR;
4048 }
4049 if(buf[0] == '#')
4050 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4051 else
4052 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4053 }
4054 else if(apIndex == 5) //public_wifi for 5G
4055 {
4056 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4057 }
4058
4059 GetIfacestatus(interface_name, interface_status);
4060
4061 if(0 != strcmp(interface_status, "1"))
4062 return RETURN_ERR;
4063
4064 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4065 system(cmd);
4066
4067 fp = fopen("/tmp/SSID_Stats.txt", "r");
4068 if(fp == NULL)
4069 {
4070 printf("/tmp/SSID_Stats.txt not exists \n");
4071 return RETURN_ERR;
4072 }
4073 fclose(fp);
4074
4075 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4076 File_Reading(buf, Value);
4077 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4078
4079 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4080 File_Reading(buf, Value);
4081 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4082
4083 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4084 File_Reading(buf, Value);
4085 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4086
4087 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4088 File_Reading(buf, Value);
4089 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4090 }
4091
4092 output_struct->wifi_UnicastPacketsSent = 0;
4093 output_struct->wifi_UnicastPacketsReceived = 0;
4094 output_struct->wifi_MulticastPacketsSent = 0;
4095 output_struct->wifi_MulticastPacketsReceived = 0;
4096 output_struct->wifi_BroadcastPacketsSent = 0;
4097 output_struct->wifi_BroadcastPacketsRecevied = 0;
4098 output_struct->wifi_UnknownPacketsReceived = 0;
4099
4100 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4101 return RETURN_OK;
4102}
4103
4104INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4105{
4106 INT status = RETURN_ERR;
4107
4108 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4109 //Below values should get updated from hal
4110 output_struct->wifi_RetransCount=0;
4111 output_struct->wifi_FailedRetransCount=0;
4112 output_struct->wifi_RetryCount=0;
4113 output_struct->wifi_MultipleRetryCount=0;
4114 output_struct->wifi_ACKFailureCount=0;
4115 output_struct->wifi_AggregatedPacketCount=0;
4116
4117 status = RETURN_OK;
4118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4119
4120 return status;
4121}
4122
4123INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4124{
4125 INT status = RETURN_ERR;
4126 UINT index;
4127 wifi_neighbor_ap_t *pt=NULL;
4128
4129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4130 *output_array_size=2;
4131 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4132 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4133 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4134 strcpy(pt->ap_Radio,"");
4135 strcpy(pt->ap_SSID,"");
4136 strcpy(pt->ap_BSSID,"");
4137 strcpy(pt->ap_Mode,"");
4138 pt->ap_Channel=1;
4139 pt->ap_SignalStrength=0;
4140 strcpy(pt->ap_SecurityModeEnabled,"");
4141 strcpy(pt->ap_EncryptionMode,"");
4142 strcpy(pt->ap_OperatingFrequencyBand,"");
4143 strcpy(pt->ap_SupportedStandards,"");
4144 strcpy(pt->ap_OperatingStandards,"");
4145 strcpy(pt->ap_OperatingChannelBandwidth,"");
4146 pt->ap_BeaconPeriod=1;
4147 pt->ap_Noise=0;
4148 strcpy(pt->ap_BasicDataTransferRates,"");
4149 strcpy(pt->ap_SupportedDataTransferRates,"");
4150 pt->ap_DTIMPeriod=1;
4151 pt->ap_ChannelUtilization = 1;
4152 }
4153
4154 status = RETURN_OK;
4155 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4156
4157 return status;
4158}
4159
4160//----------------- AP HAL -------------------------------
4161
4162//>> Deprecated: used for old RDKB code.
4163INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4164{
4165 if (NULL == output_ulong || NULL == output_struct)
4166 return RETURN_ERR;
4167 *output_ulong = 0;
4168 *output_struct = NULL;
4169 return RETURN_OK;
4170}
4171
4172#ifdef HAL_NETLINK_IMPL
4173static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4174 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4175 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4176 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4177 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4178 char mac_addr[20];
4179 static int count=0;
4180 int rate=0;
4181
4182 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4183
4184 nla_parse(tb,
4185 NL80211_ATTR_MAX,
4186 genlmsg_attrdata(gnlh, 0),
4187 genlmsg_attrlen(gnlh, 0),
4188 NULL);
4189
4190 if(!tb[NL80211_ATTR_STA_INFO]) {
4191 fprintf(stderr, "sta stats missing!\n");
4192 return NL_SKIP;
4193 }
4194
4195
4196 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4197 fprintf(stderr, "failed to parse nested attributes!\n");
4198 return NL_SKIP;
4199 }
4200
4201 //devIndex starts from 1
4202 if( ++count == out->wifi_devIndex )
4203 {
4204 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4205 //Getting the mac addrress
4206 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4207
4208 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4209 fprintf(stderr, "failed to parse nested rate attributes!");
4210 return NL_SKIP;
4211 }
4212
4213 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4214 if(rinfo[NL80211_RATE_INFO_BITRATE])
4215 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4216 out->wifi_devTxRate = rate/10;
4217 }
4218
4219 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4220 fprintf(stderr, "failed to parse nested rate attributes!");
4221 return NL_SKIP;
4222 }
4223
4224 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4225 if(rinfo[NL80211_RATE_INFO_BITRATE])
4226 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4227 out->wifi_devRxRate = rate/10;
4228 }
4229 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4230 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4231
4232 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4233 count = 0; //starts the count for next cycle
4234 return NL_STOP;
4235 }
4236
4237 return NL_SKIP;
4238
4239}
4240#endif
4241
4242INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4243{
4244#ifdef HAL_NETLINK_IMPL
4245 Netlink nl;
4246 char if_name[10];
4247
4248 wifi_device_info_t info;
4249 info.wifi_devIndex = devIndex;
4250
4251 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4252
4253 nl.id = initSock80211(&nl);
4254
4255 if (nl.id < 0) {
4256 fprintf(stderr, "Error initializing netlink \n");
4257 return -1;
4258 }
4259
4260 struct nl_msg* msg = nlmsg_alloc();
4261
4262 if (!msg) {
4263 fprintf(stderr, "Failed to allocate netlink message.\n");
4264 nlfree(&nl);
4265 return -2;
4266 }
4267
4268 genlmsg_put(msg,
4269 NL_AUTO_PORT,
4270 NL_AUTO_SEQ,
4271 nl.id,
4272 0,
4273 NLM_F_DUMP,
4274 NL80211_CMD_GET_STATION,
4275 0);
4276
4277 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4278 nl_send_auto(nl.socket, msg);
4279 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4280 nl_recvmsgs(nl.socket, nl.cb);
4281 nlmsg_free(msg);
4282 nlfree(&nl);
4283
4284 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4285 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4286 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4287 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4288 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4289 return RETURN_OK;
4290#else
4291 //iw utility to retrieve station information
4292#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4293#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4294#define MACFILE "/tmp/wifi_AssoMac.txt"
4295#define TXRATEFILE "/tmp/wifi_txrate.txt"
4296#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4297 FILE *file = NULL;
4298 char if_name[10] = {'\0'};
4299 char pipeCmd[256] = {'\0'};
4300 char line[256];
4301 int count,device = 0;
4302
4303 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4304
4305 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4306 file = popen(pipeCmd, "r");
4307
4308 if(file == NULL)
4309 return RETURN_ERR; //popen failed
4310
4311 fgets(line, sizeof line, file);
4312 device = atoi(line);
4313 pclose(file);
4314
4315 if(device == 0)
4316 return RETURN_ERR; //No devices are connected
4317
4318 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4319 system(pipeCmd);
4320
4321 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4322
4323 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4324
4325 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4326
4327 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4328
4329 //devIndex starts from 1, ++count
4330 if((file = fopen(SIGNALFILE, "r")) != NULL )
4331 {
4332 for(count =0;fgets(line, sizeof line, file) != NULL;)
4333 {
4334 if (++count == devIndex)
4335 {
4336 output_struct->wifi_devSignalStrength = atoi(line);
4337 break;
4338 }
4339 }
4340 fclose(file);
4341 }
4342 else
4343 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4344
4345 if((file = fopen(MACFILE, "r")) != NULL )
4346 {
4347 for(count =0;fgets(line, sizeof line, file) != NULL;)
4348 {
4349 if (++count == devIndex)
4350 {
4351 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]);
4352 break;
4353 }
4354 }
4355 fclose(file);
4356 }
4357 else
4358 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4359
4360 if((file = fopen(TXRATEFILE, "r")) != NULL )
4361 {
4362 for(count =0;fgets(line, sizeof line, file) != NULL;)
4363 {
4364 if (++count == devIndex)
4365 {
4366 output_struct->wifi_devTxRate = atoi(line);
4367 break;
4368 }
4369 }
4370 fclose(file);
4371 }
4372 else
4373 fprintf(stderr,"fopen wifi_txrate.txt failed");
4374
4375 if((file = fopen(RXRATEFILE, "r")) != NULL)
4376 {
4377 for(count =0;fgets(line, sizeof line, file) != NULL;)
4378 {
4379 if (++count == devIndex)
4380 {
4381 output_struct->wifi_devRxRate = atoi(line);
4382 break;
4383 }
4384 }
4385 fclose(file);
4386 }
4387 else
4388 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4389
4390 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4391
4392 return RETURN_OK;
4393#endif
4394}
4395
4396INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4397{
4398 if (NULL == device)
4399 return RETURN_ERR;
4400 return RETURN_OK;
4401}
4402//<<
4403
4404
4405//--------------wifi_ap_hal-----------------------------
4406//enables CTS protection for the radio used by this AP
4407INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4408{
4409 //save config and Apply instantly
4410 return RETURN_ERR;
4411}
4412
4413// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4414INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4415{
developer463d39a2022-09-13 15:32:51 +08004416 char config_file[64] = {'\0'};
4417 char buf[64] = {'\0'};
4418 struct params list;
4419
4420 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4421 list.name = "ht_coex";
4422 snprintf(buf, sizeof(buf), "%d", enable);
4423 list.value = buf;
4424
4425 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4426 wifi_hostapdWrite(config_file, &list, 1);
4427 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4428
4429 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4430
4431 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004432}
4433
4434//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4435INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4436{
developerea4bcce2022-09-13 15:26:13 +08004437 char config_file[MAX_BUF_SIZE] = {'\0'};
4438 char buf[MAX_BUF_SIZE] = {'\0'};
4439 struct params list;
4440
4441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4442 if (threshold < 256 || threshold > 2346 )
4443 return RETURN_ERR;
4444 list.name = "fragm_threshold";
4445 snprintf(buf, sizeof(buf), "%d", threshold);
4446 list.value = buf;
4447
4448 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4449 wifi_hostapdWrite(config_file, &list, 1);
4450 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004451
developerea4bcce2022-09-13 15:26:13 +08004452 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004453
4454 return RETURN_OK;
4455}
4456
4457// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4458INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4459{
developer51a927d2022-09-13 15:42:22 +08004460 char config_file[64] = {'\0'};
4461 char cmd[128] = {'\0'};
4462 char buf[64] = {'\0'};
4463 char stbc_config[16] = {'\0'};
4464 wifi_band band;
4465 int iterator = 0;
4466 BOOL current_stbc = FALSE;
4467
4468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4469
4470 band = wifi_index_to_band(radioIndex);
4471 if (band == band_invalid)
4472 return RETURN_ERR;
4473
4474 if (band == band_2_4)
4475 iterator = 1;
4476 else if (band == band_5)
4477 iterator = 2;
4478 else
4479 return RETURN_OK;
4480
4481 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4482
4483 // set ht and vht config
4484 for (int i = 0; i < iterator; i++) {
4485 memset(stbc_config, 0, sizeof(stbc_config));
4486 memset(cmd, 0, sizeof(cmd));
4487 memset(buf, 0, sizeof(buf));
4488 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4489 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4490 _syscmd(cmd, buf, sizeof(buf));
4491 if (strlen(buf) != 0)
4492 current_stbc = TRUE;
4493 if (current_stbc == STBC_Enable)
4494 continue;
4495
4496 if (STBC_Enable == TRUE) {
4497 // Append the STBC flags in capab config
4498 memset(cmd, 0, sizeof(cmd));
4499 if (i == 0)
4500 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4501 else
4502 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4503 _syscmd(cmd, buf, sizeof(buf));
4504 } else if (STBC_Enable == FALSE) {
4505 // Remove the STBC flags and remain other flags in capab
4506 memset(cmd, 0, sizeof(cmd));
4507 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4508 _syscmd(cmd, buf, sizeof(buf));
4509 memset(cmd, 0, sizeof(cmd));
4510 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4511 _syscmd(cmd, buf, sizeof(buf));
4512 }
4513 }
4514
4515 wifi_reloadAp(radioIndex);
4516
4517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4518 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004519}
4520
4521// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4522INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4523{
developer54e6b9f2022-09-28 14:41:20 +08004524 char AMSDU_file_path[64] = {0};
4525
4526 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4527
4528 if(output_bool == NULL)
4529 return RETURN_ERR;
4530
4531 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4532
4533 if (access(AMSDU_file_path, F_OK) == 0)
4534 *output_bool = TRUE;
4535 else
4536 *output_bool = FALSE;
4537
4538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4539 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004540}
4541
4542// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4543INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4544{
developer54e6b9f2022-09-28 14:41:20 +08004545 char cmd[64]={0};
4546 char buf[64]={0};
4547 char AMSDU_file_path[64] = {0};
4548
4549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4550
4551 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4552 _syscmd(cmd, buf, sizeof(buf));
4553
4554 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4555 memset(cmd, 0, sizeof(cmd));
4556 if (amsduEnable == TRUE)
4557 sprintf(cmd, "touch %s", AMSDU_file_path);
4558 else
4559 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4560 _syscmd(cmd, buf, sizeof(buf));
4561
4562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4563 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004564}
4565
4566//P2 // outputs the number of Tx streams
4567INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4568{
developer2de97692022-09-26 14:00:03 +08004569 char buf[8] = {0};
4570 char cmd[128] = {0};
4571
4572 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4573
4574 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4575 _syscmd(cmd, buf, sizeof(buf));
4576
4577 // if there is no record, output the max number of spatial streams
4578 if (strlen(buf) == 0) {
4579 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4580 _syscmd(cmd, buf, sizeof(buf));
4581 }
4582
4583 *output_int = (INT)strtol(buf, NULL, 10);
4584
4585 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4586
4587 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004588}
4589
4590//P2 // sets the number of Tx streams to an enviornment variable
4591INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4592{
developer2de97692022-09-26 14:00:03 +08004593 char cmd[128] = {0};
4594 char buf[128] = {0};
4595 char chain_mask_file[128] = {0};
4596 FILE *f = NULL;
4597
4598 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4599
4600 if (numStreams == 0) {
4601 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4602 return RETURN_ERR;
4603 }
4604 wifi_setRadioEnable(radioIndex, FALSE);
4605 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4606 _syscmd(cmd, buf, sizeof(buf));
4607
4608 if (strlen(buf) > 0) {
4609 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4610 return RETURN_ERR;
4611 }
4612 wifi_setRadioEnable(radioIndex, TRUE);
4613
4614 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4615 f = fopen(chain_mask_file, "w");
4616 if (f == NULL) {
4617 fprintf(stderr, "%s: fopen failed.\n", __func__);
4618 return RETURN_ERR;
4619 }
4620 fprintf(f, "%d", numStreams);
4621 fclose(f);
4622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4623 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004624}
4625
4626//P2 // outputs the number of Rx streams
4627INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4628{
developer2de97692022-09-26 14:00:03 +08004629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4630 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4631 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004632 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004633 }
4634 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004635 return RETURN_OK;
4636}
4637
4638//P2 // sets the number of Rx streams to an enviornment variable
4639INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4640{
developer2de97692022-09-26 14:00:03 +08004641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4642 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4643 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4644 return RETURN_ERR;
4645 }
4646 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004647 return RETURN_ERR;
4648}
4649
4650//Get radio RDG enable setting
4651INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4652{
4653 if (NULL == output_bool)
4654 return RETURN_ERR;
4655 *output_bool = TRUE;
4656 return RETURN_OK;
4657}
4658
4659//Get radio RDG enable setting
4660INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4661{
4662 if (NULL == output_bool)
4663 return RETURN_ERR;
4664 *output_bool = TRUE;
4665 return RETURN_OK;
4666}
4667
4668//Set radio RDG enable setting
4669INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4670{
4671 return RETURN_ERR;
4672}
4673
4674//Get radio ADDBA enable setting
4675INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4676{
4677 if (NULL == output_bool)
4678 return RETURN_ERR;
4679 *output_bool = TRUE;
4680 return RETURN_OK;
4681}
4682
4683//Set radio ADDBA enable setting
4684INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4685{
4686 return RETURN_ERR;
4687}
4688
4689//Get radio auto block ack enable setting
4690INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4691{
4692 if (NULL == output_bool)
4693 return RETURN_ERR;
4694 *output_bool = TRUE;
4695 return RETURN_OK;
4696}
4697
4698//Set radio auto block ack enable setting
4699INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4700{
4701 return RETURN_ERR;
4702}
4703
4704//Get radio 11n pure mode enable support
4705INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4706{
4707 if (NULL == output_bool)
4708 return RETURN_ERR;
4709 *output_bool = TRUE;
4710 return RETURN_OK;
4711}
4712
4713//Get radio 11n pure mode enable setting
4714INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4715{
4716 if (NULL == output_bool)
4717 return RETURN_ERR;
4718 *output_bool = TRUE;
4719 return RETURN_OK;
4720}
4721
4722//Set radio 11n pure mode enable setting
4723INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4724{
4725 return RETURN_ERR;
4726}
4727
4728//Get radio IGMP snooping enable setting
4729INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4730{
developer81bf2ed2022-09-13 15:31:14 +08004731 char cmd[128]={0};
4732 char buf[4]={0};
4733 bool bridge = FALSE, mac80211 = FALSE;
4734 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4735
4736 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004737 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004738
4739 *output_bool = FALSE;
4740
4741 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4742 _syscmd(cmd, buf, sizeof(buf));
4743 if (strncmp(buf, "1", 1) == 0)
4744 bridge = TRUE;
4745
4746 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4747 _syscmd(cmd, buf, sizeof(buf));
4748 if (strncmp(buf, "1", 1) == 0)
4749 mac80211 = TRUE;
4750
4751 if (bridge && mac80211)
4752 *output_bool = TRUE;
4753
4754 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004755 return RETURN_OK;
4756}
4757
4758//Set radio IGMP snooping enable setting
4759INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4760{
developer81bf2ed2022-09-13 15:31:14 +08004761 char cmd[128]={0};
4762 char buf[4]={0};
4763
4764 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4765
4766 // bridge
4767 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4768 _syscmd(cmd, buf, sizeof(buf));
4769
4770 // mac80211
4771 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4772 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4773 _syscmd(cmd, buf, sizeof(buf));
4774 }
4775 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4776 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004777}
4778
4779//Get the Reset count of radio
4780INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4781{
4782 if (NULL == output_int)
4783 return RETURN_ERR;
4784 *output_int = (radioIndex==0)? 1: 3;
4785
4786 return RETURN_OK;
4787}
4788
4789
4790//---------------------------------------------------------------------------------------------------
4791//
4792// Additional Wifi AP level APIs used for Access Point devices
4793//
4794//---------------------------------------------------------------------------------------------------
4795
4796// creates a new ap and pushes these parameters to the hardware
4797INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4798{
4799 char buf[1024];
4800 char cmd[128];
4801
4802 if (NULL == essid)
4803 return RETURN_ERR;
4804
4805 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4806 _syscmd(cmd, buf, sizeof(buf));
4807
4808 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4809 _syscmd(cmd, buf, sizeof(buf));
4810
4811 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4812
4813 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4814 _syscmd(cmd, buf, sizeof(buf));
4815
4816 return RETURN_OK;
4817}
4818
4819// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4820INT wifi_deleteAp(INT apIndex)
4821{
4822 char buf[1024];
4823 char cmd[128];
4824
4825 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4826 _syscmd(cmd, buf, sizeof(buf));
4827
4828 wifi_removeApSecVaribles(apIndex);
4829
4830 return RETURN_OK;
4831}
4832
4833// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4834INT wifi_getApName(INT apIndex, CHAR *output_string)
4835{
4836 if(NULL == output_string)
4837 return RETURN_ERR;
4838
4839 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4840 return RETURN_OK;
4841}
4842
4843// Outputs the index number in that corresponds to the SSID string
4844INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4845{
4846 CHAR *pos = NULL;
4847
4848 *output_int = -1;
4849 pos = strstr(inputSsidString, AP_PREFIX);
4850 if(pos)
4851 {
4852 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4853 return RETURN_OK;
4854 }
4855 return RETURN_ERR;
4856}
4857
4858INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4859{
4860 return wifi_getIndexFromName(inputSsidString, output_int);
4861}
4862
4863// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4864INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4865{
4866 char buf[MAX_BUF_SIZE] = {0};
4867 char cmd[MAX_CMD_SIZE] = {0};
4868 char config_file[MAX_BUF_SIZE] = {0};
4869
4870 if(NULL == output_string)
4871 return RETURN_ERR;
4872
4873 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4874 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4875 if((strcmp(buf,"3")==0))
4876 snprintf(output_string, 32, "WPAand11i");
4877 else if((strcmp(buf,"2")==0))
4878 snprintf(output_string, 32, "11i");
4879 else if((strcmp(buf,"1")==0))
4880 snprintf(output_string, 32, "WPA");
4881 else
4882 snprintf(output_string, 32, "None");
4883
4884 return RETURN_OK;
4885}
4886
4887// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4888INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4889{
4890 char config_file[MAX_BUF_SIZE] = {0};
4891 struct params list;
4892
4893 if (NULL == beaconTypeString)
4894 return RETURN_ERR;
4895 list.name = "wpa";
4896 list.value = "0";
4897
4898 if((strcmp(beaconTypeString,"WPAand11i")==0))
4899 list.value="3";
4900 else if((strcmp(beaconTypeString,"11i")==0))
4901 list.value="2";
4902 else if((strcmp(beaconTypeString,"WPA")==0))
4903 list.value="1";
4904
4905 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4906 wifi_hostapdWrite(config_file, &list, 1);
4907 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4908 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4909 return RETURN_OK;
4910}
4911
4912// sets the beacon interval on the hardware for this AP
4913INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4914{
developer5f222492022-09-13 15:21:52 +08004915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4916 struct params params={'\0'};
4917 char buf[MAX_BUF_SIZE] = {'\0'};
4918 char config_file[MAX_BUF_SIZE] = {'\0'};
4919
4920 params.name = "beacon_int";
4921 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4922 params.value = buf;
4923
4924 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4925 wifi_hostapdWrite(config_file, &params, 1);
4926
4927 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4929 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004930}
4931
4932INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4933{
4934 //save config and apply instantly
4935 return RETURN_ERR;
4936}
4937
4938// Get the packet size threshold supported.
4939INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4940{
4941 //save config and apply instantly
4942 if (NULL == output_bool)
4943 return RETURN_ERR;
4944 *output_bool = FALSE;
4945 return RETURN_OK;
4946}
4947
4948// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4949INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4950{
4951 char cmd[128];
4952 char buf[512];
4953
4954 if (threshold > 0)
4955 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4956 else
4957 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4958 _syscmd(cmd, buf, sizeof(buf));
4959
4960 return RETURN_OK;
4961}
4962
4963// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4964INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4965{
4966 if (NULL == output_string)
4967 return RETURN_ERR;
4968 snprintf(output_string, 32, "TKIPandAESEncryption");
4969 return RETURN_OK;
4970
4971}
4972
4973// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4974INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4975{
4976 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4977 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4978
4979 if(NULL == output_string)
4980 return RETURN_ERR;
4981
4982 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4983 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4984
4985 if(strcmp(buf,"0")==0)
4986 {
4987 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4988 snprintf(output_string, 32, "None");
4989 return RETURN_OK;
4990 }
4991 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4992 param_name = "rsn_pairwise";
4993 else if((strcmp(buf,"1")==0))
4994 param_name = "wpa_pairwise";
4995 else
4996 return RETURN_ERR;
4997 memset(output_string,'\0',32);
4998 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4999 wifi_hostapdRead(config_file,param_name,output_string,32);
5000 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5001
5002 if(strcmp(output_string,"TKIP") == 0)
5003 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5004 else if(strcmp(output_string,"CCMP") == 0)
5005 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5006 else if(strcmp(output_string,"TKIP CCMP") == 0)
5007 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5008
5009 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5010 return RETURN_OK;
5011}
5012
5013// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5014INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5015{
5016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5017 struct params params={'\0'};
5018 char output_string[32];
5019 char config_file[MAX_BUF_SIZE] = {0};
5020
5021 memset(output_string,'\0',32);
5022 wifi_getApWpaEncryptionMode(apIndex,output_string);
5023
5024 if(strcmp(encMode, "TKIPEncryption") == 0)
5025 params.value = "TKIP";
5026 else if(strcmp(encMode,"AESEncryption") == 0)
5027 params.value = "CCMP";
5028 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5029 params.value = "TKIP CCMP";
5030
5031 if((strcmp(output_string,"WPAand11i")==0))
5032 {
5033 params.name = "wpa_pairwise";
5034 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5035 wifi_hostapdWrite(config_file, &params, 1);
5036 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5037
5038 params.name,"rsn_pairwise";
5039 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5040 wifi_hostapdWrite(config_file, &params, 1);
5041 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5042
5043 return RETURN_OK;
5044 }
5045 else if((strcmp(output_string,"11i")==0))
5046 {
5047 params.name = "rsn_pairwise";
5048 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5049 wifi_hostapdWrite(config_file, &params, 1);
5050 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5051 return RETURN_OK;
5052 }
5053 else if((strcmp(output_string,"WPA")==0))
5054 {
5055 params.name = "wpa_pairwise";
5056 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5057 wifi_hostapdWrite(config_file, &params, 1);
5058 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5059 return RETURN_OK;
5060 }
5061
5062 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5063 return RETURN_OK;
5064}
5065
5066// deletes internal security varable settings for this ap
5067INT wifi_removeApSecVaribles(INT apIndex)
5068{
5069 //TODO: remove the entry in hostapd config file
5070 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5071 //_syscmd(cmd, buf, sizeof(buf));
5072
5073 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5074 //_syscmd(cmd, buf, sizeof(buf));
5075 return RETURN_ERR;
5076}
5077
5078// changes the hardware settings to disable encryption on this ap
5079INT wifi_disableApEncryption(INT apIndex)
5080{
5081 //Apply instantly
5082 return RETURN_ERR;
5083}
5084
5085// set the authorization mode on this ap
5086// mode mapping as: 1: open, 2: shared, 4:auto
5087INT wifi_setApAuthMode(INT apIndex, INT mode)
5088{
developeraf95c502022-09-13 16:18:22 +08005089 struct params params={0};
5090 char config_file[64] = {0};
5091 int ret;
5092
5093 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5094
5095 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5096 params.name = "auth_algs";
5097
5098 if (mode & 1 && mode & 2)
5099 params.value = "3";
5100 else if (mode & 2)
5101 params.value = "2";
5102 else if (mode & 1)
5103 params.value = "1";
5104 else
5105 params.value = "0";
5106
5107 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5108 wifi_hostapdWrite(config_file, &params, 1);
5109 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5111
5112 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005113}
5114
5115// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5116INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5117{
5118 //save to wifi config, and wait for wifi restart to apply
5119 struct params params={'\0'};
5120 char config_file[MAX_BUF_SIZE] = {0};
5121 int ret;
5122
5123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5124 if(authMode == NULL)
5125 return RETURN_ERR;
5126
5127 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5128 params.name = "wpa_key_mgmt";
5129
5130 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5131 params.value = "WPA-PSK";
5132 else if(strcmp(authMode,"EAPAuthentication") == 0)
5133 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005134 else if (strcmp(authMode, "SAEAuthentication") == 0)
5135 params.value = "SAE";
5136 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5137 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005138 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5139 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005140 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5141 return RETURN_OK; //This is taken careof in beaconType
5142
5143 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5144 ret=wifi_hostapdWrite(config_file,&params,1);
5145 if(!ret)
5146 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5147 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5148
5149 return ret;
5150}
5151
5152// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5153INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5154{
5155 //save to wifi config, and wait for wifi restart to apply
5156 char BeaconType[50] = {0};
5157 char config_file[MAX_BUF_SIZE] = {0};
5158
5159 *authMode = 0;
5160 wifi_getApBeaconType(apIndex,BeaconType);
5161 printf("%s____%s \n",__FUNCTION__,BeaconType);
5162
5163 if(strcmp(BeaconType,"None") == 0)
5164 strcpy(authMode,"None");
5165 else
5166 {
5167 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5168 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5169 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5170 if(strcmp(authMode,"WPA-PSK") == 0)
5171 strcpy(authMode,"SharedAuthentication");
5172 else if(strcmp(authMode,"WPA-EAP") == 0)
5173 strcpy(authMode,"EAPAuthentication");
5174 }
5175
5176 return RETURN_OK;
5177}
5178
5179// Outputs the number of stations associated per AP
5180INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5181{
5182 char cmd[128]={0};
5183 char buf[128]={0};
5184 BOOL status = false;
5185
5186 if(apIndex > MAX_APS)
5187 return RETURN_ERR;
5188
5189 wifi_getApEnable(apIndex,&status);
5190 if (!status)
5191 return RETURN_OK;
5192
5193 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5194 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5195 _syscmd(cmd, buf, sizeof(buf));
5196 sscanf(buf,"%lu", output_ulong);
5197
5198 return RETURN_OK;
5199}
5200
5201// manually removes any active wi-fi association with the device specified on this ap
5202INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5203{
5204 char buf[126]={'\0'};
5205
5206 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5207 system(buf);
5208
5209 return RETURN_OK;
5210}
5211
5212// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5213INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5214{
5215 if(NULL == output_int)
5216 return RETURN_ERR;
5217 *output_int = apIndex%2;
5218 return RETURN_OK;
5219}
5220
5221// sets the radio index for the specific ap
5222INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5223{
5224 //set to config only and wait for wifi reset to apply settings
5225 return RETURN_ERR;
5226}
5227
5228// Get the ACL MAC list per AP
5229INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5230{
5231 char cmd[MAX_CMD_SIZE]={'\0'};
5232 int ret = 0;
5233
5234 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5235 ret = _syscmd(cmd,macArray,buf_size);
5236 if (ret != 0)
5237 return RETURN_ERR;
5238
5239 return RETURN_OK;
5240}
5241
developere6aafda2022-09-13 14:59:28 +08005242INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5243{
5244 char cmd[MAX_CMD_SIZE]={'\0'};
5245 int ret = 0;
5246
5247 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5248 ret = _syscmd(cmd,macArray,buf_size);
5249 if (ret != 0)
5250 return RETURN_ERR;
5251
5252 return RETURN_OK;
5253}
5254
5255
developer06a01d92022-09-07 16:32:39 +08005256// Get the list of stations associated per AP
5257INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5258{
5259 char cmd[128];
5260
5261 if(apIndex > 3) //Currently supporting apIndex upto 3
5262 return RETURN_ERR;
5263 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5264 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5265 _syscmd(cmd, macArray, buf_size);
5266
5267 return RETURN_OK;
5268}
5269
5270// adds the mac address to the filter list
5271//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5272INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5273{
5274 char cmd[MAX_CMD_SIZE]={'\0'};
5275 char buf[MAX_BUF_SIZE]={'\0'};
5276
5277#if 0
5278 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5279 if(_syscmd(cmd,buf,sizeof(buf)))
5280 return RETURN_ERR;
5281#endif
5282 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5283 if(_syscmd(cmd,buf,sizeof(buf)))
5284 return RETURN_ERR;
5285
5286 return RETURN_OK;
5287}
5288
5289// deletes the mac address from the filter list
5290//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5291INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5292{
5293 char cmd[MAX_CMD_SIZE]={'\0'};
5294 char buf[MAX_BUF_SIZE]={'\0'};
5295
5296#if 0
5297 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5298 if(_syscmd(cmd,buf,sizeof(buf)))
5299 return RETURN_ERR;
5300
5301#endif
5302 sprintf(cmd, "sed -i '/%s/d' %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// outputs the number of devices in the filter list
5310INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5311{
developere6aafda2022-09-13 14:59:28 +08005312 char cmd[MAX_BUF_SIZE]={0};
5313 char buf[MAX_CMD_SIZE]={0};
5314
5315 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5316 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005317 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005318
5319 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5320 _syscmd(cmd, buf, sizeof(buf));
5321
5322 *output_uint = atoi(buf);
5323
5324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5325 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005326}
5327
5328INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5329{
5330 char cmd[128]={'\0'};
5331 char buf[128]={'\0'};
5332
5333 if(strcmp(action,"DENY")==0)
5334 {
5335 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5336 system(buf);
5337 return RETURN_OK;
5338 }
5339
5340 if(strcmp(action,"ALLOW")==0)
5341 {
5342 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5343 system(buf);
5344 return RETURN_OK;
5345 }
5346
5347 return RETURN_ERR;
5348
5349}
5350
5351// enable kick for devices on acl black list
5352INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5353{
5354 char aclArray[512] = {0}, *acl = NULL;
5355 char assocArray[512] = {0}, *asso = NULL;
5356
developere6aafda2022-09-13 14:59:28 +08005357 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005358 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5359
5360 // if there are no devices connected there is nothing to do
5361 if (strlen(assocArray) < 17)
5362 return RETURN_OK;
5363
5364 if (enable == TRUE)
5365 {
5366 //kick off the MAC which is in ACL array (deny list)
5367 acl = strtok(aclArray, "\r\n");
5368 while (acl != NULL) {
5369 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5370 wifi_kickApAssociatedDevice(apIndex, acl);
5371
5372 acl = strtok(NULL, "\r\n");
5373 }
developere6aafda2022-09-13 14:59:28 +08005374 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005375 }
5376 else
5377 {
developere6aafda2022-09-13 14:59:28 +08005378 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005379 }
5380
5381#if 0
5382 //TODO: need to revisit below implementation
5383 char aclArray[512]={0}, *acl=NULL;
5384 char assocArray[512]={0}, *asso=NULL;
5385 char buf[256]={'\0'};
5386 char action[10]={'\0'};
5387 FILE *fr=NULL;
5388 char interface[10]={'\0'};
5389 char config_file[MAX_BUF_SIZE] = {0};
5390
5391 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5392 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5393 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5394 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5395
5396 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5397 system(buf);
5398 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5399 system(buf);
5400 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5401 system(buf);
5402 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5403 system(buf);
5404 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5405 system(buf);
5406
5407 if ( enable == TRUE )
5408 {
5409 int device_count=0;
5410 strcpy(action,"DENY");
5411 //kick off the MAC which is in ACL array (deny list)
5412 acl = strtok (aclArray,",");
5413 while (acl != NULL) {
5414 if(strlen(acl)>=17)
5415 {
5416 apply_rules(apIndex, acl,action,interface);
5417 device_count++;
5418 //Register mac to be blocked ,in syscfg.db persistent storage
5419 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5420 system(buf);
5421 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5422 system(buf);
5423 system("syscfg commit");
5424
5425 wifi_kickApAssociatedDevice(apIndex, acl);
5426 }
5427 acl = strtok (NULL, ",");
5428 }
5429 }
5430 else
5431 {
5432 int device_count=0;
5433 char cmdmac[20]={'\0'};
5434 strcpy(action,"ALLOW");
5435 //kick off the MAC which is not in ACL array (allow list)
5436 acl = strtok (aclArray,",");
5437 while (acl != NULL) {
5438 if(strlen(acl)>=17)
5439 {
5440 apply_rules(apIndex, acl,action,interface);
5441 device_count++;
5442 //Register mac to be Allowed ,in syscfg.db persistent storage
5443 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5444 system(buf);
5445 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5446 system(buf);
5447 sprintf(cmdmac,"%s",acl);
5448 }
5449 acl = strtok (NULL, ",");
5450 }
5451 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5452 system(buf);
5453
5454 //Disconnect the mac which is not in ACL
5455 asso = strtok (assocArray,",");
5456 while (asso != NULL) {
5457 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5458 wifi_kickApAssociatedDevice(apIndex, asso);
5459 asso = strtok (NULL, ",");
5460 }
5461 }
5462#endif
5463 return RETURN_OK;
5464}
5465
5466INT wifi_setPreferPrivateConnection(BOOL enable)
5467{
5468 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5469 char buf[1024] = {0};
5470
5471 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5472 if(enable == TRUE)
5473 {
5474 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5475 sprintf(buf,"ifconfig %s down" ,interface_name);
5476 system(buf);
5477 memset(buf,0,sizeof(buf));
5478 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5479 sprintf(buf,"ifconfig %s down" ,interface_name);
5480 system(buf);
5481 }
5482 else
5483 {
5484 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5485 if(strcmp(ssid_cur_value,"1") == 0)
5486 wifi_RestartPrivateWifi_5G();
5487 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5488 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5489 if(strcmp(ssid_cur_value,"1") == 0)
5490 wifi_RestartHostapd_2G();
5491 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5492 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5493 if(strcmp(ssid_cur_value,"1") == 0)
5494 wifi_RestartHostapd_5G();
5495 }
5496 return RETURN_OK;
5497}
5498
5499// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5500INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5501{
5502 int items = 1;
5503 struct params list[2];
5504 char buf[MAX_BUF_SIZE] = {0};
5505 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005506 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005507
5508 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005509
developer10adcc12022-09-13 14:39:17 +08005510 if (filterMode == 0) {
5511 sprintf(buf, "%d", 0);
5512 list[0].value = buf;
5513
5514 char cmd[128], rtn[128];
5515 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5516 _syscmd(cmd, rtn, sizeof(rtn));
5517 memset(cmd,0,sizeof(cmd));
5518 // Delete deny_mac_file in hostapd configuration
5519 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5520 _syscmd(cmd, rtn, sizeof(rtn));
5521 }
5522 else if (filterMode == 1) {
5523 sprintf(buf, "%d", filterMode);
5524 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005525 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5526 list[1].name = "accept_mac_file";
5527 list[1].value = acl_file;
5528 items = 2;
developer10adcc12022-09-13 14:39:17 +08005529 } else if (filterMode == 2) {
5530 //TODO: deny_mac_file
5531 sprintf(buf, "%d", 0);
5532 list[0].value = buf;
5533 list[1].name = "deny_mac_file";
5534 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5535 list[1].value = deny_file;
5536 items = 2;
5537 } else {
5538 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005539 }
developer10adcc12022-09-13 14:39:17 +08005540
developer06a01d92022-09-07 16:32:39 +08005541 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5542 wifi_hostapdWrite(config_file, list, items);
5543
5544 return RETURN_OK;
5545
5546#if 0
5547 if(apIndex==0 || apIndex==1)
5548 {
5549 //set the filtermode
5550 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5551 system(buf);
5552 system("syscfg commit");
5553
5554 if(filterMode==0)
5555 {
5556 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5557 system(buf);
5558 return RETURN_OK;
5559 }
5560 }
5561 return RETURN_OK;
5562#endif
5563}
5564
5565// 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.
5566INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5567{
5568 return RETURN_ERR;
5569}
5570
5571// gets the vlan ID for this ap from an internal enviornment variable
5572INT wifi_getApVlanID(INT apIndex, INT *output_int)
5573{
5574 if(apIndex=0)
5575 {
5576 *output_int=100;
5577 return RETURN_OK;
5578 }
5579
5580 return RETURN_ERR;
5581}
5582
5583// sets the vlan ID for this ap to an internal enviornment variable
5584INT wifi_setApVlanID(INT apIndex, INT vlanId)
5585{
5586 //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)
5587 return RETURN_ERR;
5588}
5589
5590// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5591INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5592{
5593 snprintf(bridgeName, 32, "brlan0");
5594 snprintf(IP, 32, "10.0.0.1");
5595 snprintf(subnet, 32, "255.255.255.0");
5596
5597 return RETURN_OK;
5598}
5599
5600//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5601INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5602{
5603 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5604 return RETURN_ERR;
5605}
5606
5607// reset the vlan configuration for this ap
5608INT wifi_resetApVlanCfg(INT apIndex)
5609{
developerf5fef612022-09-20 19:38:26 +08005610 char original_config_file[64] = {0};
5611 char current_config_file[64] = {0};
5612 char buf[64] = {0};
5613 char cmd[64] = {0};
5614 char vlan_file[64] = {0};
5615 char vlan_tagged_interface[16] = {0};
5616 char vlan_bridge[16] = {0};
5617 char vlan_naming[16] = {0};
5618 struct params list[4] = {0};
5619 wifi_band band;
5620
5621 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5622
5623 band = wifi_index_to_band(apIndex);
5624 if (band == band_2_4)
5625 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5626 else if (band = band_5)
5627 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5628 else if (band = band_6)
5629 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5630
5631 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5632
5633 if (strlen(vlan_file) == 0)
5634 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005635
developerf5fef612022-09-20 19:38:26 +08005636 // The file should exist or this vap would not work.
5637 if (access(vlan_file, F_OK) != 0) {
5638 sprintf(cmd, "touch %s", vlan_file);
5639 _syscmd(cmd, buf, sizeof(buf));
5640 }
5641 list[0].name = "vlan_file";
5642 list[0].value = vlan_file;
5643
5644 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5645 list[1].name = "vlan_tagged_interface";
5646 list[1].value = vlan_tagged_interface;
5647
5648 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5649 list[2].name = "vlan_bridge";
5650 list[2].value = vlan_bridge;
5651
5652 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5653 list[3].name = "vlan_naming";
5654 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005655
developerf5fef612022-09-20 19:38:26 +08005656 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5657 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005658 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005659 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005660
developerf5fef612022-09-20 19:38:26 +08005661 // restart this ap
5662 wifi_setApEnable(apIndex, FALSE);
5663 wifi_setApEnable(apIndex, TRUE);
5664
5665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5666
5667 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005668}
5669
5670// 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.
5671INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5672{
5673 return RETURN_ERR;
5674}
5675
5676// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5677INT wifi_startHostApd()
5678{
5679 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5680 system("systemctl start hostapd.service");
5681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5682 return RETURN_OK;
5683 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5684}
5685
5686// stops hostapd
5687INT wifi_stopHostApd()
5688{
5689 char cmd[128] = {0};
5690 char buf[128] = {0};
5691
5692 sprintf(cmd,"systemctl stop hostapd");
5693 _syscmd(cmd, buf, sizeof(buf));
5694
5695 return RETURN_OK;
5696}
5697
5698// restart hostapd dummy function
5699INT wifi_restartHostApd()
5700{
5701 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5702 system("systemctl restart hostapd-global");
5703 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5704
5705 return RETURN_OK;
5706}
5707
5708static int align_hostapd_config(int index)
5709{
5710 ULONG lval;
5711 wifi_getRadioChannel(index%2, &lval);
5712 wifi_setRadioChannel(index%2, lval);
5713}
5714
5715// sets the AP enable status variable for the specified ap.
5716INT wifi_setApEnable(INT apIndex, BOOL enable)
5717{
5718 char config_file[MAX_BUF_SIZE] = {0};
5719 char cmd[MAX_CMD_SIZE] = {0};
5720 char buf[MAX_BUF_SIZE] = {0};
5721 BOOL status;
5722
5723 wifi_getApEnable(apIndex,&status);
5724 if (enable == status)
5725 return RETURN_OK;
5726
5727 if (enable == TRUE) {
5728 int radioIndex = apIndex % NUMBER_OF_RADIOS;
developer06a01d92022-09-07 16:32:39 +08005729 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5730 //Hostapd will bring up this interface
5731 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5732 _syscmd(cmd, buf, sizeof(buf));
5733 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5734 _syscmd(cmd, buf, sizeof(buf));
5735 }
5736 else {
5737 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5738 _syscmd(cmd, buf, sizeof(buf));
5739 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5740 _syscmd(cmd, buf, sizeof(buf));
5741 }
5742 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5743 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5744 _syscmd(cmd, buf, sizeof(buf));
5745 //Wait for wifi up/down to apply
5746 return RETURN_OK;
5747}
5748
5749// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5750INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5751{
5752 char cmd[MAX_CMD_SIZE] = {'\0'};
5753 char buf[MAX_BUF_SIZE] = {'\0'};
5754
5755 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5756 return RETURN_ERR;
5757
5758 *output_bool = 0;
5759
5760 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5761 {
developer70490032022-09-13 15:45:20 +08005762 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005763 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5764 }
5765
5766 return RETURN_OK;
5767}
5768
5769// Outputs the AP "Enabled" "Disabled" status from driver
5770INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5771{
5772 char cmd[128] = {0};
5773 char buf[128] = {0};
5774 BOOL output_bool;
5775
5776 if ( NULL == output_string)
5777 return RETURN_ERR;
5778 wifi_getApEnable(apIndex,&output_bool);
5779
5780 if(output_bool == 1)
5781 snprintf(output_string, 32, "Up");
5782 else
5783 snprintf(output_string, 32, "Disable");
5784
5785 return RETURN_OK;
5786}
5787
5788//Indicates whether or not beacons include the SSID name.
5789// outputs a 1 if SSID on the AP is enabled, else outputs 0
5790INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5791{
5792 //get the running status
5793 char config_file[MAX_BUF_SIZE] = {0};
5794 char buf[16] = {0};
5795
5796 if (!output)
5797 return RETURN_ERR;
5798
5799 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5800 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005801 // default is enable
5802 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5803 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005804
5805 return RETURN_OK;
5806}
5807
5808// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5809INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5810{
5811 //store the config, apply instantly
5812 char config_file[MAX_BUF_SIZE] = {0};
5813 struct params list;
5814
5815 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5816 list.name = "ignore_broadcast_ssid";
5817 list.value = enable?"0":"1";
5818
5819 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5820 wifi_hostapdWrite(config_file, &list, 1);
5821 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5822 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005823 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5825
5826 return RETURN_OK;
5827}
5828
5829//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5830INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5831{
5832 //get the running status
5833 if(!output_uint)
5834 return RETURN_ERR;
5835 *output_uint=16;
5836 return RETURN_OK;
5837}
5838
5839INT wifi_setApRetryLimit(INT apIndex, UINT number)
5840{
5841 //apply instantly
5842 return RETURN_ERR;
5843}
5844
5845//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5846INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5847{
5848 if(!output)
5849 return RETURN_ERR;
5850 *output=TRUE;
5851 return RETURN_OK;
5852}
5853
5854//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5855INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5856{
5857 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005858 char cmd[128] = {0};
5859 char buf[128] = {0};
5860 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005861
developer0b246d12022-09-30 15:24:20 +08005862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005863
developer0b246d12022-09-30 15:24:20 +08005864 wifi_getMaxRadioNumber(&max_radio_num);
5865 radioIndex = apIndex % max_radio_num;
5866 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5867 _syscmd(cmd,buf, sizeof(buf));
5868
5869 if (strlen(buf) > 0)
5870 *output = true;
5871
5872 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005873
developer06a01d92022-09-07 16:32:39 +08005874 return RETURN_OK;
5875}
5876
5877//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5878INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5879{
5880 //get the running status from driver
5881 if(!output)
5882 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005883
5884 char config_file[MAX_BUF_SIZE] = {0};
5885 char buf[16] = {0};
5886
5887 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5888 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005889 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08005890 *output = TRUE;
5891 else
5892 *output = FALSE;
5893
developer06a01d92022-09-07 16:32:39 +08005894 return RETURN_OK;
5895}
5896
5897// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5898INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5899{
5900 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005901 char config_file[MAX_BUF_SIZE] = {0};
5902 struct params list;
5903
5904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5905 list.name = "wmm_enabled";
5906 list.value = enable?"1":"0";
5907
5908 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5909 wifi_hostapdWrite(config_file, &list, 1);
5910 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5911 wifi_reloadAp(apIndex);
5912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5913
5914 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005915}
5916
5917//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.
5918INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5919{
5920 //get the running status from driver
5921 if(!output)
5922 return RETURN_ERR;
5923 *output=TRUE;
5924 return RETURN_OK;
5925}
5926
5927// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5928INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5929{
5930 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005931 char config_file[MAX_BUF_SIZE] = {0};
5932 struct params list;
5933
5934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5935 list.name = "uapsd_advertisement_enabled";
5936 list.value = enable?"1":"0";
5937
5938 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5939 wifi_hostapdWrite(config_file, &list, 1);
5940 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5941 wifi_reloadAp(apIndex);
5942 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5943
5944 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005945}
5946
developer6daeb3f2022-09-30 13:36:39 +08005947// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005948INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5949{
developer6daeb3f2022-09-30 13:36:39 +08005950 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5951 char cmd[128] = {0};
5952 char buf[128] = {0};
5953 char ack_filepath[128] = {0};
5954 uint16_t bitmap = 0;
5955 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5956 FILE *f = NULL;
5957
5958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5959
5960 // Get current setting
5961 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5962 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5963 _syscmd(cmd, buf, sizeof(buf));
5964 if (strlen(buf) > 0)
5965 bitmap = strtoul(buf, NULL, 10);
5966
5967 bitmap = strtoul(buf, NULL, 10);
5968
5969 if (ackPolicy == TRUE) { // True, unset this class
5970 bitmap &= ~class_map[class];
5971 } else { // False, set this class
5972 bitmap |= class_map[class];
5973 }
5974
5975 f = fopen(ack_filepath, "w");
5976 if (f == NULL) {
5977 fprintf(stderr, "%s: fopen failed\n", __func__);
5978 return RETURN_ERR;
5979 }
5980 fprintf(f, "%hu", bitmap);
5981 fclose(f);
5982
5983 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5984 _syscmd(cmd, buf, sizeof(buf));
5985
5986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5987 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005988}
5989
5990//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.
5991INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5992{
5993 //get the running status from driver
5994 if(!output_uint)
5995 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005996
5997 char output[16]={'\0'};
5998 char config_file[MAX_BUF_SIZE] = {0};
5999
6000 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6001 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6002 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6003 else {
6004 int device_num = atoi(output);
6005 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6006 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6007 return RETURN_ERR;
6008 }
6009 else {
6010 *output_uint = device_num;
6011 }
6012 }
6013
developer06a01d92022-09-07 16:32:39 +08006014 return RETURN_OK;
6015}
6016
6017INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6018{
6019 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006020 char str[MAX_BUF_SIZE]={'\0'};
6021 char cmd[MAX_CMD_SIZE]={'\0'};
6022 struct params params;
6023 char config_file[MAX_BUF_SIZE] = {0};
6024
6025 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6026 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6027 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6028 return RETURN_ERR;
6029 }
6030 sprintf(str, "%d", number);
6031 params.name = "max_num_sta";
6032 params.value = str;
6033
6034 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6035 int ret = wifi_hostapdWrite(config_file, &params, 1);
6036 if (ret) {
6037 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6038 ,__func__, ret);
6039 }
6040
6041 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6042 if (ret) {
6043 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6044 ,__func__, ret);
6045 }
6046 wifi_reloadAp(apIndex);
6047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6048
6049 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006050}
6051
6052//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.
6053INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6054{
6055 //get the current threshold
6056 if(!output_uint)
6057 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006058 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6059 if (*output_uint == 0)
6060 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006061 return RETURN_OK;
6062}
6063
6064INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6065{
6066 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006067 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6068 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006069 return RETURN_ERR;
6070}
6071
6072//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.
6073INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6074{
6075 if(!output_uint)
6076 return RETURN_ERR;
6077 *output_uint = 3;
6078 return RETURN_OK;
6079}
6080
6081//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6082INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6083{
6084 if(!output_uint)
6085 return RETURN_ERR;
6086 *output_uint = 3;
6087 return RETURN_OK;
6088}
6089
6090//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.
6091INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6092{
6093 if(!output_in_seconds)
6094 return RETURN_ERR;
6095 *output_in_seconds = 0;
6096 return RETURN_OK;
6097}
6098
6099//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
6100INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6101{
6102 if(!output || apIndex>=MAX_APS)
6103 return RETURN_ERR;
6104 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006105 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006106 return RETURN_OK;
6107}
6108
6109//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6110INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6111{
developer587c1b62022-09-27 15:58:59 +08006112 char config_file[128] = {0};
6113 char wpa[16] = {0};
6114 char key_mgmt[64] = {0};
6115 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006116 if (!output)
6117 return RETURN_ERR;
6118
6119 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006120 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006121
developer587c1b62022-09-27 15:58:59 +08006122 strcpy(output, "None");//Copying "None" to output string for default case
6123 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006124 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006125 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006126 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006127 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006128 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006129 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006130 snprintf(output, 32, "WPA-WPA2-Personal");
6131
6132 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006133 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006134 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006135 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006136 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006137 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006138 snprintf(output, 32, "WPA-WPA2-Enterprise");
6139 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006140 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006141 snprintf(output, 32, "WPA3-Personal");
6142 else
developer4a359672022-10-13 15:30:46 +08006143 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006144 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6145 snprintf(output, 32, "WPA3-Enterprise");
6146 }
developer06a01d92022-09-07 16:32:39 +08006147
6148 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6149 return RETURN_OK;
6150#if 0
6151 //TODO: need to revisit below implementation
6152 char securityType[32], authMode[32];
6153 int enterpriseMode=0;
6154
6155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6156 if(!output)
6157 return RETURN_ERR;
6158
6159 wifi_getApBeaconType(apIndex, securityType);
6160 strcpy(output,"None");//By default, copying "None" to output string
6161 if (strncmp(securityType,"None", strlen("None")) == 0)
6162 return RETURN_OK;
6163
6164 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6165 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6166
6167 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6168 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6169 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6170 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6171 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6172 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6173 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6174
6175 return RETURN_OK;
6176#endif
6177}
6178
6179INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6180{
6181 char securityType[32];
6182 char authMode[32];
6183
6184 //store settings and wait for wifi up to apply
6185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6186 if(!encMode)
6187 return RETURN_ERR;
6188
developer06a01d92022-09-07 16:32:39 +08006189 if (strcmp(encMode, "None")==0)
6190 {
6191 strcpy(securityType,"None");
6192 strcpy(authMode,"None");
6193 }
6194 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6195 {
6196 strcpy(securityType,"WPAand11i");
6197 strcpy(authMode,"PSKAuthentication");
6198 }
6199 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6200 {
6201 strcpy(securityType,"WPAand11i");
6202 strcpy(authMode,"EAPAuthentication");
6203 }
6204 else if (strcmp(encMode, "WPA-Personal")==0)
6205 {
6206 strcpy(securityType,"WPA");
6207 strcpy(authMode,"PSKAuthentication");
6208 }
6209 else if (strcmp(encMode, "WPA-Enterprise")==0)
6210 {
6211 strcpy(securityType,"WPA");
6212 strcpy(authMode,"EAPAuthentication");
6213 }
6214 else if (strcmp(encMode, "WPA2-Personal")==0)
6215 {
6216 strcpy(securityType,"11i");
6217 strcpy(authMode,"PSKAuthentication");
6218 }
6219 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6220 {
6221 strcpy(securityType,"11i");
6222 strcpy(authMode,"EAPAuthentication");
6223 }
developer587c1b62022-09-27 15:58:59 +08006224 else if (strcmp(encMode, "WPA3-Personal") == 0)
6225 {
6226 strcpy(securityType,"11i");
6227 strcpy(authMode,"SAEAuthentication");
6228 }
developer4a359672022-10-13 15:30:46 +08006229 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006230 {
6231 strcpy(securityType, "11i");
6232 strcpy(authMode, "PSK-SAEAuthentication");
6233 }
developer587c1b62022-09-27 15:58:59 +08006234 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6235 {
6236 strcpy(securityType,"11i");
6237 strcpy(authMode,"EAP_192-bit_Authentication");
6238 }
developer06a01d92022-09-07 16:32:39 +08006239 else
6240 {
6241 strcpy(securityType,"None");
6242 strcpy(authMode,"None");
6243 }
6244 wifi_setApBeaconType(apIndex, securityType);
6245 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6246 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6247
6248 return RETURN_OK;
6249}
6250
6251
6252//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6253// output_string must be pre-allocated as 64 character string by caller
6254// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6255INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6256{
6257 char buf[16];
6258 char config_file[MAX_BUF_SIZE] = {0};
6259
6260 if(output_string==NULL)
6261 return RETURN_ERR;
6262
6263 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6264 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6265
6266 if(strcmp(buf,"0")==0)
6267 {
6268 printf("wpa_mode is %s ......... \n",buf);
6269 return RETURN_ERR;
6270 }
6271
6272 wifi_dbg_printf("\nFunc=%s\n",__func__);
6273 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6274 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6275 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6276
6277 return RETURN_OK;
6278}
6279
6280// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6281// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6282INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6283{
6284 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6285 struct params params={'\0'};
6286 int ret;
6287 char config_file[MAX_BUF_SIZE] = {0};
6288
6289 if(NULL == preSharedKey)
6290 return RETURN_ERR;
6291
6292 params.name = "wpa_passphrase";
6293
6294 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6295 {
6296 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6297 return RETURN_ERR;
6298 }
6299 params.value = preSharedKey;
6300 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6301 ret = wifi_hostapdWrite(config_file, &params, 1);
6302 if(!ret)
6303 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6304 return ret;
6305 //TODO: call hostapd_cli for dynamic_config_control
6306}
6307
6308//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6309// outputs the passphrase, maximum 63 characters
6310INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6311{
6312 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6313
6314 wifi_dbg_printf("\nFunc=%s\n",__func__);
6315 if (NULL == output_string)
6316 return RETURN_ERR;
6317
6318 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6319 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6320 if(strcmp(buf,"0")==0)
6321 {
6322 printf("wpa_mode is %s ......... \n",buf);
6323 return RETURN_ERR;
6324 }
6325
6326 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6327 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6328
6329 return RETURN_OK;
6330}
6331
6332// sets the passphrase enviornment variable, max 63 characters
6333INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6334{
6335 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6336 struct params params={'\0'};
6337 char config_file[MAX_BUF_SIZE] = {0};
6338 int ret;
6339
6340 if(NULL == passPhrase)
6341 return RETURN_ERR;
6342
6343 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6344 {
6345 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6346 return RETURN_ERR;
6347 }
6348 params.name = "wpa_passphrase";
6349 params.value = passPhrase;
6350 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6351 ret=wifi_hostapdWrite(config_file,&params,1);
6352 if(!ret)
6353 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6354
6355 return ret;
6356}
6357
6358//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.
6359INT wifi_setApSecurityReset(INT apIndex)
6360{
developer8d583982022-09-20 11:28:22 +08006361 char original_config_file[64] = {0};
6362 char current_config_file[64] = {0};
6363 char buf[64] = {0};
6364 char cmd[64] = {0};
6365 char wpa[4] = {0};
6366 char wpa_psk[64] = {0};
6367 char wpa_passphrase[64] = {0};
6368 char wpa_psk_file[128] = {0};
6369 char wpa_key_mgmt[64] = {0};
6370 char wpa_pairwise[32] = {0};
6371 wifi_band band;
6372 struct params list[6];
6373
6374 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6375
6376 band = wifi_index_to_band(apIndex);
6377 if (band == band_2_4)
6378 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6379 else if (band = band_5)
6380 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6381 else if (band = band_6)
6382 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6383 else
6384 return RETURN_ERR;
6385
6386 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6387 list[0].name = "wpa";
6388 list[0].value = wpa;
6389
6390 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6391 list[1].name = "wpa_psk";
6392 list[1].value = wpa_psk;
6393
6394 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6395 list[2].name = "wpa_passphrase";
6396 list[2].value = wpa_passphrase;
6397
6398 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6399
6400 if (strlen(wpa_psk_file) == 0)
6401 strcpy(wpa_psk_file, PSK_FILE);
6402
6403 if (access(wpa_psk_file, F_OK) != 0) {
6404 sprintf(cmd, "touch %s", wpa_psk_file);
6405 _syscmd(cmd, buf, sizeof(buf));
6406 }
6407 list[3].name = "wpa_psk_file";
6408 list[3].value = wpa_psk_file;
6409
6410 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6411 list[4].name = "wpa_key_mgmt";
6412 list[4].value = wpa_key_mgmt;
6413
6414 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6415 list[5].name = "wpa_pairwise";
6416 list[5].value = wpa_pairwise;
6417
6418 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6419 wifi_hostapdWrite(current_config_file, list, 6);
6420
6421 wifi_setApEnable(apIndex, FALSE);
6422 wifi_setApEnable(apIndex, TRUE);
6423
6424 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6425 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006426}
6427
6428//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).
6429INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6430{
developer8f2ddd52022-09-13 15:39:24 +08006431 char config_file[64] = {0};
6432 char buf[64] = {0};
6433 char cmd[256] = {0};
6434
6435 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6436
developer06a01d92022-09-07 16:32:39 +08006437 if(!IP_output || !Port_output || !RadiusSecret_output)
6438 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006439
developer8f2ddd52022-09-13 15:39:24 +08006440 // Read the first matched config
6441 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6442 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6443 _syscmd(cmd, buf, sizeof(buf));
6444 strncpy(IP_output, buf, 64);
6445
6446 memset(buf, 0, sizeof(buf));
6447 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6448 _syscmd(cmd, buf, sizeof(buf));
6449 *Port_output = atoi(buf);
6450
6451 memset(buf, 0, sizeof(buf));
6452 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6453 _syscmd(cmd, buf, sizeof(buf));
6454 strncpy(RadiusSecret_output, buf, 64);
6455
6456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006457 return RETURN_OK;
6458}
6459
6460INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6461{
developer8f2ddd52022-09-13 15:39:24 +08006462 char config_file[64] = {0};
6463 char port_str[8] = {0};
6464 char cmd[256] = {0};
6465 char buf[128] = {0};
6466
6467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6468
6469 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6470
6471 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6472 _syscmd(cmd, buf, sizeof(buf));
6473 memset(cmd, 0, sizeof(cmd));
6474
6475 snprintf(port_str, sizeof(port_str), "%d", port);
6476 if (strlen(buf) == 0)
6477 // Append
6478 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6479 "auth_server_addr=%s\\n"
6480 "auth_server_port=%s\\n"
6481 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6482 else {
6483 // Delete the three lines setting after the "# radius 1" comment
6484 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6485 _syscmd(cmd, buf, sizeof(buf));
6486 memset(cmd, 0, sizeof(cmd));
6487 // Use "# radius 1" comment to find the location to insert the radius setting
6488 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6489 "# radius 1\\n"
6490 "auth_server_addr=%s\\n"
6491 "auth_server_port=%s\\n"
6492 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6493 }
6494 if(_syscmd(cmd, buf, sizeof(buf))) {
6495 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6496 return RETURN_ERR;
6497 }
6498
6499 wifi_reloadAp(apIndex);
6500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6501 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006502}
6503
6504INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6505{
developer8f2ddd52022-09-13 15:39:24 +08006506 char config_file[64] = {0};
6507 char buf[64] = {0};
6508 char cmd[256] = {0};
6509
6510 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6511
developer06a01d92022-09-07 16:32:39 +08006512 if(!IP_output || !Port_output || !RadiusSecret_output)
6513 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006514
6515 // Read the second matched config
6516 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6517 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6518 _syscmd(cmd, buf, sizeof(buf));
6519 strncpy(IP_output, buf, 64);
6520
6521 memset(buf, 0, sizeof(buf));
6522 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6523 _syscmd(cmd, buf, sizeof(buf));
6524 *Port_output = atoi(buf);
6525
6526 memset(buf, 0, sizeof(buf));
6527 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6528 _syscmd(cmd, buf, sizeof(buf));
6529 strncpy(RadiusSecret_output, buf, 64);
6530
6531 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006532 return RETURN_OK;
6533}
6534
6535INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6536{
developer8f2ddd52022-09-13 15:39:24 +08006537 char config_file[64] = {0};
6538 char port_str[8] = {0};
6539 char cmd[256] = {0};
6540 char buf[128] = {0};
6541
6542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6543
6544 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6545
6546 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6547 _syscmd(cmd, buf, sizeof(buf));
6548 memset(cmd, 0, sizeof(cmd));
6549
6550 snprintf(port_str, sizeof(port_str), "%d", port);
6551 if (strlen(buf) == 0)
6552 // Append
6553 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6554 "auth_server_addr=%s\\n"
6555 "auth_server_port=%s\\n"
6556 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6557 else {
6558 // Delete the three lines setting after the "# radius 2" comment
6559 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6560 _syscmd(cmd, buf, sizeof(buf));
6561 memset(cmd, 0, sizeof(cmd));
6562 // Use "# radius 2" comment to find the location to insert the radius setting
6563 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6564 "# radius 2\\n"
6565 "auth_server_addr=%s\\n"
6566 "auth_server_port=%s\\n"
6567 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6568 }
6569 if(_syscmd(cmd, buf, sizeof(buf))) {
6570 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6571 return RETURN_ERR;
6572 }
6573
6574 wifi_reloadAp(apIndex);
6575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6576 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006577}
6578
6579//RadiusSettings
6580INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6581{
6582 if(!output)
6583 return RETURN_ERR;
6584
6585 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6586 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6587 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6588 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6589 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6590 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.
6591 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6592 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6593 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6594 //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.
6595
6596 return RETURN_OK;
6597}
6598
6599INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6600{
6601 //store the paramters, and apply instantly
6602 return RETURN_ERR;
6603}
6604
6605//Device.WiFi.AccessPoint.{i}.WPS.Enable
6606//Enables or disables WPS functionality for this access point.
6607// outputs the WPS enable state of this ap in output_bool
6608INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6609{
6610 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6611 if(!output_bool || !(apIndex==0 || apIndex==1))
6612 return RETURN_ERR;
6613 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6614 _syscmd(cmd, buf, sizeof(buf));
6615 if(strstr(buf, "configured"))
6616 *output_bool=TRUE;
6617 else
6618 *output_bool=FALSE;
6619
6620 return RETURN_OK;
6621}
6622
6623//Device.WiFi.AccessPoint.{i}.WPS.Enable
6624// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6625INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6626{
6627 char config_file[MAX_BUF_SIZE] = {0};
6628 struct params params;
6629
6630 if(!(apIndex==0 || apIndex==1))
6631 return RETURN_ERR;
6632 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6633 //store the paramters, and wait for wifi up to apply
6634 params.name = "wps_state";
6635 params.value = enable ? "2":"0";
6636
6637 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6638 wifi_hostapdWrite(config_file, &params, 1);
6639 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6640 wifi_reloadAp(apIndex);
6641
6642 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6643 return RETURN_OK;
6644}
6645
6646//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
6647INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6648{
6649 if(!output)
6650 return RETURN_ERR;
6651 snprintf(output, 128, "PushButton,PIN");
6652 return RETURN_OK;
6653}
6654
6655//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6656//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.
6657// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6658INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6659{
6660 if(!output)
6661 return RETURN_ERR;
6662 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6663
6664 return RETURN_OK;
6665}
6666
6667//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6668// 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
6669INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6670{
6671 //apply instantly. No setting need to be stored.
6672 char methods[MAX_BUF_SIZE], *token, *next_token;
6673 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6674 struct params params;
6675
6676 if(!methodString || !(apIndex==0 || apIndex==1))
6677 return RETURN_ERR;
6678 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6679 //store the paramters, and wait for wifi up to apply
6680
6681 snprintf(methods, sizeof(methods), "%s", methodString);
6682 for(token=methods; *token; token=next_token)
6683 {
6684 strtok_r(token, ",", &next_token);
6685 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6686 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6687 else if(*token=='E')
6688 {
6689 if(!strcmp(methods, "Ethernet"))
6690 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6691 else if(!strcmp(methods, "ExternalNFCToken"))
6692 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6693 else
6694 printf("%s: Unknown WpsConfigMethod\n", __func__);
6695 }
6696 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6697 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6698 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6699 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6700 else if(*token=='P' )
6701 {
6702 if(!strcmp(token, "PushButton"))
6703 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6704 else if(!strcmp(token, "PIN"))
6705 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6706 else
6707 printf("%s: Unknown WpsConfigMethod\n", __func__);
6708 }
6709 else
6710 printf("%s: Unknown WpsConfigMethod\n", __func__);
6711 }
6712 params.name = "config_methods";
6713 params.value = config_methods;
6714 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6715 wifi_hostapdWrite(config_file, &params, 1);
6716 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6718
6719 return RETURN_OK;
6720}
6721
6722// outputs the pin value, ulong_pin must be allocated by the caller
6723INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6724{
6725 char buf[MAX_BUF_SIZE] = {0};
6726 char cmd[MAX_CMD_SIZE] = {0};
6727
6728 if(!output_ulong || !(apIndex==0 || apIndex==1))
6729 return RETURN_ERR;
6730 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6731 _syscmd(cmd, buf, sizeof(buf));
6732 if(strlen(buf) > 0)
6733 *output_ulong=strtoul(buf, NULL, 10);
6734
6735 return RETURN_OK;
6736}
6737
6738// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6739INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6740{
6741 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6742 char ap_pin[16] = {0};
6743 char buf[MAX_BUF_SIZE] = {0};
6744 char config_file[MAX_BUF_SIZE] = {0};
6745 ULONG prev_pin = 0;
6746 struct params params;
6747
6748 if(!(apIndex==0 || apIndex==1))
6749 return RETURN_ERR;
6750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6751 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6752 params.name = "ap_pin";
6753 params.value = ap_pin;
6754 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6755 wifi_hostapdWrite(config_file, &params, 1);
6756 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6758
6759 return RETURN_OK;
6760}
6761
6762// Output string is either Not configured or Configured, max 32 characters
6763INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6764{
6765 char cmd[MAX_CMD_SIZE];
6766 char buf[MAX_BUF_SIZE]={0};
6767
6768 if(!output_string || !(apIndex==0 || apIndex==1))
6769 return RETURN_ERR;
6770 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6771 snprintf(output_string, 32, "Not configured");
6772 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6773 _syscmd(cmd, buf, sizeof(buf));
6774
developer348e3d92022-09-13 14:48:41 +08006775 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006776 snprintf(output_string, 32, "Configured");
6777 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6778
6779 return RETURN_OK;
6780}
6781
6782// sets the WPS pin for this AP
6783INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6784{
6785 char cmd[MAX_CMD_SIZE];
6786 char buf[MAX_BUF_SIZE]={0};
6787 BOOL enable;
6788
6789 if(!(apIndex==0 || apIndex==1))
6790 return RETURN_ERR;
6791 wifi_getApEnable(apIndex, &enable);
6792 if (!enable)
6793 return RETURN_ERR;
6794 wifi_getApWpsEnable(apIndex, &enable);
6795 if (!enable)
6796 return RETURN_ERR;
6797
6798 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6799 _syscmd(cmd, buf, sizeof(buf));
6800 if((strstr(buf, "OK"))!=NULL)
6801 return RETURN_OK;
6802
6803 return RETURN_ERR;
6804}
6805
6806// This function is called when the WPS push button has been pressed for this AP
6807INT wifi_setApWpsButtonPush(INT apIndex)
6808{
6809 char cmd[MAX_CMD_SIZE];
6810 char buf[MAX_BUF_SIZE]={0};
6811 BOOL enable=FALSE;
6812
6813 if(!(apIndex==0 || apIndex==1))
6814 return RETURN_ERR;
6815 wifi_getApEnable(apIndex, &enable);
6816 if (!enable)
6817 return RETURN_ERR;
6818
6819 wifi_getApWpsEnable(apIndex, &enable);
6820 if (!enable)
6821 return RETURN_ERR;
6822
6823 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6824 _syscmd(cmd, buf, sizeof(buf));
6825
6826 if((strstr(buf, "OK"))!=NULL)
6827 return RETURN_OK;
6828 return RETURN_ERR;
6829}
6830
6831// cancels WPS mode for this AP
6832INT wifi_cancelApWPS(INT apIndex)
6833{
6834 char cmd[MAX_CMD_SIZE];
6835 char buf[MAX_BUF_SIZE]={0};
6836
6837 if(!(apIndex==0 || apIndex==1))
6838 return RETURN_ERR;
6839 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6840 _syscmd(cmd,buf, sizeof(buf));
6841
6842 if((strstr(buf, "OK"))!=NULL)
6843 return RETURN_OK;
6844 return RETURN_ERR;
6845}
6846
6847//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6848//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6849INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6850{
6851 FILE *f;
6852 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6853 char cmd[256], buf[2048];
6854 char *param , *value, *line=NULL;
6855 size_t len = 0;
6856 ssize_t nread;
6857 wifi_associated_dev_t *dev=NULL;
6858
6859 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6860 *associated_dev_array = NULL;
6861 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6862 _syscmd(cmd,buf,sizeof(buf));
6863 *output_array_size = atoi(buf);
6864
6865 if (*output_array_size <= 0)
6866 return RETURN_OK;
6867
6868 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6869 *associated_dev_array = dev;
6870 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6871 _syscmd(cmd,buf,sizeof(buf));
6872 f = fopen("/tmp/connected_devices.txt", "r");
6873 if (f==NULL)
6874 {
6875 *output_array_size=0;
6876 return RETURN_ERR;
6877 }
6878 while ((nread = getline(&line, &len, f)) != -1)
6879 {
6880 param = strtok(line,"=");
6881 value = strtok(NULL,"=");
6882
6883 if( strcmp("flags",param) == 0 )
6884 {
6885 value[strlen(value)-1]='\0';
6886 if(strstr (value,"AUTHORIZED") != NULL )
6887 {
6888 dev[auth_temp].cli_AuthenticationState = 1;
6889 dev[auth_temp].cli_Active = 1;
6890 auth_temp++;
6891 read_flag=1;
6892 }
6893 }
6894 if(read_flag==1)
6895 {
6896 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6897 {
6898 value[strlen(value)-1]='\0';
6899 sscanf(value, "%x:%x:%x:%x:%x:%x",
6900 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6901 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6902 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6903 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6904 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6905 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6906 mac_temp++;
6907 read_flag=0;
6908 }
6909 }
6910 }
6911 *output_array_size = auth_temp;
6912 auth_temp=0;
6913 mac_temp=0;
6914 free(line);
6915 fclose(f);
6916 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6917 return RETURN_OK;
6918}
6919
6920#define MACADDRESS_SIZE 6
6921
6922INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6923{
6924 FILE *fp = NULL;
6925 char str[MAX_BUF_SIZE] = {0};
6926 int wificlientindex = 0 ;
6927 int count = 0;
6928 int signalstrength = 0;
6929 int arr[MACADDRESS_SIZE] = {0};
6930 unsigned char mac[MACADDRESS_SIZE] = {0};
6931 UINT wifi_count = 0;
6932 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6933 char pipeCmd[MAX_CMD_SIZE] = {0};
6934
6935 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6936 *output_array_size = 0;
6937 *associated_dev_array = NULL;
6938
6939 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6940 fp = popen(pipeCmd, "r");
6941 if (fp == NULL)
6942 {
6943 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6944 return RETURN_ERR;
6945 }
6946
6947 /* Read the output a line at a time - output it. */
6948 fgets(str, sizeof(str)-1, fp);
6949 wifi_count = (unsigned int) atoi ( str );
6950 *output_array_size = wifi_count;
6951 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6952 pclose(fp);
6953
6954 if(wifi_count == 0)
6955 {
6956 return RETURN_OK;
6957 }
6958 else
6959 {
6960 wifi_associated_dev3_t* temp = NULL;
6961 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6962 if(temp == NULL)
6963 {
6964 printf("Error Statement. Insufficient memory \n");
6965 return RETURN_ERR;
6966 }
6967
6968 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6969 system(pipeCmd);
6970 memset(pipeCmd,0,sizeof(pipeCmd));
6971 if(apIndex == 0)
6972 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6973 else if(apIndex == 1)
6974 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6975 system(pipeCmd);
6976
6977 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6978 if(fp == NULL)
6979 {
6980 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6981 return RETURN_ERR;
6982 }
6983 fclose(fp);
6984
6985 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6986 fp = popen(pipeCmd, "r");
6987 if(fp)
6988 {
6989 for(count =0 ; count < wifi_count; count++)
6990 {
6991 fgets(str, MAX_BUF_SIZE, fp);
6992 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6993 {
6994 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6995 {
6996 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6997
6998 }
6999 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7000 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]);
7001 }
7002 temp[count].cli_AuthenticationState = 1; //TODO
7003 temp[count].cli_Active = 1; //TODO
7004 }
7005 pclose(fp);
7006 }
7007
7008 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7009 fp = popen(pipeCmd, "r");
7010 if(fp)
7011 {
7012 pclose(fp);
7013 }
7014 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7015 if(fp)
7016 {
7017 for(count =0 ; count < wifi_count ;count++)
7018 {
7019 fgets(str, MAX_BUF_SIZE, fp);
7020 signalstrength = atoi(str);
7021 temp[count].cli_SignalStrength = signalstrength;
7022 temp[count].cli_RSSI = signalstrength;
7023 temp[count].cli_SNR = signalstrength + 95;
7024 }
7025 pclose(fp);
7026 }
7027
7028
7029 if((apIndex == 0) || (apIndex == 4))
7030 {
7031 for(count =0 ; count < wifi_count ;count++)
7032 {
7033 strcpy(temp[count].cli_OperatingStandard,"g");
7034 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7035 }
7036
7037 //BytesSent
7038 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7039 fp = popen(pipeCmd, "r");
7040 if(fp)
7041 {
7042 pclose(fp);
7043 }
7044 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7045 if(fp)
7046 {
7047 for (count = 0; count < wifi_count; count++)
7048 {
7049 fgets(str, MAX_BUF_SIZE, fp);
7050 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7051 }
7052 pclose(fp);
7053 }
7054
7055 //BytesReceived
7056 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7057 fp = popen(pipeCmd, "r");
7058 if (fp)
7059 {
7060 pclose(fp);
7061 }
7062 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7063 if (fp)
7064 {
7065 for (count = 0; count < wifi_count; count++)
7066 {
7067 fgets(str, MAX_BUF_SIZE, fp);
7068 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7069 }
7070 pclose(fp);
7071 }
7072
7073 //PacketsSent
7074 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7075 fp = popen(pipeCmd, "r");
7076 if (fp)
7077 {
7078 pclose(fp);
7079 }
7080
7081 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7082 if (fp)
7083 {
7084 for (count = 0; count < wifi_count; count++)
7085 {
7086 fgets(str, MAX_BUF_SIZE, fp);
7087 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7088 }
7089 pclose(fp);
7090 }
7091
7092 //PacketsReceived
7093 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7094 fp = popen(pipeCmd, "r");
7095 if (fp)
7096 {
7097 pclose(fp);
7098 }
7099 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7100 if (fp)
7101 {
7102 for (count = 0; count < wifi_count; count++)
7103 {
7104 fgets(str, MAX_BUF_SIZE, fp);
7105 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7106 }
7107 pclose(fp);
7108 }
7109
7110 //ErrorsSent
7111 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7112 fp = popen(pipeCmd, "r");
7113 if (fp)
7114 {
7115 pclose(fp);
7116 }
7117 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7118 if (fp)
7119 {
7120 for (count = 0; count < wifi_count; count++)
7121 {
7122 fgets(str, MAX_BUF_SIZE, fp);
7123 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7124 }
7125 pclose(fp);
7126 }
7127
7128 //ErrorsSent
7129 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7130 fp = popen(pipeCmd, "r");
7131 if (fp)
7132 {
7133 pclose(fp);
7134 }
7135 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7136 if (fp)
7137 {
7138 for (count = 0; count < wifi_count; count++)
7139 {
7140 fgets(str, MAX_BUF_SIZE, fp);
7141 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7142 }
7143 pclose(fp);
7144 }
7145
7146 //LastDataDownlinkRate
7147 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7148 fp = popen(pipeCmd, "r");
7149 if (fp)
7150 {
7151 pclose(fp);
7152 }
7153 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7154 if (fp)
7155 {
7156 for (count = 0; count < wifi_count; count++)
7157 {
7158 fgets(str, MAX_BUF_SIZE, fp);
7159 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7160 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7161 }
7162 pclose(fp);
7163 }
7164
7165 //LastDataUplinkRate
7166 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7167 fp = popen(pipeCmd, "r");
7168 if (fp)
7169 {
7170 pclose(fp);
7171 }
7172 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7173 if (fp)
7174 {
7175 for (count = 0; count < wifi_count; count++)
7176 {
7177 fgets(str, MAX_BUF_SIZE, fp);
7178 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7179 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7180 }
7181 pclose(fp);
7182 }
7183
7184 }
7185 else if ((apIndex == 1) || (apIndex == 5))
7186 {
7187 for (count = 0; count < wifi_count; count++)
7188 {
7189 strcpy(temp[count].cli_OperatingStandard, "a");
7190 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7191 temp[count].cli_BytesSent = 0;
7192 temp[count].cli_BytesReceived = 0;
7193 temp[count].cli_LastDataUplinkRate = 0;
7194 temp[count].cli_LastDataDownlinkRate = 0;
7195 temp[count].cli_PacketsSent = 0;
7196 temp[count].cli_PacketsReceived = 0;
7197 temp[count].cli_ErrorsSent = 0;
7198 }
7199 }
7200
7201 for (count = 0; count < wifi_count; count++)
7202 {
7203 temp[count].cli_Retransmissions = 0;
7204 temp[count].cli_DataFramesSentAck = 0;
7205 temp[count].cli_DataFramesSentNoAck = 0;
7206 temp[count].cli_MinRSSI = 0;
7207 temp[count].cli_MaxRSSI = 0;
7208 strncpy(temp[count].cli_InterferenceSources, "", 64);
7209 memset(temp[count].cli_IPAddress, 0, 64);
7210 temp[count].cli_RetransCount = 0;
7211 temp[count].cli_FailedRetransCount = 0;
7212 temp[count].cli_RetryCount = 0;
7213 temp[count].cli_MultipleRetryCount = 0;
7214 }
7215 *associated_dev_array = temp;
7216 }
7217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7218 return RETURN_OK;
7219}
7220
7221int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7222{
7223 FILE *fp = NULL;
7224 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7225 char cmd[MAX_CMD_SIZE];
7226 int count = 0;
7227
7228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7229 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7230 fp = popen(cmd,"r");
7231 if(fp == NULL)
7232 {
7233 printf("Failed to run command in Function %s\n",__FUNCTION__);
7234 return 0;
7235 }
7236 if(fgets(path, sizeof(path)-1, fp) != NULL)
7237 {
7238 for(count=0;path[count]!='\n';count++)
7239 status[count]=path[count];
7240 status[count]='\0';
7241 }
7242 strcpy(wifi_status,status);
7243 pclose(fp);
7244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7245 return RETURN_OK;
7246}
7247
7248/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7249struct hostapd_sta_param {
7250 char key[50];
7251 char value[100];
7252}
7253
7254static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7255 int i = 0;
7256
7257 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7258 if (strncmp(params[i].key,key,50) == 0){
7259 return &params[i].value;
7260 }
7261 i++;
7262 }
7263 return NULL;
7264
7265} */
7266
7267static unsigned int count_occurences(const char *buf, const char *word)
7268{
7269 unsigned int n = 0;
7270 char *ptr = strstr(buf, word);
7271
7272 while (ptr++) {
7273 n++;
7274 ptr = strstr(ptr, word);
7275 }
7276
7277 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7278 return n;
7279}
7280
7281static const char *get_line_from_str_buf(const char *buf, char *line)
7282{
7283 int i;
7284 int n = strlen(buf);
7285
7286 for (i = 0; i < n; i++) {
7287 line[i] = buf[i];
7288 if (buf[i] == '\n') {
7289 line[i] = '\0';
7290 return &buf[i + 1];
7291 }
7292 }
7293
7294 return NULL;
7295}
7296
7297INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7298{
7299 unsigned int assoc_cnt = 0;
7300 char interface_name[50] = {0};
7301 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7302 char cmd[MAX_CMD_SIZE] = {'\0'};
7303 char line[256] = {'\0'};
7304 int i = 0;
7305 int ret = 0;
7306 const char *ptr = NULL;
7307 char *key = NULL;
7308 char *val = NULL;
7309 wifi_associated_dev3_t *temp = NULL;
7310 int rssi;
7311
7312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7313
7314 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7315 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7316 return RETURN_ERR;
7317 }
7318
7319 // Example filtered output of 'iw dev' command:
7320 // Station 0a:69:72:10:d2:fa (on wifi0)
7321 // signal avg:-67 [-71, -71] dBm
7322 // Station 28:c2:1f:25:5f:99 (on wifi0)
7323 // signal avg:-67 [-71, -70] dBm
7324 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7325 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7326 return RETURN_ERR;
7327 }
7328
7329 ret = _syscmd(cmd, buf, sizeof(buf));
7330 if (ret == RETURN_ERR) {
7331 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7332 return RETURN_ERR;
7333 }
7334
7335 *output_array_size = count_occurences(buf, "Station");
7336 if (*output_array_size == 0) return RETURN_OK;
7337
7338 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7339 if (temp == NULL) {
7340 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7341 return RETURN_ERR;
7342 }
7343 *associated_dev_array = temp;
7344
7345 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7346 ptr = get_line_from_str_buf(buf, line);
7347 i = -1;
7348 while (ptr) {
7349 if (strstr(line, "Station")) {
7350 i++;
7351 key = strtok(line, " ");
7352 val = strtok(NULL, " ");
7353 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7354 &temp[i].cli_MACAddress[0],
7355 &temp[i].cli_MACAddress[1],
7356 &temp[i].cli_MACAddress[2],
7357 &temp[i].cli_MACAddress[3],
7358 &temp[i].cli_MACAddress[4],
7359 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7360 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7361 free(*associated_dev_array);
7362 return RETURN_ERR;
7363 }
7364 }
7365 else if (i < 0) {
7366 ptr = get_line_from_str_buf(ptr, line);
7367 continue; // We didn't detect 'station' entry yet
7368 }
7369 else if (strstr(line, "signal avg")) {
7370 key = strtok(line, ":");
7371 val = strtok(NULL, " ");
7372 if (sscanf(val, "%d", &rssi) <= 0 ) {
7373 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7374 free(*associated_dev_array);
7375 return RETURN_ERR;
7376 }
7377 temp[i].cli_RSSI = rssi;
7378 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7379 }
7380 // Here other fields can be parsed if added to filter of 'iw dev' command
7381
7382 ptr = get_line_from_str_buf(ptr, line);
7383 };
7384
7385 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7386
7387 return RETURN_OK;
7388}
7389
7390#if 0
7391//To-do
7392INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7393{
7394 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7395
7396 //Using different approach to get required WiFi Parameters from system available commands
7397#if 0
7398 FILE *f;
7399 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7400 char cmd[256], buf[2048];
7401 char *param , *value, *line=NULL;
7402 size_t len = 0;
7403 ssize_t nread;
7404 wifi_associated_dev3_t *dev=NULL;
7405 *associated_dev_array = NULL;
7406 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7407 _syscmd(cmd,buf,sizeof(buf));
7408 *output_array_size = atoi(buf);
7409
7410 if (*output_array_size <= 0)
7411 return RETURN_OK;
7412
7413 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7414 *associated_dev_array = dev;
7415 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7416 _syscmd(cmd,buf,sizeof(buf));
7417 f = fopen("/tmp/connected_devices.txt", "r");
7418 if (f==NULL)
7419 {
7420 *output_array_size=0;
7421 return RETURN_ERR;
7422 }
7423 while ((nread = getline(&line, &len, f)) != -1)
7424 {
7425 param = strtok(line,"=");
7426 value = strtok(NULL,"=");
7427
7428 if( strcmp("flags",param) == 0 )
7429 {
7430 value[strlen(value)-1]='\0';
7431 if(strstr (value,"AUTHORIZED") != NULL )
7432 {
7433 dev[auth_temp].cli_AuthenticationState = 1;
7434 dev[auth_temp].cli_Active = 1;
7435 auth_temp++;
7436 read_flag=1;
7437 }
7438 }
7439 if(read_flag==1)
7440 {
7441 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7442 {
7443 value[strlen(value)-1]='\0';
7444 sscanf(value, "%x:%x:%x:%x:%x:%x",
7445 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7446 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7447 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7448 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7449 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7450 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7451
7452 }
7453 else if( strcmp("rx_packets",param) == 0 )
7454 {
7455 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7456 }
7457
7458 else if( strcmp("tx_packets",param) == 0 )
7459 {
7460 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7461 }
7462
7463 else if( strcmp("rx_bytes",param) == 0 )
7464 {
7465 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7466 }
7467
7468 else if( strcmp("tx_bytes",param) == 0 )
7469 {
7470 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7471 mac_temp++;
7472 read_flag=0;
7473 }
7474 }
7475 }
7476
7477 *output_array_size = auth_temp;
7478 auth_temp=0;
7479 mac_temp=0;
7480 free(line);
7481 fclose(f);
7482#endif
7483 char interface_name[MAX_BUF_SIZE] = {0};
7484 char wifi_status[MAX_BUF_SIZE] = {0};
7485 char hostapdconf[MAX_BUF_SIZE] = {0};
7486
7487 wifi_associated_dev3_t *dev_array = NULL;
7488 ULONG wifi_count = 0;
7489
7490 *associated_dev_array = NULL;
7491 *output_array_size = 0;
7492
7493 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7494 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7495 {
7496 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7497
7498 GetInterfaceName(interface_name, hostapdconf);
7499
7500 if(strlen(interface_name) > 1)
7501 {
7502 wifihal_interfacestatus(wifi_status,interface_name);
7503 if(strcmp(wifi_status,"RUNNING") == 0)
7504 {
7505 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7506
7507 *associated_dev_array = dev_array;
7508 *output_array_size = wifi_count;
7509 }
7510 else
7511 {
7512 *associated_dev_array = NULL;
7513 }
7514 }
7515 }
7516
7517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7518 return RETURN_OK;
7519}
7520#endif
7521
7522/* getIPAddress function */
7523/**
7524* @description Returning IpAddress of the Matched String
7525*
7526* @param
7527* @str Having MacAddress
7528* @ipaddr Having ipaddr
7529* @return The status of the operation
7530* @retval RETURN_OK if successful
7531* @retval RETURN_ERR if any error is detected
7532*
7533*/
7534
7535INT getIPAddress(char *str,char *ipaddr)
7536{
7537 FILE *fp = NULL;
7538 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7539 int LeaseTime = 0,ret = 0;
7540 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7541 {
7542 return RETURN_ERR;
7543 }
7544
7545 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7546 {
7547 /*
7548 Sample:sss
7549 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7550 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7551 */
7552 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7553 &(LeaseTime),
7554 phyAddr,
7555 ipAddr,
7556 hostName
7557 );
7558 if(ret != 4)
7559 continue;
7560 if(strcmp(str,phyAddr) == 0)
7561 strcpy(ipaddr,ipAddr);
7562 }
7563 return RETURN_OK;
7564}
7565
7566/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7567/**
7568* @description Returning Inactive wireless connected clients informations
7569*
7570* @param
7571* @filename Holding private_wifi 2g/5g content files
7572* @associated_dev_array Having inactiv wireless clients informations
7573* @output_array_size Returning Inactive wireless counts
7574* @return The status of the operation
7575* @retval RETURN_OK if successful
7576* @retval RETURN_ERR if any error is detected
7577*
7578*/
7579
7580INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7581{
7582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7583 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7584 FILE *fp = NULL;
7585 int arr[MACADDRESS_SIZE] = {0};
7586 unsigned char mac[MACADDRESS_SIZE] = {0};
7587 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7588 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7589 fp = popen(buf,"r");
7590 if(fp == NULL)
7591 return RETURN_ERR;
7592 else
7593 {
7594 fgets(path,sizeof(path),fp);
7595 maccount = atoi(path);
7596 }
7597 pclose(fp);
7598 *output_array_size = maccount;
7599 wifi_associated_dev3_t* temp = NULL;
7600 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7601 *associated_dev_array = temp;
7602 if(temp == NULL)
7603 {
7604 printf("Error Statement. Insufficient memory \n");
7605 return RETURN_ERR;
7606 }
7607 memset(buf,0,sizeof(buf));
7608 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7609 fp = popen(buf,"r");
7610 for(count = 0; count < maccount ; count++)
7611 {
7612 fgets(path,sizeof(path),fp);
7613 for(i = 0; path[i]!='\n';i++)
7614 str[i]=path[i];
7615 str[i]='\0';
7616 getIPAddress(str,ipaddr);
7617 memset(buf,0,sizeof(buf));
7618 if(strlen(ipaddr) > 0)
7619 {
7620 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7621 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7622 {
7623 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7624 {
7625 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7626 {
7627 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7628
7629 }
7630 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7631 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]);
7632 }
7633 temp[count].cli_AuthenticationState = 0; //TODO
7634 temp[count].cli_Active = 0; //TODO
7635 temp[count].cli_SignalStrength = 0;
7636 }
7637 else //Active wireless clients info
7638 {
7639 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7640 {
7641 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7642 {
7643 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7644
7645 }
7646 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7647 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]);
7648 }
7649 temp[count].cli_Active = 1;
7650 }
7651 }
7652 memset(ipaddr,0,sizeof(ipaddr));
7653 }
7654 pclose(fp);
7655 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7656 return RETURN_OK;
7657}
7658//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7659//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7660//To get Band Steering Capability
7661INT wifi_getBandSteeringCapability(BOOL *support)
7662{
7663 *support = FALSE;
7664 return RETURN_OK;
7665}
7666
7667
7668//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7669//To get Band Steering enable status
7670INT wifi_getBandSteeringEnable(BOOL *enable)
7671{
7672 *enable = FALSE;
7673 return RETURN_OK;
7674}
7675
7676//To turn on/off Band steering
7677INT wifi_setBandSteeringEnable(BOOL enable)
7678{
7679 return RETURN_OK;
7680}
7681
7682//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7683//To get Band Steering AP group
7684INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7685{
7686 if (NULL == output_ApGroup)
7687 return RETURN_ERR;
7688
7689 strcpy(output_ApGroup, "1,2");
7690 return RETURN_OK;
7691}
7692
7693//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7694//to set and read the band steering BandUtilizationThreshold parameters
7695INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7696{
7697 return RETURN_ERR;
7698}
7699
7700INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7701{
7702 return RETURN_ERR;
7703}
7704
7705//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7706//to set and read the band steering RSSIThreshold parameters
7707INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7708{
7709 return RETURN_ERR;
7710}
7711
7712INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7713{
7714 return RETURN_ERR;
7715}
7716
7717
7718//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7719//to set and read the band steering physical modulation rate threshold parameters
7720INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7721{
7722 //If chip is not support, return -1
7723 return RETURN_ERR;
7724}
7725
7726INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7727{
7728 //If chip is not support, return -1
7729 return RETURN_ERR;
7730}
7731
7732//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7733//to set and read the inactivity time (in seconds) for steering under overload condition
7734INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7735{
7736 return RETURN_ERR;
7737}
7738
7739INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7740{
7741 return RETURN_ERR;
7742}
7743
7744//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7745//to set and read the inactivity time (in seconds) for steering under Idle condition
7746INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7747{
7748 return RETURN_ERR;
7749}
7750
7751INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7752{
7753 return RETURN_ERR;
7754}
7755
7756//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7757//pClientMAC[64]
7758//pSourceSSIDIndex[64]
7759//pDestSSIDIndex[64]
7760//pSteeringReason[256]
7761INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7762{
7763 //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
7764 *pSteeringTime=time(NULL);
7765 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7766 return RETURN_OK;
7767}
7768
7769INT wifi_ifConfigDown(INT apIndex)
7770{
7771 INT status = RETURN_OK;
7772 char cmd[64];
7773
7774 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7775 printf("%s: %s\n", __func__, cmd);
7776 system(cmd);
7777
7778 return status;
7779}
7780
7781INT wifi_ifConfigUp(INT apIndex)
7782{
7783 char cmd[128];
7784 char buf[1024];
7785
7786 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7787 _syscmd(cmd, buf, sizeof(buf));
7788 return 0;
7789}
7790
7791//>> Deprecated. Replace with wifi_applyRadioSettings
7792INT wifi_pushBridgeInfo(INT apIndex)
7793{
7794 char ip[32];
7795 char subnet[32];
7796 char bridge[32];
7797 int vlanId;
7798 char cmd[128];
7799 char buf[1024];
7800
7801 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7802 wifi_getApVlanID(apIndex,&vlanId);
7803
7804 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7805 _syscmd(cmd,buf, sizeof(buf));
7806
7807 return 0;
7808}
7809
7810INT wifi_pushChannel(INT radioIndex, UINT channel)
7811{
7812 char cmd[128];
7813 char buf[1024];
7814 int apIndex;
7815
7816 apIndex=(radioIndex==0)?0:1;
7817 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7818 _syscmd(cmd,buf, sizeof(buf));
7819
7820 return 0;
7821}
7822
7823INT wifi_pushChannelMode(INT radioIndex)
7824{
7825 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7826 return RETURN_ERR;
7827}
7828
7829INT wifi_pushDefaultValues(INT radioIndex)
7830{
7831 //Apply Comcast specified default radio settings instantly
7832 //AMPDU=1
7833 //AMPDUFrames=32
7834 //AMPDULim=50000
7835 //txqueuelen=1000
7836
7837 return RETURN_ERR;
7838}
7839
7840INT wifi_pushTxChainMask(INT radioIndex)
7841{
7842 //Apply default TxChainMask instantly
7843 return RETURN_ERR;
7844}
7845
7846INT wifi_pushRxChainMask(INT radioIndex)
7847{
7848 //Apply default RxChainMask instantly
7849 return RETURN_ERR;
7850}
7851
7852INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7853{
7854 INT status;
7855
7856 status = wifi_setSSIDName(apIndex,ssid);
7857 wifi_setApEnable(apIndex,FALSE);
7858 wifi_setApEnable(apIndex,TRUE);
7859
7860 return status;
7861}
7862
7863INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7864{
7865 //Apply default Ssid Advertisement instantly
7866 return RETURN_ERR;
7867}
7868
7869INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7870{
7871 INT status = RETURN_ERR;
7872 *output = 0;
7873 return RETURN_ERR;
7874}
7875
7876INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7877{
7878 return RETURN_OK;
7879}
7880
7881INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7882{
7883 return RETURN_OK;
7884}
7885
7886//To-do
7887INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7888{
developereb199ae2022-09-13 14:04:27 +08007889 char output[16]={'\0'};
7890 char config_file[MAX_BUF_SIZE] = {0};
7891
7892 if (!output_string)
7893 return RETURN_ERR;
7894
7895 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7896 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7897
7898 if (strlen(output) == 0)
7899 snprintf(output_string, 64, "Disabled");
7900 else if (strncmp(output, "0", 1) == 0)
7901 snprintf(output_string, 64, "Disabled");
7902 else if (strncmp(output, "1", 1) == 0)
7903 snprintf(output_string, 64, "Optional");
7904 else if (strncmp(output, "2", 1) == 0)
7905 snprintf(output_string, 64, "Required");
7906 else {
7907 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7908 return RETURN_ERR;
7909 }
7910
7911 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007912 return RETURN_OK;
7913}
7914INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7915{
developereb199ae2022-09-13 14:04:27 +08007916 char str[MAX_BUF_SIZE]={'\0'};
7917 char cmd[MAX_CMD_SIZE]={'\0'};
7918 struct params params;
7919 char config_file[MAX_BUF_SIZE] = {0};
7920
7921 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7922 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7923 return RETURN_ERR;
7924
7925 params.name = "ieee80211w";
7926 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7927 params.value = "0";
7928 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7929 params.value = "1";
7930 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7931 params.value = "2";
7932 else{
7933 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7934 return RETURN_ERR;
7935 }
7936 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7937 wifi_hostapdWrite(config_file, &params, 1);
7938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007939 return RETURN_OK;
7940}
7941INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7942{
7943 char output[16]={'\0'};
7944 char config_file[MAX_BUF_SIZE] = {0};
7945
7946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7947 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7948 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7949
7950 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7951 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7952
7953 return RETURN_OK;
7954}
7955
7956INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7957{
7958 return RETURN_OK;
7959}
7960
7961INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7962{
7963 return RETURN_OK;
7964}
7965
7966INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7967{
7968 return RETURN_OK;
7969}
7970
7971INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7972{
7973 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7974 char config_file[MAX_BUF_SIZE] = {0};
7975
7976 if (NULL == output)
7977 return RETURN_ERR;
7978 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7979 wifi_hostapdRead(config_file,"hw_mode",output,64);
7980
7981 if(strcmp(output,"b")==0)
7982 sprintf(output, "%s", "1,2,5.5,11");
7983 else if (strcmp(output,"a")==0)
7984 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7985 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7986 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7987
7988 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7989 return RETURN_OK;
7990}
7991
7992INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7993{
7994 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7995 char *temp;
7996 char temp_output[128];
7997 char temp_TransmitRates[128];
7998 char config_file[MAX_BUF_SIZE] = {0};
7999
8000 if (NULL == output)
8001 return RETURN_ERR;
8002
8003 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8004 wifi_hostapdRead(config_file,"supported_rates",output,64);
8005
8006 strcpy(temp_TransmitRates,output);
8007 strcpy(temp_output,"");
8008 temp = strtok(temp_TransmitRates," ");
8009 while(temp!=NULL)
8010 {
8011 temp[strlen(temp)-1]=0;
8012 if((temp[0]=='5') && (temp[1]=='\0'))
8013 {
8014 temp="5.5";
8015 }
8016 strcat(temp_output,temp);
8017 temp = strtok(NULL," ");
8018 if(temp!=NULL)
8019 {
8020 strcat(temp_output,",");
8021 }
8022 }
8023 strcpy(output,temp_output);
8024 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8025
8026 return RETURN_OK;
8027}
8028
8029INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8030{
8031 return RETURN_OK;
8032}
8033
8034
8035INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8036{
8037 int i=0;
8038 char *temp;
8039 char temp1[128];
8040 char temp_output[128];
8041 char temp_TransmitRates[128];
8042 struct params params={'\0'};
8043 char config_file[MAX_BUF_SIZE] = {0};
8044
8045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8046 if(NULL == output)
8047 return RETURN_ERR;
8048
8049 strcpy(temp_TransmitRates,output);
8050
8051 for(i=0;i<strlen(temp_TransmitRates);i++)
8052 {
8053 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
8054 {
8055 continue;
8056 }
8057 else
8058 {
8059 return RETURN_ERR;
8060 }
8061 }
8062 strcpy(temp_output,"");
8063 temp = strtok(temp_TransmitRates," ");
8064 while(temp!=NULL)
8065 {
8066 strcpy(temp1,temp);
8067 if(wlanIndex==1)
8068 {
8069 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8070 {
8071 return RETURN_ERR;
8072 }
8073 }
8074
8075 if(strcmp(temp,"5.5")==0)
8076 {
8077 strcpy(temp1,"55");
8078 }
8079 else
8080 {
8081 strcat(temp1,"0");
8082 }
8083 strcat(temp_output,temp1);
8084 temp = strtok(NULL," ");
8085 if(temp!=NULL)
8086 {
8087 strcat(temp_output," ");
8088 }
8089 }
8090 strcpy(output,temp_output);
8091
8092
8093 params.name = "supported_rates";
8094 params.value = output;
8095
8096 wifi_dbg_printf("\n%s:",__func__);
8097 wifi_dbg_printf("params.value=%s\n",params.value);
8098 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8099 wifi_hostapdWrite(config_file,&params,1);
8100 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8101
8102 return RETURN_OK;
8103}
8104
8105
8106static char *sncopy(char *dst, int dst_sz, const char *src)
8107{
8108 if (src && dst && dst_sz > 0) {
8109 strncpy(dst, src, dst_sz);
8110 dst[dst_sz - 1] = '\0';
8111 }
8112 return dst;
8113}
8114
8115static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8116{
8117 if (0 == strcmp(ht_mode, "HT40") ||
8118 0 == strcmp(ht_mode, "HT80") ||
8119 0 == strcmp(ht_mode, "HT160")) {
8120 switch (channel) {
8121 case 1 ... 7:
8122 case 36:
8123 case 44:
8124 case 52:
8125 case 60:
8126 case 100:
8127 case 108:
8128 case 116:
8129 case 124:
8130 case 132:
8131 case 140:
8132 case 149:
8133 case 157:
8134 return 1;
8135 case 8 ... 13:
8136 case 40:
8137 case 48:
8138 case 56:
8139 case 64:
8140 case 104:
8141 case 112:
8142 case 120:
8143 case 128:
8144 case 136:
8145 case 144:
8146 case 153:
8147 case 161:
8148 return -1;
8149 default:
8150 return -EINVAL;
8151 }
8152 }
8153
8154 return -EINVAL;
8155}
8156
developerb7593de2022-10-18 09:51:57 +08008157static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8158{
8159 int idx = channel%8;
8160 if (0 == strcmp(ht_mode, "HT40") ||
8161 0 == strcmp(ht_mode, "HT80") ||
8162 0 == strcmp(ht_mode, "HT160")) {
8163 switch (idx) {
8164 case 1:
8165 return 1;
8166 case 5:
8167 return -1;
8168 default:
8169 return -EINVAL;
8170 }
8171 }
8172
8173 return -EINVAL;
8174}
developer06a01d92022-09-07 16:32:39 +08008175static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8176{
8177 if (NULL == hw_mode) return;
8178
8179 if (0 == strcmp(hw_mode, "ac"))
8180 sncopy(bw_mode, bw_mode_len, "ht vht");
8181
8182 if (0 == strcmp(hw_mode, "n"))
8183 sncopy(bw_mode, bw_mode_len, "ht");
8184
8185 return;
8186}
8187
8188static int util_chan_to_freq(int chan)
8189{
8190 if (chan == 14)
8191 return 2484;
8192 else if (chan < 14)
8193 return 2407 + chan * 5;
8194 else if (chan >= 182 && chan <= 196)
8195 return 4000 + chan * 5;
8196 else
8197 return 5000 + chan * 5;
8198 return 0;
8199}
8200
developerb7593de2022-10-18 09:51:57 +08008201static int util_6G_chan_to_freq(int chan)
8202{
8203 if (chan)
8204 return 5950 + chan * 5;
8205 else
8206 return 0;
8207
8208}
developer06a01d92022-09-07 16:32:39 +08008209const int *util_unii_5g_chan2list(int chan, int width)
8210{
8211 static const int lists[] = {
8212 // <width>, <chan1>, <chan2>..., 0,
8213 20, 36, 0,
8214 20, 40, 0,
8215 20, 44, 0,
8216 20, 48, 0,
8217 20, 52, 0,
8218 20, 56, 0,
8219 20, 60, 0,
8220 20, 64, 0,
8221 20, 100, 0,
8222 20, 104, 0,
8223 20, 108, 0,
8224 20, 112, 0,
8225 20, 116, 0,
8226 20, 120, 0,
8227 20, 124, 0,
8228 20, 128, 0,
8229 20, 132, 0,
8230 20, 136, 0,
8231 20, 140, 0,
8232 20, 144, 0,
8233 20, 149, 0,
8234 20, 153, 0,
8235 20, 157, 0,
8236 20, 161, 0,
8237 20, 165, 0,
8238 40, 36, 40, 0,
8239 40, 44, 48, 0,
8240 40, 52, 56, 0,
8241 40, 60, 64, 0,
8242 40, 100, 104, 0,
8243 40, 108, 112, 0,
8244 40, 116, 120, 0,
8245 40, 124, 128, 0,
8246 40, 132, 136, 0,
8247 40, 140, 144, 0,
8248 40, 149, 153, 0,
8249 40, 157, 161, 0,
8250 80, 36, 40, 44, 48, 0,
8251 80, 52, 56, 60, 64, 0,
8252 80, 100, 104, 108, 112, 0,
8253 80, 116, 120, 124, 128, 0,
8254 80, 132, 136, 140, 144, 0,
8255 80, 149, 153, 157, 161, 0,
8256 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8257 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8258 -1 // final delimiter
8259 };
8260 const int *start;
8261 const int *p;
8262
8263 for (p = lists; *p != -1; p++) {
8264 if (*p == width) {
8265 for (start = ++p; *p != 0; p++) {
8266 if (*p == chan)
8267 return start;
8268 }
8269 }
8270 // move to the end of channel list of given width
8271 while (*p != 0) {
8272 p++;
8273 }
8274 }
8275
8276 return NULL;
8277}
8278
8279static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8280{
8281 if (NULL == ht_mode)
8282 return 0;
8283
8284 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8285 const int *chans = util_unii_5g_chan2list(channel, width);
8286 int sum = 0;
8287 int cnt = 0;
8288
8289 if (NULL == chans)
8290 return 0;
8291
8292 while (*chans) {
8293 sum += *chans;
8294 cnt++;
8295 chans++;
8296 }
8297 return sum / cnt;
8298}
8299
developerb7593de2022-10-18 09:51:57 +08008300static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8301{
8302 if (NULL == ht_mode)
8303 return 0;
8304
8305 int width = strtol((ht_mode + 2), NULL, 10);
8306
8307 int idx = 0 ;
8308 int centerchan = 0;
8309 int chan_ofs = 1;
8310
8311 if (width == 40){
8312 idx = ((channel/4) + chan_ofs)%2;
8313 switch (idx) {
8314 case 0:
8315 centerchan = (channel - 2);
8316 break;
8317 case 1:
8318 centerchan = (channel + 2);
8319 break;
8320 default:
8321 return -EINVAL;
8322 }
8323 }else if (width == 80){
8324 idx = ((channel/4) + chan_ofs)%4;
8325 switch (idx) {
8326 case 0:
8327 centerchan = (channel - 6);
8328 break;
8329 case 1:
8330 centerchan = (channel + 6);
8331 break;
8332 case 2:
8333 centerchan = (channel + 2);
8334 break;
8335 case 3:
8336 centerchan = (channel - 2);
8337 break;
8338 default:
8339 return -EINVAL;
8340 }
8341 }else if (width == 160){
8342 switch (channel) {
8343 case 1 ... 29:
8344 centerchan = 15;
8345 break;
8346 case 33 ... 61:
8347 centerchan = 47;
8348 break;
8349 case 65 ... 93:
8350 centerchan = 79;
8351 break;
8352 case 97 ... 125:
8353 centerchan = 111;
8354 break;
8355 case 129 ... 157:
8356 centerchan = 143;
8357 break;
8358 case 161 ... 189:
8359 centerchan = 175;
8360 break;
8361 case 193 ... 221:
8362 centerchan = 207;
8363 break;
8364 default:
8365 return -EINVAL;
8366 }
8367 }
8368 return centerchan;
8369}
developer06a01d92022-09-07 16:32:39 +08008370static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8371{
8372 BOOL onlyG, onlyN, onlyA;
8373 CHAR tmp[64];
8374 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8375 if (ret == RETURN_OK) {
8376 sncopy(hw_mode, hw_mode_size, tmp);
8377 }
8378 return ret;
8379}
8380
8381INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8382{
8383 // Sample commands:
8384 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8385 // hostapd_cli -i wifi0 chan_switch 30 2437
8386 char cmd[MAX_CMD_SIZE] = {0};
8387 char buf[MAX_BUF_SIZE] = {0};
8388 int freq = 0, ret = 0;
8389 char center_freq1_str[32] = ""; // center_freq1=%d
8390 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8391 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8392 char hw_mode[16] = ""; // n|ac
8393 char bw_mode[16] = ""; // ht|ht vht
8394 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8395 int sec_chan_offset;
8396 int width;
developer4fb0b922022-09-30 14:29:09 +08008397 char config_file[64] = {0};
8398 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008399 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008400 wifi_band band = band_invalid;
8401 int center_chan = 0;
8402 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008403
developer4fb0b922022-09-30 14:29:09 +08008404 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008405
8406 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8407
developerb7593de2022-10-18 09:51:57 +08008408 band = wifi_index_to_band(radioIndex);
8409
developer5884e982022-10-06 10:52:50 +08008410 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008411
8412 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008413 if (channel){
developerb7593de2022-10-18 09:51:57 +08008414 if (band == band_6){
8415 freq = util_6G_chan_to_freq(channel);
8416 }else{
8417 freq = util_chan_to_freq(channel);
8418 }
developer5884e982022-10-06 10:52:50 +08008419 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008420
developer5884e982022-10-06 10:52:50 +08008421 // Provide bandwith if specified
8422 if (channel_width_MHz > 20) {
8423 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8424 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8425 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008426
developer5884e982022-10-06 10:52:50 +08008427 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8428 }else if (channel_width_MHz == 20){
8429 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8430 }
developer06a01d92022-09-07 16:32:39 +08008431
developerb7593de2022-10-18 09:51:57 +08008432
developer5884e982022-10-06 10:52:50 +08008433 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008434 if (band == band_6){
8435 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8436 if(center_chan){
8437 center_freq1 = util_6G_chan_to_freq(center_chan);
8438 }
8439 }else{
8440 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8441 if(center_chan){
8442 center_freq1 = util_chan_to_freq(center_chan);
8443 }
developer5884e982022-10-06 10:52:50 +08008444 }
developerb7593de2022-10-18 09:51:57 +08008445
8446 if (center_freq1)
8447 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8448
8449 }
8450
8451 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8452 if (band == band_6){
8453 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8454 }else{
8455 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008456 }
developerb7593de2022-10-18 09:51:57 +08008457 if (sec_chan_offset != -EINVAL)
8458 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008459
developer5884e982022-10-06 10:52:50 +08008460 // Only the first AP, other are hanging on the same radio
8461 int apIndex = radioIndex;
8462 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8463 AP_PREFIX, apIndex, csa_beacon_count, freq,
8464 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8465 wifi_dbg_printf("execute: '%s'\n", cmd);
8466 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008467
developer5884e982022-10-06 10:52:50 +08008468 ret = wifi_setRadioChannel(radioIndex, channel);
8469 if (ret != RETURN_OK) {
8470 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8471 return RETURN_ERR;
8472 }
8473
8474 if (sec_chan_offset == 1) ext_str = "Above";
8475 else if (sec_chan_offset == -1) ext_str = "Below";
8476
8477 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008478
developer5884e982022-10-06 10:52:50 +08008479 } else {
8480 if (channel_width_MHz > 20)
8481 ext_str = "Above";
8482 }
developer4fb0b922022-09-30 14:29:09 +08008483 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8484 _syscmd(cmd, buf, sizeof(buf));
8485 if (strlen(buf) != 0)
8486 stbcEnable = TRUE;
8487
developer06a01d92022-09-07 16:32:39 +08008488 wifi_setRadioExtChannel(radioIndex, ext_str);
8489
developer4fb0b922022-09-30 14:29:09 +08008490 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8491
developer06a01d92022-09-07 16:32:39 +08008492 char mhz_str[16];
8493 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8494 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8495
8496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8497
8498 return RETURN_OK;
8499}
8500
8501INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8502{
developer615510b2022-09-27 10:14:35 +08008503 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008504 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008505 char cmd[256]={0};
8506 char buf[128]={0};
8507 char file_name[32] = {0};
8508 char filter_SSID[32] = {0};
8509 char line[256] = {0};
8510 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008511 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008512 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008513 size_t len=0;
8514 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008515 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008516 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008517 bool filter_enable = false;
8518 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008519
developer615510b2022-09-27 10:14:35 +08008520 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008521
developer615510b2022-09-27 10:14:35 +08008522 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8523 f = fopen(file_name, "r");
8524 if (f != NULL) {
8525 fgets(filter_SSID, sizeof(file_name), f);
8526 if (strlen(filter_SSID) != 0)
8527 filter_enable = true;
8528 fclose(f);
8529 }
8530
8531 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8532 _syscmd(cmd, buf, sizeof(buf));
8533 channels_num = strtol(buf, NULL, 10);
8534
developer615510b2022-09-27 10:14:35 +08008535 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8536 // 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);
8537 fprintf(stderr, "cmd: %s\n", cmd);
8538 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008539 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8540 return RETURN_ERR;
8541 }
developer5550e242022-09-30 09:59:32 +08008542
8543 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8544 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8545
developer615510b2022-09-27 10:14:35 +08008546 ret = fgets(line, sizeof(line), f);
8547 while (ret != NULL) {
8548 if(strstr(line, "BSS") != NULL) { // new neighbor info
8549 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8550 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8551 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8552
8553 if (!filter_BSS) {
8554 index++;
8555 wifi_neighbor_ap2_t *tmp;
8556 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8557 if (tmp == NULL) { // no more memory to use
8558 index--;
8559 wifi_dbg_printf("%s: realloc failed\n", __func__);
8560 break;
8561 }
8562 scan_array = tmp;
8563 }
8564 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008565
developer615510b2022-09-27 10:14:35 +08008566 filter_BSS = false;
8567 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8568 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8569 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8570 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8571 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008572 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008573 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008574
developer615510b2022-09-27 10:14:35 +08008575 if (freq >= 2412 && freq <= 2484) {
8576 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8577 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8578 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8579 }
8580 else if (freq >= 5160 && freq <= 5805) {
8581 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8582 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8583 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8584 }
developer06a01d92022-09-07 16:32:39 +08008585
developer615510b2022-09-27 10:14:35 +08008586 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008587 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008588 for (int i = 0; i < channels_num; i++) {
8589 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8590 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8591 break;
8592 }
8593 }
developer06a01d92022-09-07 16:32:39 +08008594 }
developer615510b2022-09-27 10:14:35 +08008595 } else if (strstr(line, "beacon interval") != NULL) {
8596 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8597 } else if (strstr(line, "signal") != NULL) {
8598 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8599 } else if (strstr(line,"SSID") != NULL) {
8600 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8601 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8602 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008603 }
developer615510b2022-09-27 10:14:35 +08008604 } else if (strstr(line, "Supported rates") != NULL) {
8605 char SRate[80] = {0}, *tmp = NULL;
8606 memset(buf, 0, sizeof(buf));
8607 strcpy(SRate, line);
8608 tmp = strtok(SRate, ":");
8609 tmp = strtok(NULL, ":");
8610 strcpy(buf, tmp);
8611 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008612
developer615510b2022-09-27 10:14:35 +08008613 tmp = strtok(buf, " \n");
8614 while (tmp != NULL) {
8615 strcat(SRate, tmp);
8616 if (SRate[strlen(SRate) - 1] == '*') {
8617 SRate[strlen(SRate) - 1] = '\0';
8618 }
8619 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008620
developer615510b2022-09-27 10:14:35 +08008621 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008622 }
developer615510b2022-09-27 10:14:35 +08008623 SRate[strlen(SRate) - 1] = '\0';
8624 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8625 } else if (strstr(line, "DTIM") != NULL) {
8626 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8627 } else if (strstr(line, "VHT capabilities") != NULL) {
8628 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8629 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8630 } else if (strstr(line, "HT capabilities") != NULL) {
8631 strcat(scan_array[index].ap_SupportedStandards, ",n");
8632 strcpy(scan_array[index].ap_OperatingStandards, "n");
8633 } else if (strstr(line, "VHT operation") != NULL) {
8634 ret = fgets(line, sizeof(line), f);
8635 sscanf(line," * channel width: %d", &vht_channel_width);
8636 if(vht_channel_width == 1) {
8637 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8638 } else {
8639 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8640 }
8641 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8642 continue;
8643 } else if (strstr(line, "HT operation") != NULL) {
8644 ret = fgets(line, sizeof(line), f);
8645 sscanf(line," * secondary channel offset: %s", &buf);
8646 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008647 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008648 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 +08008649 }
developer615510b2022-09-27 10:14:35 +08008650 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008651 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008652 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8653 } else {
8654 //20Mhz
8655 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 +08008656 }
developer615510b2022-09-27 10:14:35 +08008657 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008658 continue;
developer615510b2022-09-27 10:14:35 +08008659 } else if (strstr(line, "HE capabilities") != NULL) {
8660 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8661 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8662 ret = fgets(line, sizeof(line), f);
8663 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8664 if (strstr(line, "HE40/2.4GHz") != NULL)
8665 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8666 else
8667 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8668 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8669 if (strstr(line, "HE80/5GHz") != NULL) {
8670 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8671 ret = fgets(line, sizeof(line), f);
8672 } else
8673 continue;
8674 if (strstr(line, "HE160/5GHz") != NULL)
8675 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008676 }
developer615510b2022-09-27 10:14:35 +08008677 continue;
8678 } else if (strstr(line, "WPA") != NULL) {
8679 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8680 } else if (strstr(line, "RSN") != NULL) {
8681 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8682 } else if (strstr(line, "Group cipher") != NULL) {
8683 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8684 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8685 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008686 }
developer06a01d92022-09-07 16:32:39 +08008687 }
developer615510b2022-09-27 10:14:35 +08008688 ret = fgets(line, sizeof(line), f);
8689 }
8690
8691 if (!filter_BSS) {
8692 *output_array_size = index + 1;
8693 } else {
8694 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8695 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008696 }
developer06a01d92022-09-07 16:32:39 +08008697 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008698 pclose(f);
developer5550e242022-09-30 09:59:32 +08008699 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008701 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008702}
developer615510b2022-09-27 10:14:35 +08008703
developer06a01d92022-09-07 16:32:39 +08008704INT wifi_getApAssociatedDeviceStats(
8705 INT apIndex,
8706 mac_address_t *clientMacAddress,
8707 wifi_associated_dev_stats_t *associated_dev_stats,
8708 u64 *handle)
8709{
8710 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8711 char interface_name[50] = {0};
8712 char cmd[1024] = {0};
8713 char mac_str[18] = {0};
8714 char *key = NULL;
8715 char *val = NULL;
8716 FILE *f = NULL;
8717 char *line = NULL;
8718 size_t len = 0;
8719 ssize_t read = 0;
8720
8721 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8722 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8723 return RETURN_ERR;
8724 }
8725
8726 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8727 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8728 if((f = popen(cmd, "r")) == NULL) {
8729 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8730 return RETURN_ERR;
8731 }
8732
8733 while ((read = getline(&line, &len, f)) != -1) {
8734 key = strtok(line,":");
8735 val = strtok(NULL,":");
8736
8737 if(!strncmp(key,"rx bytes",8))
8738 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8739 if(!strncmp(key,"tx bytes",8))
8740 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8741 if(!strncmp(key,"rx packets",10))
8742 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8743 if(!strncmp(key,"tx packets",10))
8744 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8745 if(!strncmp(key,"tx retries",10))
8746 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8747 if(!strncmp(key,"tx failed",9))
8748 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8749 if(!strncmp(key,"rx drop misc",13))
8750 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8751 if(!strncmp(key,"rx bitrate",10)) {
8752 val = strtok(val, " ");
8753 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8754 }
8755 if(!strncmp(key,"tx bitrate",10)) {
8756 val = strtok(val, " ");
8757 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8758 }
8759 }
8760 free(line);
8761 pclose(f);
8762 return RETURN_OK;
8763}
8764
8765INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8766{
8767 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8768
8769 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8770 if (NULL == output_string)
8771 return RETURN_ERR;
8772
8773 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8774 _syscmd(cmd, buf, sizeof(buf));
8775
8776 //size of SSID name restricted to value less than 32 bytes
8777 snprintf(output_string, 32, "%s", buf);
8778 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8779
8780 return RETURN_OK;
8781}
8782
8783INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8784{
8785 //char cmd[MAX_CMD_SIZE] = {0};
8786 char config_file[MAX_BUF_SIZE] = {0};
8787 char buf[32] = {0};
8788
8789 if (!output_filterMode)
8790 return RETURN_ERR;
8791
8792 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8793 //_syscmd(cmd, buf, sizeof(buf));
8794 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8795 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008796 if(strlen(buf) == 0) {
8797 *output_filterMode = 0;
8798 }
8799 else {
8800 int macaddr_acl_mode = strtol(buf, NULL, 10);
8801 if (macaddr_acl_mode == 1) {
8802 *output_filterMode = 1;
8803 } else if (macaddr_acl_mode == 0) {
8804 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8805 if (strlen(buf) == 0) {
8806 *output_filterMode = 0;
8807 } else {
8808 *output_filterMode = 2;
8809 }
8810 } else {
8811 return RETURN_ERR;
8812 }
8813 }
developer06a01d92022-09-07 16:32:39 +08008814
8815 return RETURN_OK;
8816}
8817
8818INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8819{
8820 FILE *fp = NULL;
8821 char str[MAX_BUF_SIZE] = {0};
8822 int wificlientindex = 0 ;
8823 int count = 0;
8824 int signalstrength = 0;
8825 int arr[MACADDRESS_SIZE] = {0};
8826 unsigned char mac[MACADDRESS_SIZE] = {0};
8827 UINT wifi_count = 0;
8828 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8829 char pipeCmd[MAX_CMD_SIZE] = {0};
8830
8831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8832 *output_array_size = 0;
8833 *associated_dev_array = NULL;
8834 char interface_name[50] = {0};
8835
8836 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8837 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8838 return RETURN_ERR;
8839 }
8840
8841 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8842 fp = popen(pipeCmd, "r");
8843 if (fp == NULL)
8844 {
8845 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8846 return RETURN_ERR;
8847 }
8848
8849 /* Read the output a line at a time - output it. */
8850 fgets(str, sizeof(str)-1, fp);
8851 wifi_count = (unsigned int) atoi ( str );
8852 *output_array_size = wifi_count;
8853 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8854 pclose(fp);
8855
8856 if(wifi_count == 0)
8857 {
8858 return RETURN_OK;
8859 }
8860 else
8861 {
8862 wifi_associated_dev2_t* temp = NULL;
8863 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8864 *associated_dev_array = temp;
8865 if(temp == NULL)
8866 {
8867 printf("Error Statement. Insufficient memory \n");
8868 return RETURN_ERR;
8869 }
8870
8871 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8872 system(pipeCmd);
8873
8874 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8875 if(fp == NULL)
8876 {
8877 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8878 return RETURN_ERR;
8879 }
8880 fclose(fp);
8881
8882 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8883 fp = popen(pipeCmd, "r");
8884 if(fp)
8885 {
8886 for(count =0 ; count < wifi_count; count++)
8887 {
8888 fgets(str, MAX_BUF_SIZE, fp);
8889 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8890 {
8891 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8892 {
8893 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8894
8895 }
8896 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8897 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]);
8898 }
8899 temp[count].cli_AuthenticationState = 1; //TODO
8900 temp[count].cli_Active = 1; //TODO
8901 }
8902 pclose(fp);
8903 }
8904
8905 //Updating RSSI per client
8906 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8907 fp = popen(pipeCmd, "r");
8908 if(fp)
8909 {
8910 pclose(fp);
8911 }
8912 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8913 if(fp)
8914 {
8915 for(count =0 ; count < wifi_count ;count++)
8916 {
8917 fgets(str, MAX_BUF_SIZE, fp);
8918 signalstrength = atoi(str);
8919 temp[count].cli_RSSI = signalstrength;
8920 }
8921 pclose(fp);
8922 }
8923
8924
8925 //LastDataDownlinkRate
8926 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8927 fp = popen(pipeCmd, "r");
8928 if (fp)
8929 {
8930 pclose(fp);
8931 }
8932 fp = popen("cat /tmp/Ass_Bitrate_Send.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 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8939 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8940 }
8941 pclose(fp);
8942 }
8943
8944 //LastDataUplinkRate
8945 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8946 fp = popen(pipeCmd, "r");
8947 if (fp)
8948 {
8949 pclose(fp);
8950 }
8951 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8952 if (fp)
8953 {
8954 for (count = 0; count < wifi_count; count++)
8955 {
8956 fgets(str, MAX_BUF_SIZE, fp);
8957 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8958 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8959 }
8960 pclose(fp);
8961 }
8962 }
8963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8964 return RETURN_OK;
8965
8966}
8967
8968INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8969{
8970#if 0
8971 /*char buf[1024] = {0};
8972 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8973 _syscmd(cmd, buf, sizeof(buf));*/
8974
8975 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8976 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8977 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8978 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8979
8980 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.
8981 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].
8982 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].
8983 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].
8984 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8985 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8986
8987 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8988 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8989 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8990 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.
8991 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.
8992 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.
8993 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.
8994 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.
8995 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.
8996 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.
8997 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8998#endif
8999
9000 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08009001 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08009002 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009003 char pipeCmd[128] = {0};
9004 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009005 wifi_ssidTrafficStats2_t *out = output_struct;
9006
developerce736392022-09-13 15:24:34 +08009007 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009008 if (!output_struct)
9009 return RETURN_ERR;
9010
developerce736392022-09-13 15:24:34 +08009011 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9012 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
9013 GetInterfaceName(interface_name, HConf_file);
9014 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009015
developer06a01d92022-09-07 16:32:39 +08009016 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009017 if (fp == NULL) {
9018 fprintf(stderr, "%s: popen failed\n", __func__);
9019 return RETURN_ERR;
9020 }
9021 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08009022
developerce736392022-09-13 15:24:34 +08009023 if (strlen(str) == 0) // interface not exist
9024 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009025
developerce736392022-09-13 15:24:34 +08009026 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9027 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009028 pclose(fp);
9029
developerce736392022-09-13 15:24:34 +08009030 memset(str, 0, sizeof(str));
9031 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009032 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009033 if (fp == NULL) {
9034 fprintf(stderr, "%s: popen failed\n", __func__);
9035 return RETURN_ERR;
9036 }
9037 fgets(str, sizeof(str), fp);
9038
9039 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9040 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009041 pclose(fp);
developerce736392022-09-13 15:24:34 +08009042
9043 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9044 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9045
9046 // Not supported
9047 output_struct->ssid_RetransCount = 0;
9048 output_struct->ssid_FailedRetransCount = 0;
9049 output_struct->ssid_RetryCount = 0;
9050 output_struct->ssid_MultipleRetryCount = 0;
9051 output_struct->ssid_ACKFailureCount = 0;
9052 output_struct->ssid_AggregatedPacketCount = 0;
9053
developer06a01d92022-09-07 16:32:39 +08009054 return RETURN_OK;
9055}
9056
9057//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).
9058INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9059{
9060 char output_val[16]={'\0'};
9061 char config_file[MAX_BUF_SIZE] = {0};
9062
9063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9064 if (!output)
9065 return RETURN_ERR;
9066 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9067 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9068
9069 if( strcmp(output_val,"1") == 0 )
9070 *output = TRUE;
9071 else
9072 *output = FALSE;
9073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9074
9075 return RETURN_OK;
9076}
9077
9078INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9079{
9080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9081 char str[MAX_BUF_SIZE]={'\0'};
9082 char string[MAX_BUF_SIZE]={'\0'};
9083 char cmd[MAX_CMD_SIZE]={'\0'};
9084 char *ch;
9085 char config_file[MAX_BUF_SIZE] = {0};
9086 struct params params;
9087
9088 if(enable == TRUE)
9089 strcpy(string,"1");
9090 else
9091 strcpy(string,"0");
9092
9093 params.name = "ap_isolate";
9094 params.value = string;
9095
9096 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9097 wifi_hostapdWrite(config_file,&params,1);
9098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9099
9100 return RETURN_OK;
9101}
9102
9103INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9104{
9105 if (NULL == output_dBm)
9106 return RETURN_ERR;
9107
9108 *output_dBm = 0;
9109 return RETURN_OK;
9110}
9111
9112INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9113{
9114 return RETURN_OK;
9115}
9116INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9117{
9118 return RETURN_OK;
9119}
9120INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9121{
9122 return RETURN_OK;
9123}
9124INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9125{
9126 return RETURN_OK;
9127}
9128INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9129{
9130 return RETURN_OK;
9131}
9132INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9133{
9134 char config_file[MAX_BUF_SIZE] = {0};
9135 struct params list;
9136
9137 list.name = "bss_transition";
9138 list.value = activate?"1":"0";
9139 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9140 wifi_hostapdWrite(config_file, &list, 1);
9141
9142 return RETURN_OK;
9143}
9144wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9145
9146void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9147{
9148 return;
9149}
9150
9151INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9152{
9153 // TODO Implement me!
9154 return RETURN_OK;
9155}
9156
9157INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9158{
developera3c68b92022-09-13 15:27:29 +08009159 char file_name[128] = {0};
9160 char buf[128] = {0};
9161 FILE *f = NULL;
9162
9163 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9164
9165 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9166 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
9167 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9168 f = fopen(file_name, "w");
9169 if (f == NULL)
9170 return RETURN_ERR;
9171 // For mode == 0 is to disable filter, just don't write to the file.
9172 if (mode)
9173 fprintf(f, "%s", essid);
9174
9175 fclose(f);
9176 }
9177 } else { // special case, need to set AP's SSID as filter for each radio.
9178 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9179 f = fopen(file_name, "w");
9180 if (f == NULL)
9181 return RETURN_ERR;
9182
9183 // For mode == 0 is to disable filter, just don't write to the file.
9184 if (mode)
9185 fprintf(f, "%s", essid);
9186
9187 fclose(f);
9188 }
9189
9190 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009191 return RETURN_OK;
9192}
9193
9194INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9195{
9196 // TODO Implement me!
9197 //Apply wifi_pushRadioChannel() instantly
9198 return RETURN_ERR;
9199}
9200
9201INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9202{
9203 // TODO Implement me!
9204 return RETURN_OK;
9205}
9206
9207#ifdef HAL_NETLINK_IMPL
9208static int tidStats_callback(struct nl_msg *msg, void *arg) {
9209 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9210 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9211 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9212 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9213 int rem , tid_index = 0;
9214
9215 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9216 wifi_associated_dev_tid_entry_t *stats_entry;
9217
9218 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9219 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9220 };
9221 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9222 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9223 };
9224
9225 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9226 genlmsg_attrlen(gnlh, 0), NULL);
9227
9228
9229 if (!tb[NL80211_ATTR_STA_INFO]) {
9230 fprintf(stderr, "station stats missing!\n");
9231 return NL_SKIP;
9232 }
9233
9234 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9235 tb[NL80211_ATTR_STA_INFO],
9236 stats_policy)) {
9237 fprintf(stderr, "failed to parse nested attributes!\n");
9238 return NL_SKIP;
9239 }
9240
9241 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9242 {
9243 stats_entry = &out->tid_array[tid_index];
9244
9245 stats_entry->tid = tid_index;
9246 stats_entry->ac = _tid_ac_index_get[tid_index];
9247
9248 if(sinfo[NL80211_STA_INFO_TID_STATS])
9249 {
9250 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9251 printf("failed to parse nested stats attributes!");
9252 return NL_SKIP;
9253 }
9254 }
9255 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9256 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9257
9258 if(tid_index < (PS_MAX_TID - 1))
9259 tid_index++;
9260 }
9261 //ToDo: sum_time_ms, ewma_time_ms
9262 return NL_SKIP;
9263}
9264#endif
9265
9266INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9267{
9268#ifdef HAL_NETLINK_IMPL
9269 Netlink nl;
9270 char if_name[10];
9271
9272 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9273
9274 nl.id = initSock80211(&nl);
9275
9276 if (nl.id < 0) {
9277 fprintf(stderr, "Error initializing netlink \n");
9278 return -1;
9279 }
9280
9281 struct nl_msg* msg = nlmsg_alloc();
9282
9283 if (!msg) {
9284 fprintf(stderr, "Failed to allocate netlink message.\n");
9285 nlfree(&nl);
9286 return -2;
9287 }
9288
9289 genlmsg_put(msg,
9290 NL_AUTO_PORT,
9291 NL_AUTO_SEQ,
9292 nl.id,
9293 0,
9294 0,
9295 NL80211_CMD_GET_STATION,
9296 0);
9297
9298 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9299 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9300 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9301 nl_send_auto(nl.socket, msg);
9302 nl_recvmsgs(nl.socket, nl.cb);
9303 nlmsg_free(msg);
9304 nlfree(&nl);
9305 return RETURN_OK;
9306#else
9307//iw implementation
9308#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9309#define TOTAL_MAX_LINES 50
9310
9311 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9312 char if_name[10];
9313 FILE *fp=NULL;
9314 char pipeCmd[1024]= {'\0'};
9315 int lines,tid_index=0;
9316 char mac_addr[20] = {'\0'};
9317
9318 wifi_associated_dev_tid_entry_t *stats_entry;
9319
9320 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9321 strcpy(mac_addr,clientMacAddress);
9322
9323 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9324 fp= popen(pipeCmd,"r");
9325 if(fp == NULL)
9326 {
9327 perror("popen for station dump failed\n");
9328 return RETURN_ERR;
9329 }
9330 pclose(fp);
9331
9332 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9333 fp=popen(pipeCmd,"r");
9334 if(fp == NULL)
9335 {
9336 perror("popen for grep station failed\n");
9337 return RETURN_ERR;
9338 }
9339 else if(fgets(buf,sizeof(buf),fp) != NULL)
9340 lines=atoi(buf);
9341 else
9342 {
9343 pclose(fp);
9344 fprintf(stderr,"No devices are connected \n");
9345 return RETURN_ERR;
9346 }
9347 pclose(fp);
9348
9349 if(lines == 1)
9350 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9351
9352 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9353 {
9354 stats_entry = &tid_stats->tid_array[tid_index];
9355 stats_entry->tid = tid_index;
9356
9357 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);
9358
9359 fp=popen(pipeCmd,"r");
9360 if(fp ==NULL)
9361 {
9362 perror("Failed to read from tid file \n");
9363 return RETURN_ERR;
9364 }
9365 else if(fgets(buf,sizeof(buf),fp) != NULL)
9366 stats_entry->num_msdus = atol(buf);
9367
9368 pclose(fp);
9369 stats_entry->ac = _tid_ac_index_get[tid_index];
9370// TODO:
9371// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9372// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9373 }
9374 return RETURN_OK;
9375#endif
9376}
9377
9378
9379INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9380{
developer615510b2022-09-27 10:14:35 +08009381 char cmd[128]={0};
9382 char buf[128]={0};
9383 int freq = 0;
9384
9385 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9386
9387 // full mode is used to scan all channels.
9388 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9389 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9390 ieee80211_channel_to_frequency(chan_list[0], &freq);
9391
9392 if (freq)
9393 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9394 else
9395 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9396
9397 _syscmd(cmd, buf, sizeof(buf));
9398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9399
developer06a01d92022-09-07 16:32:39 +08009400 return RETURN_OK;
9401}
9402
9403
9404INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9405{
9406 // TODO Implement me!
9407 return RETURN_ERR;
9408}
9409
9410INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9411{
9412 // TODO Implement me!
9413 return RETURN_ERR;
9414}
9415
9416INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9417{
9418 // TODO Implement me!
9419 return RETURN_ERR;
9420}
9421
9422INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9423{
9424 // TODO Implement me!
9425 return RETURN_ERR;
9426}
9427
9428INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9429{
9430 // TODO Implement me!
9431 return RETURN_ERR;
9432}
9433
9434INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9435{
9436 // TODO Implement me!
9437 return RETURN_ERR;
9438}
9439
9440INT wifi_steering_eventUnregister(void)
9441{
9442 // TODO Implement me!
9443 return RETURN_ERR;
9444}
9445
9446INT wifi_delApAclDevices(INT apIndex)
9447{
9448#if 0
9449 char cmd[MAX_BUF_SIZE] = {0};
9450 char buf[MAX_BUF_SIZE] = {0};
9451
9452 /* Not reset proof solution */
9453 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9454 if(_syscmd(cmd,buf,sizeof(buf)))
9455 return RETURN_ERR;
9456#endif
developere6aafda2022-09-13 14:59:28 +08009457 char cmd[MAX_CMD_SIZE]={0};
9458 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009459
developere6aafda2022-09-13 14:59:28 +08009460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9461 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9462 if(_syscmd(cmd, buf, sizeof(buf)))
9463 return RETURN_ERR;
9464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009465
9466 return RETURN_OK;
9467}
9468
9469#ifdef HAL_NETLINK_IMPL
9470static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9471 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9472 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9473 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9474 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9475 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9476 char mac_addr[20],dev[20];
9477
9478 nla_parse(tb,
9479 NL80211_ATTR_MAX,
9480 genlmsg_attrdata(gnlh, 0),
9481 genlmsg_attrlen(gnlh, 0),
9482 NULL);
9483
9484 if(!tb[NL80211_ATTR_STA_INFO]) {
9485 fprintf(stderr, "sta stats missing!\n");
9486 return NL_SKIP;
9487 }
9488
9489 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9490 fprintf(stderr, "failed to parse nested attributes!\n");
9491 return NL_SKIP;
9492 }
9493 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9494
9495 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9496
9497 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9498 fprintf(stderr, "failed to parse nested rate attributes!");
9499 return NL_SKIP;
9500 }
9501
9502 if(sinfo[NL80211_STA_INFO_TID_STATS])
9503 {
9504 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9505 printf("failed to parse nested stats attributes!");
9506 return NL_SKIP;
9507 }
9508 }
9509
9510 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9511 {
9512 printf("Type is VHT\n");
9513 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9514 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9515
9516 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9517 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9518 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9519 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9520 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9521 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9522 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9523 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9524 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9525 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9526 }
9527 else
9528 {
9529 printf(" OFDM or CCK \n");
9530 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9531 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9532 }
9533
9534 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9535 if(rinfo[NL80211_RATE_INFO_MCS])
9536 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9537 }
9538 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9539 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9540 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9541 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9542
9543 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9544 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9545
9546 if (sinfo[NL80211_STA_INFO_SIGNAL])
9547 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9548 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9549 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9550 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9551 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9552 //rssi_array need to be filled
9553 return NL_SKIP;
9554}
9555#endif
9556
9557INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9558{
9559#ifdef HAL_NETLINK_IMPL
9560 Netlink nl;
9561 char if_name[10];
9562
9563 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9564
9565 if (*output_array_size <= 0)
9566 return RETURN_OK;
9567
9568 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9569 nl.id = initSock80211(&nl);
9570
9571 if (nl.id < 0) {
9572 fprintf(stderr, "Error initializing netlink \n");
9573 return 0;
9574 }
9575
9576 struct nl_msg* msg = nlmsg_alloc();
9577
9578 if (!msg) {
9579 fprintf(stderr, "Failed to allocate netlink message.\n");
9580 nlfree(&nl);
9581 return 0;
9582 }
9583
9584 genlmsg_put(msg,
9585 NL_AUTO_PORT,
9586 NL_AUTO_SEQ,
9587 nl.id,
9588 0,
9589 0,
9590 NL80211_CMD_GET_STATION,
9591 0);
9592
9593 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9594 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9595 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9596 nl_send_auto(nl.socket, msg);
9597 nl_recvmsgs(nl.socket, nl.cb);
9598 nlmsg_free(msg);
9599 nlfree(&nl);
9600 return RETURN_OK;
9601#else
9602 //TODO Implement me
9603 return RETURN_OK;
9604#endif
9605}
9606
9607#ifdef HAL_NETLINK_IMPL
9608static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9609 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9610 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9611 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9612 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9613 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9614 char mac_addr[20],dev[20];
9615
9616 nla_parse(tb,
9617 NL80211_ATTR_MAX,
9618 genlmsg_attrdata(gnlh, 0),
9619 genlmsg_attrlen(gnlh, 0),
9620 NULL);
9621
9622 if(!tb[NL80211_ATTR_STA_INFO]) {
9623 fprintf(stderr, "sta stats missing!\n");
9624 return NL_SKIP;
9625 }
9626
9627 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9628 fprintf(stderr, "failed to parse nested attributes!\n");
9629 return NL_SKIP;
9630 }
9631
9632 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9633
9634 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9635
9636 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9637 fprintf(stderr, "failed to parse nested rate attributes!");
9638 return NL_SKIP;
9639 }
9640
9641 if(sinfo[NL80211_STA_INFO_TID_STATS])
9642 {
9643 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9644 printf("failed to parse nested stats attributes!");
9645 return NL_SKIP;
9646 }
9647 }
9648 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9649 {
9650 printf("Type is VHT\n");
9651 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9652 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9653
9654 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9655 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9656 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9657 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9658 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9659 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9660 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9661 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9662 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9663 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9664 }
9665 else
9666 {
9667 printf(" OFDM or CCK \n");
9668 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9669 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9670 }
9671
9672 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9673 if(rinfo[NL80211_RATE_INFO_MCS])
9674 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9675 }
9676
9677 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9678 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9679 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9680 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9681
9682 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9683 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9684 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9685
9686 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9687 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9688
9689 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9690 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9691
9692 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9693 ((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]);
9694
9695 return NL_SKIP;
9696}
9697#endif
9698
9699INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9700{
9701#ifdef HAL_NETLINK_IMPL
9702 Netlink nl;
9703 char if_name[10];
9704
9705 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9706
9707 if (*output_array_size <= 0)
9708 return RETURN_OK;
9709
9710 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9711
9712 nl.id = initSock80211(&nl);
9713
9714 if(nl.id < 0) {
9715 fprintf(stderr, "Error initializing netlink \n");
9716 return 0;
9717 }
9718
9719 struct nl_msg* msg = nlmsg_alloc();
9720
9721 if(!msg) {
9722 fprintf(stderr, "Failed to allocate netlink message.\n");
9723 nlfree(&nl);
9724 return 0;
9725 }
9726
9727 genlmsg_put(msg,
9728 NL_AUTO_PORT,
9729 NL_AUTO_SEQ,
9730 nl.id,
9731 0,
9732 0,
9733 NL80211_CMD_GET_STATION,
9734 0);
9735
9736 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9737 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9738 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9739 nl_send_auto(nl.socket, msg);
9740 nl_recvmsgs(nl.socket, nl.cb);
9741 nlmsg_free(msg);
9742 nlfree(&nl);
9743 return RETURN_OK;
9744#else
9745 //TODO Implement me
9746 return RETURN_OK;
9747#endif
9748}
9749
9750INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9751{
9752 // TODO Implement me!
9753 char buf[MAX_BUF_SIZE] = {0};
9754 char config_file[MAX_BUF_SIZE] = {0};
9755
9756 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9757 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9758 *activate = (strncmp("1",buf,1) == 0);
9759
9760 return RETURN_OK;
9761}
9762
9763INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9764{
9765 char config_file[MAX_BUF_SIZE] = {0};
9766 struct params list;
9767
9768 list.name = "rrm_neighbor_report";
9769 list.value = activate?"1":"0";
9770 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9771 wifi_hostapdWrite(config_file, &list, 1);
9772
9773 return RETURN_OK;
9774}
9775
9776INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9777{
9778 char buf[32] = {0};
9779 char config_file[MAX_BUF_SIZE] = {0};
9780
9781 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9782 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9783 *activate = (strncmp("1",buf,1) == 0);
9784
9785 return RETURN_OK;
9786}
9787#undef HAL_NETLINK_IMPL
9788#ifdef HAL_NETLINK_IMPL
9789static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9790 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9791 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9792 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9793 char dev[20];
9794 int freq =0 ;
9795 static int i=0;
9796
9797 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9798
9799 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9800 };
9801
9802 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9803
9804 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9805
9806 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9807 fprintf(stderr, "survey data missing!\n");
9808 return NL_SKIP;
9809 }
9810
9811 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9812 {
9813 fprintf(stderr, "failed to parse nested attributes!\n");
9814 return NL_SKIP;
9815 }
9816
9817
9818 if(out[0].array_size == 1 )
9819 {
9820 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9821 {
9822 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9823 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9824 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9825
9826 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9827 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9828 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9829 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9830 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9831 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9832 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9833 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9834 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9835 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9836 if (sinfo[NL80211_SURVEY_INFO_TIME])
9837 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9838 return NL_STOP;
9839 }
9840 }
9841 else
9842 {
9843 if ( i <= out[0].array_size )
9844 {
9845 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9846 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9847 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9848
9849 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9850 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9851 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9852 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9853 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9854 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9855 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9856 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9857 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9858 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9859 if (sinfo[NL80211_SURVEY_INFO_TIME])
9860 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9861 }
9862 }
9863
9864 i++;
9865 return NL_SKIP;
9866}
9867#endif
9868
9869static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9870{
9871 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9872 FILE *fp;
9873
9874 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9875 {
9876 printf("Creating Frequency-Channel Map\n");
9877 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9878 }
9879 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9880 if((fp = popen(command, "r")))
9881 {
9882 fgets(output, sizeof(output), fp);
9883 *freqMHz = atoi(output);
9884 fclose(fp);
9885 }
9886
9887 return 0;
9888}
9889
9890static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9891{
9892 int freqMHz = -1;
9893 char cmd[MAX_CMD_SIZE] = {'\0'};
9894
9895 ieee80211_channel_to_frequency(channel, &freqMHz);
9896 if (freqMHz == -1) {
9897 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9898 return -1;
9899 }
9900
9901 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9902 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9903 radioIndex, freqMHz);
9904 return -1;
9905 }
9906
9907 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9908 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9909 return -1;
9910 }
9911
9912 return 0;
9913}
9914
9915static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9916{
9917 const char *ptr = buf;
9918 char *key = NULL;
9919 char *val = NULL;
9920 char line[256] = { '\0' };
9921
9922 while (ptr = get_line_from_str_buf(ptr, line)) {
9923 if (strstr(line, "Frequency")) continue;
9924
9925 key = strtok(line, ":");
9926 val = strtok(NULL, " ");
9927 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9928
9929 if (!strcmp(key, "noise")) {
9930 sscanf(val, "%d", &stats->ch_noise);
9931 if (stats->ch_noise == 0) {
9932 // Workaround for missing noise information.
9933 // Assume -95 for 2.4G and -103 for 5G
9934 if (radioIndex == 0) stats->ch_noise = -95;
9935 if (radioIndex == 1) stats->ch_noise = -103;
9936 }
9937 }
9938 else if (!strcmp(key, "channel active time")) {
9939 sscanf(val, "%llu", &stats->ch_utilization_total);
9940 }
9941 else if (!strcmp(key, "channel busy time")) {
9942 sscanf(val, "%llu", &stats->ch_utilization_busy);
9943 }
9944 else if (!strcmp(key, "channel receive time")) {
9945 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9946 }
9947 else if (!strcmp(key, "channel transmit time")) {
9948 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9949 }
9950 };
9951
9952 return 0;
9953}
9954
9955INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9956{
9957 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9958#ifdef HAL_NETLINK_IMPL
9959 Netlink nl;
9960 wifi_channelStats_t_loc local[array_size];
9961 char if_name[10];
9962
9963 local[0].array_size = array_size;
9964
9965 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9966
9967 nl.id = initSock80211(&nl);
9968
9969 if (nl.id < 0) {
9970 fprintf(stderr, "Error initializing netlink \n");
9971 return -1;
9972 }
9973
9974 struct nl_msg* msg = nlmsg_alloc();
9975
9976 if (!msg) {
9977 fprintf(stderr, "Failed to allocate netlink message.\n");
9978 nlfree(&nl);
9979 return -2;
9980 }
9981
9982 genlmsg_put(msg,
9983 NL_AUTO_PORT,
9984 NL_AUTO_SEQ,
9985 nl.id,
9986 0,
9987 NLM_F_DUMP,
9988 NL80211_CMD_GET_SURVEY,
9989 0);
9990
9991 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9992 nl_send_auto(nl.socket, msg);
9993 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9994 nl_recvmsgs(nl.socket, nl.cb);
9995 nlmsg_free(msg);
9996 nlfree(&nl);
9997 //Copying the Values
9998 for(int i=0;i<array_size;i++)
9999 {
10000 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10001 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10002 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10003 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10004 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10005 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10006 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10007 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10008 }
10009#else
10010 ULONG channel = 0;
10011 int i;
10012 int number_of_channels = array_size;
10013 char buf[512];
10014 INT ret;
10015 wifi_channelStats_t tmp_stats;
10016
10017 if (number_of_channels == 0) {
10018 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10019 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10020 return RETURN_ERR;
10021 }
10022 number_of_channels = 1;
10023 input_output_channelStats_array[0].ch_number = channel;
10024 }
10025
10026 for (i = 0; i < number_of_channels; i++) {
10027
10028 input_output_channelStats_array[i].ch_noise = 0;
10029 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10030 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10031 input_output_channelStats_array[i].ch_utilization_busy = 0;
10032 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10033 input_output_channelStats_array[i].ch_utilization_total = 0;
10034
10035 memset(buf, 0, sizeof(buf));
10036 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10037 return RETURN_ERR;
10038 }
10039 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10040 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10041 return RETURN_ERR;
10042 }
10043
10044 // XXX: fake missing 'self' counter which is not available in iw survey output
10045 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10046 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10047
10048 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10049 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10050 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10051 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10052 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10053
10054 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",
10055 __func__,
10056 input_output_channelStats_array[i].ch_number,
10057 input_output_channelStats_array[i].ch_noise,
10058 input_output_channelStats_array[i].ch_utilization_total,
10059 input_output_channelStats_array[i].ch_utilization_busy,
10060 input_output_channelStats_array[i].ch_utilization_busy_rx,
10061 input_output_channelStats_array[i].ch_utilization_busy_tx,
10062 input_output_channelStats_array[i].ch_utilization_busy_self,
10063 input_output_channelStats_array[i].ch_utilization_busy_ext);
10064 }
10065#endif
10066 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10067 return RETURN_OK;
10068}
10069#define HAL_NETLINK_IMPL
10070
10071/* Hostapd events */
10072
10073#ifndef container_of
10074#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10075#define container_of(ptr, type, member) \
10076 ((type *)((char *)ptr - offset_of(type, member)))
10077#endif /* container_of */
10078
10079struct ctrl {
10080 char sockpath[128];
10081 char sockdir[128];
10082 char bss[IFNAMSIZ];
10083 char reply[4096];
10084 int ssid_index;
10085 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10086 void (*overrun)(struct ctrl *ctrl);
10087 struct wpa_ctrl *wpa;
10088 unsigned int ovfl;
10089 size_t reply_len;
10090 int initialized;
10091 ev_timer retry;
10092 ev_timer watchdog;
10093 ev_stat stat;
10094 ev_io io;
10095};
10096static wifi_newApAssociatedDevice_callback clients_connect_cb;
10097static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10098static struct ctrl wpa_ctrl[MAX_APS];
10099static int initialized;
10100
10101static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10102{
10103 char cbuf[256] = {};
10104 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10105 struct cmsghdr *cmsg;
10106 unsigned int ovfl = ctrl->ovfl;
10107 unsigned int drop;
10108
10109 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10110 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10111 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10112 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10113
10114 drop = ovfl - ctrl->ovfl;
10115 ctrl->ovfl = ovfl;
10116
10117 return drop;
10118}
10119
10120static void ctrl_close(struct ctrl *ctrl)
10121{
10122 if (ctrl->io.cb)
10123 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10124 if (ctrl->retry.cb)
10125 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10126 if (!ctrl->wpa)
10127 return;
10128
10129 wpa_ctrl_detach(ctrl->wpa);
10130 wpa_ctrl_close(ctrl->wpa);
10131 ctrl->wpa = NULL;
10132 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10133}
10134
10135static void ctrl_process(struct ctrl *ctrl)
10136{
10137 const char *str;
10138 int drops;
10139 int level;
10140 int err;
10141
10142 /* Example events:
10143 *
10144 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10145 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10146 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10147 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10148 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10149 */
10150 if (!(str = index(ctrl->reply, '>')))
10151 return;
10152 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10153 return;
10154
10155 str++;
10156
10157 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10158 if (!(str = index(ctrl->reply, ' ')))
10159 return;
10160 wifi_associated_dev_t sta;
10161 memset(&sta, 0, sizeof(sta));
10162
10163 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10164 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10165 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10166
10167 sta.cli_Active=true;
10168
10169 (clients_connect_cb)(ctrl->ssid_index, &sta);
10170 goto handled;
10171 }
10172
10173 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10174 if (!(str = index(ctrl->reply, ' ')))
10175 return;
10176
10177 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10178 goto handled;
10179 }
10180
10181 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10182 printf("CTRL_WPA: handle TERMINATING event\n");
10183 goto retry;
10184 }
10185
10186 if (strncmp("AP-DISABLED", str, 11) == 0) {
10187 printf("CTRL_WPA: handle AP-DISABLED\n");
10188 goto retry;
10189 }
10190
10191 printf("Event not supported!!\n");
10192
10193handled:
10194
10195 if ((drops = ctrl_get_drops(ctrl))) {
10196 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10197 if (ctrl->overrun)
10198 ctrl->overrun(ctrl);
10199 }
10200
10201 return;
10202
10203retry:
10204 printf("WPA_CTRL: closing\n");
10205 ctrl_close(ctrl);
10206 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10207 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10208}
10209
10210static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10211{
10212 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10213 int err;
10214
10215 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10216 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10217 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10218 ctrl->reply[ctrl->reply_len] = 0;
10219 if (err < 0) {
10220 if (errno == EAGAIN || errno == EWOULDBLOCK)
10221 return;
10222 ctrl_close(ctrl);
10223 ev_timer_again(EV_A_ &ctrl->retry);
10224 return;
10225 }
10226
10227 ctrl_process(ctrl);
10228}
10229
10230static int ctrl_open(struct ctrl *ctrl)
10231{
10232 int fd;
10233
10234 if (ctrl->wpa)
10235 return 0;
10236
10237 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10238 if (!ctrl->wpa)
10239 goto err;
10240
10241 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10242 goto err_close;
10243
10244 fd = wpa_ctrl_get_fd(ctrl->wpa);
10245 if (fd < 0)
10246 goto err_detach;
10247
10248 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10249 goto err_detach;
10250
10251 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10252 ev_io_start(EV_DEFAULT_ &ctrl->io);
10253
10254 return 0;
10255
10256err_detach:
10257 wpa_ctrl_detach(ctrl->wpa);
10258err_close:
10259 wpa_ctrl_close(ctrl->wpa);
10260err:
10261 ctrl->wpa = NULL;
10262 return -1;
10263}
10264
10265static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10266{
10267 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10268
10269 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10270 ctrl_open(ctrl);
10271}
10272
10273static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10274{
10275 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10276
10277 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10278 if (ctrl_open(ctrl) == 0) {
10279 printf("WPA_CTRL: retry successful\n");
10280 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10281 }
10282}
10283
10284int ctrl_enable(struct ctrl *ctrl)
10285{
10286 if (ctrl->wpa)
10287 return 0;
10288
10289 if (!ctrl->stat.cb) {
10290 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10291 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10292 }
10293
10294 if (!ctrl->retry.cb) {
10295 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10296 }
10297
10298 return ctrl_open(ctrl);
10299}
10300
10301static void
10302ctrl_msg_cb(char *buf, size_t len)
10303{
10304 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10305
10306 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10307 ctrl_process(ctrl);
10308}
10309
10310static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10311{
10312 int err;
10313
10314 if (!ctrl->wpa)
10315 return -1;
10316 if (*reply_len < 2)
10317 return -1;
10318
10319 (*reply_len)--;
10320 ctrl->reply_len = sizeof(ctrl->reply);
10321 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10322 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10323 if (err < 0)
10324 return err;
10325
10326 if (ctrl->reply_len > *reply_len)
10327 ctrl->reply_len = *reply_len;
10328
10329 *reply_len = ctrl->reply_len;
10330 memcpy(reply, ctrl->reply, *reply_len);
10331 reply[*reply_len - 1] = 0;
10332 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10333 return 0;
10334}
10335
10336static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10337{
10338 const char *pong = "PONG";
10339 const char *ping = "PING";
10340 char reply[1024];
10341 size_t len = sizeof(reply);
10342 int err;
10343 ULONG s, snum;
10344 INT ret;
10345 BOOL status;
10346
10347 printf("WPA_CTRL: watchdog cb\n");
10348
10349 ret = wifi_getSSIDNumberOfEntries(&snum);
10350 if (ret != RETURN_OK) {
10351 printf("%s: failed to get SSID count", __func__);
10352 return;
10353 }
10354
10355 if (snum > MAX_APS) {
10356 printf("more ssid than supported! %lu\n", snum);
10357 return;
10358 }
10359
10360 for (s = 0; s < snum; s++) {
10361 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10362 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10363 continue;
10364 }
10365 if (status == false) continue;
10366
10367 memset(reply, 0, sizeof(reply));
10368 len = sizeof(reply);
10369 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10370 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10371 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10372 continue;
10373
10374 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10375 ctrl_close(&wpa_ctrl[s]);
10376 printf("WPA_CTRL: ev_timer_again %d\n", s);
10377 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10378 }
10379}
10380
10381static int init_wpa()
10382{
10383 int ret = 0, i = 0;
10384 ULONG s, snum;
10385
10386 ret = wifi_getSSIDNumberOfEntries(&snum);
10387 if (ret != RETURN_OK) {
10388 printf("%s: failed to get SSID count", __func__);
10389 return RETURN_ERR;
10390 }
10391
10392 if (snum > MAX_APS) {
10393 printf("more ssid than supported! %lu\n", snum);
10394 return RETURN_ERR;
10395 }
10396
10397 for (s = 0; s < snum; s++) {
10398 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10399 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10400 wpa_ctrl[s].ssid_index = s;
10401 ctrl_enable(&wpa_ctrl[s]);
10402 }
10403
10404 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10405 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10406
10407 initialized = 1;
10408 printf("WPA_CTRL: initialized\n");
10409
10410 return RETURN_OK;
10411}
10412
10413void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10414{
10415 clients_connect_cb = callback_proc;
10416 if (!initialized)
10417 init_wpa();
10418}
10419
10420void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10421{
10422 clients_disconnect_cb = callback_proc;
10423 if (!initialized)
10424 init_wpa();
10425}
10426
10427INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10428{
10429 // TODO Implement me!
10430 return RETURN_ERR;
10431}
10432
10433INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10434{
10435 // TODO Implement me!
10436 return RETURN_ERR;
10437}
10438
10439INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10440{
10441 int i;
10442 char cmd[256];
10443 char channel_numbers_buf[256];
10444 char dfs_state_buf[256];
10445 char line[256];
10446 const char *ptr;
10447
10448 memset(cmd, 0, sizeof(cmd));
10449 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10450 memset(line, 0, sizeof(line));
10451 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10452 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10453
10454 if (radioIndex == 0) { // 2.4G - all allowed
10455 if (outputMapSize < 11) {
10456 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10457 return RETURN_ERR;
10458 }
10459
10460 for (i = 0; i < 11; i++) {
10461 outputMap[i].ch_number = i + 1;
10462 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10463 }
10464
10465 return RETURN_OK;
10466 }
10467
10468 if (radioIndex == 1) { // 5G
10469// Example output of iw list:
10470//
10471// Frequencies:
10472// * 5180 MHz [36] (17.0 dBm)
10473// * 5200 MHz [40] (17.0 dBm)
10474// * 5220 MHz [44] (17.0 dBm)
10475// * 5240 MHz [48] (17.0 dBm)
10476// * 5260 MHz [52] (23.0 dBm) (radar detection)
10477// DFS state: usable (for 78930 sec)
10478// DFS CAC time: 60000 ms
10479// * 5280 MHz [56] (23.0 dBm) (radar detection)
10480// DFS state: usable (for 78930 sec)
10481// DFS CAC time: 60000 ms
10482// * 5300 MHz [60] (23.0 dBm) (radar detection)
10483// DFS state: usable (for 78930 sec)
10484// DFS CAC time: 60000 ms
10485// * 5320 MHz [64] (23.0 dBm) (radar detection)
10486// DFS state: usable (for 78930 sec)
10487// DFS CAC time: 60000 ms
10488// * 5500 MHz [100] (disabled)
10489// * 5520 MHz [104] (disabled)
10490// * 5540 MHz [108] (disabled)
10491// * 5560 MHz [112] (disabled)
10492//
10493// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10494 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10495 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10496 return RETURN_ERR;
10497 }
10498
10499 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10500 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10501 return RETURN_ERR;
10502 }
10503
10504 ptr = channel_numbers_buf;
10505 i = 0;
10506 while (ptr = get_line_from_str_buf(ptr, line)) {
10507 if (i >= outputMapSize) {
10508 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10509 return RETURN_ERR;
10510 }
10511 sscanf(line, "%d", &outputMap[i].ch_number);
10512
10513 memset(cmd, 0, sizeof(cmd));
10514 // Below command should fetch string for DFS state (usable, available or unavailable)
10515 // Example line: "DFS state: usable (for 78930 sec)"
10516 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) {
10517 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10518 return RETURN_ERR;
10519 }
10520
10521 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10522 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10523 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10524 return RETURN_ERR;
10525 }
10526
10527 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10528
10529 if (!strcmp(dfs_state_buf, "usable")) {
10530 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10531 } else if (!strcmp(dfs_state_buf, "available")) {
10532 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10533 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10534 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10535 } else {
10536 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10537 }
10538 i++;
10539 }
10540
10541 return RETURN_OK;
10542 }
10543
10544 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10545 return RETURN_ERR;
10546}
10547
10548INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10549{
10550 // TODO Implement me!
10551 return RETURN_ERR;
10552}
10553
10554INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10555{
10556 return RETURN_OK;
10557}
10558
10559INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10560{
10561 // TODO Implement me!
10562 return RETURN_ERR;
10563}
10564
10565INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10566{
10567 // TODO API refrence Implementaion is present on RPI hal
10568 return RETURN_ERR;
10569}
10570
10571INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10572{
developera5005b62022-09-13 15:43:35 +080010573 char cmd[128]={'\0'};
10574 char buf[128]={'\0'};
10575 char *support;
10576 int maximum_tx = 0, current_tx = 0;
10577
10578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10579 if(txpwr_pcntg == NULL)
10580 return RETURN_ERR;
10581
10582 // Get the maximum tx power of the device
10583 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10584 _syscmd(cmd, buf, sizeof(buf));
10585 maximum_tx = strtol(buf, NULL, 10);
10586
10587 // Get the current tx power
10588 memset(cmd, 0, sizeof(cmd));
10589 memset(buf, 0, sizeof(buf));
10590 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10591 _syscmd(cmd, buf, sizeof(buf));
10592 current_tx = strtol(buf, NULL, 10);
10593
10594 // Get the power supported list and find the current power percentage in supported list
10595 memset(buf, 0, sizeof(buf));
10596 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10597 support = strtok(buf, ",");
10598 while(true)
10599 {
10600 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10601 *txpwr_pcntg = 0;
10602 wifi_dbg_printf("current power is not in supported list\n");
10603 return RETURN_ERR;
10604 }
10605 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10606 if (tmp == current_tx) {
10607 *txpwr_pcntg = strtol(support, NULL, 10);
10608 break;
10609 }
10610 support = strtok(NULL, ",");
10611 }
10612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010613 return RETURN_OK;
10614}
10615
10616INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10617{
developer58599c22022-09-13 16:40:34 +080010618 // TODO precac feature.
10619 struct params params = {0};
10620 char config_file[128] = {0};
10621
10622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10623
10624 params.name = "enable_background_radar";
10625 params.value = enable?"1":"0";
10626 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10627 wifi_hostapdWrite(config_file, &params, 1);
10628 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10629
10630 /* TODO precac feature */
10631
10632 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10633 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010634}
10635
10636INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10637{
developer58599c22022-09-13 16:40:34 +080010638 char config_file[128] = {0};
10639 char buf[64] = {0};
10640
10641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10642 if (NULL == enable || NULL == precac)
10643 return RETURN_ERR;
10644
10645 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10646 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10647 if (strncmp(enable, "1", 1) == 0)
10648 *enable = true;
10649 else
10650 *enable = false;
10651
10652 /* TODO precac feature */
10653
10654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10655 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010656}
10657
10658INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10659{
developer58599c22022-09-13 16:40:34 +080010660 *supported = TRUE;
10661 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010662}
10663
developer3e6b1692022-09-30 18:04:05 +080010664INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10665{
10666 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10667 struct params params = {0};
10668 char config_file[64] = {0};
10669 char buf[64] = {0};
10670 unsigned int set_mu_type = 0;
10671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10672
10673 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10674 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10675
10676 if (strlen(buf) > 0)
10677 set_mu_type = strtol(buf, NULL, 10);
10678
10679 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10680 set_mu_type &= ~0x05; // unset bit 0, 2
10681 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10682 set_mu_type |= 0x01;
10683 set_mu_type &= ~0x04;
10684 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10685 set_mu_type &= ~0x01;
10686 set_mu_type |= 0x04;
10687 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10688 set_mu_type |= 0x05; // set bit 0, 2
10689 }
10690
10691 params.name = "hemu_onoff";
10692 sprintf(buf, "%u", set_mu_type);
10693 params.value = buf;
10694 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10695 wifi_hostapdWrite(config_file, &params, 1);
10696 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10697
10698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10699 return RETURN_OK;
10700}
10701
10702INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10703{
10704 struct params params={0};
10705 char config_file[64] = {0};
10706 char buf[64] = {0};
10707 unsigned int get_mu_type = 0;
10708
10709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10710
10711 if (mu_type == NULL)
10712 return RETURN_ERR;
10713
10714 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10715 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10716 get_mu_type = strtol(buf, NULL, 10);
10717
10718 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10719 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10720 else if (get_mu_type & 0x04)
10721 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10722 else if (get_mu_type & 0x01)
10723 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10724 else
10725 *mu_type = WIFI_DL_MU_TYPE_NONE;
10726
10727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10728 return RETURN_OK;
10729}
10730
10731INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10732{
10733 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10734 struct params params={0};
10735 char config_file[64] = {0};
10736 char buf[64] = {0};
10737 unsigned int set_mu_type = 0;
10738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10739
10740 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10741 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10742
10743 if (strlen(buf) > 0)
10744 set_mu_type = strtol(buf, NULL, 10);
10745
10746 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10747 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10748 set_mu_type &= ~0x0a;
10749 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10750 set_mu_type |= 0x02;
10751 set_mu_type &= ~0x08;
10752 }
10753
10754 params.name = "hemu_onoff";
10755 sprintf(buf, "%u", set_mu_type);
10756 params.value = buf;
10757 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10758 wifi_hostapdWrite(config_file, &params, 1);
10759 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10760
10761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10762 return RETURN_OK;
10763}
10764
10765INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10766{
10767 struct params params={0};
10768 char config_file[64] = {0};
10769 char buf[64] = {0};
10770 unsigned int get_mu_type = 0;
10771
10772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10773
10774 if (mu_type == NULL)
10775 return RETURN_ERR;
10776
10777 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10778 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10779
10780 get_mu_type = strtol(buf, NULL, 10);
10781 if (get_mu_type & 0x02)
10782 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10783 else
10784 *mu_type = WIFI_DL_MU_TYPE_NONE;
10785
10786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10787 return RETURN_OK;
10788}
10789
10790
developer454b9462022-09-13 15:29:16 +080010791INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10792{
10793 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010794 char buf[256] = {0};
10795 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010796 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010797 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010798 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010799 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010800
10801 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10802
developer254882b2022-09-30 17:12:31 +080010803 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010804 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10805 return RETURN_ERR;
10806 }
developer454b9462022-09-13 15:29:16 +080010807
developer254882b2022-09-30 17:12:31 +080010808 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010809 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010810
developer254882b2022-09-30 17:12:31 +080010811 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10812 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
10813 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
10814 _syscmd(cmd, buf, sizeof(buf));
10815 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10816 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10817 if (strstr(buf, "[SHORT-GI-") == NULL) {
10818 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
10819 _syscmd(cmd, buf, sizeof(buf));
10820 }
10821 if (band == band_5) {
10822 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10823 if (strstr(buf, "[SHORT-GI-") == NULL) {
10824 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
10825 _syscmd(cmd, buf, sizeof(buf));
10826 }
10827 }
10828 }
10829 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010830
developer254882b2022-09-30 17:12:31 +080010831 if (guard_interval == wifi_guard_interval_400)
10832 strcpy(GI, "0.4");
10833 else if (guard_interval == wifi_guard_interval_800)
10834 strcpy(GI, "0.8");
10835 else if (guard_interval == wifi_guard_interval_1600)
10836 strcpy(GI, "1.6");
10837 else if (guard_interval == wifi_guard_interval_3200)
10838 strcpy(GI, "3.2");
10839 else if (guard_interval == wifi_guard_interval_auto)
10840 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010841 // Record GI for get GI function
10842 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10843 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010844 if (f == NULL)
10845 return RETURN_ERR;
10846 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010847 fclose(f);
10848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10849 return RETURN_OK;
10850}
10851
10852INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10853{
10854 char buf[32] = {0};
10855 char cmd[64] = {0};
10856
10857 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10858
10859 if (guard_interval == NULL)
10860 return RETURN_ERR;
10861
10862 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10863 _syscmd(cmd, buf, sizeof(buf));
10864
10865 if (strncmp(buf, "0.4", 3) == 0)
10866 *guard_interval = wifi_guard_interval_400;
10867 else if (strncmp(buf, "0.8", 3) == 0)
10868 *guard_interval = wifi_guard_interval_800;
10869 else if (strncmp(buf, "1.6", 3) == 0)
10870 *guard_interval = wifi_guard_interval_1600;
10871 else if (strncmp(buf, "3.2", 3) == 0)
10872 *guard_interval = wifi_guard_interval_3200;
10873 else
10874 *guard_interval = wifi_guard_interval_auto;
10875
10876 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10877 return RETURN_OK;
10878}
10879
developer3cc61d12022-09-13 16:36:05 +080010880INT wifi_setBSSColor(INT radio_index, UCHAR color)
10881{
10882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10883 struct params params = {0};
10884 char config_file[128] = {0};
10885 char bss_color[4] ={0};
10886
10887 params.name = "he_bss_color";
10888 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10889 params.value = bss_color;
10890 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10891 wifi_hostapdWrite(config_file, &params, 1);
10892 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10893
10894 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10895 return RETURN_OK;
10896}
10897
10898INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10899{
10900 char config_file[128] = {0};
10901 char buf[64] = {0};
10902 char temp_output[128] = {'\0'};
10903
10904 wifi_dbg_printf("\nFunc=%s\n", __func__);
10905 if (NULL == color)
10906 return RETURN_ERR;
10907
10908 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10909 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10910
10911 if(strlen(buf) > 0) {
10912 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10913 } else {
10914 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10915 }
10916
10917 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10918 wifi_dbg_printf("\noutput_string=%s\n", color);
10919
10920 return RETURN_OK;
10921}
10922
developer06a01d92022-09-07 16:32:39 +080010923/* multi-psk support */
10924INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10925{
10926 char cmd[256];
10927
10928 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10929 AP_PREFIX,
10930 apIndex,
10931 mac[0],
10932 mac[1],
10933 mac[2],
10934 mac[3],
10935 mac[4],
10936 mac[5]
10937 );
10938 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10939 _syscmd(cmd, key->wifi_keyId, 64);
10940
10941
10942 return RETURN_OK;
10943}
10944
10945INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10946{
10947 FILE *fd = NULL;
10948 char fname[100];
10949 char cmd[128] = {0};
10950 char out[64] = {0};
10951 wifi_key_multi_psk_t * key = NULL;
10952 if(keysNumber < 0)
10953 return RETURN_ERR;
10954
10955 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10956 fd = fopen(fname, "w");
10957 if (!fd) {
10958 return RETURN_ERR;
10959 }
10960 key= (wifi_key_multi_psk_t *) keys;
10961 for(int i=0; i<keysNumber; ++i, key++) {
10962 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10963 }
10964 fclose(fd);
10965
10966 //reload file
10967 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10968 _syscmd(cmd, out, 64);
10969 return RETURN_OK;
10970}
10971
10972INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10973{
10974 FILE *fd = NULL;
10975 char fname[100];
10976 char * line = NULL;
10977 char * pos = NULL;
10978 size_t len = 0;
10979 ssize_t read = 0;
10980 INT ret = RETURN_OK;
10981 wifi_key_multi_psk_t *keys_it = NULL;
10982
10983 if (keysNumber < 1) {
10984 return RETURN_ERR;
10985 }
10986
10987 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10988 fd = fopen(fname, "r");
10989 if (!fd) {
10990 return RETURN_ERR;
10991 }
10992
10993 if (keys == NULL) {
10994 ret = RETURN_ERR;
10995 goto close;
10996 }
10997
10998 keys_it = keys;
10999 while ((read = getline(&line, &len, fd)) != -1) {
11000 //Strip trailing new line if present
11001 if (read > 0 && line[read-1] == '\n') {
11002 line[read-1] = '\0';
11003 }
11004
11005 if(strcmp(line,"keyid=")) {
11006 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11007 if (!(pos = index(line, ' '))) {
11008 ret = RETURN_ERR;
11009 goto close;
11010 }
11011 pos++;
11012 //Here should be 00:00:00:00:00:00
11013 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11014 printf("Not supported MAC: %s\n", pos);
11015 }
11016 if (!(pos = index(pos, ' '))) {
11017 ret = RETURN_ERR;
11018 goto close;
11019 }
11020 pos++;
11021
11022 //The rest is PSK
11023 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11024 keys_it++;
11025
11026 if(--keysNumber <= 0)
11027 break;
11028 }
11029 }
11030
11031close:
11032 free(line);
11033 fclose(fd);
11034 return ret;
11035}
11036/* end of multi-psk support */
11037
11038INT wifi_setNeighborReports(UINT apIndex,
11039 UINT numNeighborReports,
11040 wifi_NeighborReport_t *neighborReports)
11041{
11042 char cmd[256] = { 0 };
11043 char hex_bssid[13] = { 0 };
11044 char bssid[18] = { 0 };
11045 char nr[256] = { 0 };
11046 char ssid[256];
11047 char hex_ssid[256];
11048 INT ret;
11049
11050 /*rmeove all neighbors*/
11051 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
11052 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);
11053 system(cmd);
11054
11055 for(unsigned int i = 0; i < numNeighborReports; i++)
11056 {
11057 memset(ssid, 0, sizeof(ssid));
11058 ret = wifi_getSSIDName(apIndex, ssid);
11059 if (ret != RETURN_OK)
11060 return RETURN_ERR;
11061
11062 memset(hex_ssid, 0, sizeof(hex_ssid));
11063 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11064 sprintf(hex_ssid + k,"%02x", ssid[j]);
11065
11066 snprintf(hex_bssid, sizeof(hex_bssid),
11067 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11068 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11069 snprintf(bssid, sizeof(bssid),
11070 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11071 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11072
11073 snprintf(nr, sizeof(nr),
11074 "%s" // bssid
11075 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11076 "%02hhx" // operclass
11077 "%02hhx" // channel
11078 "%02hhx", // phy_mode
11079 hex_bssid,
11080 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11081 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11082 neighborReports[i].opClass,
11083 neighborReports[i].channel,
11084 neighborReports[i].phyTable);
11085
11086 snprintf(cmd, sizeof(cmd),
11087 "hostapd_cli set_neighbor "
11088 "%s " // bssid
11089 "ssid=%s " // ssid
11090 "nr=%s " // nr
11091 "-i %s%d",
11092 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
11093
11094 if (WEXITSTATUS(system(cmd)) != 0)
11095 {
11096 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11097 }
11098 }
11099
11100 return RETURN_OK;
11101}
11102
11103INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11104{
11105 return RETURN_OK;
11106}
11107
11108#ifdef _WIFI_HAL_TEST_
11109int main(int argc,char **argv)
11110{
11111 int index;
11112 INT ret=0;
11113 char buf[1024]="";
11114
11115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11116 if(argc<3)
11117 {
11118 if(argc==2)
11119 {
11120 if(!strcmp(argv[1], "init"))
11121 return wifi_init();
11122 if(!strcmp(argv[1], "reset"))
11123 return wifi_reset();
11124 if(!strcmp(argv[1], "wifi_getHalVersion"))
11125 {
11126 char buffer[64];
11127 if(wifi_getHalVersion(buffer)==RETURN_OK)
11128 printf("Version: %s\n", buffer);
11129 else
11130 printf("Error in wifi_getHalVersion\n");
11131 return RETURN_OK;
11132 }
11133 }
11134 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11135 exit(-1);
11136 }
11137
11138 index = atoi(argv[2]);
11139 if(strstr(argv[1], "wifi_getApName")!=NULL)
11140 {
11141 wifi_getApName(index,buf);
11142 printf("Ap name is %s \n",buf);
11143 return 0;
11144 }
11145 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11146 {
11147 BOOL b = FALSE;
11148 BOOL *output_bool = &b;
11149 wifi_getRadioAutoChannelEnable(index,output_bool);
11150 printf("Channel enabled = %d \n",b);
11151 return 0;
11152 }
11153 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11154 {
11155 wifi_getApWpaEncryptionMode(index,buf);
11156 printf("encryption enabled = %s\n",buf);
11157 return 0;
11158 }
11159 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11160 {
11161 BOOL b = FALSE;
11162 BOOL *output_bool = &b;
11163 wifi_getApSsidAdvertisementEnable(index,output_bool);
11164 printf("advertisment enabled = %d\n",b);
11165 return 0;
11166 }
11167 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11168 {
11169 if(argc <= 3 )
11170 {
11171 printf("Insufficient arguments \n");
11172 exit(-1);
11173 }
11174
11175 char sta[20] = {'\0'};
11176 ULLONG handle= 0;
11177 strcpy(sta,argv[3]);
11178 mac_address_t st;
11179 mac_addr_aton(st,sta);
11180
11181 wifi_associated_dev_tid_stats_t tid_stats;
11182 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11183 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11184 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);
11185 }
11186
11187 if(strstr(argv[1], "getApEnable")!=NULL) {
11188 BOOL enable;
11189 ret=wifi_getApEnable(index, &enable);
11190 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11191 }
11192 else if(strstr(argv[1], "setApEnable")!=NULL) {
11193 BOOL enable = atoi(argv[3]);
11194 ret=wifi_setApEnable(index, enable);
11195 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11196 }
11197 else if(strstr(argv[1], "getApStatus")!=NULL) {
11198 char status[64];
11199 ret=wifi_getApStatus(index, status);
11200 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11201 }
11202 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11203 {
11204 wifi_getSSIDNameStatus(index,buf);
11205 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11206 return 0;
11207 }
11208 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11209 wifi_ssidTrafficStats2_t stats={0};
11210 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11211 printf("%s %d: returns %d\n", argv[1], index, ret);
11212 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11213 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11214 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11215 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11216 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11217 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11218 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11219 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11220 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11221 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11222 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11223 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11224 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11225 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11226 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11227 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11228 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11229 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11230 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11231 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11232 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11233 }
11234 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11235 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11236 UINT array_size=0;
11237 UINT i=0;
11238 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11239 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11240 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11241 printf(" neighbor %d:\n", i);
11242 printf(" ap_SSID =%s\n", pt->ap_SSID);
11243 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11244 printf(" ap_Mode =%s\n", pt->ap_Mode);
11245 printf(" ap_Channel =%d\n", pt->ap_Channel);
11246 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11247 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11248 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11249 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11250 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11251 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11252 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11253 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11254 printf(" ap_Noise =%d\n", pt->ap_Noise);
11255 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11256 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11257 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11258 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11259 }
11260 if(neighbor_ap_array)
11261 free(neighbor_ap_array); //make sure to free the list
11262 }
11263 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11264 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11265 UINT array_size=0;
11266 UINT i=0;
11267 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11268 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11269 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11270 printf(" associated_dev %d:\n", i);
11271 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11272 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11273 printf(" cli_SNR =%d\n", pt->cli_SNR);
11274 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11275 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11276 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11277 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11278 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11279 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11280 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11281 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11282 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11283 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11284 }
11285 if(associated_dev_array)
11286 free(associated_dev_array); //make sure to free the list
11287 }
11288
11289 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11290 {
11291#define MAX_ARRAY_SIZE 64
11292 int i, array_size;
11293 char *p, *ch_str;
11294 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11295
11296 if(argc != 5)
11297 {
11298 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11299 exit(-1);
11300 }
11301 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11302
11303 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11304 {
11305 strtok_r(ch_str, ",", &p);
11306 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11307 }
11308 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11309 if(!array_size)
11310 array_size=1;//Need to print current channel statistics
11311 for(i=0; i<array_size; i++)
11312 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11313 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11314 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11315 input_output_channelStats_array[i].ch_number,\
11316 input_output_channelStats_array[i].ch_noise,\
11317 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11318 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11319 input_output_channelStats_array[i].ch_utilization_busy,\
11320 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11321 input_output_channelStats_array[i].ch_utilization_total);
11322 }
11323
11324 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11325 {
11326 if(argc <= 3 )
11327 {
11328 printf("Insufficient arguments \n");
11329 exit(-1);
11330 }
11331 char mac_addr[20] = {'\0'};
11332 wifi_device_t output_struct;
11333 int dev_index = atoi(argv[3]);
11334
11335 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11336 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11337 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);
11338 }
11339
11340 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11341 {
11342 if (argc <= 3)
11343 {
11344 printf("Insufficient arguments\n");
11345 exit(-1);
11346 }
11347 char args[256];
11348 wifi_NeighborReport_t *neighborReports;
11349
11350 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11351 if (!neighborReports)
11352 {
11353 printf("Failed to allocate memory");
11354 exit(-1);
11355 }
11356
11357 for (int i = 3; i < argc; ++i)
11358 {
11359 char *val;
11360 int j = 0;
11361 memset(args, 0, sizeof(args));
11362 strncpy(args, argv[i], sizeof(args));
11363 val = strtok(args, ";");
11364 while (val != NULL)
11365 {
11366 if (j == 0)
11367 {
11368 mac_addr_aton(neighborReports[i - 3].bssid, val);
11369 } else if (j == 1)
11370 {
11371 neighborReports[i - 3].info = strtol(val, NULL, 16);
11372 } else if (j == 2)
11373 {
11374 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11375 } else if (j == 3)
11376 {
11377 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11378 } else if (j == 4)
11379 {
11380 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11381 } else {
11382 printf("Insufficient arguments]n\n");
11383 exit(-1);
11384 }
11385 val = strtok(NULL, ";");
11386 j++;
11387 }
11388 }
11389
11390 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11391 if (ret != RETURN_OK)
11392 {
11393 printf("wifi_setNeighborReports ret = %d", ret);
11394 exit(-1);
11395 }
11396 }
11397 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11398 {
11399 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11400 printf("%s.\n", buf);
11401 else
11402 printf("Error returned\n");
11403 }
11404 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11405 {
11406 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11407 printf("%s.\n", buf);
11408 else
11409 printf("Error returned\n");
11410 }
11411 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11412 {
11413 if (argc <= 2)
11414 {
11415 printf("Insufficient arguments\n");
11416 exit(-1);
11417 }
11418 char buf[64]= {'\0'};
11419 wifi_getRadioOperatingChannelBandwidth(index,buf);
11420 printf("Current bandwidth is %s \n",buf);
11421 return 0;
11422 }
11423 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11424 {
11425 if (argc <= 5)
11426 {
11427 printf("Insufficient arguments\n");
11428 exit(-1);
11429 }
11430 UINT channel = atoi(argv[3]);
11431 UINT width = atoi(argv[4]);
11432 UINT beacon = atoi(argv[5]);
11433 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11434 printf("Result = %d", ret);
11435 }
11436
11437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11438 return 0;
11439}
11440
11441#endif
11442
11443#ifdef WIFI_HAL_VERSION_3
11444
developer1e5aa162022-09-13 16:06:24 +080011445INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11446{
11447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11448 if (bitMap & WIFI_BITRATE_1MBPS)
11449 strcat(BasicRate, "1,");
11450 if (bitMap & WIFI_BITRATE_2MBPS)
11451 strcat(BasicRate, "2,");
11452 if (bitMap & WIFI_BITRATE_5_5MBPS)
11453 strcat(BasicRate, "5.5,");
11454 if (bitMap & WIFI_BITRATE_6MBPS)
11455 strcat(BasicRate, "6,");
11456 if (bitMap & WIFI_BITRATE_9MBPS)
11457 strcat(BasicRate, "9,");
11458 if (bitMap & WIFI_BITRATE_11MBPS)
11459 strcat(BasicRate, "11,");
11460 if (bitMap & WIFI_BITRATE_12MBPS)
11461 strcat(BasicRate, "12,");
11462 if (bitMap & WIFI_BITRATE_18MBPS)
11463 strcat(BasicRate, "18,");
11464 if (bitMap & WIFI_BITRATE_24MBPS)
11465 strcat(BasicRate, "24,");
11466 if (bitMap & WIFI_BITRATE_36MBPS)
11467 strcat(BasicRate, "36,");
11468 if (bitMap & WIFI_BITRATE_48MBPS)
11469 strcat(BasicRate, "48,");
11470 if (bitMap & WIFI_BITRATE_54MBPS)
11471 strcat(BasicRate, "54,");
11472 if (strlen(BasicRate) != 0) // remove last comma
11473 BasicRate[strlen(BasicRate) - 1] = '\0';
11474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11475 return RETURN_OK;
11476}
11477
11478INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11479{
11480 UINT BitMap = 0;
11481 char *rate;
11482
11483 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11484 rate = strtok(BasicRatesList, ",");
11485 while(rate != NULL)
11486 {
11487 if (strcmp(rate, "1") == 0)
11488 BitMap |= WIFI_BITRATE_1MBPS;
11489 else if (strcmp(rate, "2") == 0)
11490 BitMap |= WIFI_BITRATE_2MBPS;
11491 else if (strcmp(rate, "5.5") == 0)
11492 BitMap |= WIFI_BITRATE_5_5MBPS;
11493 else if (strcmp(rate, "6") == 0)
11494 BitMap |= WIFI_BITRATE_6MBPS;
11495 else if (strcmp(rate, "9") == 0)
11496 BitMap |= WIFI_BITRATE_9MBPS;
11497 else if (strcmp(rate, "11") == 0)
11498 BitMap |= WIFI_BITRATE_11MBPS;
11499 else if (strcmp(rate, "12") == 0)
11500 BitMap |= WIFI_BITRATE_12MBPS;
11501 else if (strcmp(rate, "18") == 0)
11502 BitMap |= WIFI_BITRATE_18MBPS;
11503 else if (strcmp(rate, "24") == 0)
11504 BitMap |= WIFI_BITRATE_24MBPS;
11505 else if (strcmp(rate, "36") == 0)
11506 BitMap |= WIFI_BITRATE_36MBPS;
11507 else if (strcmp(rate, "48") == 0)
11508 BitMap |= WIFI_BITRATE_48MBPS;
11509 else if (strcmp(rate, "54") == 0)
11510 BitMap |= WIFI_BITRATE_54MBPS;
11511 rate = strtok(NULL, ",");
11512 }
11513 *basicRateBitMap = BitMap;
11514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11515 return RETURN_OK;
11516}
11517
11518// 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 +080011519INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11520{
developer1e5aa162022-09-13 16:06:24 +080011521 char buf[128] = {0};
11522 char cmd[128] = {0};
11523 char config_file[64] = {0};
11524 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011525 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011526 wifi_radio_operationParam_t current_param;
11527
11528 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11529
11530 multiple_set = TRUE;
11531 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11532 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11533 return RETURN_ERR;
11534 }
11535 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11536 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11537 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11538 return RETURN_ERR;
11539 }
11540 }
developer5884e982022-10-06 10:52:50 +080011541
11542 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11543 bandwidth = 20;
11544 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11545 bandwidth = 40;
11546 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11547 bandwidth = 80;
11548 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11549 bandwidth = 160;
11550 if (operationParam->autoChannelEnabled){
11551 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11552 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11553 return RETURN_ERR;
11554 }
11555 }else{
developer1e5aa162022-09-13 16:06:24 +080011556 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11557 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11558 return RETURN_ERR;
11559 }
11560 }
developer5884e982022-10-06 10:52:50 +080011561
developer1e5aa162022-09-13 16:06:24 +080011562 if (current_param.variant != operationParam->variant) {
11563 // Two different definition bit map, so need to check every bit.
11564 if (operationParam->variant & WIFI_80211_VARIANT_A)
11565 set_mode |= WIFI_MODE_A;
11566 if (operationParam->variant & WIFI_80211_VARIANT_B)
11567 set_mode |= WIFI_MODE_B;
11568 if (operationParam->variant & WIFI_80211_VARIANT_G)
11569 set_mode |= WIFI_MODE_G;
11570 if (operationParam->variant & WIFI_80211_VARIANT_N)
11571 set_mode |= WIFI_MODE_N;
11572 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11573 set_mode |= WIFI_MODE_AC;
11574 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11575 set_mode |= WIFI_MODE_AX;
11576 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11577 memset(buf, 0, sizeof(buf));
11578 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11579 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11580 return RETURN_ERR;
11581 }
11582 }
11583 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11584 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11585 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11586 return RETURN_ERR;
11587 }
11588 }
11589 if (current_param.beaconInterval != operationParam->beaconInterval) {
11590 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11591 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11592 return RETURN_ERR;
11593 }
11594 }
11595 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11596 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11597 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11598 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11599 return RETURN_ERR;
11600 }
11601 }
11602 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11603 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11604 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11605 return RETURN_ERR;
11606 }
11607 }
11608 if (current_param.guardInterval != operationParam->guardInterval) {
11609 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11610 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11611 return RETURN_ERR;
11612 }
11613 }
11614 if (current_param.transmitPower != operationParam->transmitPower) {
11615 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11616 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11617 return RETURN_ERR;
11618 }
11619 }
11620 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11621 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11622 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11623 return RETURN_ERR;
11624 }
11625 }
11626 if (current_param.obssCoex != operationParam->obssCoex) {
11627 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11628 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11629 return RETURN_ERR;
11630 }
11631 }
11632 if (current_param.stbcEnable != operationParam->stbcEnable) {
11633 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11634 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11635 return RETURN_ERR;
11636 }
11637 }
11638 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11639 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11640 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11641 return RETURN_ERR;
11642 }
11643 }
11644
11645 // if enable is true, then restart the radio
11646 wifi_setRadioEnable(index, FALSE);
11647 if (operationParam->enable == TRUE)
11648 wifi_setRadioEnable(index, TRUE);
11649 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11650
developer06a01d92022-09-07 16:32:39 +080011651 return RETURN_OK;
11652}
11653
11654INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11655{
developer1e5aa162022-09-13 16:06:24 +080011656 char band[64] = {0};
11657 char buf[256] = {0};
11658 char config_file[64] = {0};
11659 char cmd[128] = {0};
11660 int ret = RETURN_ERR;
11661 int mode = 0;
11662 ULONG channel = 0;
11663 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011664
11665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11666 printf("Entering %s index = %d\n", __func__, (int)index);
11667
developer1e5aa162022-09-13 16:06:24 +080011668 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11669 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11670 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011671 {
developer1e5aa162022-09-13 16:06:24 +080011672 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011673 return RETURN_ERR;
11674 }
11675 operationParam->enable = enabled;
11676
11677 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011678 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011679 {
developer1e5aa162022-09-13 16:06:24 +080011680 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011681 return RETURN_ERR;
11682 }
11683
11684 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011685 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011686 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011687 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011688 else if (!strcmp(band, "6GHz"))
11689 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011690 else
11691 {
developer1e5aa162022-09-13 16:06:24 +080011692 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011693 band);
11694 }
11695
developer1e5aa162022-09-13 16:06:24 +080011696 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11697 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11698 operationParam->channel = 0;
11699 operationParam->autoChannelEnabled = TRUE;
11700 } else {
11701 operationParam->channel = strtol(buf, NULL, 10);
11702 operationParam->autoChannelEnabled = FALSE;
11703 }
11704
developer06a01d92022-09-07 16:32:39 +080011705 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011706 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11707 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11708 return RETURN_ERR;
11709 }
developer06a01d92022-09-07 16:32:39 +080011710 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11711 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11712 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011713 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11714 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011715 else
11716 {
developer1e5aa162022-09-13 16:06:24 +080011717 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11718 return false;
developer06a01d92022-09-07 16:32:39 +080011719 }
11720
developer1e5aa162022-09-13 16:06:24 +080011721 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11722 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11723 return RETURN_ERR;
11724 }
11725 // Two different definition bit map, so need to check every bit.
11726 if (mode & WIFI_MODE_A)
11727 operationParam->variant |= WIFI_80211_VARIANT_A;
11728 if (mode & WIFI_MODE_B)
11729 operationParam->variant |= WIFI_80211_VARIANT_B;
11730 if (mode & WIFI_MODE_G)
11731 operationParam->variant |= WIFI_80211_VARIANT_G;
11732 if (mode & WIFI_MODE_N)
11733 operationParam->variant |= WIFI_80211_VARIANT_N;
11734 if (mode & WIFI_MODE_AC)
11735 operationParam->variant |= WIFI_80211_VARIANT_AC;
11736 if (mode & WIFI_MODE_AX)
11737 operationParam->variant |= WIFI_80211_VARIANT_AX;
11738 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11739 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11740 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011741 }
developer1e5aa162022-09-13 16:06:24 +080011742 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11743 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11744 return RETURN_ERR;
11745 }
11746 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11747 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11748 return RETURN_ERR;
11749 }
developer06a01d92022-09-07 16:32:39 +080011750
developer1e5aa162022-09-13 16:06:24 +080011751 memset(buf, 0, sizeof(buf));
11752 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11753 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11754 return RETURN_ERR;
11755 }
11756 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11757
11758 memset(buf, 0, sizeof(buf));
11759 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11760 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11761 return RETURN_ERR;
11762 }
11763 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11764
11765 memset(buf, 0, sizeof(buf));
11766 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11767 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11768
11769 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11770 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11771 return RETURN_ERR;
11772 }
11773 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11774 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11775 return RETURN_ERR;
11776 }
11777
11778 memset(buf, 0, sizeof(buf));
11779 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11780 if (strcmp(buf, "-1") == 0) {
11781 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11782 operationParam->ctsProtection = FALSE;
11783 } else {
11784 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11785 operationParam->ctsProtection = TRUE;
11786 }
11787
11788 memset(buf, 0, sizeof(buf));
11789 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11790 if (strcmp(buf, "0") == 0)
11791 operationParam->obssCoex = FALSE;
11792 else
11793 operationParam->obssCoex = TRUE;
11794
11795 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11796 _syscmd(cmd, buf, sizeof(buf));
11797 if (strlen(buf) != 0)
11798 operationParam->stbcEnable = TRUE;
11799 else
11800 operationParam->stbcEnable = FALSE;
11801
11802 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11803 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11804 return RETURN_ERR;
11805 }
11806
11807 // Below value is hardcoded
11808
11809 operationParam->numSecondaryChannels = 0;
11810 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11811 operationParam->channelSecondary[i] = 0;
11812 }
11813 operationParam->csa_beacon_count = 15;
11814 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011815
11816 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11817 return RETURN_OK;
11818}
11819
11820static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11821{
developerc086fb72022-10-04 10:18:22 +080011822 int max_radio_num = 0;
11823
11824 wifi_getMaxRadioNumber(&max_radio_num);
11825 if (radioIndex >= max_radio_num || radioIndex < 0) {
11826 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11827 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011828 }
11829
developerc086fb72022-10-04 10:18:22 +080011830 return (arrayIndex * max_radio_num) + radioIndex;
11831}
developer06a01d92022-09-07 16:32:39 +080011832
developerc086fb72022-10-04 10:18:22 +080011833wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11834 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11835 return WIFI_BITRATE_1MBPS;
11836 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11837 return WIFI_BITRATE_2MBPS;
11838 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11839 return WIFI_BITRATE_5_5MBPS;
11840 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11841 return WIFI_BITRATE_6MBPS;
11842 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11843 return WIFI_BITRATE_9MBPS;
11844 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11845 return WIFI_BITRATE_11MBPS;
11846 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11847 return WIFI_BITRATE_12MBPS;
11848 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11849 return WIFI_BITRATE_18MBPS;
11850 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11851 return WIFI_BITRATE_24MBPS;
11852 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11853 return WIFI_BITRATE_36MBPS;
11854 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11855 return WIFI_BITRATE_48MBPS;
11856 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11857 return WIFI_BITRATE_54MBPS;
11858 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011859}
11860
developer1d57d002022-10-12 18:03:15 +080011861INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
11862{
11863 if (beacon == WIFI_BITRATE_1MBPS)
11864 strcpy(beacon_str, "1Mbps");
11865 else if (beacon == WIFI_BITRATE_2MBPS)
11866 strcpy(beacon_str, "2Mbps");
11867 else if (beacon == WIFI_BITRATE_5_5MBPS)
11868 strcpy(beacon_str, "5.5Mbps");
11869 else if (beacon == WIFI_BITRATE_6MBPS)
11870 strcpy(beacon_str, "6Mbps");
11871 else if (beacon == WIFI_BITRATE_9MBPS)
11872 strcpy(beacon_str, "9Mbps");
11873 else if (beacon == WIFI_BITRATE_11MBPS)
11874 strcpy(beacon_str, "11Mbps");
11875 else if (beacon == WIFI_BITRATE_12MBPS)
11876 strcpy(beacon_str, "12Mbps");
11877 else if (beacon == WIFI_BITRATE_18MBPS)
11878 strcpy(beacon_str, "18Mbps");
11879 else if (beacon == WIFI_BITRATE_24MBPS)
11880 strcpy(beacon_str, "24Mbps");
11881 else if (beacon == WIFI_BITRATE_36MBPS)
11882 strcpy(beacon_str, "36Mbps");
11883 else if (beacon == WIFI_BITRATE_48MBPS)
11884 strcpy(beacon_str, "48Mbps");
11885 else if (beacon == WIFI_BITRATE_54MBPS)
11886 strcpy(beacon_str, "54Mbps");
11887 return RETURN_OK;
11888}
11889
developer06a01d92022-09-07 16:32:39 +080011890INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11891{
developerc086fb72022-10-04 10:18:22 +080011892 INT mode = 0;
11893 INT ret = -1;
11894 INT output = 0;
11895 int i = 0;
11896 int vap_index = 0;
11897 BOOL enabled = FALSE;
11898 char buf[256] = {0};
11899 wifi_vap_security_t security;
11900 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011901
11902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11903 printf("Entering %s index = %d\n", __func__, (int)index);
11904
developer06a01d92022-09-07 16:32:39 +080011905 for (i = 0; i < 5; i++)
11906 {
developerc086fb72022-10-04 10:18:22 +080011907 map->vap_array[i].radio_index = index;
11908
developer06a01d92022-09-07 16:32:39 +080011909 vap_index = array_index_to_vap_index(index, i);
11910 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011911 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011912
developerc086fb72022-10-04 10:18:22 +080011913 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011914
11915 map->vap_array[i].vap_index = vap_index;
11916
11917 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011918 ret = wifi_getApName(vap_index, buf);
11919 if (ret != RETURN_OK) {
11920 printf("%s: wifi_getApName return error\n", __func__);
11921 return RETURN_ERR;
11922 }
11923 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
11924
11925 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080011926 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080011927 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080011928 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080011929 return RETURN_ERR;
11930 }
11931 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 +080011932
11933 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080011934 if (ret != RETURN_OK) {
11935 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011936 return RETURN_ERR;
11937 }
11938 map->vap_array[i].u.bss_info.enabled = enabled;
11939
developerc086fb72022-10-04 10:18:22 +080011940 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
11941 if (ret != RETURN_OK) {
11942 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
11943 return RETURN_ERR;
11944 }
developer06a01d92022-09-07 16:32:39 +080011945 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080011946
11947 ret = wifi_getApIsolationEnable(vap_index, &enabled);
11948 if (ret != RETURN_OK) {
11949 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
11950 return RETURN_ERR;
11951 }
11952 map->vap_array[i].u.bss_info.isolation = enabled;
11953
11954 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
11955 if (ret != RETURN_OK) {
11956 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
11957 return RETURN_ERR;
11958 }
11959 map->vap_array[i].u.bss_info.bssMaxSta = output;
11960
11961 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
11962 if (ret != RETURN_OK) {
11963 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
11964 return RETURN_ERR;
11965 }
11966 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011967
developerc086fb72022-10-04 10:18:22 +080011968 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
11969 if (ret != RETURN_OK) {
11970 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
11971 return RETURN_ERR;
11972 }
11973 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011974
developerc086fb72022-10-04 10:18:22 +080011975 ret = wifi_getApSecurity(vap_index, &security);
11976 if (ret != RETURN_OK) {
11977 printf("%s: wifi_getApSecurity return error\n", __func__);
11978 return RETURN_ERR;
11979 }
11980 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080011981
developerc086fb72022-10-04 10:18:22 +080011982 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
11983 if (ret != RETURN_OK) {
11984 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
11985 return RETURN_ERR;
11986 }
11987 if (mode == 0)
11988 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
11989 else
11990 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
11991 if (mode == 1)
11992 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11993 else if (mode == 2)
11994 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080011995
developerc086fb72022-10-04 10:18:22 +080011996 ret = wifi_getApWmmEnable(vap_index, &enabled);
11997 if (ret != RETURN_OK) {
11998 printf("%s: wifi_getApWmmEnable return error\n", __func__);
11999 return RETURN_ERR;
12000 }
12001 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012002
developerc086fb72022-10-04 10:18:22 +080012003 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12004 if (ret != RETURN_OK) {
12005 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012006 return RETURN_ERR;
12007 }
developerc086fb72022-10-04 10:18:22 +080012008 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012009
12010 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012011 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012012 if (ret != RETURN_OK) {
12013 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12014 return RETURN_ERR;
12015 }
12016 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012017
developerc086fb72022-10-04 10:18:22 +080012018 memset(buf, 0, sizeof(buf));
12019 ret = wifi_getBaseBSSID(vap_index, buf);
12020 if (ret != RETURN_OK) {
12021 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12022 return RETURN_ERR;
12023 }
12024 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12025 &map->vap_array[i].u.bss_info.bssid[0],
12026 &map->vap_array[i].u.bss_info.bssid[1],
12027 &map->vap_array[i].u.bss_info.bssid[2],
12028 &map->vap_array[i].u.bss_info.bssid[3],
12029 &map->vap_array[i].u.bss_info.bssid[4],
12030 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012031 // 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]);
12032
12033 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12034 if (ret != RETURN_OK) {
12035 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12036 return RETURN_ERR;
12037 }
12038 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012039
developerc086fb72022-10-04 10:18:22 +080012040 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012041 }
12042 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12043 return RETURN_OK;
12044}
12045
12046INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12047{
12048 unsigned int i;
12049 wifi_vap_info_t *vap_info = NULL;
12050 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012051 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012052 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012053 char buf[256] = {0};
12054 char cmd[128] = {0};
12055 char config_file[64] = {0};
12056 char bssid[32] = {0};
12057 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012058
12059 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12060 printf("Entering %s index = %d\n", __func__, (int)index);
12061 for (i = 0; i < map->num_vaps; i++)
12062 {
developer1d57d002022-10-12 18:03:15 +080012063 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012064 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012065 if (vap_info->u.bss_info.enabled == FALSE)
12066 continue;
developer06a01d92022-09-07 16:32:39 +080012067
developer1d57d002022-10-12 18:03:15 +080012068 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12069
12070 // multi-ap need to copy current radio config
12071 if (vap_info->radio_index != vap_info->vap_index) {
12072 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12073 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012074 }
developer06a01d92022-09-07 16:32:39 +080012075
developer1d57d002022-10-12 18:03:15 +080012076 struct params params[3];
12077 snprintf(vap_info->vap_name, 64, "%s%d", AP_PREFIX, vap_info->vap_index);
12078 params[0].name = "interface";
12079 params[0].value = vap_info->vap_name;
12080 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12081 params[1].name = "bssid";
12082 params[1].value = bssid;
12083 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12084 params[2].name = "wpa_psk_file";
12085 params[2].value = psk_file;
12086
12087 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12088 wifi_hostapdWrite(config_file, params, 3);
12089
12090 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12091 _syscmd(cmd, buf, sizeof(buf));
12092
12093 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12094 if (ret != RETURN_OK) {
12095 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12096 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012097 }
developer1d57d002022-10-12 18:03:15 +080012098
12099 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12100 if (ret != RETURN_OK) {
12101 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12102 return RETURN_ERR;
12103 }
12104
12105 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12106 if (ret != RETURN_OK) {
12107 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12108 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012109 }
12110
developer1d57d002022-10-12 18:03:15 +080012111 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12112 if (ret != RETURN_OK) {
12113 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12114 return RETURN_ERR;
12115 }
developer06a01d92022-09-07 16:32:39 +080012116
developer1d57d002022-10-12 18:03:15 +080012117 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12118 if (ret != RETURN_OK) {
12119 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12120 return RETURN_ERR;
12121 }
developer06a01d92022-09-07 16:32:39 +080012122
developer1d57d002022-10-12 18:03:15 +080012123 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12124 if (ret != RETURN_OK) {
12125 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12126 return RETURN_ERR;
12127 }
12128
12129 if (vap_info->u.bss_info.mac_filter_enable == false)
12130 acl_mode = 0;
12131 else {
12132 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list)
12133 acl_mode = 2;
12134 else
12135 acl_mode = 1;
12136 }
12137
12138 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12139 if (ret != RETURN_OK) {
12140 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12141 return RETURN_ERR;
12142 }
12143
12144 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12145 if (ret != RETURN_OK) {
12146 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12147 return RETURN_ERR;
12148 }
12149
12150 memset(buf, 0, sizeof(buf));
12151 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12152 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12153 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12154 if (ret != RETURN_OK) {
12155 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12156 return RETURN_ERR;
12157 }
12158
12159 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12160 if (ret != RETURN_OK) {
12161 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12162 return RETURN_ERR;
12163 }
12164
12165 wifi_setApEnable(vap_info->vap_index, TRUE);
12166 multiple_set = FALSE;
12167
12168 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12169 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12170 if (ret != RETURN_OK) {
12171 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12172 return RETURN_ERR;
12173 }
12174
12175 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12176 if (ret != RETURN_OK) {
12177 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12178 return RETURN_ERR;
12179 }
developer06a01d92022-09-07 16:32:39 +080012180
developer1d57d002022-10-12 18:03:15 +080012181 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012182 }
12183 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12184 return RETURN_OK;
12185}
12186
12187int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12188{
12189 char *token, *next;
12190 const char s[2] = ",";
12191 int count =0;
12192
12193 /* get the first token */
12194 token = strtok_r(pchannels, s, &next);
12195
12196 /* walk through other tokens */
12197 while( token != NULL && count < MAX_CHANNELS) {
12198 chlistptr->channels_list[count++] = atoi(token);
12199 token = strtok_r(NULL, s, &next);
12200 }
12201
12202 return count;
12203}
12204
12205static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12206{
12207 INT status;
12208 wifi_channels_list_t *chlistp;
12209 CHAR output_string[64];
12210 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012211 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080012212
12213 if(rcap == NULL)
12214 {
12215 return RETURN_ERR;
12216 }
12217
12218 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012219 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012220
developer1e5aa162022-09-13 16:06:24 +080012221 if (band == band_2_4)
12222 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12223 else if (band == band_5)
12224 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12225 else if (band == band_6)
12226 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012227
12228 chlistp = &(rcap->channel_list[0]);
12229 memset(pchannels, 0, sizeof(pchannels));
12230
12231 /* possible number of radio channels */
12232 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12233 {
12234 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12235 }
12236 /* Number of channels and list*/
12237 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12238
12239 /* autoChannelSupported */
12240 /* always ON with wifi_getRadioAutoChannelSupported */
12241 rcap->autoChannelSupported = TRUE;
12242
12243 /* DCSSupported */
12244 /* always ON with wifi_getRadioDCSSupported */
12245 rcap->DCSSupported = TRUE;
12246
12247 /* zeroDFSSupported - TBD */
12248 rcap->zeroDFSSupported = FALSE;
12249
12250 /* Supported Country List*/
12251 memset(output_string, 0, sizeof(output_string));
12252 status = wifi_getRadioCountryCode(radioIndex, output_string);
12253 if( status != 0 ) {
12254 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12255 return RETURN_ERR;
12256 } else {
12257 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12258 }
12259 if(!strcmp(output_string,"US")){
12260 rcap->countrySupported[0] = wifi_countrycode_US;
12261 rcap->countrySupported[1] = wifi_countrycode_CA;
12262 } else if (!strcmp(output_string,"CA")) {
12263 rcap->countrySupported[0] = wifi_countrycode_CA;
12264 rcap->countrySupported[1] = wifi_countrycode_US;
12265 } else {
12266 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12267 }
12268
12269 rcap->numcountrySupported = 2;
12270
12271 /* csi */
12272 rcap->csi.maxDevices = 8;
12273 rcap->csi.soudingFrameSupported = TRUE;
12274
12275 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
12276
12277 /* channelWidth - all supported bandwidths */
12278 int i=0;
12279 rcap->channelWidth[i] = 0;
12280 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12281 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12282 WIFI_CHANNELBANDWIDTH_40MHZ);
12283
12284 }
developer1e5aa162022-09-13 16:06:24 +080012285 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012286 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12287 WIFI_CHANNELBANDWIDTH_40MHZ |
12288 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12289 }
12290
12291
12292 /* mode - all supported variants */
12293 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12294 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012295 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 +080012296 }
12297 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012298 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12299 }
12300 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12301 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012302 }
12303 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12304 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12305
12306 /* supportedBitRate - all supported bitrates */
12307 rcap->supportedBitRate[i] = 0;
12308 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12309 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12310 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12311 }
developer1e5aa162022-09-13 16:06:24 +080012312 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012313 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12314 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12315 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12316 }
12317
12318
12319 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12320 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12321 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12322 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12323 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12324 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12325 rcap->cipherSupported = 0;
12326 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12327 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12328
12329 return RETURN_OK;
12330}
12331
12332INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12333{
12334 INT status, radioIndex;
12335 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12336 int iter = 0;
12337 unsigned int j;
12338 wifi_interface_name_idex_map_t *iface_info;
12339
12340 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12341
12342 memset(cap, 0, sizeof(wifi_hal_capability_t));
12343
12344 /* version */
12345 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12346 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12347
12348 /* number of radios platform property */
12349 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12350 _syscmd(cmd, output, sizeof(output));
12351 cap->wifi_prop.numRadios = atoi(output);
12352
12353 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12354 {
12355 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12356 if (status != 0) {
12357 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12358 return RETURN_ERR;
12359 }
12360
12361 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12362 {
12363 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12364 {
12365 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12366 return RETURN_ERR;
12367 }
12368 iface_info = &cap->wifi_prop.interface_map[iter];
12369 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12370 iface_info->rdk_radio_index = radioIndex;
12371 memset(output, 0, sizeof(output));
12372 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12373 {
12374 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12375 }
12376 // TODO: bridge name
12377 // TODO: vlan id
12378 // TODO: primary
12379 iface_info->index = array_index_to_vap_index(radioIndex, j);
12380 memset(output, 0, sizeof(output));
12381 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12382 {
12383 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12384 }
12385 iter++;
12386 }
12387 }
12388
12389 cap->BandSteeringSupported = FALSE;
12390 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12391 return RETURN_OK;
12392}
12393
developer9df4e652022-10-11 11:27:38 +080012394INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12395{
12396 struct params h_config={0};
12397 char config_file[64] = {0};
12398
12399 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12400
12401 h_config.name = "okc";
12402 h_config.value = okc_enable?"1":"0";
12403
12404 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12405 wifi_hostapdWrite(config_file, &h_config, 1);
12406 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12407
12408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12409 return RETURN_OK;
12410}
12411
12412INT wifi_setSAEMFP(int ap_index, BOOL enable)
12413{
12414 struct params h_config={0};
12415 char config_file[64] = {0};
12416 char buf[128] = {0};
12417
12418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12419
12420 h_config.name = "sae_require_mfp";
12421 h_config.value = enable?"1":"0";
12422
12423 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12424 wifi_hostapdWrite(config_file, &h_config, 1);
12425 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12426
12427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12428 return RETURN_OK;
12429}
12430
12431INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12432{
12433 struct params h_config={0};
12434 char config_file[64] = {0};
12435 char buf[128] = {0};
12436
12437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12438
12439 h_config.name = "sae_pwe";
12440 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12441 h_config.value = buf;
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_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12452{
12453 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12454 struct params h_config={0};
12455 char config_file[64] = {0};
12456
12457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12458
12459 h_config.name = "wpa_disable_eapol_key_retries";
12460 h_config.value = disable_EAPOL_retries?"1":"0";
12461
12462 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12463 wifi_hostapdWrite(config_file, &h_config, 1);
12464 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12465
12466 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12467 return RETURN_OK;
12468}
12469
developer06a01d92022-09-07 16:32:39 +080012470INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12471{
developer587c1b62022-09-27 15:58:59 +080012472 char buf[128] = {0};
12473 char config_file[128] = {0};
12474 char password[64] = {0};
12475 char mfp[32] = {0};
12476 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012477 BOOL okc_enable = FALSE;
12478 BOOL sae_MFP = FALSE;
12479 BOOL disable_EAPOL_retries = TRUE;
12480 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012481 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012482 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012483
12484 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12485
12486 multiple_set = TRUE;
12487 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12488 if (security->mode == wifi_security_mode_none) {
12489 strcpy(wpa_mode, "None");
12490 } else if (security->mode == wifi_security_mode_wpa_personal)
12491 strcpy(wpa_mode, "WPA-Personal");
12492 else if (security->mode == wifi_security_mode_wpa2_personal)
12493 strcpy(wpa_mode, "WPA2-Personal");
12494 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12495 strcpy(wpa_mode, "WPA-WPA2-Personal");
12496 else if (security->mode == wifi_security_mode_wpa_enterprise)
12497 strcpy(wpa_mode, "WPA-Enterprise");
12498 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12499 strcpy(wpa_mode, "WPA2-Enterprise");
12500 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12501 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012502 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012503 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012504 okc_enable = TRUE;
12505 sae_MFP = TRUE;
12506 sae_pwe = 2;
12507 disable_EAPOL_retries = FALSE;
12508 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012509 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012510 okc_enable = TRUE;
12511 sae_MFP = TRUE;
12512 sae_pwe = 2;
12513 disable_EAPOL_retries = FALSE;
12514 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012515 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012516 sae_MFP = TRUE;
12517 sae_pwe = 2;
12518 disable_EAPOL_retries = FALSE;
12519 }
12520
12521 band = wifi_index_to_band(ap_index);
12522 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12523 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12524 return RETURN_ERR;
12525 }
developer587c1b62022-09-27 15:58:59 +080012526
12527 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012528 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012529 wifi_setSAEMFP(ap_index, sae_MFP);
12530 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012531 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012532
developer9df4e652022-10-11 11:27:38 +080012533 if (security->mode != wifi_security_mode_none) {
12534 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12535 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12536 password[63] = '\0';
12537 wifi_setApSecurityKeyPassphrase(ap_index, password);
12538 }
12539 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12540 params.name = "sae_password";
12541 params.value = security->u.key.key;
12542 wifi_hostapdWrite(config_file, &params, 1);
12543 }
12544 }
developer587c1b62022-09-27 15:58:59 +080012545
12546 if (security->mode != wifi_security_mode_none) {
12547 memset(&params, 0, sizeof(params));
12548 params.name = "wpa_pairwise";
12549 if (security->encr == wifi_encryption_tkip)
12550 params.value = "TKIP";
12551 else if (security->encr == wifi_encryption_aes)
12552 params.value = "CCMP";
12553 else if (security->encr == wifi_encryption_aes_tkip)
12554 params.value = "TKIP CCMP";
12555 wifi_hostapdWrite(config_file, &params, 1);
12556 }
12557
12558 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012559 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012560 else if (security->mfp == wifi_mfp_cfg_optional)
12561 strcpy(mfp, "Optional");
12562 else if (security->mfp == wifi_mfp_cfg_required)
12563 strcpy(mfp, "Required");
12564 wifi_setApSecurityMFPConfig(ap_index, mfp);
12565
12566 memset(&params, 0, sizeof(params));
12567 params.name = "transition_disable";
12568 if (security->wpa3_transition_disable == TRUE)
12569 params.value = "0x01";
12570 else
12571 params.value = "0x00";
12572 wifi_hostapdWrite(config_file, &params, 1);
12573
12574 memset(&params, 0, sizeof(params));
12575 params.name = "wpa_group_rekey";
12576 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12577 params.value = buf;
12578 wifi_hostapdWrite(config_file, &params, 1);
12579
12580 memset(&params, 0, sizeof(params));
12581 params.name = "wpa_strict_rekey";
12582 params.value = security->strict_rekey?"1":"0";
12583 wifi_hostapdWrite(config_file, &params, 1);
12584
12585 memset(&params, 0, sizeof(params));
12586 params.name = "wpa_pairwise_update_count";
12587 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12588 params.value = buf;
12589 wifi_hostapdWrite(config_file, &params, 1);
12590
12591 memset(&params, 0, sizeof(params));
12592 params.name = "disable_pmksa_caching";
12593 params.value = security->disable_pmksa_caching?"1":"0";
12594 wifi_hostapdWrite(config_file, &params, 1);
12595
12596 wifi_setApEnable(ap_index, FALSE);
12597 wifi_setApEnable(ap_index, TRUE);
12598
12599 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12600
developer06a01d92022-09-07 16:32:39 +080012601 return RETURN_OK;
12602}
12603
12604INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12605{
developer9df4e652022-10-11 11:27:38 +080012606 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012607 char config_file[128] = {0};
12608 int disable = 0;
12609 // struct params params = {0};
12610
12611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12612 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12613 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12614 security->mode = wifi_security_mode_none;
12615 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012616 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012617 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012618 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012619 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012620 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012621 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012622 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012623 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012624 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012625 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012626 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012627 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012628 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012629 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012630 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012631 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012632 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012633 security->mode = wifi_security_mode_wpa3_enterprise;
12634 }
12635
12636 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12637 if (security->mode == wifi_security_mode_none)
12638 security->encr = wifi_encryption_none;
12639 else {
12640 if (strcmp(buf, "TKIP") == 0)
12641 security->encr = wifi_encryption_tkip;
12642 else if (strcmp(buf, "CCMP") == 0)
12643 security->encr = wifi_encryption_aes;
12644 else
12645 security->encr = wifi_encryption_aes_tkip;
12646 }
12647
developer9df4e652022-10-11 11:27:38 +080012648 if (security->mode != wifi_encryption_none) {
12649 memset(buf, 0, sizeof(buf));
12650 // wpa3 can use one or both configs as password, so we check sae_password first.
12651 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12652 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12653 security->u.key.type = wifi_security_key_type_sae;
12654 } else {
12655 security->u.key.type = wifi_security_key_type_psk;
12656 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12657 }
12658 strncpy(security->u.key.key, buf, sizeof(buf));
12659 security->u.key.key[255] = '\0';
12660 }
12661
developer587c1b62022-09-27 15:58:59 +080012662 memset(buf, 0, sizeof(buf));
12663 wifi_getApSecurityMFPConfig(ap_index, buf);
12664 if (strcmp(buf, "Disabled") == 0)
12665 security->mfp = wifi_mfp_cfg_disabled;
12666 else if (strcmp(buf, "Optional") == 0)
12667 security->mfp = wifi_mfp_cfg_optional;
12668 else if (strcmp(buf, "Required") == 0)
12669 security->mfp = wifi_mfp_cfg_required;
12670
12671 memset(buf, 0, sizeof(buf));
12672 security->wpa3_transition_disable = FALSE;
12673 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12674 disable = strtol(buf, NULL, 16);
12675 if (disable != 0)
12676 security->wpa3_transition_disable = TRUE;
12677
12678 memset(buf, 0, sizeof(buf));
12679 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12680 if (strlen(buf) == 0)
12681 security->rekey_interval = 86400;
12682 else
12683 security->rekey_interval = strtol(buf, NULL, 10);
12684
12685 memset(buf, 0, sizeof(buf));
12686 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12687 if (strlen(buf) == 0)
12688 security->strict_rekey = 1;
12689 else
12690 security->strict_rekey = strtol(buf, NULL, 10);
12691
12692 memset(buf, 0, sizeof(buf));
12693 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12694 if (strlen(buf) == 0)
12695 security->eapol_key_retries = 4;
12696 else
12697 security->eapol_key_retries = strtol(buf, NULL, 10);
12698
12699 memset(buf, 0, sizeof(buf));
12700 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12701 if (strlen(buf) == 0)
12702 security->disable_pmksa_caching = FALSE;
12703 else
12704 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12705
12706 /* TODO
12707 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12708 */
12709 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12710 security->eap_identity_req_timeout = 0;
12711 security->eap_identity_req_retries = 0;
12712 security->eap_req_timeout = 0;
12713 security->eap_req_retries = 0;
12714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012715 return RETURN_OK;
12716}
12717
12718#endif /* WIFI_HAL_VERSION_3 */
12719
12720#ifdef WIFI_HAL_VERSION_3_PHASE2
12721INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12722{
developer13df9332022-09-27 16:53:22 +080012723 char cmd[128] = {0};
12724 char buf[128] = {0};
12725 char *mac_addr = NULL;
12726 BOOL status = FALSE;
12727 size_t len = 0;
12728
12729 if(ap_index > MAX_APS)
12730 return RETURN_ERR;
12731
12732 *output_numDevices = 0;
12733 wifi_getApEnable(ap_index, &status);
12734 if (status == FALSE)
12735 return RETURN_OK;
12736
12737 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12738 _syscmd(cmd, buf, sizeof(buf));
12739
12740 mac_addr = strtok(buf, "\n");
12741 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12742 *output_numDevices = i + 1;
12743 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12744 addr_ptr = output_deviceMacAddressArray[i];
12745 mac_addr_aton(addr_ptr, mac_addr);
12746 mac_addr = strtok(NULL, "\n");
12747 }
12748
12749 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012750}
12751#else
12752INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12753{
12754 char cmd[128];
12755 BOOL status = false;
12756
12757 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12758 return RETURN_ERR;
12759
12760 output_buf[0] = '\0';
12761
12762 wifi_getApEnable(ap_index,&status);
12763 if (!status)
12764 return RETURN_OK;
12765
12766 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12767 _syscmd(cmd, output_buf, output_buf_size);
12768
12769 return RETURN_OK;
12770}
12771#endif
developer2f513ab2022-09-13 14:26:06 +080012772
12773INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12774{
12775 char output[16]={'\0'};
12776 char config_file[MAX_BUF_SIZE] = {0};
12777
12778 if (!enable)
12779 return RETURN_ERR;
12780
12781 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12782 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12783
12784 if (strlen(output) == 0)
12785 *enable = FALSE;
12786 else if (strncmp(output, "1", 1) == 0)
12787 *enable = TRUE;
12788 else
12789 *enable = FALSE;
12790
12791 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12792 return RETURN_OK;
12793}
developer2d9c30f2022-09-13 15:06:14 +080012794
12795INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12796{
12797 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12798 return RETURN_ERR;
12799 *output_enable=TRUE;
12800 return RETURN_OK;
12801}
developerfd7d2892022-09-13 16:44:53 +080012802
12803INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12804{
12805 char cmd[128] = {0};
12806 char buf[128] = {0};
12807 char line[128] = {0};
12808 size_t len = 0;
12809 ssize_t read = 0;
12810 FILE *f = NULL;
12811 int index = 0;
12812 int exp = 0;
12813 int mantissa = 0;
12814 int duration = 0;
12815 int radio_index = 0;
12816 int max_radio_num = 0;
12817 uint twt_wake_interval = 0;
12818
12819 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12820
12821 wifi_getMaxRadioNumber(&max_radio_num);
12822 radio_index = ap_index % max_radio_num;
12823 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12824 _syscmd(cmd, buf, sizeof(buf));
12825 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12826 if (*numSessionReturned > maxNumberSessions)
12827 *numSessionReturned = maxNumberSessions;
12828 else if (*numSessionReturned < 1) {
12829 *numSessionReturned = 0;
12830 return RETURN_OK;
12831 }
12832
12833 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12834 if ((f = popen(cmd, "r")) == NULL) {
12835 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12836 return RETURN_ERR;
12837 }
12838
12839 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12840 while((read = fgets(line, sizeof(line), f)) != NULL) {
12841 char *tmp = NULL;
12842 strcpy(buf, line);
12843 tmp = strtok(buf, " ");
12844 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12845 tmp = strtok(NULL, " ");
12846 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12847 tmp = strtok(NULL, " ");
12848 if (strstr(tmp, "t")) {
12849 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12850 }
12851 if (strstr(tmp, "a")) {
12852 twtSessions[index].twtParameters.operation.announced = TRUE;
12853 }
12854 tmp = strtok(NULL, " ");
12855 exp = strtol(tmp, NULL, 10);
12856 tmp = strtok(NULL, " ");
12857 mantissa = strtol(tmp, NULL, 10);
12858 tmp = strtok(NULL, " ");
12859 duration = strtol(tmp, NULL, 10);
12860
12861 // only implicit supported
12862 twtSessions[index].twtParameters.operation.implicit = TRUE;
12863 // only individual agreement supported
12864 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12865
12866 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12867 twt_wake_interval = mantissa * (1 << exp);
12868 if (twt_wake_interval/mantissa != (1 << exp)) {
12869 // Overflow handling
12870 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12871 } else {
12872 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12873 }
12874 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12875 index++;
12876 }
12877
12878 pclose(f);
12879 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12880 return RETURN_OK;
12881}