blob: afb2dc21192506a61792b5aaa20ef059e44cb932 [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*/
developer06a01d92022-09-07 16:32:39 +0800100
developer033b37b2022-10-18 11:27:46 +0800101
developer804c64f2022-10-19 13:54:40 +0800102#define MAX_APS MAX_NUM_RADIOS*5
developer06a01d92022-09-07 16:32:39 +0800103#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
developer033b37b2022-10-18 11:27:46 +0800454INT radio_index_to_phy(int radioIndex)
455{
456 char cmd[128] = {0};
457 char buf[64] = {0};
458 int phyIndex = 0;
459 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
460 _syscmd(cmd, buf, sizeof(buf));
461
462 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
463 fprintf(stderr, "%s: failed to get phy index\n", __func__);
464 return RETURN_ERR;
465 }
466 sscanf(buf, "phy%d", &phyIndex);
467
468 return phyIndex;
469}
developerc707e972022-09-13 15:38:02 +0800470wifi_band wifi_index_to_band(int apIndex)
471{
472 char cmd[128] = {0};
473 char buf[64] = {0};
474 int freq = 0;
developer5884e982022-10-06 10:52:50 +0800475 int i = 0;
developerc707e972022-09-13 15:38:02 +0800476 wifi_band band = band_invalid;
477
478 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5884e982022-10-06 10:52:50 +0800479 while(i < 10){
480 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
481 _syscmd(cmd, buf, sizeof(buf));
482 freq = strtol(buf, NULL, 10);
developerf70d4ec2022-11-01 11:19:18 +0800483 if (freq >= 2401 && freq <= 2495)
developer5884e982022-10-06 10:52:50 +0800484 band = band_2_4;
developerf70d4ec2022-11-01 11:19:18 +0800485 else if (freq >= 5150 && freq <= 5895)
developer5884e982022-10-06 10:52:50 +0800486 band = band_5;
developerf70d4ec2022-11-01 11:19:18 +0800487 else if (freq >= 5945 && freq <= 7125)
developer5884e982022-10-06 10:52:50 +0800488 band = band_6;
489
490 if(band != band_invalid)
491 break;
492
493 i++;
494 sleep(1);
495 }
developerc707e972022-09-13 15:38:02 +0800496
497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
498 return band;
499}
500
developer06a01d92022-09-07 16:32:39 +0800501static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
502{
503 char cmd[MAX_CMD_SIZE]={'\0'};
504 char buf[MAX_BUF_SIZE]={'\0'};
505 int ret = 0;
506
507 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
508 ret = _syscmd(cmd, buf, sizeof(buf));
509 if ((ret != 0) && (strlen(buf) == 0))
510 return -1;
511 snprintf(output, output_size, "%s", buf);
512
513 return 0;
514}
515
516static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
517{
518 char cmd[MAX_CMD_SIZE]={'\0'};
519 char buf[MAX_BUF_SIZE]={'\0'};
520
521 for(int i=0;i<item_count;i++)
522 {
523 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
524 if (strlen(buf) == 0) //Insert
525 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
526 else //Update
527 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 +0800528
developer06a01d92022-09-07 16:32:39 +0800529 if(_syscmd(cmd, buf, sizeof(buf)))
530 return -1;
531 }
532
533 return 0;
534}
535
536static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
537{
developer1e5aa162022-09-13 16:06:24 +0800538 if (multiple_set == TRUE)
539 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800540 char cmd[MAX_CMD_SIZE]="", output[32]="";
541 FILE *fp;
542 int i;
543 //NOTE RELOAD should be done in ApplySSIDSettings
544
545 for(i=0; i<item_count; i++, list++)
546 {
547 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
548 if((fp = popen(cmd, "r"))==NULL)
549 {
550 perror("popen failed");
551 return -1;
552 }
553 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
554 {
555 pclose(fp);
556 perror("fgets failed");
557 return -1;
558 }
559 pclose(fp);
560 }
561 return 0;
562}
563
564static int wifi_reloadAp(int apIndex)
565{
developer1e5aa162022-09-13 16:06:24 +0800566 if (multiple_set == TRUE)
567 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800568 char cmd[MAX_CMD_SIZE]="";
569 char buf[MAX_BUF_SIZE]="";
570
571 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
572 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
573 return RETURN_ERR;
574
575 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
576 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
577 return RETURN_ERR;
578
579 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
580 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
581 return RETURN_ERR;
582
583 return RETURN_OK;
584}
585
586
587//For Getting Current Interface Name from corresponding hostapd configuration
588void GetInterfaceName(char *interface_name, char *conf_file)
589{
590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
591 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
593}
594
595INT File_Reading(CHAR *file, char *Value)
596{
597 FILE *fp = NULL;
598 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
599 int count = 0;
600
601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
602 fp = popen(file,"r");
603 if(fp == NULL)
604 return RETURN_ERR;
605
606 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
607 {
608 for(count=0;buf[count]!='\n';count++)
609 copy_buf[count]=buf[count];
610 copy_buf[count]='\0';
611 }
612 strcpy(Value,copy_buf);
613 pclose(fp);
614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
615
616 return RETURN_OK;
617}
618
619void wifi_RestartHostapd_2G()
620{
621 int Public2GApIndex = 4;
622
623 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
624 wifi_setApEnable(Public2GApIndex, FALSE);
625 wifi_setApEnable(Public2GApIndex, TRUE);
626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
627}
628
629void wifi_RestartHostapd_5G()
630{
631 int Public5GApIndex = 5;
632
633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
634 wifi_setApEnable(Public5GApIndex, FALSE);
635 wifi_setApEnable(Public5GApIndex, TRUE);
636 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
637}
638
639void wifi_RestartPrivateWifi_2G()
640{
641 int PrivateApIndex = 0;
642
643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
644 wifi_setApEnable(PrivateApIndex, FALSE);
645 wifi_setApEnable(PrivateApIndex, TRUE);
646 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
647}
648
649void wifi_RestartPrivateWifi_5G()
650{
651 int Private5GApIndex = 1;
652
653 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
654 wifi_setApEnable(Private5GApIndex, FALSE);
655 wifi_setApEnable(Private5GApIndex, TRUE);
656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
657}
658
659static int writeBandWidth(int radioIndex,char *bw_value)
660{
661 char buf[MAX_BUF_SIZE];
662 char cmd[MAX_CMD_SIZE];
663
664 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
665 if(_syscmd(cmd, buf, sizeof(buf)))
666 {
667 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
668 _syscmd(cmd, buf, sizeof(buf));
669 return RETURN_OK;
670 }
671
672 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
673 _syscmd(cmd,buf,sizeof(buf));
674 return RETURN_OK;
675}
676
677static int readBandWidth(int radioIndex,char *bw_value)
678{
679 char buf[MAX_BUF_SIZE];
680 char cmd[MAX_CMD_SIZE];
681 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
682 _syscmd(cmd,buf,sizeof(buf));
683 if(NULL!=strstr(buf,"20MHz"))
684 {
685 strcpy(bw_value,"20MHz");
686 }
687 else if(NULL!=strstr(buf,"40MHz"))
688 {
689 strcpy(bw_value,"40MHz");
690 }
691 else if(NULL!=strstr(buf,"80MHz"))
692 {
693 strcpy(bw_value,"80MHz");
694 }
695 else
696 {
697 return RETURN_ERR;
698 }
699 return RETURN_OK;
700}
701
developer39a5efb2022-09-13 16:09:06 +0800702INT wifi_getMaxRadioNumber(INT *max_radio_num)
703{
704 char cmd[64] = {0};
705 char buf[4] = {0};
706
707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
708
709 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
710 _syscmd(cmd, buf, sizeof(buf));
developer804c64f2022-10-19 13:54:40 +0800711 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
developer39a5efb2022-09-13 16:09:06 +0800712
713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
714
715 return RETURN_OK;
716}
717
developer264159b2022-11-02 09:41:35 +0800718// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800719INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
720{
developer5f222492022-09-13 15:21:52 +0800721 struct params params={'\0'};
722 char config_file[MAX_BUF_SIZE] = {0};
723 char buf[MAX_BUF_SIZE] = {'\0'};
724
725 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800726 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800727 if (strlen (beaconRate) >= 5) {
728 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
729 buf[strlen(beaconRate) - 4] = '\0';
730 } else if (strlen(beaconRate) > 0)
731 strcpy(buf, beaconRate);
732 else
733 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800734
735 params.name = "beacon_rate";
736 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
737 if (strncmp(buf, "5.5", 3) == 0) {
738 snprintf(buf, sizeof(buf), "55");
739 params.value = buf;
740 } else {
741 strcat(buf, "0");
742 params.value = buf;
743 }
744
745 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
746 wifi_hostapdWrite(config_file, &params, 1);
747 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
748 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
749
750 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800751}
752
753INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
754{
developer1d57d002022-10-12 18:03:15 +0800755 char config_file[128] = {'\0'};
756 char temp_output[128] = {'\0'};
757 char buf[128] = {'\0'};
758 char cmd[128] = {'\0'};
759 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800760 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800761
762 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
763 if (NULL == beaconRate)
764 return RETURN_ERR;
765
766 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
767 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800768 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800769 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
770 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800771 if (strncmp(buf, "55", 2) == 0)
772 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
773 else {
774 rate = strtol(buf, NULL, 10)/10;
775 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
776 }
developer5f222492022-09-13 15:21:52 +0800777 } else {
developer1d57d002022-10-12 18:03:15 +0800778 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800779 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
developer1d57d002022-10-12 18:03:15 +0800780 _syscmd(cmd, buf, sizeof(buf));
781 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800782 }
783 strncpy(beaconRate, temp_output, sizeof(temp_output));
784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
785
786 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800787}
788
789INT wifi_setLED(INT radioIndex, BOOL enable)
790{
791 return 0;
792}
793INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
794{
795 return RETURN_OK;
796}
797/**********************************************************************************
798 *
799 * Wifi Subsystem level function prototypes
800 *
801**********************************************************************************/
802//---------------------------------------------------------------------------------------------------
803//Wifi system api
804//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
805INT wifi_getHalVersion(CHAR *output_string) //RDKB
806{
807 if(!output_string)
808 return RETURN_ERR;
809 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
810
811 return RETURN_OK;
812}
813
814
815/* wifi_factoryReset() function */
816/**
817* @description Clears internal variables to implement a factory reset of the Wi-Fi
818* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
819*
820* @param None
821*
822* @return The status of the operation.
823* @retval RETURN_OK if successful.
824* @retval RETURN_ERR if any error is detected
825*
826* @execution Synchronous
827* @sideeffect None
828*
829* @note This function must not suspend and must not invoke any blocking system
830* calls. It should probably just send a message to a driver event handler task.
831*
832*/
833INT wifi_factoryReset()
834{
835 char cmd[128];
836
837 /*delete running hostapd conf files*/
838 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
839 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
840 system(cmd);
841 system("systemctl restart hostapd.service");
842
843 return RETURN_OK;
844}
845
846/* wifi_factoryResetRadios() function */
847/**
848* @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.
849*
850* @param None
851* @return The status of the operation
852* @retval RETURN_OK if successful
853* @retval RETURN_ERR if any error is detected
854*
855* @execution Synchronous
856*
857* @sideeffect None
858*
859* @note This function must not suspend and must not invoke any blocking system
860* calls. It should probably just send a message to a driver event handler task.
861*
862*/
863INT wifi_factoryResetRadios()
864{
865 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
866 return RETURN_OK;
867
868 return RETURN_ERR;
869}
870
871
872/* wifi_factoryResetRadio() function */
873/**
874* @description Restore selected radio parameters without touching access point parameters
875*
876* @param radioIndex - Index of Wi-Fi Radio channel
877*
878* @return The status of the operation.
879* @retval RETURN_OK if successful.
880* @retval RETURN_ERR if any error is detected
881*
882* @execution Synchronous.
883* @sideeffect None.
884*
885* @note This function must not suspend and must not invoke any blocking system
886* calls. It should probably just send a message to a driver event handler task.
887*
888*/
889INT wifi_factoryResetRadio(int radioIndex) //RDKB
890{
developer5ff7f5f2022-09-13 15:12:16 +0800891 system("systemctl stop hostapd.service");
892
developer06a01d92022-09-07 16:32:39 +0800893 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
894 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800895 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800896 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800897 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800898 else
899 return RETURN_ERR;
900
developer5ff7f5f2022-09-13 15:12:16 +0800901 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
903 return RETURN_OK;
904}
905
906/* wifi_initRadio() function */
907/**
908* Description: This function call initializes the specified radio.
909* Implementation specifics may dictate the functionality since
910* different hardware implementations may have different initilization requirements.
911* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
912*
913* @return The status of the operation.
914* @retval RETURN_OK if successful.
915* @retval RETURN_ERR if any error is detected
916*
917* @execution Synchronous.
918* @sideeffect None.
919*
920* @note This function must not suspend and must not invoke any blocking system
921* calls. It should probably just send a message to a driver event handler task.
922*
923*/
924INT wifi_initRadio(INT radioIndex)
925{
926 //TODO: Initializes the wifi subsystem (for specified radio)
927 return RETURN_OK;
928}
929void macfilter_init()
930{
931 char count[4]={'\0'};
932 char buf[253]={'\0'};
933 char tmp[19]={'\0'};
934 int dev_count,block,mac_entry=0;
935 char res[4]={'\0'};
936 char acl_file_path[64] = {'\0'};
937 FILE *fp = NULL;
938 int index=0;
939 char iface[10]={'\0'};
940 char config_file[MAX_BUF_SIZE] = {0};
941
942
943 sprintf(acl_file_path,"/tmp/mac_filter.sh");
944
945 fp=fopen(acl_file_path,"w+");
946 sprintf(buf,"#!/bin/sh \n");
947 fprintf(fp,"%s\n",buf);
948
949 system("chmod 0777 /tmp/mac_filter.sh");
950
951 for(index=0;index<=1;index++)
952 {
953 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
954 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
955 sprintf(buf,"syscfg get %dcountfilter",index);
956 _syscmd(buf,count,sizeof(count));
957 mac_entry=atoi(count);
958
959 sprintf(buf,"syscfg get %dblockall",index);
960 _syscmd(buf,res,sizeof(res));
961 block = atoi(res);
962
963 //Allow only those macs mentioned in ACL
964 if(block==1)
965 {
966 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
967 fprintf(fp,"%s\n",buf);
968 for(dev_count=1;dev_count<=mac_entry;dev_count++)
969 {
970 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
971 _syscmd(buf,tmp,sizeof(tmp));
972 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
973 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
974 fprintf(fp,"%s\n",buf);
975 }
976 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
977 fprintf(fp,"%s\n",buf);
978 }
979
980 //Block all the macs mentioned in ACL
981 else if(block==2)
982 {
983 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
984 fprintf(fp,"%s\n",buf);
985
986 for(dev_count=1;dev_count<=mac_entry;dev_count++)
987 {
988 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
989 _syscmd(buf,tmp,sizeof(tmp));
990 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
991 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
992 fprintf(fp,"%s\n",buf);
993 }
994 }
995 }
996 fclose(fp);
997}
998
999// Initializes the wifi subsystem (all radios)
1000INT wifi_init() //RDKB
1001{
1002 char interface[MAX_BUF_SIZE]={'\0'};
1003 char bridge_name[MAX_BUF_SIZE]={'\0'};
1004 INT len=0;
1005
1006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1007 //Not intitializing macfilter for Turris-Omnia Platform for now
1008 //macfilter_init();
1009
1010 system("/usr/sbin/iw reg set US");
1011 system("systemctl start hostapd.service");
1012 sleep(2);//sleep to wait for hostapd to start
1013
1014 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1015
1016 return RETURN_OK;
1017}
1018
1019/* wifi_reset() function */
1020/**
1021* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1022* Implementation specifics may dictate what is actualy reset since
1023* different hardware implementations may have different requirements.
1024* Parameters : None
1025*
1026* @return The status of the operation.
1027* @retval RETURN_OK if successful.
1028* @retval RETURN_ERR if any error is detected
1029*
1030* @execution Synchronous.
1031* @sideeffect None.
1032*
1033* @note This function must not suspend and must not invoke any blocking system
1034* calls. It should probably just send a message to a driver event handler task.
1035*
1036*/
1037INT wifi_reset()
1038{
1039 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001040 system("systemctl stop hostapd.service");
1041 sleep(2);
1042 system("systemctl start hostapd.service");
1043 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001044 return RETURN_OK;
1045}
1046
1047/* wifi_down() function */
1048/**
1049* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1050* Implementation specifics may dictate some functionality since
1051* different hardware implementations may have different requirements.
1052*
1053* @param None
1054*
1055* @return The status of the operation
1056* @retval RETURN_OK if successful
1057* @retval RETURN_ERR if any error is detected
1058*
1059* @execution Synchronous
1060* @sideeffect None
1061*
1062* @note This function must not suspend and must not invoke any blocking system
1063* calls. It should probably just send a message to a driver event handler task.
1064*
1065*/
1066INT wifi_down()
1067{
1068 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001069 system("systemctl stop hostapd.service");
1070 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001071 return RETURN_OK;
1072}
1073
1074
1075/* wifi_createInitialConfigFiles() function */
1076/**
1077* @description This function creates wifi configuration files. The format
1078* and content of these files are implementation dependent. This function call is
1079* used to trigger this task if necessary. Some implementations may not need this
1080* function. If an implementation does not need to create config files the function call can
1081* do nothing and return RETURN_OK.
1082*
1083* @param None
1084*
1085* @return The status of the operation
1086* @retval RETURN_OK if successful
1087* @retval RETURN_ERR if any error is detected
1088*
1089* @execution Synchronous
1090* @sideeffect None
1091*
1092* @note This function must not suspend and must not invoke any blocking system
1093* calls. It should probably just send a message to a driver event handler task.
1094*
1095*/
1096INT wifi_createInitialConfigFiles()
1097{
1098 //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)
1099 return RETURN_OK;
1100}
1101
1102// outputs the country code to a max 64 character string
1103INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1104{
developer7543b3b2022-09-13 13:47:17 +08001105 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001106 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001107 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001108
1109 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1110 _syscmd(cmd, buf, sizeof(buf));
1111 if(strlen(buf) > 0)
1112 snprintf(output_string, 64, "%s", buf);
1113 else
1114 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001115
1116 return RETURN_OK;
1117}
1118
1119INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1120{
1121 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001122 char str[MAX_BUF_SIZE]={'\0'};
1123 char cmd[MAX_CMD_SIZE]={'\0'};
1124 struct params params;
1125 char config_file[MAX_BUF_SIZE] = {0};
1126
1127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1128 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1129 return RETURN_ERR;
1130
developerb86c6f32022-10-07 14:34:58 +08001131 if (strlen(CountryCode) == 0)
1132 strcpy(CountryCode, "US");
1133
developer7543b3b2022-09-13 13:47:17 +08001134 params.name = "country_code";
1135 params.value = CountryCode;
1136 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1137 int ret = wifi_hostapdWrite(config_file, &params, 1);
1138 if (ret) {
1139 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1140 ,__func__, ret);
1141 }
1142
1143 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1144 if (ret) {
1145 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1146 ,__func__, ret);
1147 }
developer7543b3b2022-09-13 13:47:17 +08001148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1149
developer06a01d92022-09-07 16:32:39 +08001150 return RETURN_OK;
1151}
1152
developera748dcf2022-09-13 15:56:48 +08001153INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1154{
1155 char channel_util_file[64] = {0};
1156 char cmd[128] = {0};
1157 char buf[128] = {0};
1158 char line[128] = {0};
1159 char *param = NULL, *value = NULL;
1160 int read = 0;
1161 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1162 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1163 size_t len = 0;
1164 FILE *f = NULL;
1165
1166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1167
1168 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1169 _syscmd(cmd, buf, sizeof(buf));
1170 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1171
1172 memset(cmd, 0, sizeof(cmd));
1173 memset(buf, 0, sizeof(buf));
1174 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1175 if ((f = popen(cmd, "r")) == NULL) {
1176 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1177 return RETURN_ERR;
1178 }
1179
1180 read = getline(&line, &len, f);
1181 while (read != -1) {
1182 param = strtok(line, ":\t");
1183 value = strtok(NULL, " ");
1184 if(strstr(param, "frequency") != NULL) {
1185 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1186 }
1187 if(strstr(param, "noise") != NULL) {
1188 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1189 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1190 }
1191 if(strstr(param, "channel active time") != NULL) {
1192 ActiveTime = strtol(value, NULL, 10);
1193 }
1194 if(strstr(param, "channel busy time") != NULL) {
1195 BusyTime = strtol(value, NULL, 10);
1196 }
1197 if(strstr(param, "channel transmit time") != NULL) {
1198 TransmitTime = strtol(value, NULL, 10);
1199 }
1200 read = getline(&line, &len, f);
1201 }
1202 pclose(f);
1203
1204 // The file should store the last active, busy and transmit time
1205 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1206 f = fopen(channel_util_file, "r");
1207 if (f != NULL) {
1208 read = getline(&line, &len, f);
1209 preActiveTime = strtol(line, NULL, 10);
1210 read = getline(&line, &len, f);
1211 preBusyTime = strtol(line, NULL, 10);
1212 read = getline(&line, &len, f);
1213 preTransmitTime = strtol(line, NULL, 10);
1214 fclose(f);
1215 }
1216
1217 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1218 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1219
1220 f = fopen(channel_util_file, "w");
1221 if (f != NULL) {
1222 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1223 fclose(f);
1224 }
1225 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1226 return RETURN_OK;
1227}
1228
developer06a01d92022-09-07 16:32:39 +08001229/**********************************************************************************
1230 *
1231 * Wifi radio level function prototypes
1232 *
1233**********************************************************************************/
1234
1235//Get the total number of radios in this wifi subsystem
1236INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1237{
1238 if (NULL == output)
1239 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001240 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001241
1242 return RETURN_OK;
1243}
1244
1245//Get the total number of SSID entries in this wifi subsystem
1246INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1247{
1248 if (NULL == output)
1249 return RETURN_ERR;
1250 *output = MAX_APS;
1251
1252 return RETURN_OK;
1253}
1254
1255//Get the Radio enable config parameter
1256INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1257{
1258 char interface_path[MAX_CMD_SIZE] = {0};
1259 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001260 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001261
1262 if (NULL == output_bool)
1263 return RETURN_ERR;
1264
1265 *output_bool = FALSE;
developer804c64f2022-10-19 13:54:40 +08001266 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001267 return RETURN_ERR;
1268
developer033b37b2022-10-18 11:27:46 +08001269 phyId = radio_index_to_phy(radioIndex);
1270
1271 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001272 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001273 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001274 {
developercf48e482022-09-13 14:49:50 +08001275 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001276 }
1277 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001278 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1279 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1280 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001281
developercf48e482022-09-13 14:49:50 +08001282 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1283 *output_bool = TRUE;
1284 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001285 return RETURN_OK;
1286}
1287
1288INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1289{
1290 char cmd[MAX_CMD_SIZE] = {0};
1291 char buf[MAX_CMD_SIZE] = {0};
1292 int apIndex, ret;
1293 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001294 int max_radio_num = 0;
1295 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001296
1297 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001298
1299 phyId = radio_index_to_phy(radioIndex);
1300
1301 wifi_getMaxRadioNumber(&max_radio_num);
1302
developer06a01d92022-09-07 16:32:39 +08001303 if(enable==FALSE)
1304 {
developer033b37b2022-10-18 11:27:46 +08001305 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001306 {
1307 //Detaching %s%d from hostapd daemon
1308 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1309 _syscmd(cmd, buf, sizeof(buf));
1310 if(strncmp(buf, "OK", 2))
1311 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1312 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1313 _syscmd(cmd, buf, sizeof(buf));
1314 }
developer033b37b2022-10-18 11:27:46 +08001315 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001316 _syscmd(cmd, buf, sizeof(buf));
1317 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001318 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001319 }
1320 else
1321 {
developer033b37b2022-10-18 11:27:46 +08001322 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001323 _syscmd(cmd, buf, sizeof(buf));
1324 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001325 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001326 sleep(1);
developer033b37b2022-10-18 11:27:46 +08001327
1328 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001329 {
developer033b37b2022-10-18 11:27:46 +08001330 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, phyId, AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08001331 ret = _syscmd(cmd, buf, sizeof(buf));
1332 if ( ret == RETURN_ERR)
1333 {
1334 fprintf(stderr, "VAP interface creation failed\n");
1335 continue;
1336 }
1337 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1338 _syscmd(cmd, buf, sizeof(buf));
1339 if(*buf == '1')
1340 {
1341 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001342 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001343 _syscmd(cmd, buf, sizeof(buf));
1344 if(strncmp(buf, "OK", 2))
1345 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1346 }
1347 }
1348 }
1349
1350 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1351 return RETURN_OK;
1352}
1353
1354//Get the Radio enable status
1355INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1356{
1357 if (NULL == output_bool)
1358 return RETURN_ERR;
1359
1360 return wifi_getRadioEnable(radioIndex, output_bool);
1361}
1362
1363//Get the Radio Interface name from platform, eg "wlan0"
1364INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1365{
developer033b37b2022-10-18 11:27:46 +08001366 int phyId = 0;
developer804c64f2022-10-19 13:54:40 +08001367 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001368 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08001369 phyId = radio_index_to_phy(radioIndex);
1370 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001371
1372 return RETURN_OK;
1373}
1374
1375//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1376//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.
1377INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1378{
developerbcc556a2022-09-22 20:02:45 +08001379 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1380 // For max bit rate, we should always choose the best MCS
1381 char mode[64] = {0};
1382 char channel_bandwidth_str[16] = {0};
1383 char *tmp = NULL;
1384 UINT mode_map = 0;
1385 UINT num_subcarrier = 0;
1386 UINT code_bits = 0;
1387 float code_rate = 0; // use max code rate
1388 int NSS = 0;
1389 UINT Symbol_duration = 0;
1390 UINT GI_duration = 0;
1391 wifi_band band = band_invalid;
1392 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1393 BOOL enable = FALSE;
1394 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001395
1396 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1397 if (NULL == output_string)
1398 return RETURN_ERR;
1399
developerbcc556a2022-09-22 20:02:45 +08001400 wifi_getRadioEnable(radioIndex, &enable);
1401 if (enable == FALSE) {
1402 snprintf(output_string, 64, "0 Mb/s");
1403 return RETURN_OK;
1404 }
1405
1406 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1407 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1408 return RETURN_ERR;
1409 }
1410
1411 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1412 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1413 return RETURN_ERR;
1414 }
1415
1416 if (gi == wifi_guard_interval_3200)
1417 GI_duration = 32;
1418 else if (gi == wifi_guard_interval_1600)
1419 GI_duration = 16;
1420 else if (gi == wifi_guard_interval_800)
1421 GI_duration = 8;
1422 else // auto, 400
1423 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001424
developerbcc556a2022-09-22 20:02:45 +08001425 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1426 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1427 return RETURN_ERR;
1428 }
1429
1430 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1431 strcpy(channel_bandwidth_str, "160");
1432
1433 if (mode_map & WIFI_MODE_AX) {
1434 if (strstr(channel_bandwidth_str, "160") != NULL)
1435 num_subcarrier = 1960;
1436 else if (strstr(channel_bandwidth_str, "80") != NULL)
1437 num_subcarrier = 980;
1438 else if (strstr(channel_bandwidth_str, "40") != NULL)
1439 num_subcarrier = 468;
1440 else if (strstr(channel_bandwidth_str, "20") != NULL)
1441 num_subcarrier = 234;
1442 code_bits = 10;
1443 code_rate = (float)5/6;
1444 Symbol_duration = 128;
1445 } else if (mode_map & WIFI_MODE_AC) {
1446 if (strstr(channel_bandwidth_str, "160") != NULL)
1447 num_subcarrier = 468;
1448 else if (strstr(channel_bandwidth_str, "80") != NULL)
1449 num_subcarrier = 234;
1450 else if (strstr(channel_bandwidth_str, "40") != NULL)
1451 num_subcarrier = 108;
1452 else if (strstr(channel_bandwidth_str, "20") != NULL)
1453 num_subcarrier = 52;
1454 code_bits = 8;
1455 code_rate = (float)5/6;
1456 Symbol_duration = 32;
1457 } else if (mode_map & WIFI_MODE_N) {
1458 if (strstr(channel_bandwidth_str, "160") != NULL)
1459 num_subcarrier = 468;
1460 else if (strstr(channel_bandwidth_str, "80") != NULL)
1461 num_subcarrier = 234;
1462 else if (strstr(channel_bandwidth_str, "40") != NULL)
1463 num_subcarrier = 108;
1464 else if (strstr(channel_bandwidth_str, "20") != NULL)
1465 num_subcarrier = 52;
1466 code_bits = 6;
1467 code_rate = (float)3/4;
1468 Symbol_duration = 32;
1469 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1470 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1471 snprintf(output_string, 64, "65 Mb/s");
1472 return RETURN_OK;
1473 } else {
1474 snprintf(output_string, 64, "0 Mb/s");
1475 return RETURN_OK;
1476 }
developer06a01d92022-09-07 16:32:39 +08001477
developerbcc556a2022-09-22 20:02:45 +08001478 // Spatial streams
1479 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1480 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1481 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001482 }
developerbcc556a2022-09-22 20:02:45 +08001483
1484 // multiple 10 is to align duration unit (0.1 us)
1485 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1486 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1487
developer06a01d92022-09-07 16:32:39 +08001488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1489
1490 return RETURN_OK;
1491}
1492#if 0
1493INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1494{
1495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1496 char cmd[64];
1497 char buf[1024];
1498 int apIndex;
1499
1500 if (NULL == output_string)
1501 return RETURN_ERR;
1502
1503 apIndex=(radioIndex==0)?0:1;
1504
1505 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1506 _syscmd(cmd,buf, sizeof(buf));
1507
1508 snprintf(output_string, 64, "%s", buf);
1509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1510 return RETURN_OK;
1511}
1512#endif
1513
1514
1515//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1516//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.
1517INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1518{
developer963da0c2022-09-13 15:58:27 +08001519 wifi_band band = band_invalid;
1520
developer06a01d92022-09-07 16:32:39 +08001521 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1522 if (NULL == output_string)
1523 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001524
1525 band = wifi_index_to_band(radioIndex);
1526
1527 memset(output_string, 0, 10);
1528 if (band == band_2_4)
1529 strcpy(output_string, "2.4GHz");
1530 else if (band == band_5)
1531 strcpy(output_string, "5GHz");
1532 else if (band == band_6)
1533 strcpy(output_string, "6GHz");
1534 else
1535 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001536 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1537
1538 return RETURN_OK;
1539#if 0
1540 char buf[MAX_BUF_SIZE]={'\0'};
1541 char str[MAX_BUF_SIZE]={'\0'};
1542 char cmd[MAX_CMD_SIZE]={'\0'};
1543 char *ch=NULL;
1544 char *ch2=NULL;
1545
1546 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1547 if (NULL == output_string)
1548 return RETURN_ERR;
1549
1550
1551 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1552
1553 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1554 {
1555 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1556 return RETURN_ERR;
1557 }
1558 ch=strchr(buf,'\n');
1559 *ch='\0';
1560 ch=strchr(buf,'=');
1561 if(ch==NULL)
1562 return RETURN_ERR;
1563
1564
1565 ch++;
1566
1567 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1568 strcpy(buf,"0");
1569 if(strlen(ch) == 1)
1570 ch=strcat(buf,ch);
1571
1572
1573 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1574
1575 if(_syscmd(cmd,str,64) == RETURN_ERR)
1576 {
1577 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1578 return RETURN_ERR;
1579 }
1580
1581
1582 ch2=strchr(str,'\n');
1583 //replace \n with \0
1584 *ch2='\0';
1585 ch2=strchr(str,'=');
1586 if(ch2==NULL)
1587 {
1588 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1589 return RETURN_ERR;
1590 }
1591 else
1592 wifi_dbg_printf("%s",ch2+1);
1593
1594
1595 ch2++;
1596
1597
1598 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1599
1600 memset(buf,'\0',sizeof(buf));
1601 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1602 {
1603 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1604 return RETURN_ERR;
1605 }
1606 if (strstr(buf,"2.4") != NULL )
1607 strcpy(output_string,"2.4GHz");
1608 else if(strstr(buf,"5.") != NULL )
1609 strcpy(output_string,"5GHz");
1610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1611
1612 return RETURN_OK;
1613#endif
1614}
1615
1616//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1617//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.
1618INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1619{
developerb7593de2022-10-18 09:51:57 +08001620 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001621 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1622 if (NULL == output_string)
1623 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001624 band = wifi_index_to_band(radioIndex);
1625
1626 if (band == band_2_4)
1627 snprintf(output_string, 64, "2.4GHz");
1628 else if (band == band_5)
1629 snprintf(output_string, 64, "5GHz");
1630 else if (band == band_6)
1631 snprintf(output_string, 64, "6GHz");
1632
developer06a01d92022-09-07 16:32:39 +08001633 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1634
1635 return RETURN_OK;
1636#if 0
1637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1638 char buf[MAX_BUF_SIZE]={'\0'};
1639 char str[MAX_BUF_SIZE]={'\0'};
1640 char cmd[MAX_CMD_SIZE]={'\0'};
1641 char *ch=NULL;
1642 char *ch2=NULL;
1643 char ch1[5]="0";
1644
1645 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1646
1647 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1648 {
1649 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1650 return RETURN_ERR;
1651 }
1652
1653 ch=strchr(buf,'\n');
1654 *ch='\0';
1655 ch=strchr(buf,'=');
1656 if(ch==NULL)
1657 return RETURN_ERR;
1658 ch++;
1659
1660 if(strlen(ch)==1)
1661 {
1662 strcat(ch1,ch);
1663
1664 }
1665 else
1666 {
1667 strcpy(ch1,ch);
1668 }
1669
1670
1671
1672 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1673 if(_syscmd(cmd,str,64) == RETURN_ERR)
1674 {
1675 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1676 return RETURN_ERR;
1677 }
1678
1679
1680 ch2=strchr(str,'\n');
1681 //replace \n with \0
1682 *ch2='\0';
1683 ch2=strchr(str,'=');
1684 if(ch2==NULL)
1685 {
1686 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1687 return RETURN_ERR;
1688 }
1689 else
1690 wifi_dbg_printf("%s",ch2+1);
1691 ch2++;
1692
1693
1694 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1695 memset(buf,'\0',sizeof(buf));
1696 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1697 {
1698 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1699 return RETURN_ERR;
1700 }
1701
1702
1703 if(strstr(buf,"2.4")!=NULL)
1704 {
1705 strcpy(output_string,"2.4GHz");
1706 }
1707 if(strstr(buf,"5.")!=NULL)
1708 {
1709 strcpy(output_string,"5GHz");
1710 }
1711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1712 return RETURN_OK;
1713#endif
1714}
1715
1716//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1717//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.
1718INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1719{
developer963da0c2022-09-13 15:58:27 +08001720 char cmd[128]={0};
1721 char buf[128]={0};
1722 char temp_output[128] = {0};
1723 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001724 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001725
1726 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001727 if (NULL == output_string)
1728 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001729
1730 band = wifi_index_to_band(radioIndex);
1731 if (band == band_2_4) {
1732 strcat(temp_output, "b,g,");
1733 } else if (band == band_5) {
1734 strcat(temp_output, "a,");
1735 }
developer033b37b2022-10-18 11:27:46 +08001736 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001737 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001738 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001739 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001740 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001741 strcat(temp_output, "n,");
1742 }
developer06a01d92022-09-07 16:32:39 +08001743
developer963da0c2022-09-13 15:58:27 +08001744 // vht capabilities
1745 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001746 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001747 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001748 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001749 strcat(temp_output, "ac,");
1750 }
1751 }
1752
1753 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001754 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001755 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001756 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001757 strcat(temp_output, "ax,");
1758 }
1759
1760 // Remove the last comma
1761 if (strlen(temp_output) != 0)
1762 temp_output[strlen(temp_output)-1] = '\0';
1763 strncpy(output_string, temp_output, strlen(temp_output));
1764 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001765 return RETURN_OK;
1766}
1767
1768//Get the radio operating mode, and pure mode flag. eg: "ac"
1769//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.
1770INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1771{
1772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1773 if (NULL == output_string)
1774 return RETURN_ERR;
1775
1776 if (radioIndex == 0) {
1777 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1778 *gOnly = FALSE;
1779 *nOnly = TRUE;
1780 *acOnly = FALSE;
1781 } else {
1782 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1783 *gOnly = FALSE;
1784 *nOnly = FALSE;
1785 *acOnly = FALSE;
1786 }
1787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1788
1789 return RETURN_OK;
1790#if 0
1791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1792 char buf[64] = {0};
1793 char config_file[MAX_BUF_SIZE] = {0};
1794
1795 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1796 return RETURN_ERR;
1797
1798 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1799 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1800
1801 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1802 if (strlen(buf) == 0)
1803 {
1804 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1805 return RETURN_ERR;
1806 }
1807 if(strcmp(buf,"g")==0)
1808 {
1809 wifi_dbg_printf("\nG\n");
1810 *gOnly=TRUE;
1811 *nOnly=FALSE;
1812 *acOnly=FALSE;
1813 }
1814 else if(strcmp(buf,"n")==0)
1815 {
1816 wifi_dbg_printf("\nN\n");
1817 *gOnly=FALSE;
1818 *nOnly=TRUE;
1819 *acOnly=FALSE;
1820 }
1821 else if(strcmp(buf,"ac")==0)
1822 {
1823 wifi_dbg_printf("\nac\n");
1824 *gOnly=FALSE;
1825 *nOnly=FALSE;
1826 *acOnly=TRUE;
1827 }
1828 /* hostapd-5G.conf has "a" as hw_mode */
1829 else if(strcmp(buf,"a")==0)
1830 {
1831 wifi_dbg_printf("\na\n");
1832 *gOnly=FALSE;
1833 *nOnly=FALSE;
1834 *acOnly=FALSE;
1835 }
1836 else
1837 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1838
1839 //for a,n mode
1840 if(radioIndex == 1)
1841 {
1842 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1843 if(strcmp(buf,"1")==0)
1844 {
1845 strncpy(output_string, "n", 1);
1846 *nOnly=FALSE;
1847 }
1848 }
1849
1850 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1852 return RETURN_OK;
1853#endif
1854}
1855
developerdb744382022-09-13 15:34:54 +08001856INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1857{
1858 char cmd[128] = {0};
1859 char buf[64] = {0};
1860 char config_file[64] = {0};
1861 wifi_band band;
1862
1863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1864 if(NULL == output_string || NULL == pureMode)
1865 return RETURN_ERR;
1866
1867 // grep all of the ieee80211 protocol config set to 1
1868 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1869 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1870 _syscmd(cmd, buf, sizeof(buf));
1871
1872 band = wifi_index_to_band(radioIndex);
1873 // puremode is a bit map
1874 *pureMode = 0;
1875 if (band == band_2_4) {
1876 strcat(output_string, "b,g");
1877 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1878 if (strstr(buf, "n") != NULL) {
1879 strcat(output_string, ",n");
1880 *pureMode |= WIFI_MODE_N;
1881 }
1882 if (strstr(buf, "ax") != NULL) {
1883 strcat(output_string, ",ax");
1884 *pureMode |= WIFI_MODE_AX;
1885 }
1886 } else if (band == band_5) {
1887 strcat(output_string, "a");
1888 *pureMode |= WIFI_MODE_A;
1889 if (strstr(buf, "n") != NULL) {
1890 strcat(output_string, ",n");
1891 *pureMode |= WIFI_MODE_N;
1892 }
1893 if (strstr(buf, "ac") != NULL) {
1894 strcat(output_string, ",ac");
1895 *pureMode |= WIFI_MODE_AC;
1896 }
1897 if (strstr(buf, "ax") != NULL) {
1898 strcat(output_string, ",ax");
1899 *pureMode |= WIFI_MODE_AX;
1900 }
1901 } else if (band == band_6) {
1902 if (strstr(buf, "ax") != NULL) {
1903 strcat(output_string, "ax");
1904 *pureMode |= WIFI_MODE_AX;
1905 }
1906 }
1907
1908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1909 return RETURN_OK;
1910}
1911
1912// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001913INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1914{
1915 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1916 if (strcmp (channelMode,"11A") == 0)
1917 {
1918 writeBandWidth(radioIndex,"20MHz");
1919 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1920 printf("\nChannel Mode is 802.11a (5GHz)\n");
1921 }
1922 else if (strcmp (channelMode,"11NAHT20") == 0)
1923 {
1924 writeBandWidth(radioIndex,"20MHz");
1925 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1926 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1927 }
1928 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1929 {
1930 writeBandWidth(radioIndex,"40MHz");
1931 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1932 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1933 }
1934 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1935 {
1936 writeBandWidth(radioIndex,"40MHz");
1937 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1938 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1939 }
1940 else if (strcmp (channelMode,"11ACVHT20") == 0)
1941 {
1942 writeBandWidth(radioIndex,"20MHz");
1943 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1944 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1945 }
1946 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1947 {
1948 writeBandWidth(radioIndex,"40MHz");
1949 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1950 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1951 }
1952 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1953 {
1954 writeBandWidth(radioIndex,"40MHz");
1955 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1956 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1957 }
1958 else if (strcmp (channelMode,"11ACVHT80") == 0)
1959 {
1960 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1961 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1962 }
1963 else if (strcmp (channelMode,"11ACVHT160") == 0)
1964 {
1965 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1966 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1967 }
1968 else if (strcmp (channelMode,"11B") == 0)
1969 {
1970 writeBandWidth(radioIndex,"20MHz");
1971 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1972 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1973 }
1974 else if (strcmp (channelMode,"11G") == 0)
1975 {
1976 writeBandWidth(radioIndex,"20MHz");
1977 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1978 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1979 }
1980 else if (strcmp (channelMode,"11NGHT20") == 0)
1981 {
1982 writeBandWidth(radioIndex,"20MHz");
1983 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1984 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1985 }
1986 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1987 {
1988 writeBandWidth(radioIndex,"40MHz");
1989 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1990 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1991 }
1992 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1993 {
1994 writeBandWidth(radioIndex,"40MHz");
1995 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1996 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1997 }
1998 else
1999 {
2000 return RETURN_ERR;
2001 }
2002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2003
2004 return RETURN_OK;
2005}
2006
developerdb744382022-09-13 15:34:54 +08002007// Set the radio operating mode, and pure mode flag.
2008INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2009{
2010 int num_hostapd_support_mode = 3; // n, ac, ax
2011 struct params list[num_hostapd_support_mode];
2012 char config_file[64] = {0};
2013 char bandwidth[16] = {0};
2014 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002015
developerdb744382022-09-13 15:34:54 +08002016
2017 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2018 // Set radio mode
2019 list[0].name = "ieee80211n";
2020 list[1].name = "ieee80211ac";
2021 list[2].name = "ieee80211ax";
2022 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2023
2024 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002025 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002026 list[0].value = "1";
2027 else
2028 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002029 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002030 list[1].value = "1";
2031 else
2032 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002033 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002034 list[2].value = "1";
2035 else
2036 list[2].value = "0";
2037 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2038
2039 if (channelMode == NULL || strlen(channelMode) == 0)
2040 return RETURN_OK;
2041 // Set bandwidth
2042 if (strstr(channelMode, "40") != NULL)
2043 strcpy(bandwidth, "40MHz");
2044 else if (strstr(channelMode, "80") != NULL)
2045 strcpy(bandwidth, "80MHz");
2046 else if (strstr(channelMode, "160") != NULL)
2047 strcpy(bandwidth, "160MHz");
2048 else // 11A, 11B, 11G....
2049 strcpy(bandwidth, "20MHz");
2050
2051 writeBandWidth(radioIndex, bandwidth);
2052 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2053
2054 wifi_reloadAp(radioIndex);
2055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2056
2057 return RETURN_OK;
2058}
2059
developer1d12ebf2022-10-04 15:13:38 +08002060INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2061
2062 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002063 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002064 struct params params = {0};
2065 wifi_band band = band_invalid;
2066
2067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2068
2069 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002070
2071 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002072 return RETURN_ERR;
2073 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2074 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002075 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2076 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002077
2078 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2079 params.name = "hw_mode";
2080 params.value = hw_mode;
2081 wifi_hostapdWrite(config_file, &params, 1);
2082 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2083
developeref938762022-10-19 17:21:01 +08002084 if (band == band_2_4) {
2085 if (strncmp(hw_mode, "b", 1) == 0) {
2086 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2087 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2088 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2089 snprintf(buf, sizeof(buf), "%s", "1,2");
2090 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2091 } else {
2092 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2093
2094 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2095 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2096 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2097 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2098 }
2099 }
2100
developer1d12ebf2022-10-04 15:13:38 +08002101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2102 return RETURN_OK;
2103}
2104
developere8988ba2022-10-18 17:42:30 +08002105INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2106{
2107 char config_file[64] = {0};
2108 struct params params = {0};
2109 wifi_band band = band_invalid;
2110
2111 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2112
2113 band = wifi_index_to_band(radioIndex);
2114
2115 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2116 params.name = "noscan";
2117 params.value = noscan;
2118 wifi_hostapdWrite(config_file, &params, 1);
2119 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2120
2121 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2122 return RETURN_OK;
2123}
2124
developer06a01d92022-09-07 16:32:39 +08002125//Get the list of supported channel. eg: "1-11"
2126//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.
2127INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2128{
developer6318ed52022-09-13 15:17:58 +08002129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002130 if (NULL == output_string)
2131 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002132 char cmd[256] = {0};
2133 char buf[128] = {0};
2134 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002135 int phyId = 0;
2136
developer6318ed52022-09-13 15:17:58 +08002137 // Parse possible channel number and separate them with commas.
2138 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002139 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002140 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002141 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002142 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002143 else
developer033b37b2022-10-18 11:27:46 +08002144 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002145
2146 _syscmd(cmd,buf,sizeof(buf));
2147 strncpy(output_string, buf, sizeof(buf));
2148
2149 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2150 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002151}
2152
2153//Get the list for used channel. eg: "1,6,9,11"
2154//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.
2155INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2156{
developerf5745ee2022-10-05 16:09:53 +08002157 char cmd[128] = {0};
2158 char buf[128] = {0};
2159 char config_file[64] = {0};
2160 int channel = 0;
2161 int freq = 0;
2162 int bandwidth = 0;
2163 int center_freq = 0;
2164 int center_channel = 0;
2165 int channel_delta = 0;
2166 wifi_band band = band_invalid;
2167
2168 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2169
developer06a01d92022-09-07 16:32:39 +08002170 if (NULL == output_string)
2171 return RETURN_ERR;
2172
developerf5745ee2022-10-05 16:09:53 +08002173 sprintf(cmd, "iw %s%d info | grep channel | sed -e 's/[^0-9 ]//g'", AP_PREFIX, radioIndex);
2174 _syscmd(cmd, buf, sizeof(buf));
2175 if (strlen(buf) == 0) {
2176 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2177 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002178 }
developerf5745ee2022-10-05 16:09:53 +08002179 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2180
2181 if (bandwidth == 20) {
2182 snprintf(output_string, 256, "%d", channel);
2183 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002184 }
developerf5745ee2022-10-05 16:09:53 +08002185
2186 center_channel = ieee80211_frequency_to_channel(center_freq);
2187
2188 band = wifi_index_to_band(radioIndex);
2189 if (band == band_2_4 && bandwidth == 40) {
2190 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2191 memset(buf, 0, sizeof(buf));
2192 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2193
2194 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2195 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2196 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2197 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2198 } else {
2199 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2200 return RETURN_ERR;
2201 }
2202 } else if (band == band_5 || band == band_6){
2203 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2204 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2205 channel_delta = (bandwidth-20)/10;
2206 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2207 } else
2208 return RETURN_ERR;
2209
2210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002211 return RETURN_OK;
2212}
2213
2214//Get the running channel number
2215INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2216{
developerda1ed692022-09-13 13:59:20 +08002217#ifdef MTK_IMPL
2218 if(!wifi_getApChannel(radioIndex, output_ulong))
2219 return RETURN_OK;
2220 else
2221 return RETURN_ERR;
2222#else
developer06a01d92022-09-07 16:32:39 +08002223 char cmd[1024] = {0}, buf[5] = {0};
2224
2225 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2226 if (NULL == output_ulong)
2227 return RETURN_ERR;
2228
2229 snprintf(cmd, sizeof(cmd),
2230 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2231 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2232 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2233 _syscmd(cmd, buf, sizeof(buf));
2234
2235 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2236 if (*output_ulong <= 0) {
2237 *output_ulong = 0;
2238 return RETURN_ERR;
2239 }
2240
2241 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2242 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002243#endif
developer06a01d92022-09-07 16:32:39 +08002244}
2245
2246
2247INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2248{
2249 char cmd[1024] = {0}, buf[5] = {0};
2250 char interface_name[50] = {0};
2251
2252 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2253 if (NULL == output_ulong)
2254 return RETURN_ERR;
2255
2256 wifi_getApName(apIndex,interface_name);
2257 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2258 _syscmd(cmd,buf,sizeof(buf));
2259 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2260 if (*output_ulong == 0) {
2261 return RETURN_ERR;
2262 }
2263
2264 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2265 return RETURN_OK;
2266}
2267
2268//Storing the previous channel value
2269INT wifi_storeprevchanval(INT radioIndex)
2270{
2271 char buf[256] = {0};
2272 char output[4]={'\0'};
2273 char config_file[MAX_BUF_SIZE] = {0};
2274 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2275 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2276 if(radioIndex == 0)
2277 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2278 else if(radioIndex == 1)
2279 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2280 system(buf);
2281 Radio_flag = FALSE;
2282 return RETURN_OK;
2283}
2284
2285//Set the running channel number
2286INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2287{
developer76989232022-10-04 14:13:19 +08002288 // We only write hostapd config here
2289 char str_channel[8]={0};
2290 char *list_channel;
2291 char config_file[128] = {0};
2292 char possible_channels[256] = {0};
2293 int max_radio_num = 0;
2294 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002295
developer76989232022-10-04 14:13:19 +08002296 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002297
developer76989232022-10-04 14:13:19 +08002298 // Check valid
2299 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002300
developer76989232022-10-04 14:13:19 +08002301 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2302 list_channel = strtok(possible_channels, ",");
2303 while(true)
developer06a01d92022-09-07 16:32:39 +08002304 {
developer76989232022-10-04 14:13:19 +08002305 if(list_channel == NULL) { // input not in the list
2306 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2307 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002308 }
developer76989232022-10-04 14:13:19 +08002309 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2310 break;
2311 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002312 }
2313
developer76989232022-10-04 14:13:19 +08002314 list.name = "channel";
2315 list.value = str_channel;
2316 wifi_getMaxRadioNumber(&max_radio_num);
2317 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002318 {
developer76989232022-10-04 14:13:19 +08002319 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2320 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002321 }
2322
developer76989232022-10-04 14:13:19 +08002323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002324 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002325}
developer06a01d92022-09-07 16:32:39 +08002326
2327INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2328{
developer76989232022-10-04 14:13:19 +08002329 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002330 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002331 char config_file[64];
2332 int max_num_radios = 0;
2333 wifi_band band = band_invalid;
2334
2335 band = wifi_index_to_band(radioIndex);
2336 if (band == band_2_4)
2337 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002338
developer06a01d92022-09-07 16:32:39 +08002339 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002340 list[0].name = "vht_oper_centr_freq_seg0_idx";
2341 list[0].value = str_idx;
2342 list[1].name = "he_oper_centr_freq_seg0_idx";
2343 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002344
developer76989232022-10-04 14:13:19 +08002345 wifi_getMaxRadioNumber(&max_num_radios);
2346 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002347 {
developer76989232022-10-04 14:13:19 +08002348 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2349 if (band == band_6)
2350 wifi_hostapdWrite(config_file, &list[1], 1);
2351 else
2352 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002353 }
2354
2355 return RETURN_OK;
2356}
2357
2358//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2359//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2360INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2361{
2362 //Set to wifi config only. Wait for wifi reset to apply.
2363 char buf[256] = {0};
2364 char str_channel[256] = {0};
2365 int count = 0;
2366 ULONG Value = 0;
2367 FILE *fp = NULL;
2368 if(enable == TRUE)
2369 {
developer06a01d92022-09-07 16:32:39 +08002370 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002371 }
developer5884e982022-10-06 10:52:50 +08002372 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002373}
2374
developer0b246d12022-09-30 15:24:20 +08002375INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2376{
2377 if (output_bool == NULL)
2378 return RETURN_ERR;
2379
2380 *output_bool = TRUE;
2381
2382 return RETURN_OK;
2383}
2384
developer06a01d92022-09-07 16:32:39 +08002385INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2386{
2387 if (NULL == output_bool)
2388 return RETURN_ERR;
2389 *output_bool=FALSE;
2390 return RETURN_OK;
2391}
2392
2393INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2394{
2395 if (NULL == output_bool)
2396 return RETURN_ERR;
2397 *output_bool=FALSE;
2398 return RETURN_OK;
2399}
2400
2401INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2402{
2403 //Set to wifi config only. Wait for wifi reset to apply.
2404 return RETURN_OK;
2405}
2406
2407INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2408{
2409 return RETURN_OK;
2410}
2411
2412INT wifi_factoryResetAP(int apIndex)
2413{
developer838cca92022-10-03 13:19:57 +08002414 char ap_config_file[64] = {0};
2415 char cmd[128] = {0};
2416
developer06a01d92022-09-07 16:32:39 +08002417 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002418
2419 wifi_setApEnable(apIndex, FALSE);
2420 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2421 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2422 wifi_setApEnable(apIndex, TRUE);
2423
developer06a01d92022-09-07 16:32:39 +08002424 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002425
developer06a01d92022-09-07 16:32:39 +08002426 return RETURN_OK;
2427}
2428
2429//To set Band Steering AP group
2430//To-do
2431INT wifi_setBandSteeringApGroup(char *ApGroup)
2432{
2433 return RETURN_OK;
2434}
2435
developer1e5aa162022-09-13 16:06:24 +08002436INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2437{
2438 char config_file[128] = {'\0'};
2439 char buf[128] = {'\0'};
2440
2441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2442 if (dtimInterval == NULL)
2443 return RETURN_ERR;
2444
2445 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2446 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2447
2448 if (strlen(buf) == 0) {
2449 *dtimInterval = 2;
2450 } else {
2451 *dtimInterval = strtoul(buf, NULL, 10);
2452 }
2453
2454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2455 return RETURN_OK;
2456}
2457
developer06a01d92022-09-07 16:32:39 +08002458INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2459{
developer5f222492022-09-13 15:21:52 +08002460 struct params params={0};
2461 char config_file[MAX_BUF_SIZE] = {'\0'};
2462 char buf[MAX_BUF_SIZE] = {'\0'};
2463
2464 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2465 if (dtimInterval < 1 || dtimInterval > 255) {
2466 return RETURN_ERR;
2467 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2468 }
2469
2470 params.name = "dtim_period";
2471 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2472 params.value = buf;
2473
2474 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2475 wifi_hostapdWrite(config_file, &params, 1);
2476 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2477
2478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2479 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002480}
2481
2482//Check if the driver support the Dfs
2483INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2484{
2485 if (NULL == output_bool)
2486 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002487 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002488 return RETURN_OK;
2489}
2490
2491//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.
2492//The value of this parameter is a comma seperated list of channel number
2493INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2494{
2495 if (NULL == output_pool)
2496 return RETURN_ERR;
2497 if (radioIndex==1)
2498 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2499 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2500
2501 return RETURN_OK;
2502}
2503
2504INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2505{
2506 //Set to wifi config. And apply instantly.
2507 return RETURN_OK;
2508}
2509
2510INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2511{
2512 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2513 return RETURN_ERR;
2514 *output_interval_seconds=1800;
2515 *output_dwell_milliseconds=40;
2516
2517 return RETURN_OK;
2518}
2519
2520INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2521{
2522 //Set to wifi config. And apply instantly.
2523 return RETURN_OK;
2524}
2525
developerbfc18512022-10-05 17:54:28 +08002526INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2527{
2528 if (output_bool == NULL)
2529 return RETURN_ERR;
2530 *output_bool = true;
2531 return RETURN_OK;
2532}
2533
2534INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2535{
2536 return RETURN_OK;
2537}
2538
developer06a01d92022-09-07 16:32:39 +08002539//Get the Dfs enable status
2540INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2541{
developer9964b5b2022-09-13 15:59:34 +08002542 char buf[16] = {0};
2543 FILE *f = NULL;
2544 wifi_band band;
2545
2546 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2547
2548 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002549 if (NULL == output_bool)
2550 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002551
2552 band = wifi_index_to_band(radioIndex);
2553 if (band != band_5)
2554 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002555
developer9964b5b2022-09-13 15:59:34 +08002556 f = fopen(DFS_ENABLE_FILE, "r");
2557 if (f != NULL) {
2558 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002559 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002560 *output_bool = FALSE;
2561 fclose(f);
2562 }
2563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002564 return RETURN_OK;
2565}
2566
2567//Set the Dfs enable status
2568INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2569{
developer9964b5b2022-09-13 15:59:34 +08002570 char config_file[128] = {0};
2571 FILE *f = NULL;
2572 struct params params={0};
2573 wifi_band band;
2574
2575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2576
2577 band = wifi_index_to_band(radioIndex);
2578 if (band != band_5)
2579 return RETURN_OK;
2580
2581 f = fopen(DFS_ENABLE_FILE, "w");
2582 if (f == NULL)
2583 return RETURN_ERR;
2584 fprintf(f, "%d", enable);
2585 fclose(f);
2586
2587 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002588 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002589 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2590 wifi_hostapdWrite(config_file, &params, 1);
2591 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2592
2593 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2594
developer9964b5b2022-09-13 15:59:34 +08002595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002596 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002597}
2598
2599//Check if the driver support the AutoChannelRefreshPeriod
2600INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2601{
2602 if (NULL == output_bool)
2603 return RETURN_ERR;
2604 *output_bool=FALSE; //not support
2605
2606 return RETURN_OK;
2607}
2608
2609//Get the ACS refresh period in seconds
2610INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2611{
2612 if (NULL == output_ulong)
2613 return RETURN_ERR;
2614 *output_ulong=300;
2615
2616 return RETURN_OK;
2617}
2618
2619//Set the ACS refresh period in seconds
2620INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2621{
2622 return RETURN_ERR;
2623}
2624
2625//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2626//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.
2627INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2628{
developer70490032022-09-13 15:45:20 +08002629 char cmd[128] = {0}, buf[64] = {0};
2630 char interface_name[64] = {0};
2631 int ret = 0, len=0;
2632 BOOL radio_enable = FALSE;
2633
2634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2635
developer06a01d92022-09-07 16:32:39 +08002636 if (NULL == output_string)
2637 return RETURN_ERR;
2638
developer70490032022-09-13 15:45:20 +08002639 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2640 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002641
developer70490032022-09-13 15:45:20 +08002642 if (radio_enable != TRUE)
2643 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002644
developer70490032022-09-13 15:45:20 +08002645 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002646 ret = _syscmd(cmd, buf, sizeof(buf));
2647 len = strlen(buf);
2648 if((ret != 0) || (len == 0))
2649 {
2650 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2651 return RETURN_ERR;
2652 }
2653
2654 buf[len-1] = '\0';
2655 snprintf(output_string, 64, "%sMHz", buf);
2656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2657
2658#if 0
2659 //TODO: revisit below implementation
2660 char output_buf[8]={0};
2661 char bw_value[10];
2662 char config_file[MAX_BUF_SIZE] = {0};
2663
2664 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2665 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2666 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2667 readBandWidth(radioIndex,bw_value);
2668
2669 if(strstr (output_buf,"0") != NULL )
2670 {
2671 strcpy(output_string,bw_value);
2672 }
2673 else if (strstr (output_buf,"1") != NULL)
2674 {
2675 strcpy(output_string,"80MHz");
2676 }
2677 else if (strstr (output_buf,"2") != NULL)
2678 {
2679 strcpy(output_string,"160MHz");
2680 }
2681 else if (strstr (output_buf,"3") != NULL)
2682 {
2683 strcpy(output_string,"80+80");
2684 }
2685 else
2686 {
2687 strcpy(output_string,"Auto");
2688 }
2689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2690#endif
2691
2692 return RETURN_OK;
2693}
2694
2695//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002696INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002697{
developerf7a466e2022-09-29 11:55:56 +08002698 char config_file[128];
2699 char set_value[16];
2700 struct params params[2];
2701 int max_radio_num = 0;
2702
developer06a01d92022-09-07 16:32:39 +08002703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002704
developerf7a466e2022-09-29 11:55:56 +08002705 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002706 return RETURN_ERR;
2707
developerf7a466e2022-09-29 11:55:56 +08002708 if(strstr(bandwidth,"80+80") != NULL)
2709 strcpy(set_value, "3");
2710 else if(strstr(bandwidth,"160") != NULL)
2711 strcpy(set_value, "2");
2712 else if(strstr(bandwidth,"80") != NULL)
2713 strcpy(set_value, "1");
2714 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2715 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002716 else
2717 {
developerf7a466e2022-09-29 11:55:56 +08002718 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002719 return RETURN_ERR;
2720 }
2721
developerf7a466e2022-09-29 11:55:56 +08002722 params[0].name = "vht_oper_chwidth";
2723 params[0].value = set_value;
2724 params[1].name = "he_oper_chwidth";
2725 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002726
developerf7a466e2022-09-29 11:55:56 +08002727 wifi_getMaxRadioNumber(&max_radio_num);
2728 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002729 {
developerf7a466e2022-09-29 11:55:56 +08002730 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2731 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002732 }
2733
2734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2735 return RETURN_OK;
2736}
2737
2738//Getting current radio extension channel
2739INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2740{
2741 CHAR buf[150] = {0};
2742 CHAR cmd[150] = {0};
2743 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2744 _syscmd(cmd, buf, sizeof(buf));
2745 if(NULL != strstr(buf,"HT40+"))
2746 strcpy(Value,"AboveControlChannel");
2747 else if(NULL != strstr(buf,"HT40-"))
2748 strcpy(Value,"BelowControlChannel");
2749 return RETURN_OK;
2750}
2751
2752//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2753//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2754INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2755{
2756 if (NULL == output_string)
2757 return RETURN_ERR;
2758
2759 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2760#if 0
2761 CHAR Value[100] = {0};
2762 if (NULL == output_string)
2763 return RETURN_ERR;
2764 if(radioIndex == 0)
2765 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2766 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2767 {
2768 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2769 if(strcmp(Value,"40MHz") == 0)
2770 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2771 else
2772 strcpy(Value,"Auto");
2773 }
2774 strcpy(output_string,Value);
2775#endif
2776
2777 return RETURN_OK;
2778}
2779
2780//Set the extension channel.
2781INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2782{
2783 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2784 struct params params={'\0'};
2785 char config_file[MAX_BUF_SIZE] = {0};
2786 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002787 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002788 params.name = "ht_capab";
2789
developer033b37b2022-10-18 11:27:46 +08002790 if(NULL!= strstr(string,"Above"))
2791 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2792 else if(NULL!= strstr(string,"Below"))
2793 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2794 else
2795 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2796
developer06a01d92022-09-07 16:32:39 +08002797
2798 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002799
2800 wifi_getMaxRadioNumber(&max_radio_num);
2801 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002802 {
developer033b37b2022-10-18 11:27:46 +08002803 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002804 wifi_hostapdWrite(config_file, &params, 1);
2805 }
2806
2807 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2808 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2809 return RETURN_OK;
2810}
2811
2812//Get the guard interval value. eg "400nsec" or "800nsec"
2813//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2814INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2815{
developer454b9462022-09-13 15:29:16 +08002816 wifi_guard_interval_t GI;
2817
2818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2819
2820 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002821 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002822
2823 if (GI == wifi_guard_interval_400)
2824 strcpy(output_string, "400nsec");
2825 else if (GI == wifi_guard_interval_800)
2826 strcpy(output_string, "800nsec");
2827 else if (GI == wifi_guard_interval_1600)
2828 strcpy(output_string, "1600nsec");
2829 else if (GI == wifi_guard_interval_3200)
2830 strcpy(output_string, "3200nsec");
2831 else
2832 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002833
developer454b9462022-09-13 15:29:16 +08002834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002835 return RETURN_OK;
2836}
2837
2838//Set the guard interval value.
2839INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2840{
developer454b9462022-09-13 15:29:16 +08002841 wifi_guard_interval_t GI;
2842 int ret = 0;
2843
2844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2845
2846 if (strcmp(string, "400nsec") == 0)
2847 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002848 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002849 GI = wifi_guard_interval_800;
2850 else if (strcmp(string , "1600nsec") == 0)
2851 GI = wifi_guard_interval_1600;
2852 else if (strcmp(string , "3200nsec") == 0)
2853 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002854 else
2855 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002856
2857 ret = wifi_setGuardInterval(radioIndex, GI);
2858
2859 if (ret == RETURN_ERR) {
2860 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2861 return RETURN_ERR;
2862 }
2863
2864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2865 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002866}
2867
2868//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2869INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2870{
developerf49437e2022-09-29 19:58:21 +08002871 char buf[32]={0};
2872 char mcs_file[64] = {0};
2873 char cmd[64] = {0};
2874 int mode_bitmap = 0;
2875
2876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2877 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002878 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002879 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2880
2881 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2882 _syscmd(cmd, buf, sizeof(buf));
2883 if (strlen(buf) > 0)
2884 *output_int = strtol(buf, NULL, 10);
2885 else {
2886 // output the max MCS for the current radio mode
2887 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2888 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2889 return RETURN_ERR;
2890 }
2891 if (mode_bitmap & WIFI_MODE_AX) {
2892 *output_int = 11;
2893 } else if (mode_bitmap & WIFI_MODE_AC) {
2894 *output_int = 9;
2895 } else if (mode_bitmap & WIFI_MODE_N) {
2896 *output_int = 7;
2897 }
2898 }
2899 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002900
2901 return RETURN_OK;
2902}
2903
2904//Set the Modulation Coding Scheme index
2905INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2906{
developerf49437e2022-09-29 19:58:21 +08002907 // Only HE mode can specify MCS capability. We don't support MCS in HT mode, because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).
2908 char config_file[64] = {0};
2909 char set_value[16] = {0};
2910 char mcs_file[32] = {0};
2911 wifi_band band = band_invalid;
2912 struct params set_config = {0};
2913 FILE *f = NULL;
2914
2915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2916
2917 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2918
2919 if (MCS > 11 || MCS < 0) {
2920 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2921 return RETURN_ERR;
2922 }
2923
2924 if (MCS <= 7)
2925 strcpy(set_value, "0");
2926 else if (MCS <= 9)
2927 strcpy(set_value, "1");
2928 else
2929 strcpy(set_value, "2");
2930
2931 set_config.name = "he_basic_mcs_nss_set";
2932 set_config.value = set_value;
2933
2934 wifi_hostapdWrite(config_file, &set_config, 1);
2935 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2936
2937 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2938 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2939 f = fopen(mcs_file, "w");
2940 if (f == NULL) {
2941 fprintf(stderr, "%s: fopen failed\n", __func__);
2942 return RETURN_ERR;
2943 }
2944 fprintf(f, "%d", MCS);
2945 fclose(f);
2946
2947 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2948 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002949}
2950
2951//Get supported Transmit Power list, eg : "0,25,50,75,100"
2952//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.
2953INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2954{
2955 if (NULL == output_list)
2956 return RETURN_ERR;
2957 snprintf(output_list, 64,"0,25,50,75,100");
2958 return RETURN_OK;
2959}
2960
developera5005b62022-09-13 15:43:35 +08002961//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002962//The transmite power level is in units of full power for this radio.
2963INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2964{
2965 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002966 char buf[16]={0};
2967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002968
developera5005b62022-09-13 15:43:35 +08002969 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002970 return RETURN_ERR;
2971
developera5005b62022-09-13 15:43:35 +08002972 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 +08002973 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002974
developera5005b62022-09-13 15:43:35 +08002975 *output_ulong = strtol(buf, NULL, 10);
2976
2977 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002978 return RETURN_OK;
2979}
2980
2981//Set Transmit Power
2982//The transmite power level is in units of full power for this radio.
2983INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2984{
developera5005b62022-09-13 15:43:35 +08002985 char *support;
developer06a01d92022-09-07 16:32:39 +08002986 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002987 char buf[128]={0};
2988 char txpower_str[64] = {0};
2989 int txpower = 0;
2990 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08002991 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08002992
2993 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002994
developera5005b62022-09-13 15:43:35 +08002995 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 +08002996 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002997 maximum_tx = strtol(buf, NULL, 10);
2998
2999 // Get the Tx power supported list and check that is the input in the list
3000 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3001 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3002 support = strtok(buf, ",");
3003 while(true)
3004 {
3005 if(support == NULL) { // input not in the list
3006 wifi_dbg_printf("Input value is invalid.\n");
3007 return RETURN_ERR;
3008 }
3009 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3010 break;
3011 }
3012 support = strtok(NULL, ",");
3013 }
3014 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003015 phyId = radio_index_to_phy(radioIndex);
3016 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003017 _syscmd(cmd, buf, sizeof(buf));
3018 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003019
3020 return RETURN_OK;
3021}
3022
3023//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3024INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3025{
3026 if (NULL == Supported)
3027 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003028 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003029
3030 return RETURN_OK;
3031}
3032
3033//Get 80211h feature enable
3034INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3035{
developer3885fec2022-09-13 15:13:47 +08003036 char buf[64]={'\0'};
3037 char config_file[64] = {'\0'};
3038
3039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3040 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003041 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003042
3043 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3044 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003045
developer3885fec2022-09-13 15:13:47 +08003046 if (strncmp(buf, "1", 1) == 0)
3047 *enable = TRUE;
3048 else
3049 *enable = FALSE;
3050
3051 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003052 return RETURN_OK;
3053}
3054
3055//Set 80211h feature enable
3056INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3057{
developer3885fec2022-09-13 15:13:47 +08003058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3059 struct params params={'\0'};
3060 char config_file[MAX_BUF_SIZE] = {0};
3061
3062 params.name = "ieee80211h";
3063
3064 if (enable) {
3065 params.value = "1";
3066 } else {
3067 params.value = "0";
3068 }
3069
3070 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3071 wifi_hostapdWrite(config_file, &params, 1);
3072
3073 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3075 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003076}
3077
3078//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.
3079INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3080{
3081 if (NULL == output)
3082 return RETURN_ERR;
3083 *output=100;
3084
3085 return RETURN_OK;
3086}
3087
3088//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.
3089INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3090{
3091 if (NULL == output)
3092 return RETURN_ERR;
3093 *output = -99;
3094
3095 return RETURN_OK;
3096}
3097
3098INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3099{
3100 return RETURN_ERR;
3101}
3102
3103
3104//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3105INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3106{
developer5f222492022-09-13 15:21:52 +08003107 char cmd[MAX_BUF_SIZE]={'\0'};
3108 char buf[MAX_CMD_SIZE]={'\0'};
3109
3110 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3111 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003112 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003113
3114 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3115 _syscmd(cmd, buf, sizeof(buf));
3116 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003117
developer5f222492022-09-13 15:21:52 +08003118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003119 return RETURN_OK;
3120}
3121
3122INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3123{
developer5f222492022-09-13 15:21:52 +08003124 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3125 struct params params={'\0'};
3126 char buf[MAX_BUF_SIZE] = {'\0'};
3127 char config_file[MAX_BUF_SIZE] = {'\0'};
3128
3129 params.name = "beacon_int";
3130 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3131 params.value = buf;
3132
3133 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3134 wifi_hostapdWrite(config_file, &params, 1);
3135
3136 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3137 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3138 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003139}
3140
3141//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.
3142INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3143{
developer06a01d92022-09-07 16:32:39 +08003144 //TODO: need to revisit below implementation
3145 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003146 char temp_output[128] = {0};
3147 char temp_TransmitRates[64] = {0};
3148 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003149
3150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3151 if (NULL == output)
3152 return RETURN_ERR;
3153 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003154 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3155
3156 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3157 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3158 } else {
3159 temp = strtok(temp_TransmitRates," ");
3160 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003161 {
developere9d0abd2022-09-13 15:40:57 +08003162 // Convert 100 kbps to Mbps
3163 temp[strlen(temp)-1]=0;
3164 if((temp[0]=='5') && (temp[1]=='\0'))
3165 {
3166 temp="5.5";
3167 }
3168 strcat(temp_output,temp);
3169 temp = strtok(NULL," ");
3170 if(temp!=NULL)
3171 {
3172 strcat(temp_output,",");
3173 }
developer06a01d92022-09-07 16:32:39 +08003174 }
developere9d0abd2022-09-13 15:40:57 +08003175 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003176 }
developer06a01d92022-09-07 16:32:39 +08003177 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003178 return RETURN_OK;
3179}
3180
3181INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3182{
3183 char *temp;
3184 char temp1[128];
3185 char temp_output[128];
3186 char temp_TransmitRates[128];
3187 char set[128];
3188 char sub_set[128];
3189 int set_count=0,subset_count=0;
3190 int set_index=0,subset_index=0;
3191 char *token;
3192 int flag=0, i=0;
3193 struct params params={'\0'};
3194 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003195 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003196
3197 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3198 if(NULL == TransmitRates)
3199 return RETURN_ERR;
3200 strcpy(sub_set,TransmitRates);
3201
3202 //Allow only supported Data transmit rate to be set
3203 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3204 token = strtok(sub_set,",");
3205 while( token != NULL ) /* split the basic rate to be set, by comma */
3206 {
3207 sub_set[subset_count]=atoi(token);
3208 subset_count++;
3209 token=strtok(NULL,",");
3210 }
3211 token=strtok(set,",");
3212 while(token!=NULL) /* split the supported rate by comma */
3213 {
3214 set[set_count]=atoi(token);
3215 set_count++;
3216 token=strtok(NULL,",");
3217 }
3218 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3219 {
3220 for(set_index=0;set_index < set_count;set_index++)
3221 {
3222 flag=0;
3223 if(sub_set[subset_index]==set[set_index])
3224 break;
3225 else
3226 flag=1; /* No match found */
3227 }
3228 if(flag==1)
3229 return RETURN_ERR; //If value not found return Error
3230 }
3231 strcpy(temp_TransmitRates,TransmitRates);
3232
3233 for(i=0;i<strlen(temp_TransmitRates);i++)
3234 {
3235 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003236 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003237 {
3238 continue;
3239 }
3240 else
3241 {
3242 return RETURN_ERR;
3243 }
3244 }
3245 strcpy(temp_output,"");
3246 temp = strtok(temp_TransmitRates,",");
3247 while(temp!=NULL)
3248 {
3249 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003250 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003251 {
developeref938762022-10-19 17:21:01 +08003252 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003253 {
3254 return RETURN_ERR;
3255 }
3256 }
3257
3258 if(strcmp(temp,"5.5")==0)
3259 {
3260 strcpy(temp1,"55");
3261 }
3262 else
3263 {
3264 strcat(temp1,"0");
3265 }
3266 strcat(temp_output,temp1);
3267 temp = strtok(NULL,",");
3268 if(temp!=NULL)
3269 {
3270 strcat(temp_output," ");
3271 }
3272 }
3273 strcpy(TransmitRates,temp_output);
3274
3275 params.name= "basic_rates";
3276 params.value =TransmitRates;
3277
3278 wifi_dbg_printf("\n%s:",__func__);
3279 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3280 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3281 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3282 wifi_hostapdWrite(config_file,&params,1);
3283 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3284 return RETURN_OK;
3285}
3286
3287//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3288INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3289{
3290 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3291 FILE *fp = NULL;
3292 char path[256] = {0}, output_string[256] = {0};
3293 int count = 0;
3294 char *interface = NULL;
3295
3296 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3297 if (fp == NULL)
3298 {
3299 printf("Failed to run command in Function %s\n", __FUNCTION__);
3300 return RETURN_ERR;
3301 }
3302 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3303 {
3304 interface = strchr(path, '=');
3305
3306 if (interface != NULL)
3307 {
3308 strcpy(output_string, interface + 1);
3309 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3310 interface_name[count] = output_string[count];
3311
3312 interface_name[count] = '\0';
3313 }
3314 }
3315 pclose(fp);
3316 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3317 return RETURN_OK;
3318}
3319
3320INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3321{
3322 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3323 output_struct->radio_BytesSent = 0;
3324 output_struct->radio_BytesReceived = 0;
3325 output_struct->radio_PacketsSent = 0;
3326 output_struct->radio_PacketsReceived = 0;
3327 output_struct->radio_ErrorsSent = 0;
3328 output_struct->radio_ErrorsReceived = 0;
3329 output_struct->radio_DiscardPacketsSent = 0;
3330 output_struct->radio_DiscardPacketsReceived = 0;
3331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3332 return RETURN_OK;
3333}
3334
3335
3336INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3337{
3338 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3339 CHAR buf[MAX_CMD_SIZE] = {0};
3340 CHAR Value[MAX_BUF_SIZE] = {0};
3341 FILE *fp = NULL;
3342
3343 if (ifname == NULL || strlen(ifname) <= 1)
3344 return RETURN_OK;
3345
3346 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3347 system(buf);
3348
3349 fp = fopen("/tmp/Radio_Stats.txt", "r");
3350 if(fp == NULL)
3351 {
3352 printf("/tmp/Radio_Stats.txt not exists \n");
3353 return RETURN_ERR;
3354 }
3355 fclose(fp);
3356
3357 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3358 File_Reading(buf, Value);
3359 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3360
3361 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3362 File_Reading(buf, Value);
3363 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3364
3365 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3366 File_Reading(buf, Value);
3367 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3368
3369 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3370 File_Reading(buf, Value);
3371 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3372
3373 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3374 File_Reading(buf, Value);
3375 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3376
3377 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3378 File_Reading(buf, Value);
3379 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3380
3381 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3382 File_Reading(buf, Value);
3383 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3384
3385 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3386 File_Reading(buf, Value);
3387 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3388
3389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3390 return RETURN_OK;
3391}
3392
3393INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3394{
3395 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3396 CHAR buf[MAX_CMD_SIZE] = {0};
3397 FILE *fp = NULL;
3398 INT count = 0;
3399
3400 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3401 {
3402 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3403 File_Reading(buf, status);
3404 }
3405 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3406 return RETURN_OK;
3407}
3408
3409//Get detail radio traffic static info
3410INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3411{
3412
3413#if 0
3414 //ifconfig radio_x
3415 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3416 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3417 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3418 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3419
3420 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3421 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3422 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.
3423 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.
3424
3425 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3426 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].
3427 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3428 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.
3429 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
3430 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
3431 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
3432 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
3433 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
3434
3435 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
3436 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
3437 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
3438 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.
3439
3440 return RETURN_OK;
3441#endif
3442
developera91d99f2022-09-29 15:59:10 +08003443 CHAR interface_name[64] = {0};
3444 CHAR config_path[64] = {0};
3445 BOOL iface_status = FALSE;
3446 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003447
3448 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3449 if (NULL == output_struct)
3450 return RETURN_ERR;
3451
developera91d99f2022-09-29 15:59:10 +08003452 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3453 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003454
developera91d99f2022-09-29 15:59:10 +08003455 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003456
developera91d99f2022-09-29 15:59:10 +08003457 if (iface_status == TRUE)
3458 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3459 else
3460 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003461
developera91d99f2022-09-29 15:59:10 +08003462 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3463 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3464 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3465 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3466 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3467 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3468 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3469 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003470
3471 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3472 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].
3473 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3474 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.
3475 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
3476 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
3477 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
3478 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
3479 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
3480
3481 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
3482 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
3483 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
3484 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.
3485
3486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3487
3488 return RETURN_OK;
3489}
3490
3491//Set radio traffic static Measureing rules
3492INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3493{
3494 //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
3495 // Else, save the MeasuringRate and MeasuringInterval for future usage
3496
3497 return RETURN_OK;
3498}
3499
3500//To start or stop RadioTrafficStats
3501INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3502{
3503 //zqiu: If the RadioTrafficStats process running
3504 // if(enable)
3505 // return RETURN_OK.
3506 // else
3507 // Stop RadioTrafficStats process
3508 // Else
3509 // if(enable)
3510 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3511 // else
3512 // return RETURN_OK.
3513
3514 return RETURN_OK;
3515}
3516
3517//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
3518INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3519{
3520 //zqiu: Please ignor signalIndex.
3521 if (NULL == SignalLevel)
3522 return RETURN_ERR;
3523 *SignalLevel=(radioIndex==0)?-19:-19;
3524
3525 return RETURN_OK;
3526}
3527
3528//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3529INT wifi_applyRadioSettings(INT radioIndex)
3530{
3531 return RETURN_OK;
3532}
3533
3534//Get the radio index assocated with this SSID entry
3535INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3536{
3537 if (NULL == radioIndex)
3538 return RETURN_ERR;
3539 *radioIndex=ssidIndex%2;
3540
3541 return RETURN_OK;
3542}
3543
3544//Device.WiFi.SSID.{i}.Enable
3545//Get SSID enable configuration parameters (not the SSID enable status)
3546INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3547{
3548 if (NULL == output_bool)
3549 return RETURN_ERR;
3550
developer06a01d92022-09-07 16:32:39 +08003551 return wifi_getApEnable(ssidIndex, output_bool);
3552}
3553
3554//Device.WiFi.SSID.{i}.Enable
3555//Set SSID enable configuration parameters
3556INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3557{
developer06a01d92022-09-07 16:32:39 +08003558 return wifi_setApEnable(ssidIndex, enable);
3559}
3560
3561//Device.WiFi.SSID.{i}.Status
3562//Get the SSID enable status
3563INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3564{
3565 char cmd[MAX_CMD_SIZE]={0};
3566 char buf[MAX_BUF_SIZE]={0};
3567 BOOL output_bool;
3568
3569 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3570 if (NULL == output_string)
3571 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003572
developer06a01d92022-09-07 16:32:39 +08003573 wifi_getApEnable(ssidIndex,&output_bool);
3574 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3575
3576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3577 return RETURN_OK;
3578}
3579
3580// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3581INT wifi_getSSIDName(INT apIndex, CHAR *output)
3582{
3583 char config_file[MAX_BUF_SIZE] = {0};
3584
3585 if (NULL == output)
3586 return RETURN_ERR;
3587
3588 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3589 wifi_hostapdRead(config_file,"ssid",output,32);
3590
3591 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3592 return RETURN_OK;
3593}
3594
3595// Set a max 32 byte string and sets an internal variable to the SSID name
3596INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3597{
3598 char str[MAX_BUF_SIZE]={'\0'};
3599 char cmd[MAX_CMD_SIZE]={'\0'};
3600 struct params params;
3601 char config_file[MAX_BUF_SIZE] = {0};
3602
3603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3604 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3605 return RETURN_ERR;
3606
3607 params.name = "ssid";
3608 params.value = ssid_string;
3609 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3610 wifi_hostapdWrite(config_file, &params, 1);
3611 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3613
3614 return RETURN_OK;
3615}
3616
3617//Get the BSSID
3618INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3619{
3620 char cmd[MAX_CMD_SIZE]="";
3621
3622 if (NULL == output_string)
3623 return RETURN_ERR;
3624
3625 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3626 {
developer1d57d002022-10-12 18:03:15 +08003627 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 +08003628 _syscmd(cmd, output_string, 64);
3629 return RETURN_OK;
3630 }
3631 strncpy(output_string, "\0", 1);
3632
3633 return RETURN_ERR;
3634}
3635
3636//Get the MAC address associated with this Wifi SSID
3637INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3638{
3639 wifi_getBaseBSSID(ssidIndex,output_string);
3640 return RETURN_OK;
3641}
3642
3643//Get the basic SSID traffic static info
3644//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3645//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3646INT wifi_applySSIDSettings(INT ssidIndex)
3647{
3648 BOOL status = false;
3649 char cmd[MAX_CMD_SIZE] = {0};
3650 char buf[MAX_CMD_SIZE] = {0};
3651 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003652 int max_radio_num = 0;
3653 int radioIndex = 0;
3654
3655 wifi_getMaxRadioNumber(&max_radio_num);
3656
3657 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003658
3659 wifi_getApEnable(ssidIndex,&status);
3660 // Do not apply when ssid index is disabled
3661 if (status == false)
3662 return RETURN_OK;
3663
3664 /* Doing full remove and add for ssid Index
3665 * Not all hostapd options are supported with reload
3666 * for example macaddr_acl
3667 */
3668 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3669 return RETURN_ERR;
3670
3671 ret = wifi_setApEnable(ssidIndex,true);
3672
3673 /* Workaround for hostapd issue with multiple bss definitions
3674 * when first created interface will be removed
3675 * then all vaps other vaps on same phy are removed
3676 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003677 for(int i=0; i < MAX_APS/max_radio_num; i++) {
3678 apIndex = max_radio_num*i+radioIndex;
developer06a01d92022-09-07 16:32:39 +08003679 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3680 _syscmd(cmd, buf, sizeof(buf));
3681 if(*buf == '1')
3682 wifi_setApEnable(apIndex, true);
3683 }
3684
3685 return ret;
3686}
3687
developera3c68b92022-09-13 15:27:29 +08003688struct channels_noise {
3689 int channel;
3690 int noise;
3691};
3692
3693// Return noise array for each channel
3694int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3695{
3696 FILE *f = NULL;
3697 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003698 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003699 size_t len = 0;
3700 ssize_t read = 0;
3701 int tmp = 0, arr_index = -1;
3702
3703 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3704
3705 if ((f = popen(cmd, "r")) == NULL) {
3706 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3707 return RETURN_ERR;
3708 }
developer5550e242022-09-30 09:59:32 +08003709
3710 while(fgets(line, sizeof(line), f) != NULL) {
3711 if(arr_index < channels_num){
3712 sscanf(line, "%d", &tmp);
3713 if (tmp > 0) { // channel frequency, the first line must be frequency
3714 arr_index++;
3715 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3716 } else { // noise
3717 channels_noise_arr[arr_index].noise = tmp;
3718 }
3719 }else{
3720 break;
developera3c68b92022-09-13 15:27:29 +08003721 }
3722 }
developera3c68b92022-09-13 15:27:29 +08003723 pclose(f);
3724 return RETURN_OK;
3725}
3726
developer06a01d92022-09-07 16:32:39 +08003727//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3728//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3729INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3730{
developera3c68b92022-09-13 15:27:29 +08003731 int index = -1;
3732 wifi_neighbor_ap2_t *scan_array = NULL;
3733 char cmd[256]={0};
3734 char buf[128]={0};
3735 char file_name[32] = {0};
3736 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003737 char line[256] = {0};
3738 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003739 int freq=0;
3740 FILE *f = NULL;
3741 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003742 int channels_num = 0;
3743 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003744 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003745 bool filter_enable = false;
3746 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003747 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003748
developer615510b2022-09-27 10:14:35 +08003749 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003750
3751 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3752 f = fopen(file_name, "r");
3753 if (f != NULL) {
3754 fgets(filter_SSID, sizeof(file_name), f);
3755 if (strlen(filter_SSID) != 0)
3756 filter_enable = true;
3757 fclose(f);
3758 }
3759
developer033b37b2022-10-18 11:27:46 +08003760 phyId = radio_index_to_phy(radioIndex);
3761 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003762 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003763 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003764
developer5550e242022-09-30 09:59:32 +08003765
developer06a01d92022-09-07 16:32:39 +08003766
developera3c68b92022-09-13 15:27:29 +08003767 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 +08003768 // 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 +08003769 fprintf(stderr, "cmd: %s\n", cmd);
3770 if ((f = popen(cmd, "r")) == NULL) {
3771 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3772 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003773 }
developer5550e242022-09-30 09:59:32 +08003774
3775 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3776 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3777
developer615510b2022-09-27 10:14:35 +08003778 ret = fgets(line, sizeof(line), f);
3779 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003780 if(strstr(line, "BSS") != NULL) { // new neighbor info
3781 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3782 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3783 // 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 +08003784
developera3c68b92022-09-13 15:27:29 +08003785 if (!filter_BSS) {
3786 index++;
3787 wifi_neighbor_ap2_t *tmp;
3788 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3789 if (tmp == NULL) { // no more memory to use
3790 index--;
3791 wifi_dbg_printf("%s: realloc failed\n", __func__);
3792 break;
3793 }
3794 scan_array = tmp;
3795 }
3796 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3797
3798 filter_BSS = false;
3799 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3800 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3801 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3802 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3803 } else if (strstr(line, "freq") != NULL) {
3804 sscanf(line," freq: %d", &freq);
3805 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3806
3807 if (freq >= 2412 && freq <= 2484) {
3808 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3809 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3810 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3811 }
3812 else if (freq >= 5160 && freq <= 5805) {
3813 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3814 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3815 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3816 }
3817
3818 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003819 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003820 for (int i = 0; i < channels_num; i++) {
3821 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3822 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3823 break;
3824 }
3825 }
3826 }
3827 } else if (strstr(line, "beacon interval") != NULL) {
3828 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3829 } else if (strstr(line, "signal") != NULL) {
3830 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3831 } else if (strstr(line,"SSID") != NULL) {
3832 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3833 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3834 filter_BSS = true;
3835 }
3836 } else if (strstr(line, "Supported rates") != NULL) {
3837 char SRate[80] = {0}, *tmp = NULL;
3838 memset(buf, 0, sizeof(buf));
3839 strcpy(SRate, line);
3840 tmp = strtok(SRate, ":");
3841 tmp = strtok(NULL, ":");
3842 strcpy(buf, tmp);
3843 memset(SRate, 0, sizeof(SRate));
3844
3845 tmp = strtok(buf, " \n");
3846 while (tmp != NULL) {
3847 strcat(SRate, tmp);
3848 if (SRate[strlen(SRate) - 1] == '*') {
3849 SRate[strlen(SRate) - 1] = '\0';
3850 }
3851 strcat(SRate, ",");
3852
3853 tmp = strtok(NULL, " \n");
3854 }
3855 SRate[strlen(SRate) - 1] = '\0';
3856 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3857 } else if (strstr(line, "DTIM") != NULL) {
3858 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3859 } else if (strstr(line, "VHT capabilities") != NULL) {
3860 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3861 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3862 } else if (strstr(line, "HT capabilities") != NULL) {
3863 strcat(scan_array[index].ap_SupportedStandards, ",n");
3864 strcpy(scan_array[index].ap_OperatingStandards, "n");
3865 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003866 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003867 sscanf(line," * channel width: %d", &vht_channel_width);
3868 if(vht_channel_width == 1) {
3869 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3870 } else {
3871 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3872 }
3873 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3874 continue;
3875 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003876 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003877 sscanf(line," * secondary channel offset: %s", &buf);
3878 if (!strcmp(buf, "above")) {
3879 //40Mhz +
3880 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3881 }
3882 else if (!strcmp(buf, "below")) {
3883 //40Mhz -
3884 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3885 } else {
3886 //20Mhz
3887 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3888 }
3889 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3890 continue;
3891 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003892 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3893 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3894 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003895 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3896 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003897 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003898 else
developer615510b2022-09-27 10:14:35 +08003899 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003900 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003901 if (strstr(line, "HE80/5GHz") != NULL) {
3902 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3903 ret = fgets(line, sizeof(line), f);
3904 } else
3905 continue;
developera3c68b92022-09-13 15:27:29 +08003906 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003907 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003908 }
developer615510b2022-09-27 10:14:35 +08003909 continue;
developera3c68b92022-09-13 15:27:29 +08003910 } else if (strstr(line, "WPA") != NULL) {
3911 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3912 } else if (strstr(line, "RSN") != NULL) {
3913 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3914 } else if (strstr(line, "Group cipher") != NULL) {
3915 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3916 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3917 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3918 }
3919 }
developer615510b2022-09-27 10:14:35 +08003920 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003921 }
3922
3923 if (!filter_BSS) {
3924 *output_array_size = index + 1;
3925 } else {
3926 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3927 *output_array_size = index;
3928 }
3929 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003930 pclose(f);
developer5550e242022-09-30 09:59:32 +08003931 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003932 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003933 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003934}
3935
3936//>> Deprecated: used for old RDKB code.
3937INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3938{
3939 INT status = RETURN_ERR;
3940
3941 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3942 output_struct->wifi_PLCPErrorCount = 0;
3943 output_struct->wifi_FCSErrorCount = 0;
3944 output_struct->wifi_InvalidMACCount = 0;
3945 output_struct->wifi_PacketsOtherReceived = 0;
3946 output_struct->wifi_Noise = 0;
3947 status = RETURN_OK;
3948 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3949 return status;
3950}
3951
3952INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3953{
3954 char cmd[128];
3955 char buf[1280];
3956 char *pos = NULL;
3957
3958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3959 if (NULL == output_struct)
3960 return RETURN_ERR;
3961
3962 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3963
3964 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3965 _syscmd(cmd, buf, sizeof(buf));
3966
3967 pos = buf;
3968 if ((pos = strstr(pos, "RX packets:")) == NULL)
3969 return RETURN_ERR;
3970 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3971
3972 if ((pos = strstr(pos, "TX packets:")) == NULL)
3973 return RETURN_ERR;
3974 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3975
3976 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3977 return RETURN_ERR;
3978 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3979
3980 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3981 return RETURN_ERR;
3982 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3983
3984 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3985 _syscmd(cmd, buf, sizeof(buf));
3986 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3987
3988#if 0
3989 //TODO: need to revisit below implementation
3990 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3991 char interface_name[MAX_BUF_SIZE] = {0};
3992 char interface_status[MAX_BUF_SIZE] = {0};
3993 char Value[MAX_BUF_SIZE] = {0};
3994 char buf[MAX_CMD_SIZE] = {0};
3995 char cmd[MAX_CMD_SIZE] = {0};
3996 FILE *fp = NULL;
3997
3998 if (NULL == output_struct) {
3999 return RETURN_ERR;
4000 }
4001
4002 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4003
4004 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4005 {
4006 if(apIndex == 0) //private_wifi for 2.4G
4007 {
4008 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4009 }
4010 else if(apIndex == 1) //private_wifi for 5G
4011 {
4012 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4013 }
4014 else if(apIndex == 4) //public_wifi for 2.4G
4015 {
4016 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4017 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4018 {
4019 return RETURN_ERR;
4020 }
4021 if(buf[0] == '#')//tp-link
4022 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4023 else//tenda
4024 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4025 }
4026 else if(apIndex == 5) //public_wifi for 5G
4027 {
4028 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4029 }
4030
4031 GetIfacestatus(interface_name, interface_status);
4032
4033 if(0 != strcmp(interface_status, "1"))
4034 return RETURN_ERR;
4035
4036 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4037 system(cmd);
4038
4039 fp = fopen("/tmp/SSID_Stats.txt", "r");
4040 if(fp == NULL)
4041 {
4042 printf("/tmp/SSID_Stats.txt not exists \n");
4043 return RETURN_ERR;
4044 }
4045 fclose(fp);
4046
4047 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4048 File_Reading(buf, Value);
4049 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4050
4051 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4052 File_Reading(buf, Value);
4053 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4054
4055 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4056 File_Reading(buf, Value);
4057 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4058
4059 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4060 File_Reading(buf, Value);
4061 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4062
4063 /* There is no specific parameter from caller to associate the value wifi_Associations */
4064 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4065 //_syscmd(cmd, buf, sizeof(buf));
4066 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4067 }
4068#endif
4069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4070 return RETURN_OK;
4071}
4072
4073INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4074{
4075 char interface_name[MAX_BUF_SIZE] = {0};
4076 char interface_status[MAX_BUF_SIZE] = {0};
4077 char Value[MAX_BUF_SIZE] = {0};
4078 char buf[MAX_CMD_SIZE] = {0};
4079 char cmd[MAX_CMD_SIZE] = {0};
4080 FILE *fp = NULL;
4081
4082 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4083 if (NULL == output_struct)
4084 return RETURN_ERR;
4085
4086 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4087
4088 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4089 {
4090 if(apIndex == 0) //private_wifi for 2.4G
4091 {
4092 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4093 }
4094 else if(apIndex == 1) //private_wifi for 5G
4095 {
4096 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4097 }
4098 else if(apIndex == 4) //public_wifi for 2.4G
4099 {
4100 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4101 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4102 {
4103 return RETURN_ERR;
4104 }
4105 if(buf[0] == '#')
4106 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4107 else
4108 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4109 }
4110 else if(apIndex == 5) //public_wifi for 5G
4111 {
4112 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4113 }
4114
4115 GetIfacestatus(interface_name, interface_status);
4116
4117 if(0 != strcmp(interface_status, "1"))
4118 return RETURN_ERR;
4119
4120 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4121 system(cmd);
4122
4123 fp = fopen("/tmp/SSID_Stats.txt", "r");
4124 if(fp == NULL)
4125 {
4126 printf("/tmp/SSID_Stats.txt not exists \n");
4127 return RETURN_ERR;
4128 }
4129 fclose(fp);
4130
4131 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4132 File_Reading(buf, Value);
4133 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4134
4135 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4136 File_Reading(buf, Value);
4137 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4138
4139 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4140 File_Reading(buf, Value);
4141 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4142
4143 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4144 File_Reading(buf, Value);
4145 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4146 }
4147
4148 output_struct->wifi_UnicastPacketsSent = 0;
4149 output_struct->wifi_UnicastPacketsReceived = 0;
4150 output_struct->wifi_MulticastPacketsSent = 0;
4151 output_struct->wifi_MulticastPacketsReceived = 0;
4152 output_struct->wifi_BroadcastPacketsSent = 0;
4153 output_struct->wifi_BroadcastPacketsRecevied = 0;
4154 output_struct->wifi_UnknownPacketsReceived = 0;
4155
4156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4157 return RETURN_OK;
4158}
4159
4160INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4161{
4162 INT status = RETURN_ERR;
4163
4164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4165 //Below values should get updated from hal
4166 output_struct->wifi_RetransCount=0;
4167 output_struct->wifi_FailedRetransCount=0;
4168 output_struct->wifi_RetryCount=0;
4169 output_struct->wifi_MultipleRetryCount=0;
4170 output_struct->wifi_ACKFailureCount=0;
4171 output_struct->wifi_AggregatedPacketCount=0;
4172
4173 status = RETURN_OK;
4174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4175
4176 return status;
4177}
4178
4179INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4180{
4181 INT status = RETURN_ERR;
4182 UINT index;
4183 wifi_neighbor_ap_t *pt=NULL;
4184
4185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4186 *output_array_size=2;
4187 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4188 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4189 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4190 strcpy(pt->ap_Radio,"");
4191 strcpy(pt->ap_SSID,"");
4192 strcpy(pt->ap_BSSID,"");
4193 strcpy(pt->ap_Mode,"");
4194 pt->ap_Channel=1;
4195 pt->ap_SignalStrength=0;
4196 strcpy(pt->ap_SecurityModeEnabled,"");
4197 strcpy(pt->ap_EncryptionMode,"");
4198 strcpy(pt->ap_OperatingFrequencyBand,"");
4199 strcpy(pt->ap_SupportedStandards,"");
4200 strcpy(pt->ap_OperatingStandards,"");
4201 strcpy(pt->ap_OperatingChannelBandwidth,"");
4202 pt->ap_BeaconPeriod=1;
4203 pt->ap_Noise=0;
4204 strcpy(pt->ap_BasicDataTransferRates,"");
4205 strcpy(pt->ap_SupportedDataTransferRates,"");
4206 pt->ap_DTIMPeriod=1;
4207 pt->ap_ChannelUtilization = 1;
4208 }
4209
4210 status = RETURN_OK;
4211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4212
4213 return status;
4214}
4215
4216//----------------- AP HAL -------------------------------
4217
4218//>> Deprecated: used for old RDKB code.
4219INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4220{
4221 if (NULL == output_ulong || NULL == output_struct)
4222 return RETURN_ERR;
4223 *output_ulong = 0;
4224 *output_struct = NULL;
4225 return RETURN_OK;
4226}
4227
4228#ifdef HAL_NETLINK_IMPL
4229static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4230 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4231 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4232 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4233 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4234 char mac_addr[20];
4235 static int count=0;
4236 int rate=0;
4237
4238 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4239
4240 nla_parse(tb,
4241 NL80211_ATTR_MAX,
4242 genlmsg_attrdata(gnlh, 0),
4243 genlmsg_attrlen(gnlh, 0),
4244 NULL);
4245
4246 if(!tb[NL80211_ATTR_STA_INFO]) {
4247 fprintf(stderr, "sta stats missing!\n");
4248 return NL_SKIP;
4249 }
4250
4251
4252 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4253 fprintf(stderr, "failed to parse nested attributes!\n");
4254 return NL_SKIP;
4255 }
4256
4257 //devIndex starts from 1
4258 if( ++count == out->wifi_devIndex )
4259 {
4260 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4261 //Getting the mac addrress
4262 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4263
4264 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4265 fprintf(stderr, "failed to parse nested rate attributes!");
4266 return NL_SKIP;
4267 }
4268
4269 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4270 if(rinfo[NL80211_RATE_INFO_BITRATE])
4271 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4272 out->wifi_devTxRate = rate/10;
4273 }
4274
4275 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4276 fprintf(stderr, "failed to parse nested rate attributes!");
4277 return NL_SKIP;
4278 }
4279
4280 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4281 if(rinfo[NL80211_RATE_INFO_BITRATE])
4282 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4283 out->wifi_devRxRate = rate/10;
4284 }
4285 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4286 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4287
4288 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4289 count = 0; //starts the count for next cycle
4290 return NL_STOP;
4291 }
4292
4293 return NL_SKIP;
4294
4295}
4296#endif
4297
4298INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4299{
4300#ifdef HAL_NETLINK_IMPL
4301 Netlink nl;
4302 char if_name[10];
4303
4304 wifi_device_info_t info;
4305 info.wifi_devIndex = devIndex;
4306
4307 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4308
4309 nl.id = initSock80211(&nl);
4310
4311 if (nl.id < 0) {
4312 fprintf(stderr, "Error initializing netlink \n");
4313 return -1;
4314 }
4315
4316 struct nl_msg* msg = nlmsg_alloc();
4317
4318 if (!msg) {
4319 fprintf(stderr, "Failed to allocate netlink message.\n");
4320 nlfree(&nl);
4321 return -2;
4322 }
4323
4324 genlmsg_put(msg,
4325 NL_AUTO_PORT,
4326 NL_AUTO_SEQ,
4327 nl.id,
4328 0,
4329 NLM_F_DUMP,
4330 NL80211_CMD_GET_STATION,
4331 0);
4332
4333 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4334 nl_send_auto(nl.socket, msg);
4335 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4336 nl_recvmsgs(nl.socket, nl.cb);
4337 nlmsg_free(msg);
4338 nlfree(&nl);
4339
4340 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4341 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4342 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4343 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4344 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4345 return RETURN_OK;
4346#else
4347 //iw utility to retrieve station information
4348#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4349#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4350#define MACFILE "/tmp/wifi_AssoMac.txt"
4351#define TXRATEFILE "/tmp/wifi_txrate.txt"
4352#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4353 FILE *file = NULL;
4354 char if_name[10] = {'\0'};
4355 char pipeCmd[256] = {'\0'};
4356 char line[256];
4357 int count,device = 0;
4358
4359 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4360
4361 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4362 file = popen(pipeCmd, "r");
4363
4364 if(file == NULL)
4365 return RETURN_ERR; //popen failed
4366
4367 fgets(line, sizeof line, file);
4368 device = atoi(line);
4369 pclose(file);
4370
4371 if(device == 0)
4372 return RETURN_ERR; //No devices are connected
4373
4374 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4375 system(pipeCmd);
4376
4377 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4378
4379 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4380
4381 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4382
4383 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4384
4385 //devIndex starts from 1, ++count
4386 if((file = fopen(SIGNALFILE, "r")) != NULL )
4387 {
4388 for(count =0;fgets(line, sizeof line, file) != NULL;)
4389 {
4390 if (++count == devIndex)
4391 {
4392 output_struct->wifi_devSignalStrength = atoi(line);
4393 break;
4394 }
4395 }
4396 fclose(file);
4397 }
4398 else
4399 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4400
4401 if((file = fopen(MACFILE, "r")) != NULL )
4402 {
4403 for(count =0;fgets(line, sizeof line, file) != NULL;)
4404 {
4405 if (++count == devIndex)
4406 {
4407 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]);
4408 break;
4409 }
4410 }
4411 fclose(file);
4412 }
4413 else
4414 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4415
4416 if((file = fopen(TXRATEFILE, "r")) != NULL )
4417 {
4418 for(count =0;fgets(line, sizeof line, file) != NULL;)
4419 {
4420 if (++count == devIndex)
4421 {
4422 output_struct->wifi_devTxRate = atoi(line);
4423 break;
4424 }
4425 }
4426 fclose(file);
4427 }
4428 else
4429 fprintf(stderr,"fopen wifi_txrate.txt failed");
4430
4431 if((file = fopen(RXRATEFILE, "r")) != NULL)
4432 {
4433 for(count =0;fgets(line, sizeof line, file) != NULL;)
4434 {
4435 if (++count == devIndex)
4436 {
4437 output_struct->wifi_devRxRate = atoi(line);
4438 break;
4439 }
4440 }
4441 fclose(file);
4442 }
4443 else
4444 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4445
4446 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4447
4448 return RETURN_OK;
4449#endif
4450}
4451
4452INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4453{
4454 if (NULL == device)
4455 return RETURN_ERR;
4456 return RETURN_OK;
4457}
4458//<<
4459
4460
4461//--------------wifi_ap_hal-----------------------------
4462//enables CTS protection for the radio used by this AP
4463INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4464{
4465 //save config and Apply instantly
4466 return RETURN_ERR;
4467}
4468
4469// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4470INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4471{
developer463d39a2022-09-13 15:32:51 +08004472 char config_file[64] = {'\0'};
4473 char buf[64] = {'\0'};
4474 struct params list;
4475
4476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4477 list.name = "ht_coex";
4478 snprintf(buf, sizeof(buf), "%d", enable);
4479 list.value = buf;
4480
4481 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4482 wifi_hostapdWrite(config_file, &list, 1);
4483 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4484
4485 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4486
4487 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004488}
4489
4490//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4491INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4492{
developerea4bcce2022-09-13 15:26:13 +08004493 char config_file[MAX_BUF_SIZE] = {'\0'};
4494 char buf[MAX_BUF_SIZE] = {'\0'};
4495 struct params list;
4496
4497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4498 if (threshold < 256 || threshold > 2346 )
4499 return RETURN_ERR;
4500 list.name = "fragm_threshold";
4501 snprintf(buf, sizeof(buf), "%d", threshold);
4502 list.value = buf;
4503
4504 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4505 wifi_hostapdWrite(config_file, &list, 1);
4506 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004507
developerea4bcce2022-09-13 15:26:13 +08004508 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004509
4510 return RETURN_OK;
4511}
4512
4513// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4514INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4515{
developer51a927d2022-09-13 15:42:22 +08004516 char config_file[64] = {'\0'};
4517 char cmd[128] = {'\0'};
4518 char buf[64] = {'\0'};
4519 char stbc_config[16] = {'\0'};
4520 wifi_band band;
4521 int iterator = 0;
4522 BOOL current_stbc = FALSE;
4523
4524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4525
4526 band = wifi_index_to_band(radioIndex);
4527 if (band == band_invalid)
4528 return RETURN_ERR;
4529
4530 if (band == band_2_4)
4531 iterator = 1;
4532 else if (band == band_5)
4533 iterator = 2;
4534 else
4535 return RETURN_OK;
4536
4537 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4538
4539 // set ht and vht config
4540 for (int i = 0; i < iterator; i++) {
4541 memset(stbc_config, 0, sizeof(stbc_config));
4542 memset(cmd, 0, sizeof(cmd));
4543 memset(buf, 0, sizeof(buf));
4544 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4545 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4546 _syscmd(cmd, buf, sizeof(buf));
4547 if (strlen(buf) != 0)
4548 current_stbc = TRUE;
4549 if (current_stbc == STBC_Enable)
4550 continue;
4551
4552 if (STBC_Enable == TRUE) {
4553 // Append the STBC flags in capab config
4554 memset(cmd, 0, sizeof(cmd));
4555 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004556 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004557 else
developer6372c2b2022-10-27 17:39:51 +08004558 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004559 _syscmd(cmd, buf, sizeof(buf));
4560 } else if (STBC_Enable == FALSE) {
4561 // Remove the STBC flags and remain other flags in capab
4562 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004563 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004564 _syscmd(cmd, buf, sizeof(buf));
4565 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004566 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004567 _syscmd(cmd, buf, sizeof(buf));
4568 }
4569 }
4570
4571 wifi_reloadAp(radioIndex);
4572
4573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4574 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004575}
4576
4577// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4578INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4579{
developer54e6b9f2022-09-28 14:41:20 +08004580 char AMSDU_file_path[64] = {0};
4581
4582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4583
4584 if(output_bool == NULL)
4585 return RETURN_ERR;
4586
4587 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4588
4589 if (access(AMSDU_file_path, F_OK) == 0)
4590 *output_bool = TRUE;
4591 else
4592 *output_bool = FALSE;
4593
4594 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4595 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004596}
4597
4598// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4599INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4600{
developer54e6b9f2022-09-28 14:41:20 +08004601 char cmd[64]={0};
4602 char buf[64]={0};
4603 char AMSDU_file_path[64] = {0};
4604
4605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4606
4607 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4608 _syscmd(cmd, buf, sizeof(buf));
4609
4610 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4611 memset(cmd, 0, sizeof(cmd));
4612 if (amsduEnable == TRUE)
4613 sprintf(cmd, "touch %s", AMSDU_file_path);
4614 else
4615 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4616 _syscmd(cmd, buf, sizeof(buf));
4617
4618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4619 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004620}
4621
4622//P2 // outputs the number of Tx streams
4623INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4624{
developer2de97692022-09-26 14:00:03 +08004625 char buf[8] = {0};
4626 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004627 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004628
4629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4630
4631 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4632 _syscmd(cmd, buf, sizeof(buf));
4633
developer033b37b2022-10-18 11:27:46 +08004634 phyId = radio_index_to_phy(radioIndex);
developer2de97692022-09-26 14:00:03 +08004635 // if there is no record, output the max number of spatial streams
4636 if (strlen(buf) == 0) {
developer033b37b2022-10-18 11:27:46 +08004637 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", phyId);
developer2de97692022-09-26 14:00:03 +08004638 _syscmd(cmd, buf, sizeof(buf));
4639 }
4640
4641 *output_int = (INT)strtol(buf, NULL, 10);
4642
4643 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4644
4645 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004646}
4647
4648//P2 // sets the number of Tx streams to an enviornment variable
4649INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4650{
developer2de97692022-09-26 14:00:03 +08004651 char cmd[128] = {0};
4652 char buf[128] = {0};
4653 char chain_mask_file[128] = {0};
4654 FILE *f = NULL;
developer033b37b2022-10-18 11:27:46 +08004655 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004656
4657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4658
4659 if (numStreams == 0) {
4660 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4661 return RETURN_ERR;
4662 }
4663 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004664
4665 phyId = radio_index_to_phy(radioIndex);
4666 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004667 _syscmd(cmd, buf, sizeof(buf));
4668
4669 if (strlen(buf) > 0) {
4670 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4671 return RETURN_ERR;
4672 }
4673 wifi_setRadioEnable(radioIndex, TRUE);
4674
4675 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4676 f = fopen(chain_mask_file, "w");
4677 if (f == NULL) {
4678 fprintf(stderr, "%s: fopen failed.\n", __func__);
4679 return RETURN_ERR;
4680 }
4681 fprintf(f, "%d", numStreams);
4682 fclose(f);
4683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4684 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004685}
4686
4687//P2 // outputs the number of Rx streams
4688INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4689{
developer2de97692022-09-26 14:00:03 +08004690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4691 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4692 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004693 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004694 }
4695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004696 return RETURN_OK;
4697}
4698
4699//P2 // sets the number of Rx streams to an enviornment variable
4700INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4701{
developer2de97692022-09-26 14:00:03 +08004702 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4703 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4704 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4705 return RETURN_ERR;
4706 }
4707 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004708 return RETURN_ERR;
4709}
4710
4711//Get radio RDG enable setting
4712INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4713{
4714 if (NULL == output_bool)
4715 return RETURN_ERR;
4716 *output_bool = TRUE;
4717 return RETURN_OK;
4718}
4719
4720//Get radio RDG enable setting
4721INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4722{
4723 if (NULL == output_bool)
4724 return RETURN_ERR;
4725 *output_bool = TRUE;
4726 return RETURN_OK;
4727}
4728
4729//Set radio RDG enable setting
4730INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4731{
4732 return RETURN_ERR;
4733}
4734
4735//Get radio ADDBA enable setting
4736INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4737{
4738 if (NULL == output_bool)
4739 return RETURN_ERR;
4740 *output_bool = TRUE;
4741 return RETURN_OK;
4742}
4743
4744//Set radio ADDBA enable setting
4745INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4746{
4747 return RETURN_ERR;
4748}
4749
4750//Get radio auto block ack enable setting
4751INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4752{
4753 if (NULL == output_bool)
4754 return RETURN_ERR;
4755 *output_bool = TRUE;
4756 return RETURN_OK;
4757}
4758
4759//Set radio auto block ack enable setting
4760INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4761{
4762 return RETURN_ERR;
4763}
4764
4765//Get radio 11n pure mode enable support
4766INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4767{
4768 if (NULL == output_bool)
4769 return RETURN_ERR;
4770 *output_bool = TRUE;
4771 return RETURN_OK;
4772}
4773
4774//Get radio 11n pure mode enable setting
4775INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4776{
4777 if (NULL == output_bool)
4778 return RETURN_ERR;
4779 *output_bool = TRUE;
4780 return RETURN_OK;
4781}
4782
4783//Set radio 11n pure mode enable setting
4784INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4785{
4786 return RETURN_ERR;
4787}
4788
4789//Get radio IGMP snooping enable setting
4790INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4791{
developer81bf2ed2022-09-13 15:31:14 +08004792 char cmd[128]={0};
4793 char buf[4]={0};
4794 bool bridge = FALSE, mac80211 = FALSE;
4795 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4796
4797 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004798 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004799
4800 *output_bool = FALSE;
4801
4802 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4803 _syscmd(cmd, buf, sizeof(buf));
4804 if (strncmp(buf, "1", 1) == 0)
4805 bridge = TRUE;
4806
4807 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4808 _syscmd(cmd, buf, sizeof(buf));
4809 if (strncmp(buf, "1", 1) == 0)
4810 mac80211 = TRUE;
4811
4812 if (bridge && mac80211)
4813 *output_bool = TRUE;
4814
4815 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004816 return RETURN_OK;
4817}
4818
4819//Set radio IGMP snooping enable setting
4820INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4821{
developer81bf2ed2022-09-13 15:31:14 +08004822 char cmd[128]={0};
4823 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004824 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004825 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4826
4827 // bridge
4828 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4829 _syscmd(cmd, buf, sizeof(buf));
4830
developer804c64f2022-10-19 13:54:40 +08004831 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004832 // mac80211
developer804c64f2022-10-19 13:54:40 +08004833 for (int i = 0; i < max_num_radios; i++) {
developer81bf2ed2022-09-13 15:31:14 +08004834 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4835 _syscmd(cmd, buf, sizeof(buf));
4836 }
4837 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4838 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004839}
4840
4841//Get the Reset count of radio
4842INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4843{
4844 if (NULL == output_int)
4845 return RETURN_ERR;
4846 *output_int = (radioIndex==0)? 1: 3;
4847
4848 return RETURN_OK;
4849}
4850
4851
4852//---------------------------------------------------------------------------------------------------
4853//
4854// Additional Wifi AP level APIs used for Access Point devices
4855//
4856//---------------------------------------------------------------------------------------------------
4857
4858// creates a new ap and pushes these parameters to the hardware
4859INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4860{
4861 char buf[1024];
4862 char cmd[128];
developer033b37b2022-10-18 11:27:46 +08004863 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004864
4865 if (NULL == essid)
4866 return RETURN_ERR;
4867
developer033b37b2022-10-18 11:27:46 +08004868 phyId = radio_index_to_phy(radioIndex);
4869 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08004870 _syscmd(cmd, buf, sizeof(buf));
4871
4872 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4873 _syscmd(cmd, buf, sizeof(buf));
4874
4875 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4876
4877 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4878 _syscmd(cmd, buf, sizeof(buf));
4879
4880 return RETURN_OK;
4881}
4882
4883// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4884INT wifi_deleteAp(INT apIndex)
4885{
4886 char buf[1024];
4887 char cmd[128];
4888
4889 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4890 _syscmd(cmd, buf, sizeof(buf));
4891
4892 wifi_removeApSecVaribles(apIndex);
4893
4894 return RETURN_OK;
4895}
4896
4897// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4898INT wifi_getApName(INT apIndex, CHAR *output_string)
4899{
4900 if(NULL == output_string)
4901 return RETURN_ERR;
4902
4903 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4904 return RETURN_OK;
4905}
4906
4907// Outputs the index number in that corresponds to the SSID string
4908INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4909{
4910 CHAR *pos = NULL;
4911
4912 *output_int = -1;
4913 pos = strstr(inputSsidString, AP_PREFIX);
4914 if(pos)
4915 {
4916 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4917 return RETURN_OK;
4918 }
4919 return RETURN_ERR;
4920}
4921
4922INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4923{
4924 return wifi_getIndexFromName(inputSsidString, output_int);
4925}
4926
4927// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4928INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4929{
4930 char buf[MAX_BUF_SIZE] = {0};
4931 char cmd[MAX_CMD_SIZE] = {0};
4932 char config_file[MAX_BUF_SIZE] = {0};
4933
4934 if(NULL == output_string)
4935 return RETURN_ERR;
4936
4937 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4938 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4939 if((strcmp(buf,"3")==0))
4940 snprintf(output_string, 32, "WPAand11i");
4941 else if((strcmp(buf,"2")==0))
4942 snprintf(output_string, 32, "11i");
4943 else if((strcmp(buf,"1")==0))
4944 snprintf(output_string, 32, "WPA");
4945 else
4946 snprintf(output_string, 32, "None");
4947
4948 return RETURN_OK;
4949}
4950
4951// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4952INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4953{
4954 char config_file[MAX_BUF_SIZE] = {0};
4955 struct params list;
4956
4957 if (NULL == beaconTypeString)
4958 return RETURN_ERR;
4959 list.name = "wpa";
4960 list.value = "0";
4961
4962 if((strcmp(beaconTypeString,"WPAand11i")==0))
4963 list.value="3";
4964 else if((strcmp(beaconTypeString,"11i")==0))
4965 list.value="2";
4966 else if((strcmp(beaconTypeString,"WPA")==0))
4967 list.value="1";
4968
4969 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4970 wifi_hostapdWrite(config_file, &list, 1);
4971 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4972 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4973 return RETURN_OK;
4974}
4975
4976// sets the beacon interval on the hardware for this AP
4977INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4978{
developer5f222492022-09-13 15:21:52 +08004979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4980 struct params params={'\0'};
4981 char buf[MAX_BUF_SIZE] = {'\0'};
4982 char config_file[MAX_BUF_SIZE] = {'\0'};
4983
4984 params.name = "beacon_int";
4985 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4986 params.value = buf;
4987
4988 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4989 wifi_hostapdWrite(config_file, &params, 1);
4990
4991 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4993 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004994}
4995
4996INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4997{
4998 //save config and apply instantly
4999 return RETURN_ERR;
5000}
5001
5002// Get the packet size threshold supported.
5003INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5004{
5005 //save config and apply instantly
5006 if (NULL == output_bool)
5007 return RETURN_ERR;
5008 *output_bool = FALSE;
5009 return RETURN_OK;
5010}
5011
5012// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5013INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5014{
5015 char cmd[128];
5016 char buf[512];
5017
5018 if (threshold > 0)
5019 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
5020 else
5021 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
5022 _syscmd(cmd, buf, sizeof(buf));
5023
5024 return RETURN_OK;
5025}
5026
5027// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5028INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5029{
5030 if (NULL == output_string)
5031 return RETURN_ERR;
5032 snprintf(output_string, 32, "TKIPandAESEncryption");
5033 return RETURN_OK;
5034
5035}
5036
5037// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5038INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5039{
5040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5041 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
5042
5043 if(NULL == output_string)
5044 return RETURN_ERR;
5045
5046 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5047 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5048
5049 if(strcmp(buf,"0")==0)
5050 {
5051 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5052 snprintf(output_string, 32, "None");
5053 return RETURN_OK;
5054 }
5055 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5056 param_name = "rsn_pairwise";
5057 else if((strcmp(buf,"1")==0))
5058 param_name = "wpa_pairwise";
5059 else
5060 return RETURN_ERR;
5061 memset(output_string,'\0',32);
5062 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5063 wifi_hostapdRead(config_file,param_name,output_string,32);
5064 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5065
5066 if(strcmp(output_string,"TKIP") == 0)
5067 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5068 else if(strcmp(output_string,"CCMP") == 0)
5069 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5070 else if(strcmp(output_string,"TKIP CCMP") == 0)
5071 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5072
5073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5074 return RETURN_OK;
5075}
5076
5077// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5078INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5079{
5080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5081 struct params params={'\0'};
5082 char output_string[32];
5083 char config_file[MAX_BUF_SIZE] = {0};
5084
5085 memset(output_string,'\0',32);
5086 wifi_getApWpaEncryptionMode(apIndex,output_string);
5087
5088 if(strcmp(encMode, "TKIPEncryption") == 0)
5089 params.value = "TKIP";
5090 else if(strcmp(encMode,"AESEncryption") == 0)
5091 params.value = "CCMP";
5092 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5093 params.value = "TKIP CCMP";
5094
5095 if((strcmp(output_string,"WPAand11i")==0))
5096 {
5097 params.name = "wpa_pairwise";
5098 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5099 wifi_hostapdWrite(config_file, &params, 1);
5100 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5101
5102 params.name,"rsn_pairwise";
5103 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5104 wifi_hostapdWrite(config_file, &params, 1);
5105 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5106
5107 return RETURN_OK;
5108 }
5109 else if((strcmp(output_string,"11i")==0))
5110 {
5111 params.name = "rsn_pairwise";
5112 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5113 wifi_hostapdWrite(config_file, &params, 1);
5114 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5115 return RETURN_OK;
5116 }
5117 else if((strcmp(output_string,"WPA")==0))
5118 {
5119 params.name = "wpa_pairwise";
5120 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5121 wifi_hostapdWrite(config_file, &params, 1);
5122 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5123 return RETURN_OK;
5124 }
5125
5126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5127 return RETURN_OK;
5128}
5129
5130// deletes internal security varable settings for this ap
5131INT wifi_removeApSecVaribles(INT apIndex)
5132{
5133 //TODO: remove the entry in hostapd config file
5134 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5135 //_syscmd(cmd, buf, sizeof(buf));
5136
5137 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5138 //_syscmd(cmd, buf, sizeof(buf));
5139 return RETURN_ERR;
5140}
5141
5142// changes the hardware settings to disable encryption on this ap
5143INT wifi_disableApEncryption(INT apIndex)
5144{
5145 //Apply instantly
5146 return RETURN_ERR;
5147}
5148
5149// set the authorization mode on this ap
5150// mode mapping as: 1: open, 2: shared, 4:auto
5151INT wifi_setApAuthMode(INT apIndex, INT mode)
5152{
developeraf95c502022-09-13 16:18:22 +08005153 struct params params={0};
5154 char config_file[64] = {0};
5155 int ret;
5156
5157 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5158
5159 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5160 params.name = "auth_algs";
5161
5162 if (mode & 1 && mode & 2)
5163 params.value = "3";
5164 else if (mode & 2)
5165 params.value = "2";
5166 else if (mode & 1)
5167 params.value = "1";
5168 else
5169 params.value = "0";
5170
5171 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5172 wifi_hostapdWrite(config_file, &params, 1);
5173 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5175
5176 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005177}
5178
5179// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5180INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5181{
5182 //save to wifi config, and wait for wifi restart to apply
5183 struct params params={'\0'};
5184 char config_file[MAX_BUF_SIZE] = {0};
5185 int ret;
5186
5187 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5188 if(authMode == NULL)
5189 return RETURN_ERR;
5190
5191 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5192 params.name = "wpa_key_mgmt";
5193
5194 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5195 params.value = "WPA-PSK";
5196 else if(strcmp(authMode,"EAPAuthentication") == 0)
5197 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005198 else if (strcmp(authMode, "SAEAuthentication") == 0)
5199 params.value = "SAE";
5200 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5201 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005202 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5203 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005204 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5205 return RETURN_OK; //This is taken careof in beaconType
5206
5207 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5208 ret=wifi_hostapdWrite(config_file,&params,1);
5209 if(!ret)
5210 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5212
5213 return ret;
5214}
5215
5216// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5217INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5218{
5219 //save to wifi config, and wait for wifi restart to apply
5220 char BeaconType[50] = {0};
5221 char config_file[MAX_BUF_SIZE] = {0};
5222
5223 *authMode = 0;
5224 wifi_getApBeaconType(apIndex,BeaconType);
5225 printf("%s____%s \n",__FUNCTION__,BeaconType);
5226
5227 if(strcmp(BeaconType,"None") == 0)
5228 strcpy(authMode,"None");
5229 else
5230 {
5231 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5232 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5233 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5234 if(strcmp(authMode,"WPA-PSK") == 0)
5235 strcpy(authMode,"SharedAuthentication");
5236 else if(strcmp(authMode,"WPA-EAP") == 0)
5237 strcpy(authMode,"EAPAuthentication");
5238 }
5239
5240 return RETURN_OK;
5241}
5242
5243// Outputs the number of stations associated per AP
5244INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5245{
5246 char cmd[128]={0};
5247 char buf[128]={0};
5248 BOOL status = false;
5249
5250 if(apIndex > MAX_APS)
5251 return RETURN_ERR;
5252
5253 wifi_getApEnable(apIndex,&status);
5254 if (!status)
5255 return RETURN_OK;
5256
5257 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5258 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5259 _syscmd(cmd, buf, sizeof(buf));
5260 sscanf(buf,"%lu", output_ulong);
5261
5262 return RETURN_OK;
5263}
5264
5265// manually removes any active wi-fi association with the device specified on this ap
5266INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5267{
5268 char buf[126]={'\0'};
5269
5270 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5271 system(buf);
5272
5273 return RETURN_OK;
5274}
5275
5276// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5277INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5278{
5279 if(NULL == output_int)
5280 return RETURN_ERR;
5281 *output_int = apIndex%2;
5282 return RETURN_OK;
5283}
5284
5285// sets the radio index for the specific ap
5286INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5287{
5288 //set to config only and wait for wifi reset to apply settings
5289 return RETURN_ERR;
5290}
5291
5292// Get the ACL MAC list per AP
5293INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5294{
5295 char cmd[MAX_CMD_SIZE]={'\0'};
5296 int ret = 0;
5297
5298 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5299 ret = _syscmd(cmd,macArray,buf_size);
5300 if (ret != 0)
5301 return RETURN_ERR;
5302
5303 return RETURN_OK;
5304}
5305
developere6aafda2022-09-13 14:59:28 +08005306INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5307{
5308 char cmd[MAX_CMD_SIZE]={'\0'};
5309 int ret = 0;
5310
5311 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5312 ret = _syscmd(cmd,macArray,buf_size);
5313 if (ret != 0)
5314 return RETURN_ERR;
5315
5316 return RETURN_OK;
5317}
5318
5319
developer06a01d92022-09-07 16:32:39 +08005320// Get the list of stations associated per AP
5321INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5322{
5323 char cmd[128];
5324
5325 if(apIndex > 3) //Currently supporting apIndex upto 3
5326 return RETURN_ERR;
5327 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5328 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5329 _syscmd(cmd, macArray, buf_size);
5330
5331 return RETURN_OK;
5332}
5333
5334// adds the mac address to the filter list
5335//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5336INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5337{
5338 char cmd[MAX_CMD_SIZE]={'\0'};
5339 char buf[MAX_BUF_SIZE]={'\0'};
5340
5341#if 0
5342 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5343 if(_syscmd(cmd,buf,sizeof(buf)))
5344 return RETURN_ERR;
5345#endif
5346 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5347 if(_syscmd(cmd,buf,sizeof(buf)))
5348 return RETURN_ERR;
5349
5350 return RETURN_OK;
5351}
5352
5353// deletes the mac address from the filter list
5354//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5355INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5356{
5357 char cmd[MAX_CMD_SIZE]={'\0'};
5358 char buf[MAX_BUF_SIZE]={'\0'};
5359
5360#if 0
5361 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5362 if(_syscmd(cmd,buf,sizeof(buf)))
5363 return RETURN_ERR;
5364
5365#endif
5366 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5367 if(_syscmd(cmd,buf,sizeof(buf)))
5368 return RETURN_ERR;
5369
5370 return RETURN_OK;
5371}
5372
5373// outputs the number of devices in the filter list
5374INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5375{
developere6aafda2022-09-13 14:59:28 +08005376 char cmd[MAX_BUF_SIZE]={0};
5377 char buf[MAX_CMD_SIZE]={0};
5378
5379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5380 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005381 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005382
5383 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5384 _syscmd(cmd, buf, sizeof(buf));
5385
5386 *output_uint = atoi(buf);
5387
5388 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5389 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005390}
5391
5392INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5393{
5394 char cmd[128]={'\0'};
5395 char buf[128]={'\0'};
5396
5397 if(strcmp(action,"DENY")==0)
5398 {
5399 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5400 system(buf);
5401 return RETURN_OK;
5402 }
5403
5404 if(strcmp(action,"ALLOW")==0)
5405 {
5406 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5407 system(buf);
5408 return RETURN_OK;
5409 }
5410
5411 return RETURN_ERR;
5412
5413}
5414
5415// enable kick for devices on acl black list
5416INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5417{
5418 char aclArray[512] = {0}, *acl = NULL;
5419 char assocArray[512] = {0}, *asso = NULL;
5420
developere6aafda2022-09-13 14:59:28 +08005421 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005422 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5423
5424 // if there are no devices connected there is nothing to do
5425 if (strlen(assocArray) < 17)
5426 return RETURN_OK;
5427
5428 if (enable == TRUE)
5429 {
5430 //kick off the MAC which is in ACL array (deny list)
5431 acl = strtok(aclArray, "\r\n");
5432 while (acl != NULL) {
5433 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5434 wifi_kickApAssociatedDevice(apIndex, acl);
5435
5436 acl = strtok(NULL, "\r\n");
5437 }
developere6aafda2022-09-13 14:59:28 +08005438 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005439 }
5440 else
5441 {
developere6aafda2022-09-13 14:59:28 +08005442 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005443 }
5444
5445#if 0
5446 //TODO: need to revisit below implementation
5447 char aclArray[512]={0}, *acl=NULL;
5448 char assocArray[512]={0}, *asso=NULL;
5449 char buf[256]={'\0'};
5450 char action[10]={'\0'};
5451 FILE *fr=NULL;
5452 char interface[10]={'\0'};
5453 char config_file[MAX_BUF_SIZE] = {0};
5454
5455 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5456 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5457 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5458 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5459
5460 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5461 system(buf);
5462 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5463 system(buf);
5464 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5465 system(buf);
5466 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5467 system(buf);
5468 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5469 system(buf);
5470
5471 if ( enable == TRUE )
5472 {
5473 int device_count=0;
5474 strcpy(action,"DENY");
5475 //kick off the MAC which is in ACL array (deny list)
5476 acl = strtok (aclArray,",");
5477 while (acl != NULL) {
5478 if(strlen(acl)>=17)
5479 {
5480 apply_rules(apIndex, acl,action,interface);
5481 device_count++;
5482 //Register mac to be blocked ,in syscfg.db persistent storage
5483 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5484 system(buf);
5485 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5486 system(buf);
5487 system("syscfg commit");
5488
5489 wifi_kickApAssociatedDevice(apIndex, acl);
5490 }
5491 acl = strtok (NULL, ",");
5492 }
5493 }
5494 else
5495 {
5496 int device_count=0;
5497 char cmdmac[20]={'\0'};
5498 strcpy(action,"ALLOW");
5499 //kick off the MAC which is not in ACL array (allow list)
5500 acl = strtok (aclArray,",");
5501 while (acl != NULL) {
5502 if(strlen(acl)>=17)
5503 {
5504 apply_rules(apIndex, acl,action,interface);
5505 device_count++;
5506 //Register mac to be Allowed ,in syscfg.db persistent storage
5507 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5508 system(buf);
5509 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5510 system(buf);
5511 sprintf(cmdmac,"%s",acl);
5512 }
5513 acl = strtok (NULL, ",");
5514 }
5515 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5516 system(buf);
5517
5518 //Disconnect the mac which is not in ACL
5519 asso = strtok (assocArray,",");
5520 while (asso != NULL) {
5521 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5522 wifi_kickApAssociatedDevice(apIndex, asso);
5523 asso = strtok (NULL, ",");
5524 }
5525 }
5526#endif
5527 return RETURN_OK;
5528}
5529
5530INT wifi_setPreferPrivateConnection(BOOL enable)
5531{
5532 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5533 char buf[1024] = {0};
5534
5535 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5536 if(enable == TRUE)
5537 {
5538 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5539 sprintf(buf,"ifconfig %s down" ,interface_name);
5540 system(buf);
5541 memset(buf,0,sizeof(buf));
5542 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5543 sprintf(buf,"ifconfig %s down" ,interface_name);
5544 system(buf);
5545 }
5546 else
5547 {
5548 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5549 if(strcmp(ssid_cur_value,"1") == 0)
5550 wifi_RestartPrivateWifi_5G();
5551 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5552 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5553 if(strcmp(ssid_cur_value,"1") == 0)
5554 wifi_RestartHostapd_2G();
5555 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5556 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5557 if(strcmp(ssid_cur_value,"1") == 0)
5558 wifi_RestartHostapd_5G();
5559 }
5560 return RETURN_OK;
5561}
5562
5563// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5564INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5565{
5566 int items = 1;
5567 struct params list[2];
5568 char buf[MAX_BUF_SIZE] = {0};
5569 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005570 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005571
5572 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005573
developer10adcc12022-09-13 14:39:17 +08005574 if (filterMode == 0) {
5575 sprintf(buf, "%d", 0);
5576 list[0].value = buf;
5577
5578 char cmd[128], rtn[128];
5579 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5580 _syscmd(cmd, rtn, sizeof(rtn));
5581 memset(cmd,0,sizeof(cmd));
5582 // Delete deny_mac_file in hostapd configuration
5583 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5584 _syscmd(cmd, rtn, sizeof(rtn));
5585 }
5586 else if (filterMode == 1) {
5587 sprintf(buf, "%d", filterMode);
5588 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005589 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5590 list[1].name = "accept_mac_file";
5591 list[1].value = acl_file;
5592 items = 2;
developer10adcc12022-09-13 14:39:17 +08005593 } else if (filterMode == 2) {
5594 //TODO: deny_mac_file
5595 sprintf(buf, "%d", 0);
5596 list[0].value = buf;
5597 list[1].name = "deny_mac_file";
5598 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5599 list[1].value = deny_file;
5600 items = 2;
5601 } else {
5602 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005603 }
developer10adcc12022-09-13 14:39:17 +08005604
developer06a01d92022-09-07 16:32:39 +08005605 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5606 wifi_hostapdWrite(config_file, list, items);
5607
5608 return RETURN_OK;
5609
5610#if 0
5611 if(apIndex==0 || apIndex==1)
5612 {
5613 //set the filtermode
5614 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5615 system(buf);
5616 system("syscfg commit");
5617
5618 if(filterMode==0)
5619 {
5620 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5621 system(buf);
5622 return RETURN_OK;
5623 }
5624 }
5625 return RETURN_OK;
5626#endif
5627}
5628
5629// 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.
5630INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5631{
5632 return RETURN_ERR;
5633}
5634
5635// gets the vlan ID for this ap from an internal enviornment variable
5636INT wifi_getApVlanID(INT apIndex, INT *output_int)
5637{
5638 if(apIndex=0)
5639 {
5640 *output_int=100;
5641 return RETURN_OK;
5642 }
5643
5644 return RETURN_ERR;
5645}
5646
5647// sets the vlan ID for this ap to an internal enviornment variable
5648INT wifi_setApVlanID(INT apIndex, INT vlanId)
5649{
5650 //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)
5651 return RETURN_ERR;
5652}
5653
5654// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5655INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5656{
5657 snprintf(bridgeName, 32, "brlan0");
5658 snprintf(IP, 32, "10.0.0.1");
5659 snprintf(subnet, 32, "255.255.255.0");
5660
5661 return RETURN_OK;
5662}
5663
5664//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5665INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5666{
5667 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5668 return RETURN_ERR;
5669}
5670
5671// reset the vlan configuration for this ap
5672INT wifi_resetApVlanCfg(INT apIndex)
5673{
developerf5fef612022-09-20 19:38:26 +08005674 char original_config_file[64] = {0};
5675 char current_config_file[64] = {0};
5676 char buf[64] = {0};
5677 char cmd[64] = {0};
5678 char vlan_file[64] = {0};
5679 char vlan_tagged_interface[16] = {0};
5680 char vlan_bridge[16] = {0};
5681 char vlan_naming[16] = {0};
5682 struct params list[4] = {0};
5683 wifi_band band;
5684
5685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5686
5687 band = wifi_index_to_band(apIndex);
5688 if (band == band_2_4)
5689 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5690 else if (band = band_5)
5691 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5692 else if (band = band_6)
5693 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5694
5695 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5696
5697 if (strlen(vlan_file) == 0)
5698 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005699
developerf5fef612022-09-20 19:38:26 +08005700 // The file should exist or this vap would not work.
5701 if (access(vlan_file, F_OK) != 0) {
5702 sprintf(cmd, "touch %s", vlan_file);
5703 _syscmd(cmd, buf, sizeof(buf));
5704 }
5705 list[0].name = "vlan_file";
5706 list[0].value = vlan_file;
5707
5708 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5709 list[1].name = "vlan_tagged_interface";
5710 list[1].value = vlan_tagged_interface;
5711
5712 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5713 list[2].name = "vlan_bridge";
5714 list[2].value = vlan_bridge;
5715
5716 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5717 list[3].name = "vlan_naming";
5718 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005719
developerf5fef612022-09-20 19:38:26 +08005720 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5721 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005722 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005723 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005724
developerf5fef612022-09-20 19:38:26 +08005725 // restart this ap
5726 wifi_setApEnable(apIndex, FALSE);
5727 wifi_setApEnable(apIndex, TRUE);
5728
5729 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5730
5731 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005732}
5733
5734// 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.
5735INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5736{
5737 return RETURN_ERR;
5738}
5739
5740// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5741INT wifi_startHostApd()
5742{
5743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5744 system("systemctl start hostapd.service");
5745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5746 return RETURN_OK;
5747 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5748}
5749
5750// stops hostapd
5751INT wifi_stopHostApd()
5752{
5753 char cmd[128] = {0};
5754 char buf[128] = {0};
5755
5756 sprintf(cmd,"systemctl stop hostapd");
5757 _syscmd(cmd, buf, sizeof(buf));
5758
5759 return RETURN_OK;
5760}
5761
5762// restart hostapd dummy function
5763INT wifi_restartHostApd()
5764{
5765 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5766 system("systemctl restart hostapd-global");
5767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5768
5769 return RETURN_OK;
5770}
5771
5772static int align_hostapd_config(int index)
5773{
5774 ULONG lval;
5775 wifi_getRadioChannel(index%2, &lval);
5776 wifi_setRadioChannel(index%2, lval);
5777}
5778
5779// sets the AP enable status variable for the specified ap.
5780INT wifi_setApEnable(INT apIndex, BOOL enable)
5781{
5782 char config_file[MAX_BUF_SIZE] = {0};
5783 char cmd[MAX_CMD_SIZE] = {0};
5784 char buf[MAX_BUF_SIZE] = {0};
5785 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005786 int max_radio_num = 0;
5787 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005788
5789 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005790
5791 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005792 if (enable == status)
5793 return RETURN_OK;
5794
5795 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005796 int radioIndex = apIndex % max_radio_num;
5797 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005798 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5799 //Hostapd will bring up this interface
5800 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5801 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005802 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005803 _syscmd(cmd, buf, sizeof(buf));
5804 }
5805 else {
5806 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5807 _syscmd(cmd, buf, sizeof(buf));
5808 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5809 _syscmd(cmd, buf, sizeof(buf));
5810 }
5811 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5812 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5813 _syscmd(cmd, buf, sizeof(buf));
5814 //Wait for wifi up/down to apply
5815 return RETURN_OK;
5816}
5817
5818// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5819INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5820{
5821 char cmd[MAX_CMD_SIZE] = {'\0'};
5822 char buf[MAX_BUF_SIZE] = {'\0'};
5823
5824 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5825 return RETURN_ERR;
5826
5827 *output_bool = 0;
5828
5829 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5830 {
developer70490032022-09-13 15:45:20 +08005831 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005832 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5833 }
5834
5835 return RETURN_OK;
5836}
5837
5838// Outputs the AP "Enabled" "Disabled" status from driver
5839INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5840{
5841 char cmd[128] = {0};
5842 char buf[128] = {0};
5843 BOOL output_bool;
5844
5845 if ( NULL == output_string)
5846 return RETURN_ERR;
5847 wifi_getApEnable(apIndex,&output_bool);
5848
5849 if(output_bool == 1)
5850 snprintf(output_string, 32, "Up");
5851 else
5852 snprintf(output_string, 32, "Disable");
5853
5854 return RETURN_OK;
5855}
5856
5857//Indicates whether or not beacons include the SSID name.
5858// outputs a 1 if SSID on the AP is enabled, else outputs 0
5859INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5860{
5861 //get the running status
5862 char config_file[MAX_BUF_SIZE] = {0};
5863 char buf[16] = {0};
5864
5865 if (!output)
5866 return RETURN_ERR;
5867
5868 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5869 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005870 // default is enable
5871 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5872 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005873
5874 return RETURN_OK;
5875}
5876
5877// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5878INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5879{
5880 //store the config, apply instantly
5881 char config_file[MAX_BUF_SIZE] = {0};
5882 struct params list;
5883
5884 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5885 list.name = "ignore_broadcast_ssid";
5886 list.value = enable?"0":"1";
5887
5888 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5889 wifi_hostapdWrite(config_file, &list, 1);
5890 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5891 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005892 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5894
5895 return RETURN_OK;
5896}
5897
5898//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5899INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5900{
5901 //get the running status
5902 if(!output_uint)
5903 return RETURN_ERR;
5904 *output_uint=16;
5905 return RETURN_OK;
5906}
5907
5908INT wifi_setApRetryLimit(INT apIndex, UINT number)
5909{
5910 //apply instantly
5911 return RETURN_ERR;
5912}
5913
5914//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5915INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5916{
5917 if(!output)
5918 return RETURN_ERR;
5919 *output=TRUE;
5920 return RETURN_OK;
5921}
5922
5923//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5924INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5925{
5926 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005927 char cmd[128] = {0};
5928 char buf[128] = {0};
5929 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08005930 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08005931
developer0b246d12022-09-30 15:24:20 +08005932 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005933
developer0b246d12022-09-30 15:24:20 +08005934 wifi_getMaxRadioNumber(&max_radio_num);
5935 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08005936 phyId = radio_index_to_phy(radioIndex);
5937 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08005938 _syscmd(cmd,buf, sizeof(buf));
5939
5940 if (strlen(buf) > 0)
5941 *output = true;
5942
5943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005944
developer06a01d92022-09-07 16:32:39 +08005945 return RETURN_OK;
5946}
5947
5948//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5949INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5950{
5951 //get the running status from driver
5952 if(!output)
5953 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005954
5955 char config_file[MAX_BUF_SIZE] = {0};
5956 char buf[16] = {0};
5957
5958 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5959 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005960 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08005961 *output = TRUE;
5962 else
5963 *output = FALSE;
5964
developer06a01d92022-09-07 16:32:39 +08005965 return RETURN_OK;
5966}
5967
5968// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5969INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5970{
5971 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005972 char config_file[MAX_BUF_SIZE] = {0};
5973 struct params list;
5974
5975 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5976 list.name = "wmm_enabled";
5977 list.value = enable?"1":"0";
5978
5979 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5980 wifi_hostapdWrite(config_file, &list, 1);
5981 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5982 wifi_reloadAp(apIndex);
5983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5984
5985 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005986}
5987
5988//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.
5989INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5990{
5991 //get the running status from driver
5992 if(!output)
5993 return RETURN_ERR;
5994 *output=TRUE;
5995 return RETURN_OK;
5996}
5997
5998// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5999INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6000{
6001 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006002 char config_file[MAX_BUF_SIZE] = {0};
6003 struct params list;
6004
6005 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6006 list.name = "uapsd_advertisement_enabled";
6007 list.value = enable?"1":"0";
6008
6009 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6010 wifi_hostapdWrite(config_file, &list, 1);
6011 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6012 wifi_reloadAp(apIndex);
6013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6014
6015 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006016}
6017
developer6daeb3f2022-09-30 13:36:39 +08006018// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006019INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6020{
developer6daeb3f2022-09-30 13:36:39 +08006021 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6022 char cmd[128] = {0};
6023 char buf[128] = {0};
6024 char ack_filepath[128] = {0};
6025 uint16_t bitmap = 0;
6026 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6027 FILE *f = NULL;
6028
6029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6030
6031 // Get current setting
6032 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6033 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6034 _syscmd(cmd, buf, sizeof(buf));
6035 if (strlen(buf) > 0)
6036 bitmap = strtoul(buf, NULL, 10);
6037
6038 bitmap = strtoul(buf, NULL, 10);
6039
6040 if (ackPolicy == TRUE) { // True, unset this class
6041 bitmap &= ~class_map[class];
6042 } else { // False, set this class
6043 bitmap |= class_map[class];
6044 }
6045
6046 f = fopen(ack_filepath, "w");
6047 if (f == NULL) {
6048 fprintf(stderr, "%s: fopen failed\n", __func__);
6049 return RETURN_ERR;
6050 }
6051 fprintf(f, "%hu", bitmap);
6052 fclose(f);
6053
6054 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
6055 _syscmd(cmd, buf, sizeof(buf));
6056
6057 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6058 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006059}
6060
6061//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.
6062INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6063{
6064 //get the running status from driver
6065 if(!output_uint)
6066 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006067
6068 char output[16]={'\0'};
6069 char config_file[MAX_BUF_SIZE] = {0};
6070
6071 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6072 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6073 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6074 else {
6075 int device_num = atoi(output);
6076 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6077 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6078 return RETURN_ERR;
6079 }
6080 else {
6081 *output_uint = device_num;
6082 }
6083 }
6084
developer06a01d92022-09-07 16:32:39 +08006085 return RETURN_OK;
6086}
6087
6088INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6089{
6090 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006091 char str[MAX_BUF_SIZE]={'\0'};
6092 char cmd[MAX_CMD_SIZE]={'\0'};
6093 struct params params;
6094 char config_file[MAX_BUF_SIZE] = {0};
6095
6096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6097 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6098 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6099 return RETURN_ERR;
6100 }
6101 sprintf(str, "%d", number);
6102 params.name = "max_num_sta";
6103 params.value = str;
6104
6105 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6106 int ret = wifi_hostapdWrite(config_file, &params, 1);
6107 if (ret) {
6108 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6109 ,__func__, ret);
6110 }
6111
6112 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6113 if (ret) {
6114 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6115 ,__func__, ret);
6116 }
6117 wifi_reloadAp(apIndex);
6118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6119
6120 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006121}
6122
6123//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.
6124INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6125{
6126 //get the current threshold
6127 if(!output_uint)
6128 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006129 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6130 if (*output_uint == 0)
6131 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006132 return RETURN_OK;
6133}
6134
6135INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6136{
6137 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006138 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6139 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006140 return RETURN_ERR;
6141}
6142
6143//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.
6144INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6145{
6146 if(!output_uint)
6147 return RETURN_ERR;
6148 *output_uint = 3;
6149 return RETURN_OK;
6150}
6151
6152//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6153INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6154{
6155 if(!output_uint)
6156 return RETURN_ERR;
6157 *output_uint = 3;
6158 return RETURN_OK;
6159}
6160
6161//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.
6162INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6163{
6164 if(!output_in_seconds)
6165 return RETURN_ERR;
6166 *output_in_seconds = 0;
6167 return RETURN_OK;
6168}
6169
6170//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
6171INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6172{
6173 if(!output || apIndex>=MAX_APS)
6174 return RETURN_ERR;
6175 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006176 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006177 return RETURN_OK;
6178}
6179
6180//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6181INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6182{
developer587c1b62022-09-27 15:58:59 +08006183 char config_file[128] = {0};
6184 char wpa[16] = {0};
6185 char key_mgmt[64] = {0};
6186 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006187 if (!output)
6188 return RETURN_ERR;
6189
6190 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006191 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006192
developer587c1b62022-09-27 15:58:59 +08006193 strcpy(output, "None");//Copying "None" to output string for default case
6194 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006195 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006196 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006197 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006198 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006199 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006200 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006201 snprintf(output, 32, "WPA-WPA2-Personal");
6202
6203 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006204 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006205 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006206 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006207 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006208 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006209 snprintf(output, 32, "WPA-WPA2-Enterprise");
6210 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006211 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006212 snprintf(output, 32, "WPA3-Personal");
6213 else
developer4a359672022-10-13 15:30:46 +08006214 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006215 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6216 snprintf(output, 32, "WPA3-Enterprise");
6217 }
developer06a01d92022-09-07 16:32:39 +08006218
6219 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6220 return RETURN_OK;
6221#if 0
6222 //TODO: need to revisit below implementation
6223 char securityType[32], authMode[32];
6224 int enterpriseMode=0;
6225
6226 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6227 if(!output)
6228 return RETURN_ERR;
6229
6230 wifi_getApBeaconType(apIndex, securityType);
6231 strcpy(output,"None");//By default, copying "None" to output string
6232 if (strncmp(securityType,"None", strlen("None")) == 0)
6233 return RETURN_OK;
6234
6235 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6236 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6237
6238 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6239 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6240 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6241 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6242 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6243 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6245
6246 return RETURN_OK;
6247#endif
6248}
6249
6250INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6251{
6252 char securityType[32];
6253 char authMode[32];
6254
6255 //store settings and wait for wifi up to apply
6256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6257 if(!encMode)
6258 return RETURN_ERR;
6259
developer06a01d92022-09-07 16:32:39 +08006260 if (strcmp(encMode, "None")==0)
6261 {
6262 strcpy(securityType,"None");
6263 strcpy(authMode,"None");
6264 }
6265 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6266 {
6267 strcpy(securityType,"WPAand11i");
6268 strcpy(authMode,"PSKAuthentication");
6269 }
6270 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6271 {
6272 strcpy(securityType,"WPAand11i");
6273 strcpy(authMode,"EAPAuthentication");
6274 }
6275 else if (strcmp(encMode, "WPA-Personal")==0)
6276 {
6277 strcpy(securityType,"WPA");
6278 strcpy(authMode,"PSKAuthentication");
6279 }
6280 else if (strcmp(encMode, "WPA-Enterprise")==0)
6281 {
6282 strcpy(securityType,"WPA");
6283 strcpy(authMode,"EAPAuthentication");
6284 }
6285 else if (strcmp(encMode, "WPA2-Personal")==0)
6286 {
6287 strcpy(securityType,"11i");
6288 strcpy(authMode,"PSKAuthentication");
6289 }
6290 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6291 {
6292 strcpy(securityType,"11i");
6293 strcpy(authMode,"EAPAuthentication");
6294 }
developer587c1b62022-09-27 15:58:59 +08006295 else if (strcmp(encMode, "WPA3-Personal") == 0)
6296 {
6297 strcpy(securityType,"11i");
6298 strcpy(authMode,"SAEAuthentication");
6299 }
developer4a359672022-10-13 15:30:46 +08006300 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006301 {
6302 strcpy(securityType, "11i");
6303 strcpy(authMode, "PSK-SAEAuthentication");
6304 }
developer587c1b62022-09-27 15:58:59 +08006305 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6306 {
6307 strcpy(securityType,"11i");
6308 strcpy(authMode,"EAP_192-bit_Authentication");
6309 }
developer06a01d92022-09-07 16:32:39 +08006310 else
6311 {
6312 strcpy(securityType,"None");
6313 strcpy(authMode,"None");
6314 }
6315 wifi_setApBeaconType(apIndex, securityType);
6316 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6317 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6318
6319 return RETURN_OK;
6320}
6321
6322
6323//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6324// output_string must be pre-allocated as 64 character string by caller
6325// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6326INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6327{
6328 char buf[16];
6329 char config_file[MAX_BUF_SIZE] = {0};
6330
6331 if(output_string==NULL)
6332 return RETURN_ERR;
6333
6334 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6335 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6336
6337 if(strcmp(buf,"0")==0)
6338 {
6339 printf("wpa_mode is %s ......... \n",buf);
6340 return RETURN_ERR;
6341 }
6342
6343 wifi_dbg_printf("\nFunc=%s\n",__func__);
6344 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6345 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6346 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6347
6348 return RETURN_OK;
6349}
6350
6351// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6352// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6353INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6354{
6355 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6356 struct params params={'\0'};
6357 int ret;
6358 char config_file[MAX_BUF_SIZE] = {0};
6359
6360 if(NULL == preSharedKey)
6361 return RETURN_ERR;
6362
6363 params.name = "wpa_passphrase";
6364
6365 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6366 {
6367 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6368 return RETURN_ERR;
6369 }
6370 params.value = preSharedKey;
6371 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6372 ret = wifi_hostapdWrite(config_file, &params, 1);
6373 if(!ret)
6374 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6375 return ret;
6376 //TODO: call hostapd_cli for dynamic_config_control
6377}
6378
6379//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6380// outputs the passphrase, maximum 63 characters
6381INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6382{
6383 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6384
6385 wifi_dbg_printf("\nFunc=%s\n",__func__);
6386 if (NULL == output_string)
6387 return RETURN_ERR;
6388
6389 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6390 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6391 if(strcmp(buf,"0")==0)
6392 {
6393 printf("wpa_mode is %s ......... \n",buf);
6394 return RETURN_ERR;
6395 }
6396
6397 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6398 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6399
6400 return RETURN_OK;
6401}
6402
6403// sets the passphrase enviornment variable, max 63 characters
6404INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6405{
6406 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6407 struct params params={'\0'};
6408 char config_file[MAX_BUF_SIZE] = {0};
6409 int ret;
6410
6411 if(NULL == passPhrase)
6412 return RETURN_ERR;
6413
6414 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6415 {
6416 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6417 return RETURN_ERR;
6418 }
6419 params.name = "wpa_passphrase";
6420 params.value = passPhrase;
6421 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6422 ret=wifi_hostapdWrite(config_file,&params,1);
6423 if(!ret)
6424 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6425
6426 return ret;
6427}
6428
6429//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.
6430INT wifi_setApSecurityReset(INT apIndex)
6431{
developer8d583982022-09-20 11:28:22 +08006432 char original_config_file[64] = {0};
6433 char current_config_file[64] = {0};
6434 char buf[64] = {0};
6435 char cmd[64] = {0};
6436 char wpa[4] = {0};
6437 char wpa_psk[64] = {0};
6438 char wpa_passphrase[64] = {0};
6439 char wpa_psk_file[128] = {0};
6440 char wpa_key_mgmt[64] = {0};
6441 char wpa_pairwise[32] = {0};
6442 wifi_band band;
6443 struct params list[6];
6444
6445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6446
6447 band = wifi_index_to_band(apIndex);
6448 if (band == band_2_4)
6449 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6450 else if (band = band_5)
6451 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6452 else if (band = band_6)
6453 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6454 else
6455 return RETURN_ERR;
6456
6457 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6458 list[0].name = "wpa";
6459 list[0].value = wpa;
6460
6461 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6462 list[1].name = "wpa_psk";
6463 list[1].value = wpa_psk;
6464
6465 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6466 list[2].name = "wpa_passphrase";
6467 list[2].value = wpa_passphrase;
6468
6469 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6470
6471 if (strlen(wpa_psk_file) == 0)
6472 strcpy(wpa_psk_file, PSK_FILE);
6473
6474 if (access(wpa_psk_file, F_OK) != 0) {
6475 sprintf(cmd, "touch %s", wpa_psk_file);
6476 _syscmd(cmd, buf, sizeof(buf));
6477 }
6478 list[3].name = "wpa_psk_file";
6479 list[3].value = wpa_psk_file;
6480
6481 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6482 list[4].name = "wpa_key_mgmt";
6483 list[4].value = wpa_key_mgmt;
6484
6485 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6486 list[5].name = "wpa_pairwise";
6487 list[5].value = wpa_pairwise;
6488
6489 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6490 wifi_hostapdWrite(current_config_file, list, 6);
6491
6492 wifi_setApEnable(apIndex, FALSE);
6493 wifi_setApEnable(apIndex, TRUE);
6494
6495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6496 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006497}
6498
6499//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).
6500INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6501{
developer8f2ddd52022-09-13 15:39:24 +08006502 char config_file[64] = {0};
6503 char buf[64] = {0};
6504 char cmd[256] = {0};
6505
6506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6507
developer06a01d92022-09-07 16:32:39 +08006508 if(!IP_output || !Port_output || !RadiusSecret_output)
6509 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006510
developer8f2ddd52022-09-13 15:39:24 +08006511 // Read the first matched config
6512 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6513 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6514 _syscmd(cmd, buf, sizeof(buf));
6515 strncpy(IP_output, buf, 64);
6516
6517 memset(buf, 0, sizeof(buf));
6518 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6519 _syscmd(cmd, buf, sizeof(buf));
6520 *Port_output = atoi(buf);
6521
6522 memset(buf, 0, sizeof(buf));
6523 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6524 _syscmd(cmd, buf, sizeof(buf));
6525 strncpy(RadiusSecret_output, buf, 64);
6526
6527 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006528 return RETURN_OK;
6529}
6530
6531INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6532{
developer8f2ddd52022-09-13 15:39:24 +08006533 char config_file[64] = {0};
6534 char port_str[8] = {0};
6535 char cmd[256] = {0};
6536 char buf[128] = {0};
6537
6538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6539
6540 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6541
6542 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6543 _syscmd(cmd, buf, sizeof(buf));
6544 memset(cmd, 0, sizeof(cmd));
6545
6546 snprintf(port_str, sizeof(port_str), "%d", port);
6547 if (strlen(buf) == 0)
6548 // Append
6549 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6550 "auth_server_addr=%s\\n"
6551 "auth_server_port=%s\\n"
6552 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6553 else {
6554 // Delete the three lines setting after the "# radius 1" comment
6555 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6556 _syscmd(cmd, buf, sizeof(buf));
6557 memset(cmd, 0, sizeof(cmd));
6558 // Use "# radius 1" comment to find the location to insert the radius setting
6559 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6560 "# radius 1\\n"
6561 "auth_server_addr=%s\\n"
6562 "auth_server_port=%s\\n"
6563 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6564 }
6565 if(_syscmd(cmd, buf, sizeof(buf))) {
6566 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6567 return RETURN_ERR;
6568 }
6569
6570 wifi_reloadAp(apIndex);
6571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6572 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006573}
6574
6575INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6576{
developer8f2ddd52022-09-13 15:39:24 +08006577 char config_file[64] = {0};
6578 char buf[64] = {0};
6579 char cmd[256] = {0};
6580
6581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6582
developer06a01d92022-09-07 16:32:39 +08006583 if(!IP_output || !Port_output || !RadiusSecret_output)
6584 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006585
6586 // Read the second matched config
6587 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6588 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6589 _syscmd(cmd, buf, sizeof(buf));
6590 strncpy(IP_output, buf, 64);
6591
6592 memset(buf, 0, sizeof(buf));
6593 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6594 _syscmd(cmd, buf, sizeof(buf));
6595 *Port_output = atoi(buf);
6596
6597 memset(buf, 0, sizeof(buf));
6598 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6599 _syscmd(cmd, buf, sizeof(buf));
6600 strncpy(RadiusSecret_output, buf, 64);
6601
6602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006603 return RETURN_OK;
6604}
6605
6606INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6607{
developer8f2ddd52022-09-13 15:39:24 +08006608 char config_file[64] = {0};
6609 char port_str[8] = {0};
6610 char cmd[256] = {0};
6611 char buf[128] = {0};
6612
6613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6614
6615 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6616
6617 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6618 _syscmd(cmd, buf, sizeof(buf));
6619 memset(cmd, 0, sizeof(cmd));
6620
6621 snprintf(port_str, sizeof(port_str), "%d", port);
6622 if (strlen(buf) == 0)
6623 // Append
6624 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6625 "auth_server_addr=%s\\n"
6626 "auth_server_port=%s\\n"
6627 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6628 else {
6629 // Delete the three lines setting after the "# radius 2" comment
6630 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6631 _syscmd(cmd, buf, sizeof(buf));
6632 memset(cmd, 0, sizeof(cmd));
6633 // Use "# radius 2" comment to find the location to insert the radius setting
6634 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6635 "# radius 2\\n"
6636 "auth_server_addr=%s\\n"
6637 "auth_server_port=%s\\n"
6638 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6639 }
6640 if(_syscmd(cmd, buf, sizeof(buf))) {
6641 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6642 return RETURN_ERR;
6643 }
6644
6645 wifi_reloadAp(apIndex);
6646 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6647 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006648}
6649
6650//RadiusSettings
6651INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6652{
6653 if(!output)
6654 return RETURN_ERR;
6655
6656 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6657 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6658 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6659 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6660 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6661 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.
6662 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6663 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6664 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6665 //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.
6666
6667 return RETURN_OK;
6668}
6669
6670INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6671{
6672 //store the paramters, and apply instantly
6673 return RETURN_ERR;
6674}
6675
6676//Device.WiFi.AccessPoint.{i}.WPS.Enable
6677//Enables or disables WPS functionality for this access point.
6678// outputs the WPS enable state of this ap in output_bool
6679INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6680{
6681 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6682 if(!output_bool || !(apIndex==0 || apIndex==1))
6683 return RETURN_ERR;
6684 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6685 _syscmd(cmd, buf, sizeof(buf));
6686 if(strstr(buf, "configured"))
6687 *output_bool=TRUE;
6688 else
6689 *output_bool=FALSE;
6690
6691 return RETURN_OK;
6692}
6693
6694//Device.WiFi.AccessPoint.{i}.WPS.Enable
6695// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6696INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6697{
6698 char config_file[MAX_BUF_SIZE] = {0};
6699 struct params params;
6700
6701 if(!(apIndex==0 || apIndex==1))
6702 return RETURN_ERR;
6703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6704 //store the paramters, and wait for wifi up to apply
6705 params.name = "wps_state";
6706 params.value = enable ? "2":"0";
6707
6708 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6709 wifi_hostapdWrite(config_file, &params, 1);
6710 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6711 wifi_reloadAp(apIndex);
6712
6713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6714 return RETURN_OK;
6715}
6716
6717//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
6718INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6719{
6720 if(!output)
6721 return RETURN_ERR;
6722 snprintf(output, 128, "PushButton,PIN");
6723 return RETURN_OK;
6724}
6725
6726//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6727//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.
6728// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6729INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6730{
6731 if(!output)
6732 return RETURN_ERR;
6733 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6734
6735 return RETURN_OK;
6736}
6737
6738//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6739// 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
6740INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6741{
6742 //apply instantly. No setting need to be stored.
6743 char methods[MAX_BUF_SIZE], *token, *next_token;
6744 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6745 struct params params;
6746
6747 if(!methodString || !(apIndex==0 || apIndex==1))
6748 return RETURN_ERR;
6749 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6750 //store the paramters, and wait for wifi up to apply
6751
6752 snprintf(methods, sizeof(methods), "%s", methodString);
6753 for(token=methods; *token; token=next_token)
6754 {
6755 strtok_r(token, ",", &next_token);
6756 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6757 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6758 else if(*token=='E')
6759 {
6760 if(!strcmp(methods, "Ethernet"))
6761 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6762 else if(!strcmp(methods, "ExternalNFCToken"))
6763 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6764 else
6765 printf("%s: Unknown WpsConfigMethod\n", __func__);
6766 }
6767 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6768 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6769 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6770 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6771 else if(*token=='P' )
6772 {
6773 if(!strcmp(token, "PushButton"))
6774 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6775 else if(!strcmp(token, "PIN"))
6776 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6777 else
6778 printf("%s: Unknown WpsConfigMethod\n", __func__);
6779 }
6780 else
6781 printf("%s: Unknown WpsConfigMethod\n", __func__);
6782 }
6783 params.name = "config_methods";
6784 params.value = config_methods;
6785 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6786 wifi_hostapdWrite(config_file, &params, 1);
6787 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6788 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6789
6790 return RETURN_OK;
6791}
6792
6793// outputs the pin value, ulong_pin must be allocated by the caller
6794INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6795{
6796 char buf[MAX_BUF_SIZE] = {0};
6797 char cmd[MAX_CMD_SIZE] = {0};
6798
6799 if(!output_ulong || !(apIndex==0 || apIndex==1))
6800 return RETURN_ERR;
6801 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6802 _syscmd(cmd, buf, sizeof(buf));
6803 if(strlen(buf) > 0)
6804 *output_ulong=strtoul(buf, NULL, 10);
6805
6806 return RETURN_OK;
6807}
6808
6809// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6810INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6811{
6812 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6813 char ap_pin[16] = {0};
6814 char buf[MAX_BUF_SIZE] = {0};
6815 char config_file[MAX_BUF_SIZE] = {0};
6816 ULONG prev_pin = 0;
6817 struct params params;
6818
6819 if(!(apIndex==0 || apIndex==1))
6820 return RETURN_ERR;
6821 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6822 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6823 params.name = "ap_pin";
6824 params.value = ap_pin;
6825 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6826 wifi_hostapdWrite(config_file, &params, 1);
6827 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6828 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6829
6830 return RETURN_OK;
6831}
6832
6833// Output string is either Not configured or Configured, max 32 characters
6834INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6835{
6836 char cmd[MAX_CMD_SIZE];
6837 char buf[MAX_BUF_SIZE]={0};
6838
6839 if(!output_string || !(apIndex==0 || apIndex==1))
6840 return RETURN_ERR;
6841 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6842 snprintf(output_string, 32, "Not configured");
6843 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6844 _syscmd(cmd, buf, sizeof(buf));
6845
developer348e3d92022-09-13 14:48:41 +08006846 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006847 snprintf(output_string, 32, "Configured");
6848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6849
6850 return RETURN_OK;
6851}
6852
6853// sets the WPS pin for this AP
6854INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6855{
6856 char cmd[MAX_CMD_SIZE];
6857 char buf[MAX_BUF_SIZE]={0};
6858 BOOL enable;
6859
6860 if(!(apIndex==0 || apIndex==1))
6861 return RETURN_ERR;
6862 wifi_getApEnable(apIndex, &enable);
6863 if (!enable)
6864 return RETURN_ERR;
6865 wifi_getApWpsEnable(apIndex, &enable);
6866 if (!enable)
6867 return RETURN_ERR;
6868
6869 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6870 _syscmd(cmd, buf, sizeof(buf));
6871 if((strstr(buf, "OK"))!=NULL)
6872 return RETURN_OK;
6873
6874 return RETURN_ERR;
6875}
6876
6877// This function is called when the WPS push button has been pressed for this AP
6878INT wifi_setApWpsButtonPush(INT apIndex)
6879{
6880 char cmd[MAX_CMD_SIZE];
6881 char buf[MAX_BUF_SIZE]={0};
6882 BOOL enable=FALSE;
6883
6884 if(!(apIndex==0 || apIndex==1))
6885 return RETURN_ERR;
6886 wifi_getApEnable(apIndex, &enable);
6887 if (!enable)
6888 return RETURN_ERR;
6889
6890 wifi_getApWpsEnable(apIndex, &enable);
6891 if (!enable)
6892 return RETURN_ERR;
6893
6894 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6895 _syscmd(cmd, buf, sizeof(buf));
6896
6897 if((strstr(buf, "OK"))!=NULL)
6898 return RETURN_OK;
6899 return RETURN_ERR;
6900}
6901
6902// cancels WPS mode for this AP
6903INT wifi_cancelApWPS(INT apIndex)
6904{
6905 char cmd[MAX_CMD_SIZE];
6906 char buf[MAX_BUF_SIZE]={0};
6907
6908 if(!(apIndex==0 || apIndex==1))
6909 return RETURN_ERR;
6910 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6911 _syscmd(cmd,buf, sizeof(buf));
6912
6913 if((strstr(buf, "OK"))!=NULL)
6914 return RETURN_OK;
6915 return RETURN_ERR;
6916}
6917
6918//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6919//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6920INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6921{
6922 FILE *f;
6923 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6924 char cmd[256], buf[2048];
6925 char *param , *value, *line=NULL;
6926 size_t len = 0;
6927 ssize_t nread;
6928 wifi_associated_dev_t *dev=NULL;
6929
6930 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6931 *associated_dev_array = NULL;
6932 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6933 _syscmd(cmd,buf,sizeof(buf));
6934 *output_array_size = atoi(buf);
6935
6936 if (*output_array_size <= 0)
6937 return RETURN_OK;
6938
6939 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6940 *associated_dev_array = dev;
6941 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6942 _syscmd(cmd,buf,sizeof(buf));
6943 f = fopen("/tmp/connected_devices.txt", "r");
6944 if (f==NULL)
6945 {
6946 *output_array_size=0;
6947 return RETURN_ERR;
6948 }
6949 while ((nread = getline(&line, &len, f)) != -1)
6950 {
6951 param = strtok(line,"=");
6952 value = strtok(NULL,"=");
6953
6954 if( strcmp("flags",param) == 0 )
6955 {
6956 value[strlen(value)-1]='\0';
6957 if(strstr (value,"AUTHORIZED") != NULL )
6958 {
6959 dev[auth_temp].cli_AuthenticationState = 1;
6960 dev[auth_temp].cli_Active = 1;
6961 auth_temp++;
6962 read_flag=1;
6963 }
6964 }
6965 if(read_flag==1)
6966 {
6967 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6968 {
6969 value[strlen(value)-1]='\0';
6970 sscanf(value, "%x:%x:%x:%x:%x:%x",
6971 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6972 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6973 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6974 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6975 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6976 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6977 mac_temp++;
6978 read_flag=0;
6979 }
6980 }
6981 }
6982 *output_array_size = auth_temp;
6983 auth_temp=0;
6984 mac_temp=0;
6985 free(line);
6986 fclose(f);
6987 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6988 return RETURN_OK;
6989}
6990
6991#define MACADDRESS_SIZE 6
6992
6993INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6994{
6995 FILE *fp = NULL;
6996 char str[MAX_BUF_SIZE] = {0};
6997 int wificlientindex = 0 ;
6998 int count = 0;
6999 int signalstrength = 0;
7000 int arr[MACADDRESS_SIZE] = {0};
7001 unsigned char mac[MACADDRESS_SIZE] = {0};
7002 UINT wifi_count = 0;
7003 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7004 char pipeCmd[MAX_CMD_SIZE] = {0};
7005
7006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7007 *output_array_size = 0;
7008 *associated_dev_array = NULL;
7009
7010 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7011 fp = popen(pipeCmd, "r");
7012 if (fp == NULL)
7013 {
7014 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7015 return RETURN_ERR;
7016 }
7017
7018 /* Read the output a line at a time - output it. */
7019 fgets(str, sizeof(str)-1, fp);
7020 wifi_count = (unsigned int) atoi ( str );
7021 *output_array_size = wifi_count;
7022 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7023 pclose(fp);
7024
7025 if(wifi_count == 0)
7026 {
7027 return RETURN_OK;
7028 }
7029 else
7030 {
7031 wifi_associated_dev3_t* temp = NULL;
7032 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7033 if(temp == NULL)
7034 {
7035 printf("Error Statement. Insufficient memory \n");
7036 return RETURN_ERR;
7037 }
7038
7039 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7040 system(pipeCmd);
7041 memset(pipeCmd,0,sizeof(pipeCmd));
7042 if(apIndex == 0)
7043 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7044 else if(apIndex == 1)
7045 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7046 system(pipeCmd);
7047
7048 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7049 if(fp == NULL)
7050 {
7051 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7052 return RETURN_ERR;
7053 }
7054 fclose(fp);
7055
7056 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7057 fp = popen(pipeCmd, "r");
7058 if(fp)
7059 {
7060 for(count =0 ; count < wifi_count; count++)
7061 {
7062 fgets(str, MAX_BUF_SIZE, fp);
7063 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7064 {
7065 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7066 {
7067 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7068
7069 }
7070 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7071 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]);
7072 }
7073 temp[count].cli_AuthenticationState = 1; //TODO
7074 temp[count].cli_Active = 1; //TODO
7075 }
7076 pclose(fp);
7077 }
7078
7079 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7080 fp = popen(pipeCmd, "r");
7081 if(fp)
7082 {
7083 pclose(fp);
7084 }
7085 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7086 if(fp)
7087 {
7088 for(count =0 ; count < wifi_count ;count++)
7089 {
7090 fgets(str, MAX_BUF_SIZE, fp);
7091 signalstrength = atoi(str);
7092 temp[count].cli_SignalStrength = signalstrength;
7093 temp[count].cli_RSSI = signalstrength;
7094 temp[count].cli_SNR = signalstrength + 95;
7095 }
7096 pclose(fp);
7097 }
7098
7099
7100 if((apIndex == 0) || (apIndex == 4))
7101 {
7102 for(count =0 ; count < wifi_count ;count++)
7103 {
7104 strcpy(temp[count].cli_OperatingStandard,"g");
7105 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7106 }
7107
7108 //BytesSent
7109 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7110 fp = popen(pipeCmd, "r");
7111 if(fp)
7112 {
7113 pclose(fp);
7114 }
7115 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7116 if(fp)
7117 {
7118 for (count = 0; count < wifi_count; count++)
7119 {
7120 fgets(str, MAX_BUF_SIZE, fp);
7121 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7122 }
7123 pclose(fp);
7124 }
7125
7126 //BytesReceived
7127 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7128 fp = popen(pipeCmd, "r");
7129 if (fp)
7130 {
7131 pclose(fp);
7132 }
7133 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7134 if (fp)
7135 {
7136 for (count = 0; count < wifi_count; count++)
7137 {
7138 fgets(str, MAX_BUF_SIZE, fp);
7139 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7140 }
7141 pclose(fp);
7142 }
7143
7144 //PacketsSent
7145 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7146 fp = popen(pipeCmd, "r");
7147 if (fp)
7148 {
7149 pclose(fp);
7150 }
7151
7152 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7153 if (fp)
7154 {
7155 for (count = 0; count < wifi_count; count++)
7156 {
7157 fgets(str, MAX_BUF_SIZE, fp);
7158 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7159 }
7160 pclose(fp);
7161 }
7162
7163 //PacketsReceived
7164 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7165 fp = popen(pipeCmd, "r");
7166 if (fp)
7167 {
7168 pclose(fp);
7169 }
7170 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7171 if (fp)
7172 {
7173 for (count = 0; count < wifi_count; count++)
7174 {
7175 fgets(str, MAX_BUF_SIZE, fp);
7176 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7177 }
7178 pclose(fp);
7179 }
7180
7181 //ErrorsSent
7182 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7183 fp = popen(pipeCmd, "r");
7184 if (fp)
7185 {
7186 pclose(fp);
7187 }
7188 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7189 if (fp)
7190 {
7191 for (count = 0; count < wifi_count; count++)
7192 {
7193 fgets(str, MAX_BUF_SIZE, fp);
7194 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7195 }
7196 pclose(fp);
7197 }
7198
7199 //ErrorsSent
7200 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7201 fp = popen(pipeCmd, "r");
7202 if (fp)
7203 {
7204 pclose(fp);
7205 }
7206 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7207 if (fp)
7208 {
7209 for (count = 0; count < wifi_count; count++)
7210 {
7211 fgets(str, MAX_BUF_SIZE, fp);
7212 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7213 }
7214 pclose(fp);
7215 }
7216
7217 //LastDataDownlinkRate
7218 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7219 fp = popen(pipeCmd, "r");
7220 if (fp)
7221 {
7222 pclose(fp);
7223 }
7224 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7225 if (fp)
7226 {
7227 for (count = 0; count < wifi_count; count++)
7228 {
7229 fgets(str, MAX_BUF_SIZE, fp);
7230 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7231 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7232 }
7233 pclose(fp);
7234 }
7235
7236 //LastDataUplinkRate
7237 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7238 fp = popen(pipeCmd, "r");
7239 if (fp)
7240 {
7241 pclose(fp);
7242 }
7243 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7244 if (fp)
7245 {
7246 for (count = 0; count < wifi_count; count++)
7247 {
7248 fgets(str, MAX_BUF_SIZE, fp);
7249 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7250 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7251 }
7252 pclose(fp);
7253 }
7254
7255 }
7256 else if ((apIndex == 1) || (apIndex == 5))
7257 {
7258 for (count = 0; count < wifi_count; count++)
7259 {
7260 strcpy(temp[count].cli_OperatingStandard, "a");
7261 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7262 temp[count].cli_BytesSent = 0;
7263 temp[count].cli_BytesReceived = 0;
7264 temp[count].cli_LastDataUplinkRate = 0;
7265 temp[count].cli_LastDataDownlinkRate = 0;
7266 temp[count].cli_PacketsSent = 0;
7267 temp[count].cli_PacketsReceived = 0;
7268 temp[count].cli_ErrorsSent = 0;
7269 }
7270 }
7271
7272 for (count = 0; count < wifi_count; count++)
7273 {
7274 temp[count].cli_Retransmissions = 0;
7275 temp[count].cli_DataFramesSentAck = 0;
7276 temp[count].cli_DataFramesSentNoAck = 0;
7277 temp[count].cli_MinRSSI = 0;
7278 temp[count].cli_MaxRSSI = 0;
7279 strncpy(temp[count].cli_InterferenceSources, "", 64);
7280 memset(temp[count].cli_IPAddress, 0, 64);
7281 temp[count].cli_RetransCount = 0;
7282 temp[count].cli_FailedRetransCount = 0;
7283 temp[count].cli_RetryCount = 0;
7284 temp[count].cli_MultipleRetryCount = 0;
7285 }
7286 *associated_dev_array = temp;
7287 }
7288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7289 return RETURN_OK;
7290}
7291
7292int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7293{
7294 FILE *fp = NULL;
7295 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7296 char cmd[MAX_CMD_SIZE];
7297 int count = 0;
7298
7299 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7300 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7301 fp = popen(cmd,"r");
7302 if(fp == NULL)
7303 {
7304 printf("Failed to run command in Function %s\n",__FUNCTION__);
7305 return 0;
7306 }
7307 if(fgets(path, sizeof(path)-1, fp) != NULL)
7308 {
7309 for(count=0;path[count]!='\n';count++)
7310 status[count]=path[count];
7311 status[count]='\0';
7312 }
7313 strcpy(wifi_status,status);
7314 pclose(fp);
7315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7316 return RETURN_OK;
7317}
7318
7319/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7320struct hostapd_sta_param {
7321 char key[50];
7322 char value[100];
7323}
7324
7325static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7326 int i = 0;
7327
7328 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7329 if (strncmp(params[i].key,key,50) == 0){
7330 return &params[i].value;
7331 }
7332 i++;
7333 }
7334 return NULL;
7335
7336} */
7337
7338static unsigned int count_occurences(const char *buf, const char *word)
7339{
7340 unsigned int n = 0;
7341 char *ptr = strstr(buf, word);
7342
7343 while (ptr++) {
7344 n++;
7345 ptr = strstr(ptr, word);
7346 }
7347
7348 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7349 return n;
7350}
7351
7352static const char *get_line_from_str_buf(const char *buf, char *line)
7353{
7354 int i;
7355 int n = strlen(buf);
7356
7357 for (i = 0; i < n; i++) {
7358 line[i] = buf[i];
7359 if (buf[i] == '\n') {
7360 line[i] = '\0';
7361 return &buf[i + 1];
7362 }
7363 }
7364
7365 return NULL;
7366}
7367
7368INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7369{
7370 unsigned int assoc_cnt = 0;
7371 char interface_name[50] = {0};
7372 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7373 char cmd[MAX_CMD_SIZE] = {'\0'};
7374 char line[256] = {'\0'};
7375 int i = 0;
7376 int ret = 0;
7377 const char *ptr = NULL;
7378 char *key = NULL;
7379 char *val = NULL;
7380 wifi_associated_dev3_t *temp = NULL;
7381 int rssi;
7382
7383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7384
7385 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7386 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7387 return RETURN_ERR;
7388 }
7389
7390 // Example filtered output of 'iw dev' command:
7391 // Station 0a:69:72:10:d2:fa (on wifi0)
7392 // signal avg:-67 [-71, -71] dBm
7393 // Station 28:c2:1f:25:5f:99 (on wifi0)
7394 // signal avg:-67 [-71, -70] dBm
7395 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7396 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7397 return RETURN_ERR;
7398 }
7399
7400 ret = _syscmd(cmd, buf, sizeof(buf));
7401 if (ret == RETURN_ERR) {
7402 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7403 return RETURN_ERR;
7404 }
7405
7406 *output_array_size = count_occurences(buf, "Station");
7407 if (*output_array_size == 0) return RETURN_OK;
7408
7409 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7410 if (temp == NULL) {
7411 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7412 return RETURN_ERR;
7413 }
7414 *associated_dev_array = temp;
7415
7416 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7417 ptr = get_line_from_str_buf(buf, line);
7418 i = -1;
7419 while (ptr) {
7420 if (strstr(line, "Station")) {
7421 i++;
7422 key = strtok(line, " ");
7423 val = strtok(NULL, " ");
7424 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7425 &temp[i].cli_MACAddress[0],
7426 &temp[i].cli_MACAddress[1],
7427 &temp[i].cli_MACAddress[2],
7428 &temp[i].cli_MACAddress[3],
7429 &temp[i].cli_MACAddress[4],
7430 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7431 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7432 free(*associated_dev_array);
7433 return RETURN_ERR;
7434 }
7435 }
7436 else if (i < 0) {
7437 ptr = get_line_from_str_buf(ptr, line);
7438 continue; // We didn't detect 'station' entry yet
7439 }
7440 else if (strstr(line, "signal avg")) {
7441 key = strtok(line, ":");
7442 val = strtok(NULL, " ");
7443 if (sscanf(val, "%d", &rssi) <= 0 ) {
7444 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7445 free(*associated_dev_array);
7446 return RETURN_ERR;
7447 }
7448 temp[i].cli_RSSI = rssi;
7449 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7450 }
7451 // Here other fields can be parsed if added to filter of 'iw dev' command
7452
7453 ptr = get_line_from_str_buf(ptr, line);
7454 };
7455
7456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7457
7458 return RETURN_OK;
7459}
7460
7461#if 0
7462//To-do
7463INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7464{
7465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7466
7467 //Using different approach to get required WiFi Parameters from system available commands
7468#if 0
7469 FILE *f;
7470 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7471 char cmd[256], buf[2048];
7472 char *param , *value, *line=NULL;
7473 size_t len = 0;
7474 ssize_t nread;
7475 wifi_associated_dev3_t *dev=NULL;
7476 *associated_dev_array = NULL;
7477 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7478 _syscmd(cmd,buf,sizeof(buf));
7479 *output_array_size = atoi(buf);
7480
7481 if (*output_array_size <= 0)
7482 return RETURN_OK;
7483
7484 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7485 *associated_dev_array = dev;
7486 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7487 _syscmd(cmd,buf,sizeof(buf));
7488 f = fopen("/tmp/connected_devices.txt", "r");
7489 if (f==NULL)
7490 {
7491 *output_array_size=0;
7492 return RETURN_ERR;
7493 }
7494 while ((nread = getline(&line, &len, f)) != -1)
7495 {
7496 param = strtok(line,"=");
7497 value = strtok(NULL,"=");
7498
7499 if( strcmp("flags",param) == 0 )
7500 {
7501 value[strlen(value)-1]='\0';
7502 if(strstr (value,"AUTHORIZED") != NULL )
7503 {
7504 dev[auth_temp].cli_AuthenticationState = 1;
7505 dev[auth_temp].cli_Active = 1;
7506 auth_temp++;
7507 read_flag=1;
7508 }
7509 }
7510 if(read_flag==1)
7511 {
7512 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7513 {
7514 value[strlen(value)-1]='\0';
7515 sscanf(value, "%x:%x:%x:%x:%x:%x",
7516 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7517 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7518 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7519 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7520 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7521 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7522
7523 }
7524 else if( strcmp("rx_packets",param) == 0 )
7525 {
7526 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7527 }
7528
7529 else if( strcmp("tx_packets",param) == 0 )
7530 {
7531 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7532 }
7533
7534 else if( strcmp("rx_bytes",param) == 0 )
7535 {
7536 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7537 }
7538
7539 else if( strcmp("tx_bytes",param) == 0 )
7540 {
7541 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7542 mac_temp++;
7543 read_flag=0;
7544 }
7545 }
7546 }
7547
7548 *output_array_size = auth_temp;
7549 auth_temp=0;
7550 mac_temp=0;
7551 free(line);
7552 fclose(f);
7553#endif
7554 char interface_name[MAX_BUF_SIZE] = {0};
7555 char wifi_status[MAX_BUF_SIZE] = {0};
7556 char hostapdconf[MAX_BUF_SIZE] = {0};
7557
7558 wifi_associated_dev3_t *dev_array = NULL;
7559 ULONG wifi_count = 0;
7560
7561 *associated_dev_array = NULL;
7562 *output_array_size = 0;
7563
7564 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7565 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7566 {
7567 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7568
7569 GetInterfaceName(interface_name, hostapdconf);
7570
7571 if(strlen(interface_name) > 1)
7572 {
7573 wifihal_interfacestatus(wifi_status,interface_name);
7574 if(strcmp(wifi_status,"RUNNING") == 0)
7575 {
7576 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7577
7578 *associated_dev_array = dev_array;
7579 *output_array_size = wifi_count;
7580 }
7581 else
7582 {
7583 *associated_dev_array = NULL;
7584 }
7585 }
7586 }
7587
7588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7589 return RETURN_OK;
7590}
7591#endif
7592
7593/* getIPAddress function */
7594/**
7595* @description Returning IpAddress of the Matched String
7596*
7597* @param
7598* @str Having MacAddress
7599* @ipaddr Having ipaddr
7600* @return The status of the operation
7601* @retval RETURN_OK if successful
7602* @retval RETURN_ERR if any error is detected
7603*
7604*/
7605
7606INT getIPAddress(char *str,char *ipaddr)
7607{
7608 FILE *fp = NULL;
7609 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7610 int LeaseTime = 0,ret = 0;
7611 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7612 {
7613 return RETURN_ERR;
7614 }
7615
7616 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7617 {
7618 /*
7619 Sample:sss
7620 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7621 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7622 */
7623 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7624 &(LeaseTime),
7625 phyAddr,
7626 ipAddr,
7627 hostName
7628 );
7629 if(ret != 4)
7630 continue;
7631 if(strcmp(str,phyAddr) == 0)
7632 strcpy(ipaddr,ipAddr);
7633 }
7634 return RETURN_OK;
7635}
7636
7637/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7638/**
7639* @description Returning Inactive wireless connected clients informations
7640*
7641* @param
7642* @filename Holding private_wifi 2g/5g content files
7643* @associated_dev_array Having inactiv wireless clients informations
7644* @output_array_size Returning Inactive wireless counts
7645* @return The status of the operation
7646* @retval RETURN_OK if successful
7647* @retval RETURN_ERR if any error is detected
7648*
7649*/
7650
7651INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7652{
7653 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7654 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7655 FILE *fp = NULL;
7656 int arr[MACADDRESS_SIZE] = {0};
7657 unsigned char mac[MACADDRESS_SIZE] = {0};
7658 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7659 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7660 fp = popen(buf,"r");
7661 if(fp == NULL)
7662 return RETURN_ERR;
7663 else
7664 {
7665 fgets(path,sizeof(path),fp);
7666 maccount = atoi(path);
7667 }
7668 pclose(fp);
7669 *output_array_size = maccount;
7670 wifi_associated_dev3_t* temp = NULL;
7671 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7672 *associated_dev_array = temp;
7673 if(temp == NULL)
7674 {
7675 printf("Error Statement. Insufficient memory \n");
7676 return RETURN_ERR;
7677 }
7678 memset(buf,0,sizeof(buf));
7679 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7680 fp = popen(buf,"r");
7681 for(count = 0; count < maccount ; count++)
7682 {
7683 fgets(path,sizeof(path),fp);
7684 for(i = 0; path[i]!='\n';i++)
7685 str[i]=path[i];
7686 str[i]='\0';
7687 getIPAddress(str,ipaddr);
7688 memset(buf,0,sizeof(buf));
7689 if(strlen(ipaddr) > 0)
7690 {
7691 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7692 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7693 {
7694 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7695 {
7696 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7697 {
7698 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7699
7700 }
7701 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7702 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]);
7703 }
7704 temp[count].cli_AuthenticationState = 0; //TODO
7705 temp[count].cli_Active = 0; //TODO
7706 temp[count].cli_SignalStrength = 0;
7707 }
7708 else //Active wireless clients info
7709 {
7710 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7711 {
7712 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7713 {
7714 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7715
7716 }
7717 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7718 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]);
7719 }
7720 temp[count].cli_Active = 1;
7721 }
7722 }
7723 memset(ipaddr,0,sizeof(ipaddr));
7724 }
7725 pclose(fp);
7726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7727 return RETURN_OK;
7728}
7729//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7730//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7731//To get Band Steering Capability
7732INT wifi_getBandSteeringCapability(BOOL *support)
7733{
7734 *support = FALSE;
7735 return RETURN_OK;
7736}
7737
7738
7739//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7740//To get Band Steering enable status
7741INT wifi_getBandSteeringEnable(BOOL *enable)
7742{
7743 *enable = FALSE;
7744 return RETURN_OK;
7745}
7746
7747//To turn on/off Band steering
7748INT wifi_setBandSteeringEnable(BOOL enable)
7749{
7750 return RETURN_OK;
7751}
7752
7753//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7754//To get Band Steering AP group
7755INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7756{
7757 if (NULL == output_ApGroup)
7758 return RETURN_ERR;
7759
7760 strcpy(output_ApGroup, "1,2");
7761 return RETURN_OK;
7762}
7763
7764//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7765//to set and read the band steering BandUtilizationThreshold parameters
7766INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7767{
7768 return RETURN_ERR;
7769}
7770
7771INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7772{
7773 return RETURN_ERR;
7774}
7775
7776//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7777//to set and read the band steering RSSIThreshold parameters
7778INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7779{
7780 return RETURN_ERR;
7781}
7782
7783INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7784{
7785 return RETURN_ERR;
7786}
7787
7788
7789//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7790//to set and read the band steering physical modulation rate threshold parameters
7791INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7792{
7793 //If chip is not support, return -1
7794 return RETURN_ERR;
7795}
7796
7797INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7798{
7799 //If chip is not support, return -1
7800 return RETURN_ERR;
7801}
7802
7803//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7804//to set and read the inactivity time (in seconds) for steering under overload condition
7805INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7806{
7807 return RETURN_ERR;
7808}
7809
7810INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7811{
7812 return RETURN_ERR;
7813}
7814
7815//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7816//to set and read the inactivity time (in seconds) for steering under Idle condition
7817INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7818{
7819 return RETURN_ERR;
7820}
7821
7822INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7823{
7824 return RETURN_ERR;
7825}
7826
7827//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7828//pClientMAC[64]
7829//pSourceSSIDIndex[64]
7830//pDestSSIDIndex[64]
7831//pSteeringReason[256]
7832INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7833{
7834 //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
7835 *pSteeringTime=time(NULL);
7836 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7837 return RETURN_OK;
7838}
7839
7840INT wifi_ifConfigDown(INT apIndex)
7841{
7842 INT status = RETURN_OK;
7843 char cmd[64];
7844
7845 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7846 printf("%s: %s\n", __func__, cmd);
7847 system(cmd);
7848
7849 return status;
7850}
7851
7852INT wifi_ifConfigUp(INT apIndex)
7853{
7854 char cmd[128];
7855 char buf[1024];
7856
7857 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7858 _syscmd(cmd, buf, sizeof(buf));
7859 return 0;
7860}
7861
7862//>> Deprecated. Replace with wifi_applyRadioSettings
7863INT wifi_pushBridgeInfo(INT apIndex)
7864{
7865 char ip[32];
7866 char subnet[32];
7867 char bridge[32];
7868 int vlanId;
7869 char cmd[128];
7870 char buf[1024];
7871
7872 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7873 wifi_getApVlanID(apIndex,&vlanId);
7874
7875 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7876 _syscmd(cmd,buf, sizeof(buf));
7877
7878 return 0;
7879}
7880
7881INT wifi_pushChannel(INT radioIndex, UINT channel)
7882{
7883 char cmd[128];
7884 char buf[1024];
7885 int apIndex;
7886
7887 apIndex=(radioIndex==0)?0:1;
7888 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7889 _syscmd(cmd,buf, sizeof(buf));
7890
7891 return 0;
7892}
7893
7894INT wifi_pushChannelMode(INT radioIndex)
7895{
7896 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7897 return RETURN_ERR;
7898}
7899
7900INT wifi_pushDefaultValues(INT radioIndex)
7901{
7902 //Apply Comcast specified default radio settings instantly
7903 //AMPDU=1
7904 //AMPDUFrames=32
7905 //AMPDULim=50000
7906 //txqueuelen=1000
7907
7908 return RETURN_ERR;
7909}
7910
7911INT wifi_pushTxChainMask(INT radioIndex)
7912{
7913 //Apply default TxChainMask instantly
7914 return RETURN_ERR;
7915}
7916
7917INT wifi_pushRxChainMask(INT radioIndex)
7918{
7919 //Apply default RxChainMask instantly
7920 return RETURN_ERR;
7921}
7922
7923INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7924{
7925 INT status;
7926
7927 status = wifi_setSSIDName(apIndex,ssid);
7928 wifi_setApEnable(apIndex,FALSE);
7929 wifi_setApEnable(apIndex,TRUE);
7930
7931 return status;
7932}
7933
7934INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7935{
7936 //Apply default Ssid Advertisement instantly
7937 return RETURN_ERR;
7938}
7939
7940INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7941{
7942 INT status = RETURN_ERR;
7943 *output = 0;
7944 return RETURN_ERR;
7945}
7946
7947INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7948{
7949 return RETURN_OK;
7950}
7951
7952INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7953{
7954 return RETURN_OK;
7955}
7956
7957//To-do
7958INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7959{
developereb199ae2022-09-13 14:04:27 +08007960 char output[16]={'\0'};
7961 char config_file[MAX_BUF_SIZE] = {0};
7962
7963 if (!output_string)
7964 return RETURN_ERR;
7965
7966 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7967 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7968
7969 if (strlen(output) == 0)
7970 snprintf(output_string, 64, "Disabled");
7971 else if (strncmp(output, "0", 1) == 0)
7972 snprintf(output_string, 64, "Disabled");
7973 else if (strncmp(output, "1", 1) == 0)
7974 snprintf(output_string, 64, "Optional");
7975 else if (strncmp(output, "2", 1) == 0)
7976 snprintf(output_string, 64, "Required");
7977 else {
7978 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7979 return RETURN_ERR;
7980 }
7981
7982 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007983 return RETURN_OK;
7984}
7985INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7986{
developereb199ae2022-09-13 14:04:27 +08007987 char str[MAX_BUF_SIZE]={'\0'};
7988 char cmd[MAX_CMD_SIZE]={'\0'};
7989 struct params params;
7990 char config_file[MAX_BUF_SIZE] = {0};
7991
7992 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7993 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7994 return RETURN_ERR;
7995
7996 params.name = "ieee80211w";
7997 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7998 params.value = "0";
7999 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8000 params.value = "1";
8001 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8002 params.value = "2";
8003 else{
8004 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8005 return RETURN_ERR;
8006 }
8007 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8008 wifi_hostapdWrite(config_file, &params, 1);
8009 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008010 return RETURN_OK;
8011}
8012INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8013{
8014 char output[16]={'\0'};
8015 char config_file[MAX_BUF_SIZE] = {0};
8016
8017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8018 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8019 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8020
8021 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8022 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8023
8024 return RETURN_OK;
8025}
8026
8027INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8028{
8029 return RETURN_OK;
8030}
8031
8032INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8033{
8034 return RETURN_OK;
8035}
8036
8037INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8038{
8039 return RETURN_OK;
8040}
8041
8042INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8043{
8044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8045 char config_file[MAX_BUF_SIZE] = {0};
8046
8047 if (NULL == output)
8048 return RETURN_ERR;
8049 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8050 wifi_hostapdRead(config_file,"hw_mode",output,64);
8051
8052 if(strcmp(output,"b")==0)
8053 sprintf(output, "%s", "1,2,5.5,11");
8054 else if (strcmp(output,"a")==0)
8055 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8056 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8057 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8058
8059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8060 return RETURN_OK;
8061}
8062
8063INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8064{
8065 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8066 char *temp;
8067 char temp_output[128];
8068 char temp_TransmitRates[128];
8069 char config_file[MAX_BUF_SIZE] = {0};
8070
8071 if (NULL == output)
8072 return RETURN_ERR;
8073
8074 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8075 wifi_hostapdRead(config_file,"supported_rates",output,64);
8076
8077 strcpy(temp_TransmitRates,output);
8078 strcpy(temp_output,"");
8079 temp = strtok(temp_TransmitRates," ");
8080 while(temp!=NULL)
8081 {
8082 temp[strlen(temp)-1]=0;
8083 if((temp[0]=='5') && (temp[1]=='\0'))
8084 {
8085 temp="5.5";
8086 }
8087 strcat(temp_output,temp);
8088 temp = strtok(NULL," ");
8089 if(temp!=NULL)
8090 {
8091 strcat(temp_output,",");
8092 }
8093 }
8094 strcpy(output,temp_output);
8095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8096
8097 return RETURN_OK;
8098}
8099
8100INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8101{
8102 return RETURN_OK;
8103}
8104
8105
8106INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8107{
8108 int i=0;
8109 char *temp;
developeref938762022-10-19 17:21:01 +08008110 char temp1[128] = {0};
8111 char temp_output[128] = {0};
8112 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008113 struct params params={'\0'};
8114 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008115 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008116
8117 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8118 if(NULL == output)
8119 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008120 strcpy(temp_TransmitRates,output);
8121
8122 for(i=0;i<strlen(temp_TransmitRates);i++)
8123 {
developeref938762022-10-19 17:21:01 +08008124 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008125 {
8126 continue;
8127 }
8128 else
8129 {
8130 return RETURN_ERR;
8131 }
8132 }
8133 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008134 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008135 while(temp!=NULL)
8136 {
8137 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008138 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008139 {
developeref938762022-10-19 17:21:01 +08008140 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008141 {
8142 return RETURN_ERR;
8143 }
8144 }
8145
8146 if(strcmp(temp,"5.5")==0)
8147 {
8148 strcpy(temp1,"55");
8149 }
8150 else
8151 {
8152 strcat(temp1,"0");
8153 }
8154 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008155 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008156 if(temp!=NULL)
8157 {
8158 strcat(temp_output," ");
8159 }
8160 }
8161 strcpy(output,temp_output);
8162
developer06a01d92022-09-07 16:32:39 +08008163 params.name = "supported_rates";
8164 params.value = output;
8165
8166 wifi_dbg_printf("\n%s:",__func__);
8167 wifi_dbg_printf("params.value=%s\n",params.value);
8168 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8169 wifi_hostapdWrite(config_file,&params,1);
8170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8171
8172 return RETURN_OK;
8173}
8174
8175
8176static char *sncopy(char *dst, int dst_sz, const char *src)
8177{
8178 if (src && dst && dst_sz > 0) {
8179 strncpy(dst, src, dst_sz);
8180 dst[dst_sz - 1] = '\0';
8181 }
8182 return dst;
8183}
8184
8185static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8186{
8187 if (0 == strcmp(ht_mode, "HT40") ||
8188 0 == strcmp(ht_mode, "HT80") ||
8189 0 == strcmp(ht_mode, "HT160")) {
8190 switch (channel) {
8191 case 1 ... 7:
8192 case 36:
8193 case 44:
8194 case 52:
8195 case 60:
8196 case 100:
8197 case 108:
8198 case 116:
8199 case 124:
8200 case 132:
8201 case 140:
8202 case 149:
8203 case 157:
8204 return 1;
8205 case 8 ... 13:
8206 case 40:
8207 case 48:
8208 case 56:
8209 case 64:
8210 case 104:
8211 case 112:
8212 case 120:
8213 case 128:
8214 case 136:
8215 case 144:
8216 case 153:
8217 case 161:
8218 return -1;
8219 default:
8220 return -EINVAL;
8221 }
8222 }
8223
8224 return -EINVAL;
8225}
8226
developerb7593de2022-10-18 09:51:57 +08008227static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8228{
8229 int idx = channel%8;
8230 if (0 == strcmp(ht_mode, "HT40") ||
8231 0 == strcmp(ht_mode, "HT80") ||
8232 0 == strcmp(ht_mode, "HT160")) {
8233 switch (idx) {
8234 case 1:
8235 return 1;
8236 case 5:
8237 return -1;
8238 default:
8239 return -EINVAL;
8240 }
8241 }
8242
8243 return -EINVAL;
8244}
developer06a01d92022-09-07 16:32:39 +08008245static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8246{
8247 if (NULL == hw_mode) return;
8248
8249 if (0 == strcmp(hw_mode, "ac"))
8250 sncopy(bw_mode, bw_mode_len, "ht vht");
8251
8252 if (0 == strcmp(hw_mode, "n"))
8253 sncopy(bw_mode, bw_mode_len, "ht");
8254
8255 return;
8256}
8257
8258static int util_chan_to_freq(int chan)
8259{
8260 if (chan == 14)
8261 return 2484;
8262 else if (chan < 14)
8263 return 2407 + chan * 5;
8264 else if (chan >= 182 && chan <= 196)
8265 return 4000 + chan * 5;
8266 else
8267 return 5000 + chan * 5;
8268 return 0;
8269}
8270
developerb7593de2022-10-18 09:51:57 +08008271static int util_6G_chan_to_freq(int chan)
8272{
8273 if (chan)
8274 return 5950 + chan * 5;
8275 else
8276 return 0;
8277
8278}
developer06a01d92022-09-07 16:32:39 +08008279const int *util_unii_5g_chan2list(int chan, int width)
8280{
8281 static const int lists[] = {
8282 // <width>, <chan1>, <chan2>..., 0,
8283 20, 36, 0,
8284 20, 40, 0,
8285 20, 44, 0,
8286 20, 48, 0,
8287 20, 52, 0,
8288 20, 56, 0,
8289 20, 60, 0,
8290 20, 64, 0,
8291 20, 100, 0,
8292 20, 104, 0,
8293 20, 108, 0,
8294 20, 112, 0,
8295 20, 116, 0,
8296 20, 120, 0,
8297 20, 124, 0,
8298 20, 128, 0,
8299 20, 132, 0,
8300 20, 136, 0,
8301 20, 140, 0,
8302 20, 144, 0,
8303 20, 149, 0,
8304 20, 153, 0,
8305 20, 157, 0,
8306 20, 161, 0,
8307 20, 165, 0,
8308 40, 36, 40, 0,
8309 40, 44, 48, 0,
8310 40, 52, 56, 0,
8311 40, 60, 64, 0,
8312 40, 100, 104, 0,
8313 40, 108, 112, 0,
8314 40, 116, 120, 0,
8315 40, 124, 128, 0,
8316 40, 132, 136, 0,
8317 40, 140, 144, 0,
8318 40, 149, 153, 0,
8319 40, 157, 161, 0,
8320 80, 36, 40, 44, 48, 0,
8321 80, 52, 56, 60, 64, 0,
8322 80, 100, 104, 108, 112, 0,
8323 80, 116, 120, 124, 128, 0,
8324 80, 132, 136, 140, 144, 0,
8325 80, 149, 153, 157, 161, 0,
8326 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8327 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8328 -1 // final delimiter
8329 };
8330 const int *start;
8331 const int *p;
8332
8333 for (p = lists; *p != -1; p++) {
8334 if (*p == width) {
8335 for (start = ++p; *p != 0; p++) {
8336 if (*p == chan)
8337 return start;
8338 }
8339 }
8340 // move to the end of channel list of given width
8341 while (*p != 0) {
8342 p++;
8343 }
8344 }
8345
8346 return NULL;
8347}
8348
8349static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8350{
8351 if (NULL == ht_mode)
8352 return 0;
8353
8354 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8355 const int *chans = util_unii_5g_chan2list(channel, width);
8356 int sum = 0;
8357 int cnt = 0;
8358
8359 if (NULL == chans)
8360 return 0;
8361
8362 while (*chans) {
8363 sum += *chans;
8364 cnt++;
8365 chans++;
8366 }
8367 return sum / cnt;
8368}
8369
developerb7593de2022-10-18 09:51:57 +08008370static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8371{
8372 if (NULL == ht_mode)
8373 return 0;
8374
8375 int width = strtol((ht_mode + 2), NULL, 10);
8376
8377 int idx = 0 ;
8378 int centerchan = 0;
8379 int chan_ofs = 1;
8380
8381 if (width == 40){
8382 idx = ((channel/4) + chan_ofs)%2;
8383 switch (idx) {
8384 case 0:
8385 centerchan = (channel - 2);
8386 break;
8387 case 1:
8388 centerchan = (channel + 2);
8389 break;
8390 default:
8391 return -EINVAL;
8392 }
8393 }else if (width == 80){
8394 idx = ((channel/4) + chan_ofs)%4;
8395 switch (idx) {
8396 case 0:
8397 centerchan = (channel - 6);
8398 break;
8399 case 1:
8400 centerchan = (channel + 6);
8401 break;
8402 case 2:
8403 centerchan = (channel + 2);
8404 break;
8405 case 3:
8406 centerchan = (channel - 2);
8407 break;
8408 default:
8409 return -EINVAL;
8410 }
8411 }else if (width == 160){
8412 switch (channel) {
8413 case 1 ... 29:
8414 centerchan = 15;
8415 break;
8416 case 33 ... 61:
8417 centerchan = 47;
8418 break;
8419 case 65 ... 93:
8420 centerchan = 79;
8421 break;
8422 case 97 ... 125:
8423 centerchan = 111;
8424 break;
8425 case 129 ... 157:
8426 centerchan = 143;
8427 break;
8428 case 161 ... 189:
8429 centerchan = 175;
8430 break;
8431 case 193 ... 221:
8432 centerchan = 207;
8433 break;
8434 default:
8435 return -EINVAL;
8436 }
8437 }
8438 return centerchan;
8439}
developer06a01d92022-09-07 16:32:39 +08008440static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8441{
8442 BOOL onlyG, onlyN, onlyA;
8443 CHAR tmp[64];
8444 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8445 if (ret == RETURN_OK) {
8446 sncopy(hw_mode, hw_mode_size, tmp);
8447 }
8448 return ret;
8449}
8450
8451INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8452{
8453 // Sample commands:
8454 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8455 // hostapd_cli -i wifi0 chan_switch 30 2437
8456 char cmd[MAX_CMD_SIZE] = {0};
8457 char buf[MAX_BUF_SIZE] = {0};
8458 int freq = 0, ret = 0;
8459 char center_freq1_str[32] = ""; // center_freq1=%d
8460 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8461 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8462 char hw_mode[16] = ""; // n|ac
8463 char bw_mode[16] = ""; // ht|ht vht
8464 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8465 int sec_chan_offset;
8466 int width;
developer4fb0b922022-09-30 14:29:09 +08008467 char config_file[64] = {0};
8468 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008469 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008470 wifi_band band = band_invalid;
8471 int center_chan = 0;
8472 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008473
developer4fb0b922022-09-30 14:29:09 +08008474 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008475
8476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8477
developerb7593de2022-10-18 09:51:57 +08008478 band = wifi_index_to_band(radioIndex);
8479
developer5884e982022-10-06 10:52:50 +08008480 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008481
8482 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008483 if (channel){
developerb7593de2022-10-18 09:51:57 +08008484 if (band == band_6){
8485 freq = util_6G_chan_to_freq(channel);
8486 }else{
8487 freq = util_chan_to_freq(channel);
8488 }
developer5884e982022-10-06 10:52:50 +08008489 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008490
developer5884e982022-10-06 10:52:50 +08008491 // Provide bandwith if specified
8492 if (channel_width_MHz > 20) {
8493 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8494 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8495 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008496
developer5884e982022-10-06 10:52:50 +08008497 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8498 }else if (channel_width_MHz == 20){
8499 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8500 }
developer06a01d92022-09-07 16:32:39 +08008501
developerb7593de2022-10-18 09:51:57 +08008502
developer5884e982022-10-06 10:52:50 +08008503 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008504 if (band == band_6){
8505 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8506 if(center_chan){
8507 center_freq1 = util_6G_chan_to_freq(center_chan);
8508 }
8509 }else{
8510 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8511 if(center_chan){
8512 center_freq1 = util_chan_to_freq(center_chan);
8513 }
developer5884e982022-10-06 10:52:50 +08008514 }
developerb7593de2022-10-18 09:51:57 +08008515
8516 if (center_freq1)
8517 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8518
8519 }
8520
8521 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8522 if (band == band_6){
8523 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8524 }else{
8525 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008526 }
developerb7593de2022-10-18 09:51:57 +08008527 if (sec_chan_offset != -EINVAL)
8528 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008529
developer5884e982022-10-06 10:52:50 +08008530 // Only the first AP, other are hanging on the same radio
8531 int apIndex = radioIndex;
8532 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8533 AP_PREFIX, apIndex, csa_beacon_count, freq,
8534 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8535 wifi_dbg_printf("execute: '%s'\n", cmd);
8536 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008537
developer5884e982022-10-06 10:52:50 +08008538 ret = wifi_setRadioChannel(radioIndex, channel);
8539 if (ret != RETURN_OK) {
8540 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8541 return RETURN_ERR;
8542 }
8543
8544 if (sec_chan_offset == 1) ext_str = "Above";
8545 else if (sec_chan_offset == -1) ext_str = "Below";
8546
8547 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008548
developer5884e982022-10-06 10:52:50 +08008549 } else {
8550 if (channel_width_MHz > 20)
8551 ext_str = "Above";
8552 }
developer4fb0b922022-09-30 14:29:09 +08008553 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8554 _syscmd(cmd, buf, sizeof(buf));
8555 if (strlen(buf) != 0)
8556 stbcEnable = TRUE;
8557
developer06a01d92022-09-07 16:32:39 +08008558 wifi_setRadioExtChannel(radioIndex, ext_str);
8559
developer4fb0b922022-09-30 14:29:09 +08008560 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8561
developer06a01d92022-09-07 16:32:39 +08008562 char mhz_str[16];
8563 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8564 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8565
8566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8567
8568 return RETURN_OK;
8569}
8570
8571INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8572{
developer615510b2022-09-27 10:14:35 +08008573 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008574 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008575 char cmd[256]={0};
8576 char buf[128]={0};
8577 char file_name[32] = {0};
8578 char filter_SSID[32] = {0};
8579 char line[256] = {0};
8580 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008581 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008582 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008583 size_t len=0;
8584 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008585 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008586 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008587 bool filter_enable = false;
8588 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008589 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008590
developer615510b2022-09-27 10:14:35 +08008591 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008592
developer615510b2022-09-27 10:14:35 +08008593 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8594 f = fopen(file_name, "r");
8595 if (f != NULL) {
8596 fgets(filter_SSID, sizeof(file_name), f);
8597 if (strlen(filter_SSID) != 0)
8598 filter_enable = true;
8599 fclose(f);
8600 }
8601
developer033b37b2022-10-18 11:27:46 +08008602 phyId = radio_index_to_phy(radio_index);
8603
8604 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008605 _syscmd(cmd, buf, sizeof(buf));
8606 channels_num = strtol(buf, NULL, 10);
8607
developer615510b2022-09-27 10:14:35 +08008608 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8609 // 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);
8610 fprintf(stderr, "cmd: %s\n", cmd);
8611 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008612 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8613 return RETURN_ERR;
8614 }
developer5550e242022-09-30 09:59:32 +08008615
8616 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8617 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8618
developer615510b2022-09-27 10:14:35 +08008619 ret = fgets(line, sizeof(line), f);
8620 while (ret != NULL) {
8621 if(strstr(line, "BSS") != NULL) { // new neighbor info
8622 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8623 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8624 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8625
8626 if (!filter_BSS) {
8627 index++;
8628 wifi_neighbor_ap2_t *tmp;
8629 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8630 if (tmp == NULL) { // no more memory to use
8631 index--;
8632 wifi_dbg_printf("%s: realloc failed\n", __func__);
8633 break;
8634 }
8635 scan_array = tmp;
8636 }
8637 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008638
developer615510b2022-09-27 10:14:35 +08008639 filter_BSS = false;
8640 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8641 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8642 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8643 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8644 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008645 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008646 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008647
developer615510b2022-09-27 10:14:35 +08008648 if (freq >= 2412 && freq <= 2484) {
8649 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8650 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8651 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8652 }
8653 else if (freq >= 5160 && freq <= 5805) {
8654 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8655 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8656 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8657 }
developer06a01d92022-09-07 16:32:39 +08008658
developer615510b2022-09-27 10:14:35 +08008659 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008660 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008661 for (int i = 0; i < channels_num; i++) {
8662 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8663 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8664 break;
8665 }
8666 }
developer06a01d92022-09-07 16:32:39 +08008667 }
developer615510b2022-09-27 10:14:35 +08008668 } else if (strstr(line, "beacon interval") != NULL) {
8669 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8670 } else if (strstr(line, "signal") != NULL) {
8671 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8672 } else if (strstr(line,"SSID") != NULL) {
8673 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8674 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8675 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008676 }
developer615510b2022-09-27 10:14:35 +08008677 } else if (strstr(line, "Supported rates") != NULL) {
8678 char SRate[80] = {0}, *tmp = NULL;
8679 memset(buf, 0, sizeof(buf));
8680 strcpy(SRate, line);
8681 tmp = strtok(SRate, ":");
8682 tmp = strtok(NULL, ":");
8683 strcpy(buf, tmp);
8684 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008685
developer615510b2022-09-27 10:14:35 +08008686 tmp = strtok(buf, " \n");
8687 while (tmp != NULL) {
8688 strcat(SRate, tmp);
8689 if (SRate[strlen(SRate) - 1] == '*') {
8690 SRate[strlen(SRate) - 1] = '\0';
8691 }
8692 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008693
developer615510b2022-09-27 10:14:35 +08008694 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008695 }
developer615510b2022-09-27 10:14:35 +08008696 SRate[strlen(SRate) - 1] = '\0';
8697 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8698 } else if (strstr(line, "DTIM") != NULL) {
8699 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8700 } else if (strstr(line, "VHT capabilities") != NULL) {
8701 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8702 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8703 } else if (strstr(line, "HT capabilities") != NULL) {
8704 strcat(scan_array[index].ap_SupportedStandards, ",n");
8705 strcpy(scan_array[index].ap_OperatingStandards, "n");
8706 } else if (strstr(line, "VHT operation") != NULL) {
8707 ret = fgets(line, sizeof(line), f);
8708 sscanf(line," * channel width: %d", &vht_channel_width);
8709 if(vht_channel_width == 1) {
8710 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8711 } else {
8712 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8713 }
8714 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8715 continue;
8716 } else if (strstr(line, "HT operation") != NULL) {
8717 ret = fgets(line, sizeof(line), f);
8718 sscanf(line," * secondary channel offset: %s", &buf);
8719 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008720 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008721 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 +08008722 }
developer615510b2022-09-27 10:14:35 +08008723 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008724 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008725 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8726 } else {
8727 //20Mhz
8728 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 +08008729 }
developer615510b2022-09-27 10:14:35 +08008730 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008731 continue;
developer615510b2022-09-27 10:14:35 +08008732 } else if (strstr(line, "HE capabilities") != NULL) {
8733 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8734 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8735 ret = fgets(line, sizeof(line), f);
8736 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8737 if (strstr(line, "HE40/2.4GHz") != NULL)
8738 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8739 else
8740 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8741 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8742 if (strstr(line, "HE80/5GHz") != NULL) {
8743 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8744 ret = fgets(line, sizeof(line), f);
8745 } else
8746 continue;
8747 if (strstr(line, "HE160/5GHz") != NULL)
8748 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008749 }
developer615510b2022-09-27 10:14:35 +08008750 continue;
8751 } else if (strstr(line, "WPA") != NULL) {
8752 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8753 } else if (strstr(line, "RSN") != NULL) {
8754 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8755 } else if (strstr(line, "Group cipher") != NULL) {
8756 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8757 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8758 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008759 }
developer06a01d92022-09-07 16:32:39 +08008760 }
developer615510b2022-09-27 10:14:35 +08008761 ret = fgets(line, sizeof(line), f);
8762 }
8763
8764 if (!filter_BSS) {
8765 *output_array_size = index + 1;
8766 } else {
8767 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8768 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008769 }
developer06a01d92022-09-07 16:32:39 +08008770 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008771 pclose(f);
developer5550e242022-09-30 09:59:32 +08008772 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008774 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008775}
developer615510b2022-09-27 10:14:35 +08008776
developer06a01d92022-09-07 16:32:39 +08008777INT wifi_getApAssociatedDeviceStats(
8778 INT apIndex,
8779 mac_address_t *clientMacAddress,
8780 wifi_associated_dev_stats_t *associated_dev_stats,
8781 u64 *handle)
8782{
8783 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8784 char interface_name[50] = {0};
8785 char cmd[1024] = {0};
8786 char mac_str[18] = {0};
8787 char *key = NULL;
8788 char *val = NULL;
8789 FILE *f = NULL;
8790 char *line = NULL;
8791 size_t len = 0;
8792 ssize_t read = 0;
8793
8794 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8795 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8796 return RETURN_ERR;
8797 }
8798
8799 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8800 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8801 if((f = popen(cmd, "r")) == NULL) {
8802 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8803 return RETURN_ERR;
8804 }
8805
8806 while ((read = getline(&line, &len, f)) != -1) {
8807 key = strtok(line,":");
8808 val = strtok(NULL,":");
8809
8810 if(!strncmp(key,"rx bytes",8))
8811 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8812 if(!strncmp(key,"tx bytes",8))
8813 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8814 if(!strncmp(key,"rx packets",10))
8815 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8816 if(!strncmp(key,"tx packets",10))
8817 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8818 if(!strncmp(key,"tx retries",10))
8819 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8820 if(!strncmp(key,"tx failed",9))
8821 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8822 if(!strncmp(key,"rx drop misc",13))
8823 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8824 if(!strncmp(key,"rx bitrate",10)) {
8825 val = strtok(val, " ");
8826 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8827 }
8828 if(!strncmp(key,"tx bitrate",10)) {
8829 val = strtok(val, " ");
8830 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8831 }
8832 }
8833 free(line);
8834 pclose(f);
8835 return RETURN_OK;
8836}
8837
8838INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8839{
8840 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8841
8842 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8843 if (NULL == output_string)
8844 return RETURN_ERR;
8845
8846 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8847 _syscmd(cmd, buf, sizeof(buf));
8848
8849 //size of SSID name restricted to value less than 32 bytes
8850 snprintf(output_string, 32, "%s", buf);
8851 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8852
8853 return RETURN_OK;
8854}
8855
8856INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8857{
8858 //char cmd[MAX_CMD_SIZE] = {0};
8859 char config_file[MAX_BUF_SIZE] = {0};
8860 char buf[32] = {0};
8861
8862 if (!output_filterMode)
8863 return RETURN_ERR;
8864
8865 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8866 //_syscmd(cmd, buf, sizeof(buf));
8867 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8868 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008869 if(strlen(buf) == 0) {
8870 *output_filterMode = 0;
8871 }
8872 else {
8873 int macaddr_acl_mode = strtol(buf, NULL, 10);
8874 if (macaddr_acl_mode == 1) {
8875 *output_filterMode = 1;
8876 } else if (macaddr_acl_mode == 0) {
8877 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8878 if (strlen(buf) == 0) {
8879 *output_filterMode = 0;
8880 } else {
8881 *output_filterMode = 2;
8882 }
8883 } else {
8884 return RETURN_ERR;
8885 }
8886 }
developer06a01d92022-09-07 16:32:39 +08008887
8888 return RETURN_OK;
8889}
8890
8891INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8892{
8893 FILE *fp = NULL;
8894 char str[MAX_BUF_SIZE] = {0};
8895 int wificlientindex = 0 ;
8896 int count = 0;
8897 int signalstrength = 0;
8898 int arr[MACADDRESS_SIZE] = {0};
8899 unsigned char mac[MACADDRESS_SIZE] = {0};
8900 UINT wifi_count = 0;
8901 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8902 char pipeCmd[MAX_CMD_SIZE] = {0};
8903
8904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8905 *output_array_size = 0;
8906 *associated_dev_array = NULL;
8907 char interface_name[50] = {0};
8908
8909 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8910 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8911 return RETURN_ERR;
8912 }
8913
8914 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8915 fp = popen(pipeCmd, "r");
8916 if (fp == NULL)
8917 {
8918 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8919 return RETURN_ERR;
8920 }
8921
8922 /* Read the output a line at a time - output it. */
8923 fgets(str, sizeof(str)-1, fp);
8924 wifi_count = (unsigned int) atoi ( str );
8925 *output_array_size = wifi_count;
8926 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8927 pclose(fp);
8928
8929 if(wifi_count == 0)
8930 {
8931 return RETURN_OK;
8932 }
8933 else
8934 {
8935 wifi_associated_dev2_t* temp = NULL;
8936 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8937 *associated_dev_array = temp;
8938 if(temp == NULL)
8939 {
8940 printf("Error Statement. Insufficient memory \n");
8941 return RETURN_ERR;
8942 }
8943
8944 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8945 system(pipeCmd);
8946
8947 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8948 if(fp == NULL)
8949 {
8950 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8951 return RETURN_ERR;
8952 }
8953 fclose(fp);
8954
8955 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8956 fp = popen(pipeCmd, "r");
8957 if(fp)
8958 {
8959 for(count =0 ; count < wifi_count; count++)
8960 {
8961 fgets(str, MAX_BUF_SIZE, fp);
8962 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8963 {
8964 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8965 {
8966 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8967
8968 }
8969 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8970 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]);
8971 }
8972 temp[count].cli_AuthenticationState = 1; //TODO
8973 temp[count].cli_Active = 1; //TODO
8974 }
8975 pclose(fp);
8976 }
8977
8978 //Updating RSSI per client
8979 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8980 fp = popen(pipeCmd, "r");
8981 if(fp)
8982 {
8983 pclose(fp);
8984 }
8985 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8986 if(fp)
8987 {
8988 for(count =0 ; count < wifi_count ;count++)
8989 {
8990 fgets(str, MAX_BUF_SIZE, fp);
8991 signalstrength = atoi(str);
8992 temp[count].cli_RSSI = signalstrength;
8993 }
8994 pclose(fp);
8995 }
8996
8997
8998 //LastDataDownlinkRate
8999 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
9000 fp = popen(pipeCmd, "r");
9001 if (fp)
9002 {
9003 pclose(fp);
9004 }
9005 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9006 if (fp)
9007 {
9008 for (count = 0; count < wifi_count; count++)
9009 {
9010 fgets(str, MAX_BUF_SIZE, fp);
9011 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9012 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9013 }
9014 pclose(fp);
9015 }
9016
9017 //LastDataUplinkRate
9018 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
9019 fp = popen(pipeCmd, "r");
9020 if (fp)
9021 {
9022 pclose(fp);
9023 }
9024 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9025 if (fp)
9026 {
9027 for (count = 0; count < wifi_count; count++)
9028 {
9029 fgets(str, MAX_BUF_SIZE, fp);
9030 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9031 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9032 }
9033 pclose(fp);
9034 }
9035 }
9036 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9037 return RETURN_OK;
9038
9039}
9040
9041INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9042{
9043#if 0
9044 /*char buf[1024] = {0};
9045 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
9046 _syscmd(cmd, buf, sizeof(buf));*/
9047
9048 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9049 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9050 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9051 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9052
9053 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.
9054 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].
9055 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].
9056 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].
9057 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9058 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9059
9060 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9061 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9062 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9063 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.
9064 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.
9065 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.
9066 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.
9067 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.
9068 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.
9069 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.
9070 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9071#endif
9072
9073 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08009074 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08009075 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009076 char pipeCmd[128] = {0};
9077 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009078 wifi_ssidTrafficStats2_t *out = output_struct;
9079
developerce736392022-09-13 15:24:34 +08009080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009081 if (!output_struct)
9082 return RETURN_ERR;
9083
developerce736392022-09-13 15:24:34 +08009084 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9085 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
9086 GetInterfaceName(interface_name, HConf_file);
9087 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009088
developer06a01d92022-09-07 16:32:39 +08009089 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009090 if (fp == NULL) {
9091 fprintf(stderr, "%s: popen failed\n", __func__);
9092 return RETURN_ERR;
9093 }
9094 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08009095
developerce736392022-09-13 15:24:34 +08009096 if (strlen(str) == 0) // interface not exist
9097 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009098
developerce736392022-09-13 15:24:34 +08009099 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9100 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009101 pclose(fp);
9102
developerce736392022-09-13 15:24:34 +08009103 memset(str, 0, sizeof(str));
9104 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009105 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009106 if (fp == NULL) {
9107 fprintf(stderr, "%s: popen failed\n", __func__);
9108 return RETURN_ERR;
9109 }
9110 fgets(str, sizeof(str), fp);
9111
9112 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9113 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009114 pclose(fp);
developerce736392022-09-13 15:24:34 +08009115
9116 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9117 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9118
9119 // Not supported
9120 output_struct->ssid_RetransCount = 0;
9121 output_struct->ssid_FailedRetransCount = 0;
9122 output_struct->ssid_RetryCount = 0;
9123 output_struct->ssid_MultipleRetryCount = 0;
9124 output_struct->ssid_ACKFailureCount = 0;
9125 output_struct->ssid_AggregatedPacketCount = 0;
9126
developer06a01d92022-09-07 16:32:39 +08009127 return RETURN_OK;
9128}
9129
9130//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).
9131INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9132{
9133 char output_val[16]={'\0'};
9134 char config_file[MAX_BUF_SIZE] = {0};
9135
9136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9137 if (!output)
9138 return RETURN_ERR;
9139 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9140 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9141
9142 if( strcmp(output_val,"1") == 0 )
9143 *output = TRUE;
9144 else
9145 *output = FALSE;
9146 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9147
9148 return RETURN_OK;
9149}
9150
9151INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9152{
9153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9154 char str[MAX_BUF_SIZE]={'\0'};
9155 char string[MAX_BUF_SIZE]={'\0'};
9156 char cmd[MAX_CMD_SIZE]={'\0'};
9157 char *ch;
9158 char config_file[MAX_BUF_SIZE] = {0};
9159 struct params params;
9160
9161 if(enable == TRUE)
9162 strcpy(string,"1");
9163 else
9164 strcpy(string,"0");
9165
9166 params.name = "ap_isolate";
9167 params.value = string;
9168
9169 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9170 wifi_hostapdWrite(config_file,&params,1);
9171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9172
9173 return RETURN_OK;
9174}
9175
9176INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9177{
9178 if (NULL == output_dBm)
9179 return RETURN_ERR;
9180
9181 *output_dBm = 0;
9182 return RETURN_OK;
9183}
9184
9185INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9186{
9187 return RETURN_OK;
9188}
9189INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9190{
9191 return RETURN_OK;
9192}
9193INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9194{
9195 return RETURN_OK;
9196}
9197INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9198{
9199 return RETURN_OK;
9200}
9201INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9202{
9203 return RETURN_OK;
9204}
9205INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9206{
9207 char config_file[MAX_BUF_SIZE] = {0};
9208 struct params list;
9209
9210 list.name = "bss_transition";
9211 list.value = activate?"1":"0";
9212 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9213 wifi_hostapdWrite(config_file, &list, 1);
9214
9215 return RETURN_OK;
9216}
9217wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9218
9219void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9220{
9221 return;
9222}
9223
9224INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9225{
9226 // TODO Implement me!
9227 return RETURN_OK;
9228}
9229
9230INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9231{
developera3c68b92022-09-13 15:27:29 +08009232 char file_name[128] = {0};
9233 char buf[128] = {0};
9234 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009235 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009236
9237 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9238
developer804c64f2022-10-19 13:54:40 +08009239 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009240 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009241 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009242 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9243 f = fopen(file_name, "w");
9244 if (f == NULL)
9245 return RETURN_ERR;
9246 // For mode == 0 is to disable filter, just don't write to the file.
9247 if (mode)
9248 fprintf(f, "%s", essid);
9249
9250 fclose(f);
9251 }
9252 } else { // special case, need to set AP's SSID as filter for each radio.
9253 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9254 f = fopen(file_name, "w");
9255 if (f == NULL)
9256 return RETURN_ERR;
9257
9258 // For mode == 0 is to disable filter, just don't write to the file.
9259 if (mode)
9260 fprintf(f, "%s", essid);
9261
9262 fclose(f);
9263 }
9264
9265 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009266 return RETURN_OK;
9267}
9268
9269INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9270{
9271 // TODO Implement me!
9272 //Apply wifi_pushRadioChannel() instantly
9273 return RETURN_ERR;
9274}
9275
9276INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9277{
9278 // TODO Implement me!
9279 return RETURN_OK;
9280}
9281
9282#ifdef HAL_NETLINK_IMPL
9283static int tidStats_callback(struct nl_msg *msg, void *arg) {
9284 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9285 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9286 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9287 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9288 int rem , tid_index = 0;
9289
9290 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9291 wifi_associated_dev_tid_entry_t *stats_entry;
9292
9293 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9294 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9295 };
9296 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9297 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9298 };
9299
9300 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9301 genlmsg_attrlen(gnlh, 0), NULL);
9302
9303
9304 if (!tb[NL80211_ATTR_STA_INFO]) {
9305 fprintf(stderr, "station stats missing!\n");
9306 return NL_SKIP;
9307 }
9308
9309 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9310 tb[NL80211_ATTR_STA_INFO],
9311 stats_policy)) {
9312 fprintf(stderr, "failed to parse nested attributes!\n");
9313 return NL_SKIP;
9314 }
9315
9316 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9317 {
9318 stats_entry = &out->tid_array[tid_index];
9319
9320 stats_entry->tid = tid_index;
9321 stats_entry->ac = _tid_ac_index_get[tid_index];
9322
9323 if(sinfo[NL80211_STA_INFO_TID_STATS])
9324 {
9325 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9326 printf("failed to parse nested stats attributes!");
9327 return NL_SKIP;
9328 }
9329 }
9330 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9331 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9332
9333 if(tid_index < (PS_MAX_TID - 1))
9334 tid_index++;
9335 }
9336 //ToDo: sum_time_ms, ewma_time_ms
9337 return NL_SKIP;
9338}
9339#endif
9340
9341INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9342{
9343#ifdef HAL_NETLINK_IMPL
9344 Netlink nl;
9345 char if_name[10];
9346
9347 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9348
9349 nl.id = initSock80211(&nl);
9350
9351 if (nl.id < 0) {
9352 fprintf(stderr, "Error initializing netlink \n");
9353 return -1;
9354 }
9355
9356 struct nl_msg* msg = nlmsg_alloc();
9357
9358 if (!msg) {
9359 fprintf(stderr, "Failed to allocate netlink message.\n");
9360 nlfree(&nl);
9361 return -2;
9362 }
9363
9364 genlmsg_put(msg,
9365 NL_AUTO_PORT,
9366 NL_AUTO_SEQ,
9367 nl.id,
9368 0,
9369 0,
9370 NL80211_CMD_GET_STATION,
9371 0);
9372
9373 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9374 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9375 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9376 nl_send_auto(nl.socket, msg);
9377 nl_recvmsgs(nl.socket, nl.cb);
9378 nlmsg_free(msg);
9379 nlfree(&nl);
9380 return RETURN_OK;
9381#else
9382//iw implementation
9383#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9384#define TOTAL_MAX_LINES 50
9385
9386 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9387 char if_name[10];
9388 FILE *fp=NULL;
9389 char pipeCmd[1024]= {'\0'};
9390 int lines,tid_index=0;
9391 char mac_addr[20] = {'\0'};
9392
9393 wifi_associated_dev_tid_entry_t *stats_entry;
9394
9395 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9396 strcpy(mac_addr,clientMacAddress);
9397
9398 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9399 fp= popen(pipeCmd,"r");
9400 if(fp == NULL)
9401 {
9402 perror("popen for station dump failed\n");
9403 return RETURN_ERR;
9404 }
9405 pclose(fp);
9406
9407 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9408 fp=popen(pipeCmd,"r");
9409 if(fp == NULL)
9410 {
9411 perror("popen for grep station failed\n");
9412 return RETURN_ERR;
9413 }
9414 else if(fgets(buf,sizeof(buf),fp) != NULL)
9415 lines=atoi(buf);
9416 else
9417 {
9418 pclose(fp);
9419 fprintf(stderr,"No devices are connected \n");
9420 return RETURN_ERR;
9421 }
9422 pclose(fp);
9423
9424 if(lines == 1)
9425 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9426
9427 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9428 {
9429 stats_entry = &tid_stats->tid_array[tid_index];
9430 stats_entry->tid = tid_index;
9431
9432 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);
9433
9434 fp=popen(pipeCmd,"r");
9435 if(fp ==NULL)
9436 {
9437 perror("Failed to read from tid file \n");
9438 return RETURN_ERR;
9439 }
9440 else if(fgets(buf,sizeof(buf),fp) != NULL)
9441 stats_entry->num_msdus = atol(buf);
9442
9443 pclose(fp);
9444 stats_entry->ac = _tid_ac_index_get[tid_index];
9445// TODO:
9446// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9447// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9448 }
9449 return RETURN_OK;
9450#endif
9451}
9452
9453
9454INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9455{
developer615510b2022-09-27 10:14:35 +08009456 char cmd[128]={0};
9457 char buf[128]={0};
9458 int freq = 0;
9459
9460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9461
9462 // full mode is used to scan all channels.
9463 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9464 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9465 ieee80211_channel_to_frequency(chan_list[0], &freq);
9466
9467 if (freq)
9468 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9469 else
9470 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9471
9472 _syscmd(cmd, buf, sizeof(buf));
9473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9474
developer06a01d92022-09-07 16:32:39 +08009475 return RETURN_OK;
9476}
9477
9478
9479INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9480{
9481 // TODO Implement me!
9482 return RETURN_ERR;
9483}
9484
9485INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9486{
9487 // TODO Implement me!
9488 return RETURN_ERR;
9489}
9490
9491INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9492{
9493 // TODO Implement me!
9494 return RETURN_ERR;
9495}
9496
9497INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9498{
9499 // TODO Implement me!
9500 return RETURN_ERR;
9501}
9502
9503INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9504{
9505 // TODO Implement me!
9506 return RETURN_ERR;
9507}
9508
9509INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9510{
9511 // TODO Implement me!
9512 return RETURN_ERR;
9513}
9514
9515INT wifi_steering_eventUnregister(void)
9516{
9517 // TODO Implement me!
9518 return RETURN_ERR;
9519}
9520
9521INT wifi_delApAclDevices(INT apIndex)
9522{
9523#if 0
9524 char cmd[MAX_BUF_SIZE] = {0};
9525 char buf[MAX_BUF_SIZE] = {0};
9526
9527 /* Not reset proof solution */
9528 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9529 if(_syscmd(cmd,buf,sizeof(buf)))
9530 return RETURN_ERR;
9531#endif
developere6aafda2022-09-13 14:59:28 +08009532 char cmd[MAX_CMD_SIZE]={0};
9533 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009534
developere6aafda2022-09-13 14:59:28 +08009535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9536 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9537 if(_syscmd(cmd, buf, sizeof(buf)))
9538 return RETURN_ERR;
9539 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009540
9541 return RETURN_OK;
9542}
9543
9544#ifdef HAL_NETLINK_IMPL
9545static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9546 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9547 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9548 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9549 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9550 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9551 char mac_addr[20],dev[20];
9552
9553 nla_parse(tb,
9554 NL80211_ATTR_MAX,
9555 genlmsg_attrdata(gnlh, 0),
9556 genlmsg_attrlen(gnlh, 0),
9557 NULL);
9558
9559 if(!tb[NL80211_ATTR_STA_INFO]) {
9560 fprintf(stderr, "sta stats missing!\n");
9561 return NL_SKIP;
9562 }
9563
9564 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9565 fprintf(stderr, "failed to parse nested attributes!\n");
9566 return NL_SKIP;
9567 }
9568 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9569
9570 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9571
9572 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9573 fprintf(stderr, "failed to parse nested rate attributes!");
9574 return NL_SKIP;
9575 }
9576
9577 if(sinfo[NL80211_STA_INFO_TID_STATS])
9578 {
9579 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9580 printf("failed to parse nested stats attributes!");
9581 return NL_SKIP;
9582 }
9583 }
9584
9585 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9586 {
9587 printf("Type is VHT\n");
9588 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9589 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9590
9591 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9592 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9593 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9594 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9595 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9596 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9597 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9598 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9599 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9600 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9601 }
9602 else
9603 {
9604 printf(" OFDM or CCK \n");
9605 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9606 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9607 }
9608
9609 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9610 if(rinfo[NL80211_RATE_INFO_MCS])
9611 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9612 }
9613 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9614 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9615 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9616 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9617
9618 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9619 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9620
9621 if (sinfo[NL80211_STA_INFO_SIGNAL])
9622 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9623 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9624 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9625 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9626 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9627 //rssi_array need to be filled
9628 return NL_SKIP;
9629}
9630#endif
9631
9632INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9633{
9634#ifdef HAL_NETLINK_IMPL
9635 Netlink nl;
9636 char if_name[10];
9637
9638 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9639
9640 if (*output_array_size <= 0)
9641 return RETURN_OK;
9642
9643 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9644 nl.id = initSock80211(&nl);
9645
9646 if (nl.id < 0) {
9647 fprintf(stderr, "Error initializing netlink \n");
9648 return 0;
9649 }
9650
9651 struct nl_msg* msg = nlmsg_alloc();
9652
9653 if (!msg) {
9654 fprintf(stderr, "Failed to allocate netlink message.\n");
9655 nlfree(&nl);
9656 return 0;
9657 }
9658
9659 genlmsg_put(msg,
9660 NL_AUTO_PORT,
9661 NL_AUTO_SEQ,
9662 nl.id,
9663 0,
9664 0,
9665 NL80211_CMD_GET_STATION,
9666 0);
9667
9668 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9669 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9670 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9671 nl_send_auto(nl.socket, msg);
9672 nl_recvmsgs(nl.socket, nl.cb);
9673 nlmsg_free(msg);
9674 nlfree(&nl);
9675 return RETURN_OK;
9676#else
9677 //TODO Implement me
9678 return RETURN_OK;
9679#endif
9680}
9681
9682#ifdef HAL_NETLINK_IMPL
9683static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9684 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9685 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9686 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9687 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9688 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9689 char mac_addr[20],dev[20];
9690
9691 nla_parse(tb,
9692 NL80211_ATTR_MAX,
9693 genlmsg_attrdata(gnlh, 0),
9694 genlmsg_attrlen(gnlh, 0),
9695 NULL);
9696
9697 if(!tb[NL80211_ATTR_STA_INFO]) {
9698 fprintf(stderr, "sta stats missing!\n");
9699 return NL_SKIP;
9700 }
9701
9702 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9703 fprintf(stderr, "failed to parse nested attributes!\n");
9704 return NL_SKIP;
9705 }
9706
9707 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9708
9709 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9710
9711 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9712 fprintf(stderr, "failed to parse nested rate attributes!");
9713 return NL_SKIP;
9714 }
9715
9716 if(sinfo[NL80211_STA_INFO_TID_STATS])
9717 {
9718 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9719 printf("failed to parse nested stats attributes!");
9720 return NL_SKIP;
9721 }
9722 }
9723 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9724 {
9725 printf("Type is VHT\n");
9726 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9727 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9728
9729 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9730 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9731 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9732 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9733 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9734 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9735 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9736 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9737 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9738 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9739 }
9740 else
9741 {
9742 printf(" OFDM or CCK \n");
9743 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9744 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9745 }
9746
9747 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9748 if(rinfo[NL80211_RATE_INFO_MCS])
9749 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9750 }
9751
9752 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9753 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9754 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9755 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9756
9757 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9758 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9759 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9760
9761 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9762 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9763
9764 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9765 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9766
9767 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9768 ((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]);
9769
9770 return NL_SKIP;
9771}
9772#endif
9773
9774INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9775{
9776#ifdef HAL_NETLINK_IMPL
9777 Netlink nl;
9778 char if_name[10];
9779
9780 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9781
9782 if (*output_array_size <= 0)
9783 return RETURN_OK;
9784
9785 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9786
9787 nl.id = initSock80211(&nl);
9788
9789 if(nl.id < 0) {
9790 fprintf(stderr, "Error initializing netlink \n");
9791 return 0;
9792 }
9793
9794 struct nl_msg* msg = nlmsg_alloc();
9795
9796 if(!msg) {
9797 fprintf(stderr, "Failed to allocate netlink message.\n");
9798 nlfree(&nl);
9799 return 0;
9800 }
9801
9802 genlmsg_put(msg,
9803 NL_AUTO_PORT,
9804 NL_AUTO_SEQ,
9805 nl.id,
9806 0,
9807 0,
9808 NL80211_CMD_GET_STATION,
9809 0);
9810
9811 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9812 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9813 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9814 nl_send_auto(nl.socket, msg);
9815 nl_recvmsgs(nl.socket, nl.cb);
9816 nlmsg_free(msg);
9817 nlfree(&nl);
9818 return RETURN_OK;
9819#else
9820 //TODO Implement me
9821 return RETURN_OK;
9822#endif
9823}
9824
9825INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9826{
9827 // TODO Implement me!
9828 char buf[MAX_BUF_SIZE] = {0};
9829 char config_file[MAX_BUF_SIZE] = {0};
9830
9831 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9832 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9833 *activate = (strncmp("1",buf,1) == 0);
9834
9835 return RETURN_OK;
9836}
9837
9838INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9839{
9840 char config_file[MAX_BUF_SIZE] = {0};
9841 struct params list;
9842
9843 list.name = "rrm_neighbor_report";
9844 list.value = activate?"1":"0";
9845 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9846 wifi_hostapdWrite(config_file, &list, 1);
9847
9848 return RETURN_OK;
9849}
9850
9851INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9852{
9853 char buf[32] = {0};
9854 char config_file[MAX_BUF_SIZE] = {0};
9855
9856 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9857 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9858 *activate = (strncmp("1",buf,1) == 0);
9859
9860 return RETURN_OK;
9861}
9862#undef HAL_NETLINK_IMPL
9863#ifdef HAL_NETLINK_IMPL
9864static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9865 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9866 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9867 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9868 char dev[20];
9869 int freq =0 ;
9870 static int i=0;
9871
9872 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9873
9874 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9875 };
9876
9877 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9878
9879 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9880
9881 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9882 fprintf(stderr, "survey data missing!\n");
9883 return NL_SKIP;
9884 }
9885
9886 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9887 {
9888 fprintf(stderr, "failed to parse nested attributes!\n");
9889 return NL_SKIP;
9890 }
9891
9892
9893 if(out[0].array_size == 1 )
9894 {
9895 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9896 {
9897 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9898 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9899 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9900
9901 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9902 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9903 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9904 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9905 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9906 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9907 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9908 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9909 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9910 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9911 if (sinfo[NL80211_SURVEY_INFO_TIME])
9912 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9913 return NL_STOP;
9914 }
9915 }
9916 else
9917 {
9918 if ( i <= out[0].array_size )
9919 {
9920 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9921 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9922 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9923
9924 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9925 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9926 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9927 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9928 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9929 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9930 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9931 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9932 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9933 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9934 if (sinfo[NL80211_SURVEY_INFO_TIME])
9935 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9936 }
9937 }
9938
9939 i++;
9940 return NL_SKIP;
9941}
9942#endif
9943
9944static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9945{
9946 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9947 FILE *fp;
9948
9949 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9950 {
9951 printf("Creating Frequency-Channel Map\n");
9952 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9953 }
9954 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9955 if((fp = popen(command, "r")))
9956 {
9957 fgets(output, sizeof(output), fp);
9958 *freqMHz = atoi(output);
9959 fclose(fp);
9960 }
9961
9962 return 0;
9963}
9964
9965static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9966{
9967 int freqMHz = -1;
9968 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +08009969 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009970
9971 ieee80211_channel_to_frequency(channel, &freqMHz);
9972 if (freqMHz == -1) {
9973 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9974 return -1;
9975 }
9976
developer033b37b2022-10-18 11:27:46 +08009977 phyId = radio_index_to_phy(radioIndex);
9978 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, phyId, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +08009979 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9980 radioIndex, freqMHz);
9981 return -1;
9982 }
9983
9984 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9985 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9986 return -1;
9987 }
9988
9989 return 0;
9990}
9991
9992static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9993{
9994 const char *ptr = buf;
9995 char *key = NULL;
9996 char *val = NULL;
9997 char line[256] = { '\0' };
9998
9999 while (ptr = get_line_from_str_buf(ptr, line)) {
10000 if (strstr(line, "Frequency")) continue;
10001
10002 key = strtok(line, ":");
10003 val = strtok(NULL, " ");
10004 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10005
10006 if (!strcmp(key, "noise")) {
10007 sscanf(val, "%d", &stats->ch_noise);
10008 if (stats->ch_noise == 0) {
10009 // Workaround for missing noise information.
10010 // Assume -95 for 2.4G and -103 for 5G
10011 if (radioIndex == 0) stats->ch_noise = -95;
10012 if (radioIndex == 1) stats->ch_noise = -103;
10013 }
10014 }
10015 else if (!strcmp(key, "channel active time")) {
10016 sscanf(val, "%llu", &stats->ch_utilization_total);
10017 }
10018 else if (!strcmp(key, "channel busy time")) {
10019 sscanf(val, "%llu", &stats->ch_utilization_busy);
10020 }
10021 else if (!strcmp(key, "channel receive time")) {
10022 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10023 }
10024 else if (!strcmp(key, "channel transmit time")) {
10025 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10026 }
10027 };
10028
10029 return 0;
10030}
10031
10032INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10033{
10034 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10035#ifdef HAL_NETLINK_IMPL
10036 Netlink nl;
10037 wifi_channelStats_t_loc local[array_size];
10038 char if_name[10];
10039
10040 local[0].array_size = array_size;
10041
10042 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
10043
10044 nl.id = initSock80211(&nl);
10045
10046 if (nl.id < 0) {
10047 fprintf(stderr, "Error initializing netlink \n");
10048 return -1;
10049 }
10050
10051 struct nl_msg* msg = nlmsg_alloc();
10052
10053 if (!msg) {
10054 fprintf(stderr, "Failed to allocate netlink message.\n");
10055 nlfree(&nl);
10056 return -2;
10057 }
10058
10059 genlmsg_put(msg,
10060 NL_AUTO_PORT,
10061 NL_AUTO_SEQ,
10062 nl.id,
10063 0,
10064 NLM_F_DUMP,
10065 NL80211_CMD_GET_SURVEY,
10066 0);
10067
10068 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10069 nl_send_auto(nl.socket, msg);
10070 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10071 nl_recvmsgs(nl.socket, nl.cb);
10072 nlmsg_free(msg);
10073 nlfree(&nl);
10074 //Copying the Values
10075 for(int i=0;i<array_size;i++)
10076 {
10077 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10078 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10079 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10080 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10081 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10082 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10083 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10084 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10085 }
10086#else
10087 ULONG channel = 0;
10088 int i;
10089 int number_of_channels = array_size;
10090 char buf[512];
10091 INT ret;
10092 wifi_channelStats_t tmp_stats;
10093
10094 if (number_of_channels == 0) {
10095 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10096 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10097 return RETURN_ERR;
10098 }
10099 number_of_channels = 1;
10100 input_output_channelStats_array[0].ch_number = channel;
10101 }
10102
10103 for (i = 0; i < number_of_channels; i++) {
10104
10105 input_output_channelStats_array[i].ch_noise = 0;
10106 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10107 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10108 input_output_channelStats_array[i].ch_utilization_busy = 0;
10109 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10110 input_output_channelStats_array[i].ch_utilization_total = 0;
10111
10112 memset(buf, 0, sizeof(buf));
10113 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10114 return RETURN_ERR;
10115 }
10116 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10117 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10118 return RETURN_ERR;
10119 }
10120
10121 // XXX: fake missing 'self' counter which is not available in iw survey output
10122 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10123 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10124
10125 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10126 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10127 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10128 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10129 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10130
10131 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",
10132 __func__,
10133 input_output_channelStats_array[i].ch_number,
10134 input_output_channelStats_array[i].ch_noise,
10135 input_output_channelStats_array[i].ch_utilization_total,
10136 input_output_channelStats_array[i].ch_utilization_busy,
10137 input_output_channelStats_array[i].ch_utilization_busy_rx,
10138 input_output_channelStats_array[i].ch_utilization_busy_tx,
10139 input_output_channelStats_array[i].ch_utilization_busy_self,
10140 input_output_channelStats_array[i].ch_utilization_busy_ext);
10141 }
10142#endif
10143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10144 return RETURN_OK;
10145}
10146#define HAL_NETLINK_IMPL
10147
10148/* Hostapd events */
10149
10150#ifndef container_of
10151#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10152#define container_of(ptr, type, member) \
10153 ((type *)((char *)ptr - offset_of(type, member)))
10154#endif /* container_of */
10155
10156struct ctrl {
10157 char sockpath[128];
10158 char sockdir[128];
10159 char bss[IFNAMSIZ];
10160 char reply[4096];
10161 int ssid_index;
10162 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10163 void (*overrun)(struct ctrl *ctrl);
10164 struct wpa_ctrl *wpa;
10165 unsigned int ovfl;
10166 size_t reply_len;
10167 int initialized;
10168 ev_timer retry;
10169 ev_timer watchdog;
10170 ev_stat stat;
10171 ev_io io;
10172};
10173static wifi_newApAssociatedDevice_callback clients_connect_cb;
10174static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10175static struct ctrl wpa_ctrl[MAX_APS];
10176static int initialized;
10177
10178static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10179{
10180 char cbuf[256] = {};
10181 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10182 struct cmsghdr *cmsg;
10183 unsigned int ovfl = ctrl->ovfl;
10184 unsigned int drop;
10185
10186 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10187 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10188 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10189 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10190
10191 drop = ovfl - ctrl->ovfl;
10192 ctrl->ovfl = ovfl;
10193
10194 return drop;
10195}
10196
10197static void ctrl_close(struct ctrl *ctrl)
10198{
10199 if (ctrl->io.cb)
10200 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10201 if (ctrl->retry.cb)
10202 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10203 if (!ctrl->wpa)
10204 return;
10205
10206 wpa_ctrl_detach(ctrl->wpa);
10207 wpa_ctrl_close(ctrl->wpa);
10208 ctrl->wpa = NULL;
10209 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10210}
10211
10212static void ctrl_process(struct ctrl *ctrl)
10213{
10214 const char *str;
10215 int drops;
10216 int level;
10217 int err;
10218
10219 /* Example events:
10220 *
10221 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10222 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10223 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10224 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10225 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10226 */
10227 if (!(str = index(ctrl->reply, '>')))
10228 return;
10229 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10230 return;
10231
10232 str++;
10233
10234 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10235 if (!(str = index(ctrl->reply, ' ')))
10236 return;
10237 wifi_associated_dev_t sta;
10238 memset(&sta, 0, sizeof(sta));
10239
10240 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10241 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10242 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10243
10244 sta.cli_Active=true;
10245
10246 (clients_connect_cb)(ctrl->ssid_index, &sta);
10247 goto handled;
10248 }
10249
10250 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10251 if (!(str = index(ctrl->reply, ' ')))
10252 return;
10253
10254 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10255 goto handled;
10256 }
10257
10258 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10259 printf("CTRL_WPA: handle TERMINATING event\n");
10260 goto retry;
10261 }
10262
10263 if (strncmp("AP-DISABLED", str, 11) == 0) {
10264 printf("CTRL_WPA: handle AP-DISABLED\n");
10265 goto retry;
10266 }
10267
10268 printf("Event not supported!!\n");
10269
10270handled:
10271
10272 if ((drops = ctrl_get_drops(ctrl))) {
10273 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10274 if (ctrl->overrun)
10275 ctrl->overrun(ctrl);
10276 }
10277
10278 return;
10279
10280retry:
10281 printf("WPA_CTRL: closing\n");
10282 ctrl_close(ctrl);
10283 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10284 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10285}
10286
10287static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10288{
10289 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10290 int err;
10291
10292 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10293 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10294 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10295 ctrl->reply[ctrl->reply_len] = 0;
10296 if (err < 0) {
10297 if (errno == EAGAIN || errno == EWOULDBLOCK)
10298 return;
10299 ctrl_close(ctrl);
10300 ev_timer_again(EV_A_ &ctrl->retry);
10301 return;
10302 }
10303
10304 ctrl_process(ctrl);
10305}
10306
10307static int ctrl_open(struct ctrl *ctrl)
10308{
10309 int fd;
10310
10311 if (ctrl->wpa)
10312 return 0;
10313
10314 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10315 if (!ctrl->wpa)
10316 goto err;
10317
10318 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10319 goto err_close;
10320
10321 fd = wpa_ctrl_get_fd(ctrl->wpa);
10322 if (fd < 0)
10323 goto err_detach;
10324
10325 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10326 goto err_detach;
10327
10328 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10329 ev_io_start(EV_DEFAULT_ &ctrl->io);
10330
10331 return 0;
10332
10333err_detach:
10334 wpa_ctrl_detach(ctrl->wpa);
10335err_close:
10336 wpa_ctrl_close(ctrl->wpa);
10337err:
10338 ctrl->wpa = NULL;
10339 return -1;
10340}
10341
10342static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10343{
10344 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10345
10346 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10347 ctrl_open(ctrl);
10348}
10349
10350static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10351{
10352 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10353
10354 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10355 if (ctrl_open(ctrl) == 0) {
10356 printf("WPA_CTRL: retry successful\n");
10357 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10358 }
10359}
10360
10361int ctrl_enable(struct ctrl *ctrl)
10362{
10363 if (ctrl->wpa)
10364 return 0;
10365
10366 if (!ctrl->stat.cb) {
10367 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10368 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10369 }
10370
10371 if (!ctrl->retry.cb) {
10372 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10373 }
10374
10375 return ctrl_open(ctrl);
10376}
10377
10378static void
10379ctrl_msg_cb(char *buf, size_t len)
10380{
10381 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10382
10383 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10384 ctrl_process(ctrl);
10385}
10386
10387static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10388{
10389 int err;
10390
10391 if (!ctrl->wpa)
10392 return -1;
10393 if (*reply_len < 2)
10394 return -1;
10395
10396 (*reply_len)--;
10397 ctrl->reply_len = sizeof(ctrl->reply);
10398 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10399 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10400 if (err < 0)
10401 return err;
10402
10403 if (ctrl->reply_len > *reply_len)
10404 ctrl->reply_len = *reply_len;
10405
10406 *reply_len = ctrl->reply_len;
10407 memcpy(reply, ctrl->reply, *reply_len);
10408 reply[*reply_len - 1] = 0;
10409 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10410 return 0;
10411}
10412
10413static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10414{
10415 const char *pong = "PONG";
10416 const char *ping = "PING";
10417 char reply[1024];
10418 size_t len = sizeof(reply);
10419 int err;
10420 ULONG s, snum;
10421 INT ret;
10422 BOOL status;
10423
10424 printf("WPA_CTRL: watchdog cb\n");
10425
10426 ret = wifi_getSSIDNumberOfEntries(&snum);
10427 if (ret != RETURN_OK) {
10428 printf("%s: failed to get SSID count", __func__);
10429 return;
10430 }
10431
10432 if (snum > MAX_APS) {
10433 printf("more ssid than supported! %lu\n", snum);
10434 return;
10435 }
10436
10437 for (s = 0; s < snum; s++) {
10438 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10439 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10440 continue;
10441 }
10442 if (status == false) continue;
10443
10444 memset(reply, 0, sizeof(reply));
10445 len = sizeof(reply);
10446 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10447 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10448 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10449 continue;
10450
10451 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10452 ctrl_close(&wpa_ctrl[s]);
10453 printf("WPA_CTRL: ev_timer_again %d\n", s);
10454 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10455 }
10456}
10457
10458static int init_wpa()
10459{
10460 int ret = 0, i = 0;
10461 ULONG s, snum;
10462
10463 ret = wifi_getSSIDNumberOfEntries(&snum);
10464 if (ret != RETURN_OK) {
10465 printf("%s: failed to get SSID count", __func__);
10466 return RETURN_ERR;
10467 }
10468
10469 if (snum > MAX_APS) {
10470 printf("more ssid than supported! %lu\n", snum);
10471 return RETURN_ERR;
10472 }
10473
10474 for (s = 0; s < snum; s++) {
10475 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10476 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10477 wpa_ctrl[s].ssid_index = s;
10478 ctrl_enable(&wpa_ctrl[s]);
10479 }
10480
10481 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10482 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10483
10484 initialized = 1;
10485 printf("WPA_CTRL: initialized\n");
10486
10487 return RETURN_OK;
10488}
10489
10490void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10491{
10492 clients_connect_cb = callback_proc;
10493 if (!initialized)
10494 init_wpa();
10495}
10496
10497void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10498{
10499 clients_disconnect_cb = callback_proc;
10500 if (!initialized)
10501 init_wpa();
10502}
10503
10504INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10505{
10506 // TODO Implement me!
10507 return RETURN_ERR;
10508}
10509
10510INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10511{
10512 // TODO Implement me!
10513 return RETURN_ERR;
10514}
10515
10516INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10517{
10518 int i;
10519 char cmd[256];
10520 char channel_numbers_buf[256];
10521 char dfs_state_buf[256];
10522 char line[256];
10523 const char *ptr;
10524
10525 memset(cmd, 0, sizeof(cmd));
10526 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10527 memset(line, 0, sizeof(line));
10528 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10529 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10530
10531 if (radioIndex == 0) { // 2.4G - all allowed
10532 if (outputMapSize < 11) {
10533 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10534 return RETURN_ERR;
10535 }
10536
10537 for (i = 0; i < 11; i++) {
10538 outputMap[i].ch_number = i + 1;
10539 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10540 }
10541
10542 return RETURN_OK;
10543 }
10544
10545 if (radioIndex == 1) { // 5G
10546// Example output of iw list:
10547//
10548// Frequencies:
10549// * 5180 MHz [36] (17.0 dBm)
10550// * 5200 MHz [40] (17.0 dBm)
10551// * 5220 MHz [44] (17.0 dBm)
10552// * 5240 MHz [48] (17.0 dBm)
10553// * 5260 MHz [52] (23.0 dBm) (radar detection)
10554// DFS state: usable (for 78930 sec)
10555// DFS CAC time: 60000 ms
10556// * 5280 MHz [56] (23.0 dBm) (radar detection)
10557// DFS state: usable (for 78930 sec)
10558// DFS CAC time: 60000 ms
10559// * 5300 MHz [60] (23.0 dBm) (radar detection)
10560// DFS state: usable (for 78930 sec)
10561// DFS CAC time: 60000 ms
10562// * 5320 MHz [64] (23.0 dBm) (radar detection)
10563// DFS state: usable (for 78930 sec)
10564// DFS CAC time: 60000 ms
10565// * 5500 MHz [100] (disabled)
10566// * 5520 MHz [104] (disabled)
10567// * 5540 MHz [108] (disabled)
10568// * 5560 MHz [112] (disabled)
10569//
10570// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10571 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10572 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10573 return RETURN_ERR;
10574 }
10575
10576 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10577 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10578 return RETURN_ERR;
10579 }
10580
10581 ptr = channel_numbers_buf;
10582 i = 0;
10583 while (ptr = get_line_from_str_buf(ptr, line)) {
10584 if (i >= outputMapSize) {
10585 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10586 return RETURN_ERR;
10587 }
10588 sscanf(line, "%d", &outputMap[i].ch_number);
10589
10590 memset(cmd, 0, sizeof(cmd));
10591 // Below command should fetch string for DFS state (usable, available or unavailable)
10592 // Example line: "DFS state: usable (for 78930 sec)"
10593 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) {
10594 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10595 return RETURN_ERR;
10596 }
10597
10598 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10599 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10600 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10601 return RETURN_ERR;
10602 }
10603
10604 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10605
10606 if (!strcmp(dfs_state_buf, "usable")) {
10607 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10608 } else if (!strcmp(dfs_state_buf, "available")) {
10609 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10610 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10611 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10612 } else {
10613 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10614 }
10615 i++;
10616 }
10617
10618 return RETURN_OK;
10619 }
10620
10621 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10622 return RETURN_ERR;
10623}
10624
10625INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10626{
10627 // TODO Implement me!
10628 return RETURN_ERR;
10629}
10630
10631INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10632{
10633 return RETURN_OK;
10634}
10635
10636INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10637{
10638 // TODO Implement me!
10639 return RETURN_ERR;
10640}
10641
10642INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10643{
10644 // TODO API refrence Implementaion is present on RPI hal
10645 return RETURN_ERR;
10646}
10647
10648INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10649{
developera5005b62022-09-13 15:43:35 +080010650 char cmd[128]={'\0'};
10651 char buf[128]={'\0'};
10652 char *support;
10653 int maximum_tx = 0, current_tx = 0;
10654
10655 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10656 if(txpwr_pcntg == NULL)
10657 return RETURN_ERR;
10658
10659 // Get the maximum tx power of the device
10660 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10661 _syscmd(cmd, buf, sizeof(buf));
10662 maximum_tx = strtol(buf, NULL, 10);
10663
10664 // Get the current tx power
10665 memset(cmd, 0, sizeof(cmd));
10666 memset(buf, 0, sizeof(buf));
10667 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10668 _syscmd(cmd, buf, sizeof(buf));
10669 current_tx = strtol(buf, NULL, 10);
10670
10671 // Get the power supported list and find the current power percentage in supported list
10672 memset(buf, 0, sizeof(buf));
10673 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10674 support = strtok(buf, ",");
10675 while(true)
10676 {
10677 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
developer033b37b2022-10-18 11:27:46 +080010678 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010679 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010680 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010681 }
10682 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10683 if (tmp == current_tx) {
10684 *txpwr_pcntg = strtol(support, NULL, 10);
10685 break;
10686 }
10687 support = strtok(NULL, ",");
10688 }
10689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010690 return RETURN_OK;
10691}
10692
10693INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10694{
developer58599c22022-09-13 16:40:34 +080010695 // TODO precac feature.
10696 struct params params = {0};
10697 char config_file[128] = {0};
10698
10699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10700
10701 params.name = "enable_background_radar";
10702 params.value = enable?"1":"0";
10703 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10704 wifi_hostapdWrite(config_file, &params, 1);
10705 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10706
10707 /* TODO precac feature */
10708
10709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10710 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010711}
10712
10713INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10714{
developer58599c22022-09-13 16:40:34 +080010715 char config_file[128] = {0};
10716 char buf[64] = {0};
10717
10718 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10719 if (NULL == enable || NULL == precac)
10720 return RETURN_ERR;
10721
10722 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10723 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10724 if (strncmp(enable, "1", 1) == 0)
10725 *enable = true;
10726 else
10727 *enable = false;
10728
10729 /* TODO precac feature */
10730
10731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10732 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010733}
10734
10735INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10736{
developer58599c22022-09-13 16:40:34 +080010737 *supported = TRUE;
10738 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010739}
10740
developer3e6b1692022-09-30 18:04:05 +080010741INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10742{
10743 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10744 struct params params = {0};
10745 char config_file[64] = {0};
10746 char buf[64] = {0};
10747 unsigned int set_mu_type = 0;
10748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10749
10750 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10751 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10752
10753 if (strlen(buf) > 0)
10754 set_mu_type = strtol(buf, NULL, 10);
10755
10756 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10757 set_mu_type &= ~0x05; // unset bit 0, 2
10758 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10759 set_mu_type |= 0x01;
10760 set_mu_type &= ~0x04;
10761 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10762 set_mu_type &= ~0x01;
10763 set_mu_type |= 0x04;
10764 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10765 set_mu_type |= 0x05; // set bit 0, 2
10766 }
10767
10768 params.name = "hemu_onoff";
10769 sprintf(buf, "%u", set_mu_type);
10770 params.value = buf;
10771 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10772 wifi_hostapdWrite(config_file, &params, 1);
10773 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10774
10775 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10776 return RETURN_OK;
10777}
10778
10779INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10780{
10781 struct params params={0};
10782 char config_file[64] = {0};
10783 char buf[64] = {0};
10784 unsigned int get_mu_type = 0;
10785
10786 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10787
10788 if (mu_type == NULL)
10789 return RETURN_ERR;
10790
10791 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10792 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10793 get_mu_type = strtol(buf, NULL, 10);
10794
10795 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10796 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10797 else if (get_mu_type & 0x04)
10798 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10799 else if (get_mu_type & 0x01)
10800 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10801 else
10802 *mu_type = WIFI_DL_MU_TYPE_NONE;
10803
10804 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10805 return RETURN_OK;
10806}
10807
10808INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10809{
10810 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10811 struct params params={0};
10812 char config_file[64] = {0};
10813 char buf[64] = {0};
10814 unsigned int set_mu_type = 0;
10815 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10816
10817 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10818 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10819
10820 if (strlen(buf) > 0)
10821 set_mu_type = strtol(buf, NULL, 10);
10822
10823 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10824 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10825 set_mu_type &= ~0x0a;
10826 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10827 set_mu_type |= 0x02;
10828 set_mu_type &= ~0x08;
10829 }
10830
10831 params.name = "hemu_onoff";
10832 sprintf(buf, "%u", set_mu_type);
10833 params.value = buf;
10834 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10835 wifi_hostapdWrite(config_file, &params, 1);
10836 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10837
10838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10839 return RETURN_OK;
10840}
10841
10842INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10843{
10844 struct params params={0};
10845 char config_file[64] = {0};
10846 char buf[64] = {0};
10847 unsigned int get_mu_type = 0;
10848
10849 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10850
10851 if (mu_type == NULL)
10852 return RETURN_ERR;
10853
10854 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10855 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10856
10857 get_mu_type = strtol(buf, NULL, 10);
10858 if (get_mu_type & 0x02)
10859 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10860 else
10861 *mu_type = WIFI_DL_MU_TYPE_NONE;
10862
10863 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10864 return RETURN_OK;
10865}
10866
10867
developer454b9462022-09-13 15:29:16 +080010868INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10869{
10870 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010871 char buf[256] = {0};
10872 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010873 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010874 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010875 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010876 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010877
10878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10879
developer254882b2022-09-30 17:12:31 +080010880 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010881 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10882 return RETURN_ERR;
10883 }
developer454b9462022-09-13 15:29:16 +080010884
developer254882b2022-09-30 17:12:31 +080010885 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010886 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010887
developer254882b2022-09-30 17:12:31 +080010888 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10889 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080010890 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010891 _syscmd(cmd, buf, sizeof(buf));
10892 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10893 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10894 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010895 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010896 _syscmd(cmd, buf, sizeof(buf));
10897 }
10898 if (band == band_5) {
10899 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10900 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010901 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010902 _syscmd(cmd, buf, sizeof(buf));
10903 }
10904 }
10905 }
10906 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010907
developer254882b2022-09-30 17:12:31 +080010908 if (guard_interval == wifi_guard_interval_400)
10909 strcpy(GI, "0.4");
10910 else if (guard_interval == wifi_guard_interval_800)
10911 strcpy(GI, "0.8");
10912 else if (guard_interval == wifi_guard_interval_1600)
10913 strcpy(GI, "1.6");
10914 else if (guard_interval == wifi_guard_interval_3200)
10915 strcpy(GI, "3.2");
10916 else if (guard_interval == wifi_guard_interval_auto)
10917 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010918 // Record GI for get GI function
10919 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10920 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010921 if (f == NULL)
10922 return RETURN_ERR;
10923 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010924 fclose(f);
10925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10926 return RETURN_OK;
10927}
10928
10929INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10930{
10931 char buf[32] = {0};
10932 char cmd[64] = {0};
10933
10934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10935
10936 if (guard_interval == NULL)
10937 return RETURN_ERR;
10938
10939 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10940 _syscmd(cmd, buf, sizeof(buf));
10941
10942 if (strncmp(buf, "0.4", 3) == 0)
10943 *guard_interval = wifi_guard_interval_400;
10944 else if (strncmp(buf, "0.8", 3) == 0)
10945 *guard_interval = wifi_guard_interval_800;
10946 else if (strncmp(buf, "1.6", 3) == 0)
10947 *guard_interval = wifi_guard_interval_1600;
10948 else if (strncmp(buf, "3.2", 3) == 0)
10949 *guard_interval = wifi_guard_interval_3200;
10950 else
10951 *guard_interval = wifi_guard_interval_auto;
10952
10953 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10954 return RETURN_OK;
10955}
10956
developer3cc61d12022-09-13 16:36:05 +080010957INT wifi_setBSSColor(INT radio_index, UCHAR color)
10958{
10959 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10960 struct params params = {0};
10961 char config_file[128] = {0};
10962 char bss_color[4] ={0};
10963
10964 params.name = "he_bss_color";
10965 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10966 params.value = bss_color;
10967 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10968 wifi_hostapdWrite(config_file, &params, 1);
10969 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10970
10971 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10972 return RETURN_OK;
10973}
10974
10975INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10976{
10977 char config_file[128] = {0};
10978 char buf[64] = {0};
10979 char temp_output[128] = {'\0'};
10980
10981 wifi_dbg_printf("\nFunc=%s\n", __func__);
10982 if (NULL == color)
10983 return RETURN_ERR;
10984
10985 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10986 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10987
10988 if(strlen(buf) > 0) {
10989 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10990 } else {
10991 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10992 }
10993
10994 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10995 wifi_dbg_printf("\noutput_string=%s\n", color);
10996
10997 return RETURN_OK;
10998}
10999
developer06a01d92022-09-07 16:32:39 +080011000/* multi-psk support */
11001INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11002{
11003 char cmd[256];
11004
11005 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11006 AP_PREFIX,
11007 apIndex,
11008 mac[0],
11009 mac[1],
11010 mac[2],
11011 mac[3],
11012 mac[4],
11013 mac[5]
11014 );
11015 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11016 _syscmd(cmd, key->wifi_keyId, 64);
11017
11018
11019 return RETURN_OK;
11020}
11021
11022INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11023{
11024 FILE *fd = NULL;
11025 char fname[100];
11026 char cmd[128] = {0};
11027 char out[64] = {0};
11028 wifi_key_multi_psk_t * key = NULL;
11029 if(keysNumber < 0)
11030 return RETURN_ERR;
11031
11032 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11033 fd = fopen(fname, "w");
11034 if (!fd) {
11035 return RETURN_ERR;
11036 }
11037 key= (wifi_key_multi_psk_t *) keys;
11038 for(int i=0; i<keysNumber; ++i, key++) {
11039 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11040 }
11041 fclose(fd);
11042
11043 //reload file
11044 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
11045 _syscmd(cmd, out, 64);
11046 return RETURN_OK;
11047}
11048
11049INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11050{
11051 FILE *fd = NULL;
11052 char fname[100];
11053 char * line = NULL;
11054 char * pos = NULL;
11055 size_t len = 0;
11056 ssize_t read = 0;
11057 INT ret = RETURN_OK;
11058 wifi_key_multi_psk_t *keys_it = NULL;
11059
11060 if (keysNumber < 1) {
11061 return RETURN_ERR;
11062 }
11063
11064 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11065 fd = fopen(fname, "r");
11066 if (!fd) {
11067 return RETURN_ERR;
11068 }
11069
11070 if (keys == NULL) {
11071 ret = RETURN_ERR;
11072 goto close;
11073 }
11074
11075 keys_it = keys;
11076 while ((read = getline(&line, &len, fd)) != -1) {
11077 //Strip trailing new line if present
11078 if (read > 0 && line[read-1] == '\n') {
11079 line[read-1] = '\0';
11080 }
11081
11082 if(strcmp(line,"keyid=")) {
11083 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11084 if (!(pos = index(line, ' '))) {
11085 ret = RETURN_ERR;
11086 goto close;
11087 }
11088 pos++;
11089 //Here should be 00:00:00:00:00:00
11090 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11091 printf("Not supported MAC: %s\n", pos);
11092 }
11093 if (!(pos = index(pos, ' '))) {
11094 ret = RETURN_ERR;
11095 goto close;
11096 }
11097 pos++;
11098
11099 //The rest is PSK
11100 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11101 keys_it++;
11102
11103 if(--keysNumber <= 0)
11104 break;
11105 }
11106 }
11107
11108close:
11109 free(line);
11110 fclose(fd);
11111 return ret;
11112}
11113/* end of multi-psk support */
11114
11115INT wifi_setNeighborReports(UINT apIndex,
11116 UINT numNeighborReports,
11117 wifi_NeighborReport_t *neighborReports)
11118{
11119 char cmd[256] = { 0 };
11120 char hex_bssid[13] = { 0 };
11121 char bssid[18] = { 0 };
11122 char nr[256] = { 0 };
11123 char ssid[256];
11124 char hex_ssid[256];
11125 INT ret;
11126
11127 /*rmeove all neighbors*/
11128 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
11129 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);
11130 system(cmd);
11131
11132 for(unsigned int i = 0; i < numNeighborReports; i++)
11133 {
11134 memset(ssid, 0, sizeof(ssid));
11135 ret = wifi_getSSIDName(apIndex, ssid);
11136 if (ret != RETURN_OK)
11137 return RETURN_ERR;
11138
11139 memset(hex_ssid, 0, sizeof(hex_ssid));
11140 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11141 sprintf(hex_ssid + k,"%02x", ssid[j]);
11142
11143 snprintf(hex_bssid, sizeof(hex_bssid),
11144 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11145 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11146 snprintf(bssid, sizeof(bssid),
11147 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11148 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11149
11150 snprintf(nr, sizeof(nr),
11151 "%s" // bssid
11152 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11153 "%02hhx" // operclass
11154 "%02hhx" // channel
11155 "%02hhx", // phy_mode
11156 hex_bssid,
11157 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11158 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11159 neighborReports[i].opClass,
11160 neighborReports[i].channel,
11161 neighborReports[i].phyTable);
11162
11163 snprintf(cmd, sizeof(cmd),
11164 "hostapd_cli set_neighbor "
11165 "%s " // bssid
11166 "ssid=%s " // ssid
11167 "nr=%s " // nr
11168 "-i %s%d",
11169 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
11170
11171 if (WEXITSTATUS(system(cmd)) != 0)
11172 {
11173 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11174 }
11175 }
11176
11177 return RETURN_OK;
11178}
11179
11180INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11181{
11182 return RETURN_OK;
11183}
11184
11185#ifdef _WIFI_HAL_TEST_
11186int main(int argc,char **argv)
11187{
11188 int index;
11189 INT ret=0;
11190 char buf[1024]="";
11191
11192 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11193 if(argc<3)
11194 {
11195 if(argc==2)
11196 {
11197 if(!strcmp(argv[1], "init"))
11198 return wifi_init();
11199 if(!strcmp(argv[1], "reset"))
11200 return wifi_reset();
11201 if(!strcmp(argv[1], "wifi_getHalVersion"))
11202 {
11203 char buffer[64];
11204 if(wifi_getHalVersion(buffer)==RETURN_OK)
11205 printf("Version: %s\n", buffer);
11206 else
11207 printf("Error in wifi_getHalVersion\n");
11208 return RETURN_OK;
11209 }
11210 }
11211 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11212 exit(-1);
11213 }
11214
11215 index = atoi(argv[2]);
11216 if(strstr(argv[1], "wifi_getApName")!=NULL)
11217 {
11218 wifi_getApName(index,buf);
11219 printf("Ap name is %s \n",buf);
11220 return 0;
11221 }
11222 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11223 {
11224 BOOL b = FALSE;
11225 BOOL *output_bool = &b;
11226 wifi_getRadioAutoChannelEnable(index,output_bool);
11227 printf("Channel enabled = %d \n",b);
11228 return 0;
11229 }
11230 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11231 {
11232 wifi_getApWpaEncryptionMode(index,buf);
11233 printf("encryption enabled = %s\n",buf);
11234 return 0;
11235 }
11236 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11237 {
11238 BOOL b = FALSE;
11239 BOOL *output_bool = &b;
11240 wifi_getApSsidAdvertisementEnable(index,output_bool);
11241 printf("advertisment enabled = %d\n",b);
11242 return 0;
11243 }
11244 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11245 {
11246 if(argc <= 3 )
11247 {
11248 printf("Insufficient arguments \n");
11249 exit(-1);
11250 }
11251
11252 char sta[20] = {'\0'};
11253 ULLONG handle= 0;
11254 strcpy(sta,argv[3]);
11255 mac_address_t st;
11256 mac_addr_aton(st,sta);
11257
11258 wifi_associated_dev_tid_stats_t tid_stats;
11259 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11260 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11261 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);
11262 }
11263
11264 if(strstr(argv[1], "getApEnable")!=NULL) {
11265 BOOL enable;
11266 ret=wifi_getApEnable(index, &enable);
11267 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11268 }
11269 else if(strstr(argv[1], "setApEnable")!=NULL) {
11270 BOOL enable = atoi(argv[3]);
11271 ret=wifi_setApEnable(index, enable);
11272 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11273 }
11274 else if(strstr(argv[1], "getApStatus")!=NULL) {
11275 char status[64];
11276 ret=wifi_getApStatus(index, status);
11277 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11278 }
11279 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11280 {
11281 wifi_getSSIDNameStatus(index,buf);
11282 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11283 return 0;
11284 }
11285 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11286 wifi_ssidTrafficStats2_t stats={0};
11287 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11288 printf("%s %d: returns %d\n", argv[1], index, ret);
11289 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11290 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11291 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11292 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11293 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11294 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11295 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11296 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11297 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11298 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11299 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11300 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11301 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11302 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11303 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11304 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11305 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11306 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11307 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11308 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11309 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11310 }
11311 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11312 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11313 UINT array_size=0;
11314 UINT i=0;
11315 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11316 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11317 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11318 printf(" neighbor %d:\n", i);
11319 printf(" ap_SSID =%s\n", pt->ap_SSID);
11320 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11321 printf(" ap_Mode =%s\n", pt->ap_Mode);
11322 printf(" ap_Channel =%d\n", pt->ap_Channel);
11323 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11324 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11325 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11326 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11327 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11328 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11329 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11330 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11331 printf(" ap_Noise =%d\n", pt->ap_Noise);
11332 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11333 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11334 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11335 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11336 }
11337 if(neighbor_ap_array)
11338 free(neighbor_ap_array); //make sure to free the list
11339 }
11340 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11341 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11342 UINT array_size=0;
11343 UINT i=0;
11344 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11345 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11346 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11347 printf(" associated_dev %d:\n", i);
11348 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11349 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11350 printf(" cli_SNR =%d\n", pt->cli_SNR);
11351 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11352 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11353 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11354 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11355 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11356 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11357 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11358 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11359 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11360 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11361 }
11362 if(associated_dev_array)
11363 free(associated_dev_array); //make sure to free the list
11364 }
11365
11366 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11367 {
11368#define MAX_ARRAY_SIZE 64
11369 int i, array_size;
11370 char *p, *ch_str;
11371 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11372
11373 if(argc != 5)
11374 {
11375 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11376 exit(-1);
11377 }
11378 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11379
11380 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11381 {
11382 strtok_r(ch_str, ",", &p);
11383 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11384 }
11385 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11386 if(!array_size)
11387 array_size=1;//Need to print current channel statistics
11388 for(i=0; i<array_size; i++)
11389 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11390 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11391 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11392 input_output_channelStats_array[i].ch_number,\
11393 input_output_channelStats_array[i].ch_noise,\
11394 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11395 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11396 input_output_channelStats_array[i].ch_utilization_busy,\
11397 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11398 input_output_channelStats_array[i].ch_utilization_total);
11399 }
11400
11401 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11402 {
11403 if(argc <= 3 )
11404 {
11405 printf("Insufficient arguments \n");
11406 exit(-1);
11407 }
11408 char mac_addr[20] = {'\0'};
11409 wifi_device_t output_struct;
11410 int dev_index = atoi(argv[3]);
11411
11412 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11413 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11414 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);
11415 }
11416
11417 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11418 {
11419 if (argc <= 3)
11420 {
11421 printf("Insufficient arguments\n");
11422 exit(-1);
11423 }
11424 char args[256];
11425 wifi_NeighborReport_t *neighborReports;
11426
11427 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11428 if (!neighborReports)
11429 {
11430 printf("Failed to allocate memory");
11431 exit(-1);
11432 }
11433
11434 for (int i = 3; i < argc; ++i)
11435 {
11436 char *val;
11437 int j = 0;
11438 memset(args, 0, sizeof(args));
11439 strncpy(args, argv[i], sizeof(args));
11440 val = strtok(args, ";");
11441 while (val != NULL)
11442 {
11443 if (j == 0)
11444 {
11445 mac_addr_aton(neighborReports[i - 3].bssid, val);
11446 } else if (j == 1)
11447 {
11448 neighborReports[i - 3].info = strtol(val, NULL, 16);
11449 } else if (j == 2)
11450 {
11451 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11452 } else if (j == 3)
11453 {
11454 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11455 } else if (j == 4)
11456 {
11457 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11458 } else {
11459 printf("Insufficient arguments]n\n");
11460 exit(-1);
11461 }
11462 val = strtok(NULL, ";");
11463 j++;
11464 }
11465 }
11466
11467 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11468 if (ret != RETURN_OK)
11469 {
11470 printf("wifi_setNeighborReports ret = %d", ret);
11471 exit(-1);
11472 }
11473 }
11474 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11475 {
11476 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11477 printf("%s.\n", buf);
11478 else
11479 printf("Error returned\n");
11480 }
11481 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11482 {
11483 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11484 printf("%s.\n", buf);
11485 else
11486 printf("Error returned\n");
11487 }
11488 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11489 {
11490 if (argc <= 2)
11491 {
11492 printf("Insufficient arguments\n");
11493 exit(-1);
11494 }
11495 char buf[64]= {'\0'};
11496 wifi_getRadioOperatingChannelBandwidth(index,buf);
11497 printf("Current bandwidth is %s \n",buf);
11498 return 0;
11499 }
11500 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11501 {
11502 if (argc <= 5)
11503 {
11504 printf("Insufficient arguments\n");
11505 exit(-1);
11506 }
11507 UINT channel = atoi(argv[3]);
11508 UINT width = atoi(argv[4]);
11509 UINT beacon = atoi(argv[5]);
11510 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11511 printf("Result = %d", ret);
11512 }
11513
11514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11515 return 0;
11516}
11517
11518#endif
11519
11520#ifdef WIFI_HAL_VERSION_3
11521
developer1e5aa162022-09-13 16:06:24 +080011522INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11523{
11524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11525 if (bitMap & WIFI_BITRATE_1MBPS)
11526 strcat(BasicRate, "1,");
11527 if (bitMap & WIFI_BITRATE_2MBPS)
11528 strcat(BasicRate, "2,");
11529 if (bitMap & WIFI_BITRATE_5_5MBPS)
11530 strcat(BasicRate, "5.5,");
11531 if (bitMap & WIFI_BITRATE_6MBPS)
11532 strcat(BasicRate, "6,");
11533 if (bitMap & WIFI_BITRATE_9MBPS)
11534 strcat(BasicRate, "9,");
11535 if (bitMap & WIFI_BITRATE_11MBPS)
11536 strcat(BasicRate, "11,");
11537 if (bitMap & WIFI_BITRATE_12MBPS)
11538 strcat(BasicRate, "12,");
11539 if (bitMap & WIFI_BITRATE_18MBPS)
11540 strcat(BasicRate, "18,");
11541 if (bitMap & WIFI_BITRATE_24MBPS)
11542 strcat(BasicRate, "24,");
11543 if (bitMap & WIFI_BITRATE_36MBPS)
11544 strcat(BasicRate, "36,");
11545 if (bitMap & WIFI_BITRATE_48MBPS)
11546 strcat(BasicRate, "48,");
11547 if (bitMap & WIFI_BITRATE_54MBPS)
11548 strcat(BasicRate, "54,");
11549 if (strlen(BasicRate) != 0) // remove last comma
11550 BasicRate[strlen(BasicRate) - 1] = '\0';
11551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11552 return RETURN_OK;
11553}
11554
11555INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11556{
11557 UINT BitMap = 0;
11558 char *rate;
11559
11560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11561 rate = strtok(BasicRatesList, ",");
11562 while(rate != NULL)
11563 {
11564 if (strcmp(rate, "1") == 0)
11565 BitMap |= WIFI_BITRATE_1MBPS;
11566 else if (strcmp(rate, "2") == 0)
11567 BitMap |= WIFI_BITRATE_2MBPS;
11568 else if (strcmp(rate, "5.5") == 0)
11569 BitMap |= WIFI_BITRATE_5_5MBPS;
11570 else if (strcmp(rate, "6") == 0)
11571 BitMap |= WIFI_BITRATE_6MBPS;
11572 else if (strcmp(rate, "9") == 0)
11573 BitMap |= WIFI_BITRATE_9MBPS;
11574 else if (strcmp(rate, "11") == 0)
11575 BitMap |= WIFI_BITRATE_11MBPS;
11576 else if (strcmp(rate, "12") == 0)
11577 BitMap |= WIFI_BITRATE_12MBPS;
11578 else if (strcmp(rate, "18") == 0)
11579 BitMap |= WIFI_BITRATE_18MBPS;
11580 else if (strcmp(rate, "24") == 0)
11581 BitMap |= WIFI_BITRATE_24MBPS;
11582 else if (strcmp(rate, "36") == 0)
11583 BitMap |= WIFI_BITRATE_36MBPS;
11584 else if (strcmp(rate, "48") == 0)
11585 BitMap |= WIFI_BITRATE_48MBPS;
11586 else if (strcmp(rate, "54") == 0)
11587 BitMap |= WIFI_BITRATE_54MBPS;
11588 rate = strtok(NULL, ",");
11589 }
11590 *basicRateBitMap = BitMap;
11591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11592 return RETURN_OK;
11593}
11594
11595// 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 +080011596INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11597{
developer1e5aa162022-09-13 16:06:24 +080011598 char buf[128] = {0};
11599 char cmd[128] = {0};
11600 char config_file[64] = {0};
11601 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011602 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011603 wifi_radio_operationParam_t current_param;
11604
11605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11606
11607 multiple_set = TRUE;
11608 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11609 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11610 return RETURN_ERR;
11611 }
11612 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11613 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11614 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11615 return RETURN_ERR;
11616 }
11617 }
developer5884e982022-10-06 10:52:50 +080011618
11619 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11620 bandwidth = 20;
11621 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11622 bandwidth = 40;
11623 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11624 bandwidth = 80;
11625 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11626 bandwidth = 160;
11627 if (operationParam->autoChannelEnabled){
11628 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11629 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11630 return RETURN_ERR;
11631 }
11632 }else{
developer1e5aa162022-09-13 16:06:24 +080011633 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11634 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11635 return RETURN_ERR;
11636 }
11637 }
developer5884e982022-10-06 10:52:50 +080011638
developer1e5aa162022-09-13 16:06:24 +080011639 if (current_param.variant != operationParam->variant) {
11640 // Two different definition bit map, so need to check every bit.
11641 if (operationParam->variant & WIFI_80211_VARIANT_A)
11642 set_mode |= WIFI_MODE_A;
11643 if (operationParam->variant & WIFI_80211_VARIANT_B)
11644 set_mode |= WIFI_MODE_B;
11645 if (operationParam->variant & WIFI_80211_VARIANT_G)
11646 set_mode |= WIFI_MODE_G;
11647 if (operationParam->variant & WIFI_80211_VARIANT_N)
11648 set_mode |= WIFI_MODE_N;
11649 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11650 set_mode |= WIFI_MODE_AC;
11651 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11652 set_mode |= WIFI_MODE_AX;
11653 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11654 memset(buf, 0, sizeof(buf));
11655 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11656 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11657 return RETURN_ERR;
11658 }
11659 }
11660 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11661 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11662 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11663 return RETURN_ERR;
11664 }
11665 }
11666 if (current_param.beaconInterval != operationParam->beaconInterval) {
11667 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11668 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11669 return RETURN_ERR;
11670 }
11671 }
11672 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11673 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11674 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11675 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11676 return RETURN_ERR;
11677 }
11678 }
11679 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11680 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11681 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11682 return RETURN_ERR;
11683 }
11684 }
11685 if (current_param.guardInterval != operationParam->guardInterval) {
11686 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11687 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11688 return RETURN_ERR;
11689 }
11690 }
11691 if (current_param.transmitPower != operationParam->transmitPower) {
11692 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11693 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11694 return RETURN_ERR;
11695 }
11696 }
11697 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11698 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11699 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11700 return RETURN_ERR;
11701 }
11702 }
11703 if (current_param.obssCoex != operationParam->obssCoex) {
11704 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11705 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11706 return RETURN_ERR;
11707 }
11708 }
11709 if (current_param.stbcEnable != operationParam->stbcEnable) {
11710 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11711 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11712 return RETURN_ERR;
11713 }
11714 }
11715 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11716 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11717 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11718 return RETURN_ERR;
11719 }
11720 }
11721
11722 // if enable is true, then restart the radio
11723 wifi_setRadioEnable(index, FALSE);
11724 if (operationParam->enable == TRUE)
11725 wifi_setRadioEnable(index, TRUE);
11726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11727
developer06a01d92022-09-07 16:32:39 +080011728 return RETURN_OK;
11729}
11730
11731INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11732{
developer1e5aa162022-09-13 16:06:24 +080011733 char band[64] = {0};
11734 char buf[256] = {0};
11735 char config_file[64] = {0};
11736 char cmd[128] = {0};
11737 int ret = RETURN_ERR;
11738 int mode = 0;
11739 ULONG channel = 0;
11740 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011741
11742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11743 printf("Entering %s index = %d\n", __func__, (int)index);
11744
developer1e5aa162022-09-13 16:06:24 +080011745 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11746 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11747 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011748 {
developer1e5aa162022-09-13 16:06:24 +080011749 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011750 return RETURN_ERR;
11751 }
11752 operationParam->enable = enabled;
11753
11754 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011755 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011756 {
developer1e5aa162022-09-13 16:06:24 +080011757 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011758 return RETURN_ERR;
11759 }
11760
11761 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011762 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011763 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011764 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011765 else if (!strcmp(band, "6GHz"))
11766 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011767 else
11768 {
developer1e5aa162022-09-13 16:06:24 +080011769 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011770 band);
11771 }
11772
developer1e5aa162022-09-13 16:06:24 +080011773 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11774 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11775 operationParam->channel = 0;
11776 operationParam->autoChannelEnabled = TRUE;
11777 } else {
11778 operationParam->channel = strtol(buf, NULL, 10);
11779 operationParam->autoChannelEnabled = FALSE;
11780 }
11781
developer06a01d92022-09-07 16:32:39 +080011782 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011783 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11784 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11785 return RETURN_ERR;
11786 }
developer06a01d92022-09-07 16:32:39 +080011787 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11788 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11789 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011790 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11791 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011792 else
11793 {
developer1e5aa162022-09-13 16:06:24 +080011794 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11795 return false;
developer06a01d92022-09-07 16:32:39 +080011796 }
11797
developer1e5aa162022-09-13 16:06:24 +080011798 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11799 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11800 return RETURN_ERR;
11801 }
11802 // Two different definition bit map, so need to check every bit.
11803 if (mode & WIFI_MODE_A)
11804 operationParam->variant |= WIFI_80211_VARIANT_A;
11805 if (mode & WIFI_MODE_B)
11806 operationParam->variant |= WIFI_80211_VARIANT_B;
11807 if (mode & WIFI_MODE_G)
11808 operationParam->variant |= WIFI_80211_VARIANT_G;
11809 if (mode & WIFI_MODE_N)
11810 operationParam->variant |= WIFI_80211_VARIANT_N;
11811 if (mode & WIFI_MODE_AC)
11812 operationParam->variant |= WIFI_80211_VARIANT_AC;
11813 if (mode & WIFI_MODE_AX)
11814 operationParam->variant |= WIFI_80211_VARIANT_AX;
11815 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11816 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11817 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011818 }
developer1e5aa162022-09-13 16:06:24 +080011819 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11820 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11821 return RETURN_ERR;
11822 }
11823 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11824 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11825 return RETURN_ERR;
11826 }
developer06a01d92022-09-07 16:32:39 +080011827
developer1e5aa162022-09-13 16:06:24 +080011828 memset(buf, 0, sizeof(buf));
11829 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11830 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11831 return RETURN_ERR;
11832 }
11833 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11834
11835 memset(buf, 0, sizeof(buf));
11836 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11837 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11838 return RETURN_ERR;
11839 }
11840 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11841
11842 memset(buf, 0, sizeof(buf));
11843 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11844 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11845
11846 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11847 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11848 return RETURN_ERR;
11849 }
11850 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11851 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11852 return RETURN_ERR;
11853 }
11854
11855 memset(buf, 0, sizeof(buf));
11856 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11857 if (strcmp(buf, "-1") == 0) {
11858 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11859 operationParam->ctsProtection = FALSE;
11860 } else {
11861 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11862 operationParam->ctsProtection = TRUE;
11863 }
11864
11865 memset(buf, 0, sizeof(buf));
11866 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11867 if (strcmp(buf, "0") == 0)
11868 operationParam->obssCoex = FALSE;
11869 else
11870 operationParam->obssCoex = TRUE;
11871
11872 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11873 _syscmd(cmd, buf, sizeof(buf));
11874 if (strlen(buf) != 0)
11875 operationParam->stbcEnable = TRUE;
11876 else
11877 operationParam->stbcEnable = FALSE;
11878
11879 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11880 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11881 return RETURN_ERR;
11882 }
11883
11884 // Below value is hardcoded
11885
11886 operationParam->numSecondaryChannels = 0;
11887 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11888 operationParam->channelSecondary[i] = 0;
11889 }
11890 operationParam->csa_beacon_count = 15;
11891 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011892
11893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11894 return RETURN_OK;
11895}
11896
11897static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11898{
developerc086fb72022-10-04 10:18:22 +080011899 int max_radio_num = 0;
11900
11901 wifi_getMaxRadioNumber(&max_radio_num);
11902 if (radioIndex >= max_radio_num || radioIndex < 0) {
11903 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11904 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011905 }
11906
developerc086fb72022-10-04 10:18:22 +080011907 return (arrayIndex * max_radio_num) + radioIndex;
11908}
developer06a01d92022-09-07 16:32:39 +080011909
developerc086fb72022-10-04 10:18:22 +080011910wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11911 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11912 return WIFI_BITRATE_1MBPS;
11913 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11914 return WIFI_BITRATE_2MBPS;
11915 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11916 return WIFI_BITRATE_5_5MBPS;
11917 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11918 return WIFI_BITRATE_6MBPS;
11919 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11920 return WIFI_BITRATE_9MBPS;
11921 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11922 return WIFI_BITRATE_11MBPS;
11923 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11924 return WIFI_BITRATE_12MBPS;
11925 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11926 return WIFI_BITRATE_18MBPS;
11927 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11928 return WIFI_BITRATE_24MBPS;
11929 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11930 return WIFI_BITRATE_36MBPS;
11931 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11932 return WIFI_BITRATE_48MBPS;
11933 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11934 return WIFI_BITRATE_54MBPS;
11935 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011936}
11937
developer1d57d002022-10-12 18:03:15 +080011938INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
11939{
11940 if (beacon == WIFI_BITRATE_1MBPS)
11941 strcpy(beacon_str, "1Mbps");
11942 else if (beacon == WIFI_BITRATE_2MBPS)
11943 strcpy(beacon_str, "2Mbps");
11944 else if (beacon == WIFI_BITRATE_5_5MBPS)
11945 strcpy(beacon_str, "5.5Mbps");
11946 else if (beacon == WIFI_BITRATE_6MBPS)
11947 strcpy(beacon_str, "6Mbps");
11948 else if (beacon == WIFI_BITRATE_9MBPS)
11949 strcpy(beacon_str, "9Mbps");
11950 else if (beacon == WIFI_BITRATE_11MBPS)
11951 strcpy(beacon_str, "11Mbps");
11952 else if (beacon == WIFI_BITRATE_12MBPS)
11953 strcpy(beacon_str, "12Mbps");
11954 else if (beacon == WIFI_BITRATE_18MBPS)
11955 strcpy(beacon_str, "18Mbps");
11956 else if (beacon == WIFI_BITRATE_24MBPS)
11957 strcpy(beacon_str, "24Mbps");
11958 else if (beacon == WIFI_BITRATE_36MBPS)
11959 strcpy(beacon_str, "36Mbps");
11960 else if (beacon == WIFI_BITRATE_48MBPS)
11961 strcpy(beacon_str, "48Mbps");
11962 else if (beacon == WIFI_BITRATE_54MBPS)
11963 strcpy(beacon_str, "54Mbps");
11964 return RETURN_OK;
11965}
11966
developer06a01d92022-09-07 16:32:39 +080011967INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11968{
developerc086fb72022-10-04 10:18:22 +080011969 INT mode = 0;
11970 INT ret = -1;
11971 INT output = 0;
11972 int i = 0;
11973 int vap_index = 0;
11974 BOOL enabled = FALSE;
11975 char buf[256] = {0};
11976 wifi_vap_security_t security;
11977 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011978
11979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11980 printf("Entering %s index = %d\n", __func__, (int)index);
11981
developer06a01d92022-09-07 16:32:39 +080011982 for (i = 0; i < 5; i++)
11983 {
developerc086fb72022-10-04 10:18:22 +080011984 map->vap_array[i].radio_index = index;
11985
developer06a01d92022-09-07 16:32:39 +080011986 vap_index = array_index_to_vap_index(index, i);
11987 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011988 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011989
developerc086fb72022-10-04 10:18:22 +080011990 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011991
11992 map->vap_array[i].vap_index = vap_index;
11993
11994 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011995 ret = wifi_getApName(vap_index, buf);
11996 if (ret != RETURN_OK) {
11997 printf("%s: wifi_getApName return error\n", __func__);
11998 return RETURN_ERR;
11999 }
12000 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12001
12002 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012003 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012004 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012005 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012006 return RETURN_ERR;
12007 }
12008 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 +080012009
12010 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012011 if (ret != RETURN_OK) {
12012 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012013 return RETURN_ERR;
12014 }
12015 map->vap_array[i].u.bss_info.enabled = enabled;
12016
developerc086fb72022-10-04 10:18:22 +080012017 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12018 if (ret != RETURN_OK) {
12019 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12020 return RETURN_ERR;
12021 }
developer06a01d92022-09-07 16:32:39 +080012022 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012023
12024 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12025 if (ret != RETURN_OK) {
12026 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12027 return RETURN_ERR;
12028 }
12029 map->vap_array[i].u.bss_info.isolation = enabled;
12030
12031 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12032 if (ret != RETURN_OK) {
12033 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12034 return RETURN_ERR;
12035 }
12036 map->vap_array[i].u.bss_info.bssMaxSta = output;
12037
12038 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12039 if (ret != RETURN_OK) {
12040 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12041 return RETURN_ERR;
12042 }
12043 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012044
developerc086fb72022-10-04 10:18:22 +080012045 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12046 if (ret != RETURN_OK) {
12047 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12048 return RETURN_ERR;
12049 }
12050 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012051
developerc086fb72022-10-04 10:18:22 +080012052 ret = wifi_getApSecurity(vap_index, &security);
12053 if (ret != RETURN_OK) {
12054 printf("%s: wifi_getApSecurity return error\n", __func__);
12055 return RETURN_ERR;
12056 }
12057 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012058
developerc086fb72022-10-04 10:18:22 +080012059 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12060 if (ret != RETURN_OK) {
12061 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12062 return RETURN_ERR;
12063 }
12064 if (mode == 0)
12065 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12066 else
12067 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12068 if (mode == 1)
12069 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12070 else if (mode == 2)
12071 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012072
developerc086fb72022-10-04 10:18:22 +080012073 ret = wifi_getApWmmEnable(vap_index, &enabled);
12074 if (ret != RETURN_OK) {
12075 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12076 return RETURN_ERR;
12077 }
12078 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012079
developerc086fb72022-10-04 10:18:22 +080012080 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12081 if (ret != RETURN_OK) {
12082 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012083 return RETURN_ERR;
12084 }
developerc086fb72022-10-04 10:18:22 +080012085 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012086
12087 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012088 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012089 if (ret != RETURN_OK) {
12090 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12091 return RETURN_ERR;
12092 }
12093 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012094
developerc086fb72022-10-04 10:18:22 +080012095 memset(buf, 0, sizeof(buf));
12096 ret = wifi_getBaseBSSID(vap_index, buf);
12097 if (ret != RETURN_OK) {
12098 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12099 return RETURN_ERR;
12100 }
12101 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12102 &map->vap_array[i].u.bss_info.bssid[0],
12103 &map->vap_array[i].u.bss_info.bssid[1],
12104 &map->vap_array[i].u.bss_info.bssid[2],
12105 &map->vap_array[i].u.bss_info.bssid[3],
12106 &map->vap_array[i].u.bss_info.bssid[4],
12107 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012108 // 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]);
12109
12110 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12111 if (ret != RETURN_OK) {
12112 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12113 return RETURN_ERR;
12114 }
12115 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012116
developerc086fb72022-10-04 10:18:22 +080012117 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012118 }
12119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12120 return RETURN_OK;
12121}
12122
12123INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12124{
12125 unsigned int i;
12126 wifi_vap_info_t *vap_info = NULL;
12127 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012128 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012129 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012130 char buf[256] = {0};
12131 char cmd[128] = {0};
12132 char config_file[64] = {0};
12133 char bssid[32] = {0};
12134 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012135
12136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12137 printf("Entering %s index = %d\n", __func__, (int)index);
12138 for (i = 0; i < map->num_vaps; i++)
12139 {
developer1d57d002022-10-12 18:03:15 +080012140 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012141 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012142 if (vap_info->u.bss_info.enabled == FALSE)
12143 continue;
developer06a01d92022-09-07 16:32:39 +080012144
developer1d57d002022-10-12 18:03:15 +080012145 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12146
12147 // multi-ap need to copy current radio config
12148 if (vap_info->radio_index != vap_info->vap_index) {
12149 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12150 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012151 }
developer06a01d92022-09-07 16:32:39 +080012152
developer1d57d002022-10-12 18:03:15 +080012153 struct params params[3];
12154 snprintf(vap_info->vap_name, 64, "%s%d", AP_PREFIX, vap_info->vap_index);
12155 params[0].name = "interface";
12156 params[0].value = vap_info->vap_name;
12157 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12158 params[1].name = "bssid";
12159 params[1].value = bssid;
12160 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12161 params[2].name = "wpa_psk_file";
12162 params[2].value = psk_file;
12163
12164 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12165 wifi_hostapdWrite(config_file, params, 3);
12166
12167 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12168 _syscmd(cmd, buf, sizeof(buf));
12169
12170 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12171 if (ret != RETURN_OK) {
12172 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12173 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012174 }
developer1d57d002022-10-12 18:03:15 +080012175
12176 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12177 if (ret != RETURN_OK) {
12178 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12179 return RETURN_ERR;
12180 }
12181
12182 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12183 if (ret != RETURN_OK) {
12184 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12185 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012186 }
12187
developer1d57d002022-10-12 18:03:15 +080012188 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12189 if (ret != RETURN_OK) {
12190 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12191 return RETURN_ERR;
12192 }
developer06a01d92022-09-07 16:32:39 +080012193
developer1d57d002022-10-12 18:03:15 +080012194 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12195 if (ret != RETURN_OK) {
12196 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12197 return RETURN_ERR;
12198 }
developer06a01d92022-09-07 16:32:39 +080012199
developer1d57d002022-10-12 18:03:15 +080012200 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12201 if (ret != RETURN_OK) {
12202 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12203 return RETURN_ERR;
12204 }
12205
developer804c64f2022-10-19 13:54:40 +080012206 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012207 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012208 }else {
12209 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012210 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012211 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12212 _syscmd(cmd, buf, sizeof(buf));
12213 }else{
developer1d57d002022-10-12 18:03:15 +080012214 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012215 }
developer1d57d002022-10-12 18:03:15 +080012216 }
12217
12218 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12219 if (ret != RETURN_OK) {
12220 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12221 return RETURN_ERR;
12222 }
12223
12224 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12225 if (ret != RETURN_OK) {
12226 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12227 return RETURN_ERR;
12228 }
12229
12230 memset(buf, 0, sizeof(buf));
12231 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12232 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12233 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12234 if (ret != RETURN_OK) {
12235 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12236 return RETURN_ERR;
12237 }
12238
12239 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12240 if (ret != RETURN_OK) {
12241 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12242 return RETURN_ERR;
12243 }
12244
12245 wifi_setApEnable(vap_info->vap_index, TRUE);
12246 multiple_set = FALSE;
12247
12248 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12249 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12250 if (ret != RETURN_OK) {
12251 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12252 return RETURN_ERR;
12253 }
12254
12255 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12256 if (ret != RETURN_OK) {
12257 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12258 return RETURN_ERR;
12259 }
developer06a01d92022-09-07 16:32:39 +080012260
developer1d57d002022-10-12 18:03:15 +080012261 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012262 }
12263 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12264 return RETURN_OK;
12265}
12266
12267int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12268{
12269 char *token, *next;
12270 const char s[2] = ",";
12271 int count =0;
12272
12273 /* get the first token */
12274 token = strtok_r(pchannels, s, &next);
12275
12276 /* walk through other tokens */
12277 while( token != NULL && count < MAX_CHANNELS) {
12278 chlistptr->channels_list[count++] = atoi(token);
12279 token = strtok_r(NULL, s, &next);
12280 }
12281
12282 return count;
12283}
12284
12285static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12286{
12287 INT status;
12288 wifi_channels_list_t *chlistp;
12289 CHAR output_string[64];
12290 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012291 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012292 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012293
12294 if(rcap == NULL)
12295 {
12296 return RETURN_ERR;
12297 }
12298
12299 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012300 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012301
developer1e5aa162022-09-13 16:06:24 +080012302 if (band == band_2_4)
12303 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12304 else if (band == band_5)
12305 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12306 else if (band == band_6)
12307 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012308
12309 chlistp = &(rcap->channel_list[0]);
12310 memset(pchannels, 0, sizeof(pchannels));
12311
12312 /* possible number of radio channels */
12313 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12314 {
12315 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12316 }
12317 /* Number of channels and list*/
12318 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12319
12320 /* autoChannelSupported */
12321 /* always ON with wifi_getRadioAutoChannelSupported */
12322 rcap->autoChannelSupported = TRUE;
12323
12324 /* DCSSupported */
12325 /* always ON with wifi_getRadioDCSSupported */
12326 rcap->DCSSupported = TRUE;
12327
12328 /* zeroDFSSupported - TBD */
12329 rcap->zeroDFSSupported = FALSE;
12330
12331 /* Supported Country List*/
12332 memset(output_string, 0, sizeof(output_string));
12333 status = wifi_getRadioCountryCode(radioIndex, output_string);
12334 if( status != 0 ) {
12335 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12336 return RETURN_ERR;
12337 } else {
12338 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12339 }
12340 if(!strcmp(output_string,"US")){
12341 rcap->countrySupported[0] = wifi_countrycode_US;
12342 rcap->countrySupported[1] = wifi_countrycode_CA;
12343 } else if (!strcmp(output_string,"CA")) {
12344 rcap->countrySupported[0] = wifi_countrycode_CA;
12345 rcap->countrySupported[1] = wifi_countrycode_US;
12346 } else {
12347 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12348 }
12349
12350 rcap->numcountrySupported = 2;
12351
12352 /* csi */
12353 rcap->csi.maxDevices = 8;
12354 rcap->csi.soudingFrameSupported = TRUE;
12355
developer033b37b2022-10-18 11:27:46 +080012356 phyId = radio_index_to_phy(radioIndex);
12357 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012358
12359 /* channelWidth - all supported bandwidths */
12360 int i=0;
12361 rcap->channelWidth[i] = 0;
12362 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12363 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12364 WIFI_CHANNELBANDWIDTH_40MHZ);
12365
12366 }
developer1e5aa162022-09-13 16:06:24 +080012367 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012368 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12369 WIFI_CHANNELBANDWIDTH_40MHZ |
12370 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12371 }
12372
12373
12374 /* mode - all supported variants */
12375 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12376 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012377 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 +080012378 }
12379 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012380 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12381 }
12382 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12383 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012384 }
12385 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12386 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12387
12388 /* supportedBitRate - all supported bitrates */
12389 rcap->supportedBitRate[i] = 0;
12390 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12391 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12392 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12393 }
developer1e5aa162022-09-13 16:06:24 +080012394 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012395 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12396 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12397 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12398 }
12399
12400
12401 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12402 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12403 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12404 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12405 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12406 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12407 rcap->cipherSupported = 0;
12408 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12409 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12410
12411 return RETURN_OK;
12412}
12413
12414INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12415{
12416 INT status, radioIndex;
12417 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12418 int iter = 0;
12419 unsigned int j;
12420 wifi_interface_name_idex_map_t *iface_info;
12421
12422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12423
12424 memset(cap, 0, sizeof(wifi_hal_capability_t));
12425
12426 /* version */
12427 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12428 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12429
12430 /* number of radios platform property */
12431 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12432 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012433 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012434
12435 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12436 {
12437 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12438 if (status != 0) {
12439 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12440 return RETURN_ERR;
12441 }
12442
12443 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12444 {
developer804c64f2022-10-19 13:54:40 +080012445 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012446 {
12447 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12448 return RETURN_ERR;
12449 }
12450 iface_info = &cap->wifi_prop.interface_map[iter];
12451 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12452 iface_info->rdk_radio_index = radioIndex;
12453 memset(output, 0, sizeof(output));
12454 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12455 {
12456 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12457 }
12458 // TODO: bridge name
12459 // TODO: vlan id
12460 // TODO: primary
12461 iface_info->index = array_index_to_vap_index(radioIndex, j);
12462 memset(output, 0, sizeof(output));
12463 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12464 {
12465 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12466 }
12467 iter++;
12468 }
12469 }
12470
12471 cap->BandSteeringSupported = FALSE;
12472 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12473 return RETURN_OK;
12474}
12475
developer9df4e652022-10-11 11:27:38 +080012476INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12477{
12478 struct params h_config={0};
12479 char config_file[64] = {0};
12480
12481 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12482
12483 h_config.name = "okc";
12484 h_config.value = okc_enable?"1":"0";
12485
12486 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12487 wifi_hostapdWrite(config_file, &h_config, 1);
12488 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12489
12490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12491 return RETURN_OK;
12492}
12493
12494INT wifi_setSAEMFP(int ap_index, BOOL enable)
12495{
12496 struct params h_config={0};
12497 char config_file[64] = {0};
12498 char buf[128] = {0};
12499
12500 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12501
12502 h_config.name = "sae_require_mfp";
12503 h_config.value = enable?"1":"0";
12504
12505 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12506 wifi_hostapdWrite(config_file, &h_config, 1);
12507 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12508
12509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12510 return RETURN_OK;
12511}
12512
12513INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12514{
12515 struct params h_config={0};
12516 char config_file[64] = {0};
12517 char buf[128] = {0};
12518
12519 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12520
12521 h_config.name = "sae_pwe";
12522 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12523 h_config.value = buf;
12524
12525 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12526 wifi_hostapdWrite(config_file, &h_config, 1);
12527 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12528
12529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12530 return RETURN_OK;
12531}
12532
12533INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12534{
12535 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12536 struct params h_config={0};
12537 char config_file[64] = {0};
12538
12539 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12540
12541 h_config.name = "wpa_disable_eapol_key_retries";
12542 h_config.value = disable_EAPOL_retries?"1":"0";
12543
12544 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12545 wifi_hostapdWrite(config_file, &h_config, 1);
12546 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12547
12548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12549 return RETURN_OK;
12550}
12551
developer06a01d92022-09-07 16:32:39 +080012552INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12553{
developer587c1b62022-09-27 15:58:59 +080012554 char buf[128] = {0};
12555 char config_file[128] = {0};
12556 char password[64] = {0};
12557 char mfp[32] = {0};
12558 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012559 BOOL okc_enable = FALSE;
12560 BOOL sae_MFP = FALSE;
12561 BOOL disable_EAPOL_retries = TRUE;
12562 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012563 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012564 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012565
12566 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12567
12568 multiple_set = TRUE;
12569 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12570 if (security->mode == wifi_security_mode_none) {
12571 strcpy(wpa_mode, "None");
12572 } else if (security->mode == wifi_security_mode_wpa_personal)
12573 strcpy(wpa_mode, "WPA-Personal");
12574 else if (security->mode == wifi_security_mode_wpa2_personal)
12575 strcpy(wpa_mode, "WPA2-Personal");
12576 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12577 strcpy(wpa_mode, "WPA-WPA2-Personal");
12578 else if (security->mode == wifi_security_mode_wpa_enterprise)
12579 strcpy(wpa_mode, "WPA-Enterprise");
12580 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12581 strcpy(wpa_mode, "WPA2-Enterprise");
12582 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12583 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012584 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012585 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012586 okc_enable = TRUE;
12587 sae_MFP = TRUE;
12588 sae_pwe = 2;
12589 disable_EAPOL_retries = FALSE;
12590 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012591 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012592 okc_enable = TRUE;
12593 sae_MFP = TRUE;
12594 sae_pwe = 2;
12595 disable_EAPOL_retries = FALSE;
12596 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012597 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012598 sae_MFP = TRUE;
12599 sae_pwe = 2;
12600 disable_EAPOL_retries = FALSE;
12601 }
12602
12603 band = wifi_index_to_band(ap_index);
12604 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12605 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12606 return RETURN_ERR;
12607 }
developer587c1b62022-09-27 15:58:59 +080012608
12609 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012610 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012611 wifi_setSAEMFP(ap_index, sae_MFP);
12612 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012613 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012614
developer9df4e652022-10-11 11:27:38 +080012615 if (security->mode != wifi_security_mode_none) {
12616 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12617 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12618 password[63] = '\0';
12619 wifi_setApSecurityKeyPassphrase(ap_index, password);
12620 }
12621 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12622 params.name = "sae_password";
12623 params.value = security->u.key.key;
12624 wifi_hostapdWrite(config_file, &params, 1);
12625 }
12626 }
developer587c1b62022-09-27 15:58:59 +080012627
12628 if (security->mode != wifi_security_mode_none) {
12629 memset(&params, 0, sizeof(params));
12630 params.name = "wpa_pairwise";
12631 if (security->encr == wifi_encryption_tkip)
12632 params.value = "TKIP";
12633 else if (security->encr == wifi_encryption_aes)
12634 params.value = "CCMP";
12635 else if (security->encr == wifi_encryption_aes_tkip)
12636 params.value = "TKIP CCMP";
12637 wifi_hostapdWrite(config_file, &params, 1);
12638 }
12639
12640 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012641 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012642 else if (security->mfp == wifi_mfp_cfg_optional)
12643 strcpy(mfp, "Optional");
12644 else if (security->mfp == wifi_mfp_cfg_required)
12645 strcpy(mfp, "Required");
12646 wifi_setApSecurityMFPConfig(ap_index, mfp);
12647
12648 memset(&params, 0, sizeof(params));
12649 params.name = "transition_disable";
12650 if (security->wpa3_transition_disable == TRUE)
12651 params.value = "0x01";
12652 else
12653 params.value = "0x00";
12654 wifi_hostapdWrite(config_file, &params, 1);
12655
12656 memset(&params, 0, sizeof(params));
12657 params.name = "wpa_group_rekey";
12658 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12659 params.value = buf;
12660 wifi_hostapdWrite(config_file, &params, 1);
12661
12662 memset(&params, 0, sizeof(params));
12663 params.name = "wpa_strict_rekey";
12664 params.value = security->strict_rekey?"1":"0";
12665 wifi_hostapdWrite(config_file, &params, 1);
12666
12667 memset(&params, 0, sizeof(params));
12668 params.name = "wpa_pairwise_update_count";
12669 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12670 params.value = buf;
12671 wifi_hostapdWrite(config_file, &params, 1);
12672
12673 memset(&params, 0, sizeof(params));
12674 params.name = "disable_pmksa_caching";
12675 params.value = security->disable_pmksa_caching?"1":"0";
12676 wifi_hostapdWrite(config_file, &params, 1);
12677
12678 wifi_setApEnable(ap_index, FALSE);
12679 wifi_setApEnable(ap_index, TRUE);
12680
12681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12682
developer06a01d92022-09-07 16:32:39 +080012683 return RETURN_OK;
12684}
12685
12686INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12687{
developer9df4e652022-10-11 11:27:38 +080012688 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012689 char config_file[128] = {0};
12690 int disable = 0;
12691 // struct params params = {0};
12692
12693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12694 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12695 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12696 security->mode = wifi_security_mode_none;
12697 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012698 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012699 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012700 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012701 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012702 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012703 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012704 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012705 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012706 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012707 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012708 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012709 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012710 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012711 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012712 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012713 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012714 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012715 security->mode = wifi_security_mode_wpa3_enterprise;
12716 }
12717
12718 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12719 if (security->mode == wifi_security_mode_none)
12720 security->encr = wifi_encryption_none;
12721 else {
12722 if (strcmp(buf, "TKIP") == 0)
12723 security->encr = wifi_encryption_tkip;
12724 else if (strcmp(buf, "CCMP") == 0)
12725 security->encr = wifi_encryption_aes;
12726 else
12727 security->encr = wifi_encryption_aes_tkip;
12728 }
12729
developer9df4e652022-10-11 11:27:38 +080012730 if (security->mode != wifi_encryption_none) {
12731 memset(buf, 0, sizeof(buf));
12732 // wpa3 can use one or both configs as password, so we check sae_password first.
12733 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12734 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12735 security->u.key.type = wifi_security_key_type_sae;
12736 } else {
12737 security->u.key.type = wifi_security_key_type_psk;
12738 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12739 }
12740 strncpy(security->u.key.key, buf, sizeof(buf));
12741 security->u.key.key[255] = '\0';
12742 }
12743
developer587c1b62022-09-27 15:58:59 +080012744 memset(buf, 0, sizeof(buf));
12745 wifi_getApSecurityMFPConfig(ap_index, buf);
12746 if (strcmp(buf, "Disabled") == 0)
12747 security->mfp = wifi_mfp_cfg_disabled;
12748 else if (strcmp(buf, "Optional") == 0)
12749 security->mfp = wifi_mfp_cfg_optional;
12750 else if (strcmp(buf, "Required") == 0)
12751 security->mfp = wifi_mfp_cfg_required;
12752
12753 memset(buf, 0, sizeof(buf));
12754 security->wpa3_transition_disable = FALSE;
12755 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12756 disable = strtol(buf, NULL, 16);
12757 if (disable != 0)
12758 security->wpa3_transition_disable = TRUE;
12759
12760 memset(buf, 0, sizeof(buf));
12761 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12762 if (strlen(buf) == 0)
12763 security->rekey_interval = 86400;
12764 else
12765 security->rekey_interval = strtol(buf, NULL, 10);
12766
12767 memset(buf, 0, sizeof(buf));
12768 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12769 if (strlen(buf) == 0)
12770 security->strict_rekey = 1;
12771 else
12772 security->strict_rekey = strtol(buf, NULL, 10);
12773
12774 memset(buf, 0, sizeof(buf));
12775 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12776 if (strlen(buf) == 0)
12777 security->eapol_key_retries = 4;
12778 else
12779 security->eapol_key_retries = strtol(buf, NULL, 10);
12780
12781 memset(buf, 0, sizeof(buf));
12782 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12783 if (strlen(buf) == 0)
12784 security->disable_pmksa_caching = FALSE;
12785 else
12786 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12787
12788 /* TODO
12789 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12790 */
12791 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12792 security->eap_identity_req_timeout = 0;
12793 security->eap_identity_req_retries = 0;
12794 security->eap_req_timeout = 0;
12795 security->eap_req_retries = 0;
12796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012797 return RETURN_OK;
12798}
12799
12800#endif /* WIFI_HAL_VERSION_3 */
12801
12802#ifdef WIFI_HAL_VERSION_3_PHASE2
12803INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12804{
developer13df9332022-09-27 16:53:22 +080012805 char cmd[128] = {0};
12806 char buf[128] = {0};
12807 char *mac_addr = NULL;
12808 BOOL status = FALSE;
12809 size_t len = 0;
12810
12811 if(ap_index > MAX_APS)
12812 return RETURN_ERR;
12813
12814 *output_numDevices = 0;
12815 wifi_getApEnable(ap_index, &status);
12816 if (status == FALSE)
12817 return RETURN_OK;
12818
12819 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12820 _syscmd(cmd, buf, sizeof(buf));
12821
12822 mac_addr = strtok(buf, "\n");
12823 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12824 *output_numDevices = i + 1;
12825 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12826 addr_ptr = output_deviceMacAddressArray[i];
12827 mac_addr_aton(addr_ptr, mac_addr);
12828 mac_addr = strtok(NULL, "\n");
12829 }
12830
12831 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012832}
12833#else
12834INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12835{
12836 char cmd[128];
12837 BOOL status = false;
12838
12839 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12840 return RETURN_ERR;
12841
12842 output_buf[0] = '\0';
12843
12844 wifi_getApEnable(ap_index,&status);
12845 if (!status)
12846 return RETURN_OK;
12847
12848 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12849 _syscmd(cmd, output_buf, output_buf_size);
12850
12851 return RETURN_OK;
12852}
12853#endif
developer2f513ab2022-09-13 14:26:06 +080012854
12855INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12856{
12857 char output[16]={'\0'};
12858 char config_file[MAX_BUF_SIZE] = {0};
12859
12860 if (!enable)
12861 return RETURN_ERR;
12862
12863 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12864 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12865
12866 if (strlen(output) == 0)
12867 *enable = FALSE;
12868 else if (strncmp(output, "1", 1) == 0)
12869 *enable = TRUE;
12870 else
12871 *enable = FALSE;
12872
12873 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12874 return RETURN_OK;
12875}
developer2d9c30f2022-09-13 15:06:14 +080012876
12877INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12878{
developer804c64f2022-10-19 13:54:40 +080012879 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080012880 return RETURN_ERR;
12881 *output_enable=TRUE;
12882 return RETURN_OK;
12883}
developerfd7d2892022-09-13 16:44:53 +080012884
12885INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12886{
12887 char cmd[128] = {0};
12888 char buf[128] = {0};
12889 char line[128] = {0};
12890 size_t len = 0;
12891 ssize_t read = 0;
12892 FILE *f = NULL;
12893 int index = 0;
12894 int exp = 0;
12895 int mantissa = 0;
12896 int duration = 0;
12897 int radio_index = 0;
12898 int max_radio_num = 0;
12899 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080012900 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080012901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12902
12903 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080012904
developerfd7d2892022-09-13 16:44:53 +080012905 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080012906
12907 phyId = radio_index_to_phy(radio_index);
12908 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080012909 _syscmd(cmd, buf, sizeof(buf));
12910 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12911 if (*numSessionReturned > maxNumberSessions)
12912 *numSessionReturned = maxNumberSessions;
12913 else if (*numSessionReturned < 1) {
12914 *numSessionReturned = 0;
12915 return RETURN_OK;
12916 }
12917
developer033b37b2022-10-18 11:27:46 +080012918 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
developerfd7d2892022-09-13 16:44:53 +080012919 if ((f = popen(cmd, "r")) == NULL) {
12920 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12921 return RETURN_ERR;
12922 }
12923
12924 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12925 while((read = fgets(line, sizeof(line), f)) != NULL) {
12926 char *tmp = NULL;
12927 strcpy(buf, line);
12928 tmp = strtok(buf, " ");
12929 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12930 tmp = strtok(NULL, " ");
12931 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12932 tmp = strtok(NULL, " ");
12933 if (strstr(tmp, "t")) {
12934 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12935 }
12936 if (strstr(tmp, "a")) {
12937 twtSessions[index].twtParameters.operation.announced = TRUE;
12938 }
12939 tmp = strtok(NULL, " ");
12940 exp = strtol(tmp, NULL, 10);
12941 tmp = strtok(NULL, " ");
12942 mantissa = strtol(tmp, NULL, 10);
12943 tmp = strtok(NULL, " ");
12944 duration = strtol(tmp, NULL, 10);
12945
12946 // only implicit supported
12947 twtSessions[index].twtParameters.operation.implicit = TRUE;
12948 // only individual agreement supported
12949 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12950
12951 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12952 twt_wake_interval = mantissa * (1 << exp);
12953 if (twt_wake_interval/mantissa != (1 << exp)) {
12954 // Overflow handling
12955 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12956 } else {
12957 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12958 }
12959 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12960 index++;
12961 }
12962
12963 pclose(f);
12964 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12965 return RETURN_OK;
12966}