blob: cf02262a6ecf72ccedb9e2ef7f61bcc282e930a4 [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;
developer97c720c2022-11-04 17:08:12 +08005994
5995 char config_file[128] = {0};
5996 char buf[16] = {0};
5997
5998 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5999 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6000 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6001 *output = TRUE;
6002 else
6003 *output = FALSE;
6004
developer06a01d92022-09-07 16:32:39 +08006005 return RETURN_OK;
6006}
6007
6008// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6009INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6010{
6011 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006012 char config_file[MAX_BUF_SIZE] = {0};
6013 struct params list;
6014
6015 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6016 list.name = "uapsd_advertisement_enabled";
6017 list.value = enable?"1":"0";
6018
6019 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6020 wifi_hostapdWrite(config_file, &list, 1);
6021 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6022 wifi_reloadAp(apIndex);
6023 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6024
6025 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006026}
6027
developer6daeb3f2022-09-30 13:36:39 +08006028// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006029INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6030{
developer6daeb3f2022-09-30 13:36:39 +08006031 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6032 char cmd[128] = {0};
6033 char buf[128] = {0};
6034 char ack_filepath[128] = {0};
6035 uint16_t bitmap = 0;
6036 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6037 FILE *f = NULL;
6038
6039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6040
6041 // Get current setting
6042 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6043 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6044 _syscmd(cmd, buf, sizeof(buf));
6045 if (strlen(buf) > 0)
6046 bitmap = strtoul(buf, NULL, 10);
6047
6048 bitmap = strtoul(buf, NULL, 10);
6049
6050 if (ackPolicy == TRUE) { // True, unset this class
6051 bitmap &= ~class_map[class];
6052 } else { // False, set this class
6053 bitmap |= class_map[class];
6054 }
6055
6056 f = fopen(ack_filepath, "w");
6057 if (f == NULL) {
6058 fprintf(stderr, "%s: fopen failed\n", __func__);
6059 return RETURN_ERR;
6060 }
6061 fprintf(f, "%hu", bitmap);
6062 fclose(f);
6063
6064 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
6065 _syscmd(cmd, buf, sizeof(buf));
6066
6067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6068 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006069}
6070
6071//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.
6072INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6073{
6074 //get the running status from driver
6075 if(!output_uint)
6076 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006077
6078 char output[16]={'\0'};
6079 char config_file[MAX_BUF_SIZE] = {0};
6080
6081 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6082 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6083 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6084 else {
6085 int device_num = atoi(output);
6086 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6087 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6088 return RETURN_ERR;
6089 }
6090 else {
6091 *output_uint = device_num;
6092 }
6093 }
6094
developer06a01d92022-09-07 16:32:39 +08006095 return RETURN_OK;
6096}
6097
6098INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6099{
6100 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006101 char str[MAX_BUF_SIZE]={'\0'};
6102 char cmd[MAX_CMD_SIZE]={'\0'};
6103 struct params params;
6104 char config_file[MAX_BUF_SIZE] = {0};
6105
6106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6107 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6108 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6109 return RETURN_ERR;
6110 }
6111 sprintf(str, "%d", number);
6112 params.name = "max_num_sta";
6113 params.value = str;
6114
6115 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6116 int ret = wifi_hostapdWrite(config_file, &params, 1);
6117 if (ret) {
6118 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6119 ,__func__, ret);
6120 }
6121
6122 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6123 if (ret) {
6124 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6125 ,__func__, ret);
6126 }
6127 wifi_reloadAp(apIndex);
6128 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6129
6130 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006131}
6132
6133//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.
6134INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6135{
6136 //get the current threshold
6137 if(!output_uint)
6138 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006139 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6140 if (*output_uint == 0)
6141 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006142 return RETURN_OK;
6143}
6144
6145INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6146{
6147 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006148 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6149 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006150 return RETURN_ERR;
6151}
6152
6153//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.
6154INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6155{
6156 if(!output_uint)
6157 return RETURN_ERR;
6158 *output_uint = 3;
6159 return RETURN_OK;
6160}
6161
6162//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6163INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6164{
6165 if(!output_uint)
6166 return RETURN_ERR;
6167 *output_uint = 3;
6168 return RETURN_OK;
6169}
6170
6171//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.
6172INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6173{
6174 if(!output_in_seconds)
6175 return RETURN_ERR;
6176 *output_in_seconds = 0;
6177 return RETURN_OK;
6178}
6179
6180//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
6181INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6182{
6183 if(!output || apIndex>=MAX_APS)
6184 return RETURN_ERR;
6185 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006186 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006187 return RETURN_OK;
6188}
6189
6190//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6191INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6192{
developer587c1b62022-09-27 15:58:59 +08006193 char config_file[128] = {0};
6194 char wpa[16] = {0};
6195 char key_mgmt[64] = {0};
6196 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006197 if (!output)
6198 return RETURN_ERR;
6199
6200 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006201 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006202
developer587c1b62022-09-27 15:58:59 +08006203 strcpy(output, "None");//Copying "None" to output string for default case
6204 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006205 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006206 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006207 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006208 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006209 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006210 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006211 snprintf(output, 32, "WPA-WPA2-Personal");
6212
6213 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006214 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006215 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006216 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006217 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006218 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006219 snprintf(output, 32, "WPA-WPA2-Enterprise");
6220 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006221 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006222 snprintf(output, 32, "WPA3-Personal");
6223 else
developer4a359672022-10-13 15:30:46 +08006224 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006225 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6226 snprintf(output, 32, "WPA3-Enterprise");
6227 }
developer06a01d92022-09-07 16:32:39 +08006228
6229 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6230 return RETURN_OK;
6231#if 0
6232 //TODO: need to revisit below implementation
6233 char securityType[32], authMode[32];
6234 int enterpriseMode=0;
6235
6236 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6237 if(!output)
6238 return RETURN_ERR;
6239
6240 wifi_getApBeaconType(apIndex, securityType);
6241 strcpy(output,"None");//By default, copying "None" to output string
6242 if (strncmp(securityType,"None", strlen("None")) == 0)
6243 return RETURN_OK;
6244
6245 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6246 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6247
6248 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6249 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6250 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6251 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6252 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6253 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6255
6256 return RETURN_OK;
6257#endif
6258}
6259
6260INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6261{
6262 char securityType[32];
6263 char authMode[32];
6264
6265 //store settings and wait for wifi up to apply
6266 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6267 if(!encMode)
6268 return RETURN_ERR;
6269
developer06a01d92022-09-07 16:32:39 +08006270 if (strcmp(encMode, "None")==0)
6271 {
6272 strcpy(securityType,"None");
6273 strcpy(authMode,"None");
6274 }
6275 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6276 {
6277 strcpy(securityType,"WPAand11i");
6278 strcpy(authMode,"PSKAuthentication");
6279 }
6280 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6281 {
6282 strcpy(securityType,"WPAand11i");
6283 strcpy(authMode,"EAPAuthentication");
6284 }
6285 else if (strcmp(encMode, "WPA-Personal")==0)
6286 {
6287 strcpy(securityType,"WPA");
6288 strcpy(authMode,"PSKAuthentication");
6289 }
6290 else if (strcmp(encMode, "WPA-Enterprise")==0)
6291 {
6292 strcpy(securityType,"WPA");
6293 strcpy(authMode,"EAPAuthentication");
6294 }
6295 else if (strcmp(encMode, "WPA2-Personal")==0)
6296 {
6297 strcpy(securityType,"11i");
6298 strcpy(authMode,"PSKAuthentication");
6299 }
6300 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6301 {
6302 strcpy(securityType,"11i");
6303 strcpy(authMode,"EAPAuthentication");
6304 }
developer587c1b62022-09-27 15:58:59 +08006305 else if (strcmp(encMode, "WPA3-Personal") == 0)
6306 {
6307 strcpy(securityType,"11i");
6308 strcpy(authMode,"SAEAuthentication");
6309 }
developer4a359672022-10-13 15:30:46 +08006310 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006311 {
6312 strcpy(securityType, "11i");
6313 strcpy(authMode, "PSK-SAEAuthentication");
6314 }
developer587c1b62022-09-27 15:58:59 +08006315 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6316 {
6317 strcpy(securityType,"11i");
6318 strcpy(authMode,"EAP_192-bit_Authentication");
6319 }
developer06a01d92022-09-07 16:32:39 +08006320 else
6321 {
6322 strcpy(securityType,"None");
6323 strcpy(authMode,"None");
6324 }
6325 wifi_setApBeaconType(apIndex, securityType);
6326 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6328
6329 return RETURN_OK;
6330}
6331
6332
6333//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6334// output_string must be pre-allocated as 64 character string by caller
6335// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6336INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6337{
6338 char buf[16];
6339 char config_file[MAX_BUF_SIZE] = {0};
6340
6341 if(output_string==NULL)
6342 return RETURN_ERR;
6343
6344 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6345 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6346
6347 if(strcmp(buf,"0")==0)
6348 {
6349 printf("wpa_mode is %s ......... \n",buf);
6350 return RETURN_ERR;
6351 }
6352
6353 wifi_dbg_printf("\nFunc=%s\n",__func__);
6354 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6355 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6356 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6357
6358 return RETURN_OK;
6359}
6360
6361// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6362// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6363INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6364{
6365 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6366 struct params params={'\0'};
6367 int ret;
6368 char config_file[MAX_BUF_SIZE] = {0};
6369
6370 if(NULL == preSharedKey)
6371 return RETURN_ERR;
6372
6373 params.name = "wpa_passphrase";
6374
6375 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6376 {
6377 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6378 return RETURN_ERR;
6379 }
6380 params.value = preSharedKey;
6381 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6382 ret = wifi_hostapdWrite(config_file, &params, 1);
6383 if(!ret)
6384 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6385 return ret;
6386 //TODO: call hostapd_cli for dynamic_config_control
6387}
6388
6389//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6390// outputs the passphrase, maximum 63 characters
6391INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6392{
6393 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6394
6395 wifi_dbg_printf("\nFunc=%s\n",__func__);
6396 if (NULL == output_string)
6397 return RETURN_ERR;
6398
6399 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6400 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6401 if(strcmp(buf,"0")==0)
6402 {
6403 printf("wpa_mode is %s ......... \n",buf);
6404 return RETURN_ERR;
6405 }
6406
6407 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6408 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6409
6410 return RETURN_OK;
6411}
6412
6413// sets the passphrase enviornment variable, max 63 characters
6414INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6415{
6416 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6417 struct params params={'\0'};
6418 char config_file[MAX_BUF_SIZE] = {0};
6419 int ret;
6420
6421 if(NULL == passPhrase)
6422 return RETURN_ERR;
6423
6424 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6425 {
6426 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6427 return RETURN_ERR;
6428 }
6429 params.name = "wpa_passphrase";
6430 params.value = passPhrase;
6431 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6432 ret=wifi_hostapdWrite(config_file,&params,1);
6433 if(!ret)
6434 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6435
6436 return ret;
6437}
6438
6439//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.
6440INT wifi_setApSecurityReset(INT apIndex)
6441{
developer8d583982022-09-20 11:28:22 +08006442 char original_config_file[64] = {0};
6443 char current_config_file[64] = {0};
6444 char buf[64] = {0};
6445 char cmd[64] = {0};
6446 char wpa[4] = {0};
6447 char wpa_psk[64] = {0};
6448 char wpa_passphrase[64] = {0};
6449 char wpa_psk_file[128] = {0};
6450 char wpa_key_mgmt[64] = {0};
6451 char wpa_pairwise[32] = {0};
6452 wifi_band band;
6453 struct params list[6];
6454
6455 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6456
6457 band = wifi_index_to_band(apIndex);
6458 if (band == band_2_4)
6459 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6460 else if (band = band_5)
6461 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6462 else if (band = band_6)
6463 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6464 else
6465 return RETURN_ERR;
6466
6467 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6468 list[0].name = "wpa";
6469 list[0].value = wpa;
6470
6471 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6472 list[1].name = "wpa_psk";
6473 list[1].value = wpa_psk;
6474
6475 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6476 list[2].name = "wpa_passphrase";
6477 list[2].value = wpa_passphrase;
6478
6479 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6480
6481 if (strlen(wpa_psk_file) == 0)
6482 strcpy(wpa_psk_file, PSK_FILE);
6483
6484 if (access(wpa_psk_file, F_OK) != 0) {
6485 sprintf(cmd, "touch %s", wpa_psk_file);
6486 _syscmd(cmd, buf, sizeof(buf));
6487 }
6488 list[3].name = "wpa_psk_file";
6489 list[3].value = wpa_psk_file;
6490
6491 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6492 list[4].name = "wpa_key_mgmt";
6493 list[4].value = wpa_key_mgmt;
6494
6495 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6496 list[5].name = "wpa_pairwise";
6497 list[5].value = wpa_pairwise;
6498
6499 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6500 wifi_hostapdWrite(current_config_file, list, 6);
6501
6502 wifi_setApEnable(apIndex, FALSE);
6503 wifi_setApEnable(apIndex, TRUE);
6504
6505 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6506 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006507}
6508
6509//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).
6510INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6511{
developer8f2ddd52022-09-13 15:39:24 +08006512 char config_file[64] = {0};
6513 char buf[64] = {0};
6514 char cmd[256] = {0};
6515
6516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6517
developer06a01d92022-09-07 16:32:39 +08006518 if(!IP_output || !Port_output || !RadiusSecret_output)
6519 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006520
developer8f2ddd52022-09-13 15:39:24 +08006521 // Read the first matched config
6522 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6523 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6524 _syscmd(cmd, buf, sizeof(buf));
6525 strncpy(IP_output, buf, 64);
6526
6527 memset(buf, 0, sizeof(buf));
6528 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6529 _syscmd(cmd, buf, sizeof(buf));
6530 *Port_output = atoi(buf);
6531
6532 memset(buf, 0, sizeof(buf));
6533 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6534 _syscmd(cmd, buf, sizeof(buf));
6535 strncpy(RadiusSecret_output, buf, 64);
6536
6537 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006538 return RETURN_OK;
6539}
6540
6541INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6542{
developer8f2ddd52022-09-13 15:39:24 +08006543 char config_file[64] = {0};
6544 char port_str[8] = {0};
6545 char cmd[256] = {0};
6546 char buf[128] = {0};
6547
6548 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6549
6550 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6551
6552 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6553 _syscmd(cmd, buf, sizeof(buf));
6554 memset(cmd, 0, sizeof(cmd));
6555
6556 snprintf(port_str, sizeof(port_str), "%d", port);
6557 if (strlen(buf) == 0)
6558 // Append
6559 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6560 "auth_server_addr=%s\\n"
6561 "auth_server_port=%s\\n"
6562 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6563 else {
6564 // Delete the three lines setting after the "# radius 1" comment
6565 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6566 _syscmd(cmd, buf, sizeof(buf));
6567 memset(cmd, 0, sizeof(cmd));
6568 // Use "# radius 1" comment to find the location to insert the radius setting
6569 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6570 "# radius 1\\n"
6571 "auth_server_addr=%s\\n"
6572 "auth_server_port=%s\\n"
6573 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6574 }
6575 if(_syscmd(cmd, buf, sizeof(buf))) {
6576 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6577 return RETURN_ERR;
6578 }
6579
6580 wifi_reloadAp(apIndex);
6581 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6582 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006583}
6584
6585INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6586{
developer8f2ddd52022-09-13 15:39:24 +08006587 char config_file[64] = {0};
6588 char buf[64] = {0};
6589 char cmd[256] = {0};
6590
6591 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6592
developer06a01d92022-09-07 16:32:39 +08006593 if(!IP_output || !Port_output || !RadiusSecret_output)
6594 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006595
6596 // Read the second matched config
6597 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6598 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6599 _syscmd(cmd, buf, sizeof(buf));
6600 strncpy(IP_output, buf, 64);
6601
6602 memset(buf, 0, sizeof(buf));
6603 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6604 _syscmd(cmd, buf, sizeof(buf));
6605 *Port_output = atoi(buf);
6606
6607 memset(buf, 0, sizeof(buf));
6608 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6609 _syscmd(cmd, buf, sizeof(buf));
6610 strncpy(RadiusSecret_output, buf, 64);
6611
6612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006613 return RETURN_OK;
6614}
6615
6616INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6617{
developer8f2ddd52022-09-13 15:39:24 +08006618 char config_file[64] = {0};
6619 char port_str[8] = {0};
6620 char cmd[256] = {0};
6621 char buf[128] = {0};
6622
6623 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6624
6625 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6626
6627 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6628 _syscmd(cmd, buf, sizeof(buf));
6629 memset(cmd, 0, sizeof(cmd));
6630
6631 snprintf(port_str, sizeof(port_str), "%d", port);
6632 if (strlen(buf) == 0)
6633 // Append
6634 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6635 "auth_server_addr=%s\\n"
6636 "auth_server_port=%s\\n"
6637 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6638 else {
6639 // Delete the three lines setting after the "# radius 2" comment
6640 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6641 _syscmd(cmd, buf, sizeof(buf));
6642 memset(cmd, 0, sizeof(cmd));
6643 // Use "# radius 2" comment to find the location to insert the radius setting
6644 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6645 "# radius 2\\n"
6646 "auth_server_addr=%s\\n"
6647 "auth_server_port=%s\\n"
6648 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6649 }
6650 if(_syscmd(cmd, buf, sizeof(buf))) {
6651 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6652 return RETURN_ERR;
6653 }
6654
6655 wifi_reloadAp(apIndex);
6656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6657 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006658}
6659
6660//RadiusSettings
6661INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6662{
6663 if(!output)
6664 return RETURN_ERR;
6665
6666 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6667 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6668 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6669 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6670 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6671 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.
6672 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6673 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6674 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6675 //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.
6676
6677 return RETURN_OK;
6678}
6679
6680INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6681{
6682 //store the paramters, and apply instantly
6683 return RETURN_ERR;
6684}
6685
6686//Device.WiFi.AccessPoint.{i}.WPS.Enable
6687//Enables or disables WPS functionality for this access point.
6688// outputs the WPS enable state of this ap in output_bool
6689INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6690{
6691 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6692 if(!output_bool || !(apIndex==0 || apIndex==1))
6693 return RETURN_ERR;
6694 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6695 _syscmd(cmd, buf, sizeof(buf));
6696 if(strstr(buf, "configured"))
6697 *output_bool=TRUE;
6698 else
6699 *output_bool=FALSE;
6700
6701 return RETURN_OK;
6702}
6703
6704//Device.WiFi.AccessPoint.{i}.WPS.Enable
6705// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6706INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6707{
6708 char config_file[MAX_BUF_SIZE] = {0};
6709 struct params params;
6710
6711 if(!(apIndex==0 || apIndex==1))
6712 return RETURN_ERR;
6713 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6714 //store the paramters, and wait for wifi up to apply
6715 params.name = "wps_state";
6716 params.value = enable ? "2":"0";
6717
6718 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6719 wifi_hostapdWrite(config_file, &params, 1);
6720 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6721 wifi_reloadAp(apIndex);
6722
6723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6724 return RETURN_OK;
6725}
6726
6727//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
6728INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6729{
6730 if(!output)
6731 return RETURN_ERR;
6732 snprintf(output, 128, "PushButton,PIN");
6733 return RETURN_OK;
6734}
6735
6736//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6737//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.
6738// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6739INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6740{
6741 if(!output)
6742 return RETURN_ERR;
6743 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6744
6745 return RETURN_OK;
6746}
6747
6748//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6749// 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
6750INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6751{
6752 //apply instantly. No setting need to be stored.
6753 char methods[MAX_BUF_SIZE], *token, *next_token;
6754 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6755 struct params params;
6756
6757 if(!methodString || !(apIndex==0 || apIndex==1))
6758 return RETURN_ERR;
6759 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6760 //store the paramters, and wait for wifi up to apply
6761
6762 snprintf(methods, sizeof(methods), "%s", methodString);
6763 for(token=methods; *token; token=next_token)
6764 {
6765 strtok_r(token, ",", &next_token);
6766 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6767 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6768 else if(*token=='E')
6769 {
6770 if(!strcmp(methods, "Ethernet"))
6771 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6772 else if(!strcmp(methods, "ExternalNFCToken"))
6773 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6774 else
6775 printf("%s: Unknown WpsConfigMethod\n", __func__);
6776 }
6777 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6778 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6779 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6780 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6781 else if(*token=='P' )
6782 {
6783 if(!strcmp(token, "PushButton"))
6784 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6785 else if(!strcmp(token, "PIN"))
6786 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6787 else
6788 printf("%s: Unknown WpsConfigMethod\n", __func__);
6789 }
6790 else
6791 printf("%s: Unknown WpsConfigMethod\n", __func__);
6792 }
6793 params.name = "config_methods";
6794 params.value = config_methods;
6795 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6796 wifi_hostapdWrite(config_file, &params, 1);
6797 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6798 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6799
6800 return RETURN_OK;
6801}
6802
6803// outputs the pin value, ulong_pin must be allocated by the caller
6804INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6805{
6806 char buf[MAX_BUF_SIZE] = {0};
6807 char cmd[MAX_CMD_SIZE] = {0};
6808
6809 if(!output_ulong || !(apIndex==0 || apIndex==1))
6810 return RETURN_ERR;
6811 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6812 _syscmd(cmd, buf, sizeof(buf));
6813 if(strlen(buf) > 0)
6814 *output_ulong=strtoul(buf, NULL, 10);
6815
6816 return RETURN_OK;
6817}
6818
6819// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6820INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6821{
6822 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6823 char ap_pin[16] = {0};
6824 char buf[MAX_BUF_SIZE] = {0};
6825 char config_file[MAX_BUF_SIZE] = {0};
6826 ULONG prev_pin = 0;
6827 struct params params;
6828
6829 if(!(apIndex==0 || apIndex==1))
6830 return RETURN_ERR;
6831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6832 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6833 params.name = "ap_pin";
6834 params.value = ap_pin;
6835 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6836 wifi_hostapdWrite(config_file, &params, 1);
6837 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6839
6840 return RETURN_OK;
6841}
6842
6843// Output string is either Not configured or Configured, max 32 characters
6844INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6845{
6846 char cmd[MAX_CMD_SIZE];
6847 char buf[MAX_BUF_SIZE]={0};
6848
6849 if(!output_string || !(apIndex==0 || apIndex==1))
6850 return RETURN_ERR;
6851 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6852 snprintf(output_string, 32, "Not configured");
6853 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6854 _syscmd(cmd, buf, sizeof(buf));
6855
developer348e3d92022-09-13 14:48:41 +08006856 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006857 snprintf(output_string, 32, "Configured");
6858 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6859
6860 return RETURN_OK;
6861}
6862
6863// sets the WPS pin for this AP
6864INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6865{
6866 char cmd[MAX_CMD_SIZE];
6867 char buf[MAX_BUF_SIZE]={0};
6868 BOOL enable;
6869
6870 if(!(apIndex==0 || apIndex==1))
6871 return RETURN_ERR;
6872 wifi_getApEnable(apIndex, &enable);
6873 if (!enable)
6874 return RETURN_ERR;
6875 wifi_getApWpsEnable(apIndex, &enable);
6876 if (!enable)
6877 return RETURN_ERR;
6878
6879 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6880 _syscmd(cmd, buf, sizeof(buf));
6881 if((strstr(buf, "OK"))!=NULL)
6882 return RETURN_OK;
6883
6884 return RETURN_ERR;
6885}
6886
6887// This function is called when the WPS push button has been pressed for this AP
6888INT wifi_setApWpsButtonPush(INT apIndex)
6889{
6890 char cmd[MAX_CMD_SIZE];
6891 char buf[MAX_BUF_SIZE]={0};
6892 BOOL enable=FALSE;
6893
6894 if(!(apIndex==0 || apIndex==1))
6895 return RETURN_ERR;
6896 wifi_getApEnable(apIndex, &enable);
6897 if (!enable)
6898 return RETURN_ERR;
6899
6900 wifi_getApWpsEnable(apIndex, &enable);
6901 if (!enable)
6902 return RETURN_ERR;
6903
6904 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6905 _syscmd(cmd, buf, sizeof(buf));
6906
6907 if((strstr(buf, "OK"))!=NULL)
6908 return RETURN_OK;
6909 return RETURN_ERR;
6910}
6911
6912// cancels WPS mode for this AP
6913INT wifi_cancelApWPS(INT apIndex)
6914{
6915 char cmd[MAX_CMD_SIZE];
6916 char buf[MAX_BUF_SIZE]={0};
6917
6918 if(!(apIndex==0 || apIndex==1))
6919 return RETURN_ERR;
6920 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6921 _syscmd(cmd,buf, sizeof(buf));
6922
6923 if((strstr(buf, "OK"))!=NULL)
6924 return RETURN_OK;
6925 return RETURN_ERR;
6926}
6927
6928//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6929//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6930INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6931{
6932 FILE *f;
6933 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6934 char cmd[256], buf[2048];
6935 char *param , *value, *line=NULL;
6936 size_t len = 0;
6937 ssize_t nread;
6938 wifi_associated_dev_t *dev=NULL;
6939
6940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6941 *associated_dev_array = NULL;
6942 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6943 _syscmd(cmd,buf,sizeof(buf));
6944 *output_array_size = atoi(buf);
6945
6946 if (*output_array_size <= 0)
6947 return RETURN_OK;
6948
6949 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6950 *associated_dev_array = dev;
6951 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6952 _syscmd(cmd,buf,sizeof(buf));
6953 f = fopen("/tmp/connected_devices.txt", "r");
6954 if (f==NULL)
6955 {
6956 *output_array_size=0;
6957 return RETURN_ERR;
6958 }
6959 while ((nread = getline(&line, &len, f)) != -1)
6960 {
6961 param = strtok(line,"=");
6962 value = strtok(NULL,"=");
6963
6964 if( strcmp("flags",param) == 0 )
6965 {
6966 value[strlen(value)-1]='\0';
6967 if(strstr (value,"AUTHORIZED") != NULL )
6968 {
6969 dev[auth_temp].cli_AuthenticationState = 1;
6970 dev[auth_temp].cli_Active = 1;
6971 auth_temp++;
6972 read_flag=1;
6973 }
6974 }
6975 if(read_flag==1)
6976 {
6977 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6978 {
6979 value[strlen(value)-1]='\0';
6980 sscanf(value, "%x:%x:%x:%x:%x:%x",
6981 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6982 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6983 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6984 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6985 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6986 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6987 mac_temp++;
6988 read_flag=0;
6989 }
6990 }
6991 }
6992 *output_array_size = auth_temp;
6993 auth_temp=0;
6994 mac_temp=0;
6995 free(line);
6996 fclose(f);
6997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6998 return RETURN_OK;
6999}
7000
7001#define MACADDRESS_SIZE 6
7002
7003INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7004{
7005 FILE *fp = NULL;
7006 char str[MAX_BUF_SIZE] = {0};
7007 int wificlientindex = 0 ;
7008 int count = 0;
7009 int signalstrength = 0;
7010 int arr[MACADDRESS_SIZE] = {0};
7011 unsigned char mac[MACADDRESS_SIZE] = {0};
7012 UINT wifi_count = 0;
7013 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7014 char pipeCmd[MAX_CMD_SIZE] = {0};
7015
7016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7017 *output_array_size = 0;
7018 *associated_dev_array = NULL;
7019
7020 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7021 fp = popen(pipeCmd, "r");
7022 if (fp == NULL)
7023 {
7024 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7025 return RETURN_ERR;
7026 }
7027
7028 /* Read the output a line at a time - output it. */
7029 fgets(str, sizeof(str)-1, fp);
7030 wifi_count = (unsigned int) atoi ( str );
7031 *output_array_size = wifi_count;
7032 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7033 pclose(fp);
7034
7035 if(wifi_count == 0)
7036 {
7037 return RETURN_OK;
7038 }
7039 else
7040 {
7041 wifi_associated_dev3_t* temp = NULL;
7042 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7043 if(temp == NULL)
7044 {
7045 printf("Error Statement. Insufficient memory \n");
7046 return RETURN_ERR;
7047 }
7048
7049 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7050 system(pipeCmd);
7051 memset(pipeCmd,0,sizeof(pipeCmd));
7052 if(apIndex == 0)
7053 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7054 else if(apIndex == 1)
7055 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7056 system(pipeCmd);
7057
7058 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7059 if(fp == NULL)
7060 {
7061 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7062 return RETURN_ERR;
7063 }
7064 fclose(fp);
7065
7066 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7067 fp = popen(pipeCmd, "r");
7068 if(fp)
7069 {
7070 for(count =0 ; count < wifi_count; count++)
7071 {
7072 fgets(str, MAX_BUF_SIZE, fp);
7073 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7074 {
7075 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7076 {
7077 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7078
7079 }
7080 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7081 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]);
7082 }
7083 temp[count].cli_AuthenticationState = 1; //TODO
7084 temp[count].cli_Active = 1; //TODO
7085 }
7086 pclose(fp);
7087 }
7088
7089 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7090 fp = popen(pipeCmd, "r");
7091 if(fp)
7092 {
7093 pclose(fp);
7094 }
7095 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7096 if(fp)
7097 {
7098 for(count =0 ; count < wifi_count ;count++)
7099 {
7100 fgets(str, MAX_BUF_SIZE, fp);
7101 signalstrength = atoi(str);
7102 temp[count].cli_SignalStrength = signalstrength;
7103 temp[count].cli_RSSI = signalstrength;
7104 temp[count].cli_SNR = signalstrength + 95;
7105 }
7106 pclose(fp);
7107 }
7108
7109
7110 if((apIndex == 0) || (apIndex == 4))
7111 {
7112 for(count =0 ; count < wifi_count ;count++)
7113 {
7114 strcpy(temp[count].cli_OperatingStandard,"g");
7115 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7116 }
7117
7118 //BytesSent
7119 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7120 fp = popen(pipeCmd, "r");
7121 if(fp)
7122 {
7123 pclose(fp);
7124 }
7125 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7126 if(fp)
7127 {
7128 for (count = 0; count < wifi_count; count++)
7129 {
7130 fgets(str, MAX_BUF_SIZE, fp);
7131 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7132 }
7133 pclose(fp);
7134 }
7135
7136 //BytesReceived
7137 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7138 fp = popen(pipeCmd, "r");
7139 if (fp)
7140 {
7141 pclose(fp);
7142 }
7143 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7144 if (fp)
7145 {
7146 for (count = 0; count < wifi_count; count++)
7147 {
7148 fgets(str, MAX_BUF_SIZE, fp);
7149 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7150 }
7151 pclose(fp);
7152 }
7153
7154 //PacketsSent
7155 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7156 fp = popen(pipeCmd, "r");
7157 if (fp)
7158 {
7159 pclose(fp);
7160 }
7161
7162 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7163 if (fp)
7164 {
7165 for (count = 0; count < wifi_count; count++)
7166 {
7167 fgets(str, MAX_BUF_SIZE, fp);
7168 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7169 }
7170 pclose(fp);
7171 }
7172
7173 //PacketsReceived
7174 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7175 fp = popen(pipeCmd, "r");
7176 if (fp)
7177 {
7178 pclose(fp);
7179 }
7180 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7181 if (fp)
7182 {
7183 for (count = 0; count < wifi_count; count++)
7184 {
7185 fgets(str, MAX_BUF_SIZE, fp);
7186 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7187 }
7188 pclose(fp);
7189 }
7190
7191 //ErrorsSent
7192 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7193 fp = popen(pipeCmd, "r");
7194 if (fp)
7195 {
7196 pclose(fp);
7197 }
7198 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7199 if (fp)
7200 {
7201 for (count = 0; count < wifi_count; count++)
7202 {
7203 fgets(str, MAX_BUF_SIZE, fp);
7204 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7205 }
7206 pclose(fp);
7207 }
7208
7209 //ErrorsSent
7210 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7211 fp = popen(pipeCmd, "r");
7212 if (fp)
7213 {
7214 pclose(fp);
7215 }
7216 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7217 if (fp)
7218 {
7219 for (count = 0; count < wifi_count; count++)
7220 {
7221 fgets(str, MAX_BUF_SIZE, fp);
7222 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7223 }
7224 pclose(fp);
7225 }
7226
7227 //LastDataDownlinkRate
7228 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7229 fp = popen(pipeCmd, "r");
7230 if (fp)
7231 {
7232 pclose(fp);
7233 }
7234 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7235 if (fp)
7236 {
7237 for (count = 0; count < wifi_count; count++)
7238 {
7239 fgets(str, MAX_BUF_SIZE, fp);
7240 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7241 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7242 }
7243 pclose(fp);
7244 }
7245
7246 //LastDataUplinkRate
7247 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7248 fp = popen(pipeCmd, "r");
7249 if (fp)
7250 {
7251 pclose(fp);
7252 }
7253 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7254 if (fp)
7255 {
7256 for (count = 0; count < wifi_count; count++)
7257 {
7258 fgets(str, MAX_BUF_SIZE, fp);
7259 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7260 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7261 }
7262 pclose(fp);
7263 }
7264
7265 }
7266 else if ((apIndex == 1) || (apIndex == 5))
7267 {
7268 for (count = 0; count < wifi_count; count++)
7269 {
7270 strcpy(temp[count].cli_OperatingStandard, "a");
7271 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7272 temp[count].cli_BytesSent = 0;
7273 temp[count].cli_BytesReceived = 0;
7274 temp[count].cli_LastDataUplinkRate = 0;
7275 temp[count].cli_LastDataDownlinkRate = 0;
7276 temp[count].cli_PacketsSent = 0;
7277 temp[count].cli_PacketsReceived = 0;
7278 temp[count].cli_ErrorsSent = 0;
7279 }
7280 }
7281
7282 for (count = 0; count < wifi_count; count++)
7283 {
7284 temp[count].cli_Retransmissions = 0;
7285 temp[count].cli_DataFramesSentAck = 0;
7286 temp[count].cli_DataFramesSentNoAck = 0;
7287 temp[count].cli_MinRSSI = 0;
7288 temp[count].cli_MaxRSSI = 0;
7289 strncpy(temp[count].cli_InterferenceSources, "", 64);
7290 memset(temp[count].cli_IPAddress, 0, 64);
7291 temp[count].cli_RetransCount = 0;
7292 temp[count].cli_FailedRetransCount = 0;
7293 temp[count].cli_RetryCount = 0;
7294 temp[count].cli_MultipleRetryCount = 0;
7295 }
7296 *associated_dev_array = temp;
7297 }
7298 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7299 return RETURN_OK;
7300}
7301
7302int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7303{
7304 FILE *fp = NULL;
7305 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7306 char cmd[MAX_CMD_SIZE];
7307 int count = 0;
7308
7309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7310 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7311 fp = popen(cmd,"r");
7312 if(fp == NULL)
7313 {
7314 printf("Failed to run command in Function %s\n",__FUNCTION__);
7315 return 0;
7316 }
7317 if(fgets(path, sizeof(path)-1, fp) != NULL)
7318 {
7319 for(count=0;path[count]!='\n';count++)
7320 status[count]=path[count];
7321 status[count]='\0';
7322 }
7323 strcpy(wifi_status,status);
7324 pclose(fp);
7325 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7326 return RETURN_OK;
7327}
7328
7329/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7330struct hostapd_sta_param {
7331 char key[50];
7332 char value[100];
7333}
7334
7335static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7336 int i = 0;
7337
7338 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7339 if (strncmp(params[i].key,key,50) == 0){
7340 return &params[i].value;
7341 }
7342 i++;
7343 }
7344 return NULL;
7345
7346} */
7347
7348static unsigned int count_occurences(const char *buf, const char *word)
7349{
7350 unsigned int n = 0;
7351 char *ptr = strstr(buf, word);
7352
7353 while (ptr++) {
7354 n++;
7355 ptr = strstr(ptr, word);
7356 }
7357
7358 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7359 return n;
7360}
7361
7362static const char *get_line_from_str_buf(const char *buf, char *line)
7363{
7364 int i;
7365 int n = strlen(buf);
7366
7367 for (i = 0; i < n; i++) {
7368 line[i] = buf[i];
7369 if (buf[i] == '\n') {
7370 line[i] = '\0';
7371 return &buf[i + 1];
7372 }
7373 }
7374
7375 return NULL;
7376}
7377
7378INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7379{
7380 unsigned int assoc_cnt = 0;
7381 char interface_name[50] = {0};
7382 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7383 char cmd[MAX_CMD_SIZE] = {'\0'};
7384 char line[256] = {'\0'};
7385 int i = 0;
7386 int ret = 0;
7387 const char *ptr = NULL;
7388 char *key = NULL;
7389 char *val = NULL;
7390 wifi_associated_dev3_t *temp = NULL;
7391 int rssi;
7392
7393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7394
7395 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7396 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7397 return RETURN_ERR;
7398 }
7399
7400 // Example filtered output of 'iw dev' command:
7401 // Station 0a:69:72:10:d2:fa (on wifi0)
7402 // signal avg:-67 [-71, -71] dBm
7403 // Station 28:c2:1f:25:5f:99 (on wifi0)
7404 // signal avg:-67 [-71, -70] dBm
7405 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7406 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7407 return RETURN_ERR;
7408 }
7409
7410 ret = _syscmd(cmd, buf, sizeof(buf));
7411 if (ret == RETURN_ERR) {
7412 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7413 return RETURN_ERR;
7414 }
7415
7416 *output_array_size = count_occurences(buf, "Station");
7417 if (*output_array_size == 0) return RETURN_OK;
7418
7419 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7420 if (temp == NULL) {
7421 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7422 return RETURN_ERR;
7423 }
7424 *associated_dev_array = temp;
7425
7426 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7427 ptr = get_line_from_str_buf(buf, line);
7428 i = -1;
7429 while (ptr) {
7430 if (strstr(line, "Station")) {
7431 i++;
7432 key = strtok(line, " ");
7433 val = strtok(NULL, " ");
7434 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7435 &temp[i].cli_MACAddress[0],
7436 &temp[i].cli_MACAddress[1],
7437 &temp[i].cli_MACAddress[2],
7438 &temp[i].cli_MACAddress[3],
7439 &temp[i].cli_MACAddress[4],
7440 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7441 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7442 free(*associated_dev_array);
7443 return RETURN_ERR;
7444 }
7445 }
7446 else if (i < 0) {
7447 ptr = get_line_from_str_buf(ptr, line);
7448 continue; // We didn't detect 'station' entry yet
7449 }
7450 else if (strstr(line, "signal avg")) {
7451 key = strtok(line, ":");
7452 val = strtok(NULL, " ");
7453 if (sscanf(val, "%d", &rssi) <= 0 ) {
7454 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7455 free(*associated_dev_array);
7456 return RETURN_ERR;
7457 }
7458 temp[i].cli_RSSI = rssi;
7459 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7460 }
7461 // Here other fields can be parsed if added to filter of 'iw dev' command
7462
7463 ptr = get_line_from_str_buf(ptr, line);
7464 };
7465
7466 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7467
7468 return RETURN_OK;
7469}
7470
7471#if 0
7472//To-do
7473INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7474{
7475 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7476
7477 //Using different approach to get required WiFi Parameters from system available commands
7478#if 0
7479 FILE *f;
7480 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7481 char cmd[256], buf[2048];
7482 char *param , *value, *line=NULL;
7483 size_t len = 0;
7484 ssize_t nread;
7485 wifi_associated_dev3_t *dev=NULL;
7486 *associated_dev_array = NULL;
7487 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7488 _syscmd(cmd,buf,sizeof(buf));
7489 *output_array_size = atoi(buf);
7490
7491 if (*output_array_size <= 0)
7492 return RETURN_OK;
7493
7494 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7495 *associated_dev_array = dev;
7496 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7497 _syscmd(cmd,buf,sizeof(buf));
7498 f = fopen("/tmp/connected_devices.txt", "r");
7499 if (f==NULL)
7500 {
7501 *output_array_size=0;
7502 return RETURN_ERR;
7503 }
7504 while ((nread = getline(&line, &len, f)) != -1)
7505 {
7506 param = strtok(line,"=");
7507 value = strtok(NULL,"=");
7508
7509 if( strcmp("flags",param) == 0 )
7510 {
7511 value[strlen(value)-1]='\0';
7512 if(strstr (value,"AUTHORIZED") != NULL )
7513 {
7514 dev[auth_temp].cli_AuthenticationState = 1;
7515 dev[auth_temp].cli_Active = 1;
7516 auth_temp++;
7517 read_flag=1;
7518 }
7519 }
7520 if(read_flag==1)
7521 {
7522 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7523 {
7524 value[strlen(value)-1]='\0';
7525 sscanf(value, "%x:%x:%x:%x:%x:%x",
7526 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7527 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7528 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7529 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7530 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7531 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7532
7533 }
7534 else if( strcmp("rx_packets",param) == 0 )
7535 {
7536 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7537 }
7538
7539 else if( strcmp("tx_packets",param) == 0 )
7540 {
7541 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7542 }
7543
7544 else if( strcmp("rx_bytes",param) == 0 )
7545 {
7546 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7547 }
7548
7549 else if( strcmp("tx_bytes",param) == 0 )
7550 {
7551 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7552 mac_temp++;
7553 read_flag=0;
7554 }
7555 }
7556 }
7557
7558 *output_array_size = auth_temp;
7559 auth_temp=0;
7560 mac_temp=0;
7561 free(line);
7562 fclose(f);
7563#endif
7564 char interface_name[MAX_BUF_SIZE] = {0};
7565 char wifi_status[MAX_BUF_SIZE] = {0};
7566 char hostapdconf[MAX_BUF_SIZE] = {0};
7567
7568 wifi_associated_dev3_t *dev_array = NULL;
7569 ULONG wifi_count = 0;
7570
7571 *associated_dev_array = NULL;
7572 *output_array_size = 0;
7573
7574 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7575 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7576 {
7577 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7578
7579 GetInterfaceName(interface_name, hostapdconf);
7580
7581 if(strlen(interface_name) > 1)
7582 {
7583 wifihal_interfacestatus(wifi_status,interface_name);
7584 if(strcmp(wifi_status,"RUNNING") == 0)
7585 {
7586 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7587
7588 *associated_dev_array = dev_array;
7589 *output_array_size = wifi_count;
7590 }
7591 else
7592 {
7593 *associated_dev_array = NULL;
7594 }
7595 }
7596 }
7597
7598 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7599 return RETURN_OK;
7600}
7601#endif
7602
7603/* getIPAddress function */
7604/**
7605* @description Returning IpAddress of the Matched String
7606*
7607* @param
7608* @str Having MacAddress
7609* @ipaddr Having ipaddr
7610* @return The status of the operation
7611* @retval RETURN_OK if successful
7612* @retval RETURN_ERR if any error is detected
7613*
7614*/
7615
7616INT getIPAddress(char *str,char *ipaddr)
7617{
7618 FILE *fp = NULL;
7619 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7620 int LeaseTime = 0,ret = 0;
7621 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7622 {
7623 return RETURN_ERR;
7624 }
7625
7626 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7627 {
7628 /*
7629 Sample:sss
7630 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7631 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7632 */
7633 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7634 &(LeaseTime),
7635 phyAddr,
7636 ipAddr,
7637 hostName
7638 );
7639 if(ret != 4)
7640 continue;
7641 if(strcmp(str,phyAddr) == 0)
7642 strcpy(ipaddr,ipAddr);
7643 }
7644 return RETURN_OK;
7645}
7646
7647/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7648/**
7649* @description Returning Inactive wireless connected clients informations
7650*
7651* @param
7652* @filename Holding private_wifi 2g/5g content files
7653* @associated_dev_array Having inactiv wireless clients informations
7654* @output_array_size Returning Inactive wireless counts
7655* @return The status of the operation
7656* @retval RETURN_OK if successful
7657* @retval RETURN_ERR if any error is detected
7658*
7659*/
7660
7661INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7662{
7663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7664 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7665 FILE *fp = NULL;
7666 int arr[MACADDRESS_SIZE] = {0};
7667 unsigned char mac[MACADDRESS_SIZE] = {0};
7668 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7669 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7670 fp = popen(buf,"r");
7671 if(fp == NULL)
7672 return RETURN_ERR;
7673 else
7674 {
7675 fgets(path,sizeof(path),fp);
7676 maccount = atoi(path);
7677 }
7678 pclose(fp);
7679 *output_array_size = maccount;
7680 wifi_associated_dev3_t* temp = NULL;
7681 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7682 *associated_dev_array = temp;
7683 if(temp == NULL)
7684 {
7685 printf("Error Statement. Insufficient memory \n");
7686 return RETURN_ERR;
7687 }
7688 memset(buf,0,sizeof(buf));
7689 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7690 fp = popen(buf,"r");
7691 for(count = 0; count < maccount ; count++)
7692 {
7693 fgets(path,sizeof(path),fp);
7694 for(i = 0; path[i]!='\n';i++)
7695 str[i]=path[i];
7696 str[i]='\0';
7697 getIPAddress(str,ipaddr);
7698 memset(buf,0,sizeof(buf));
7699 if(strlen(ipaddr) > 0)
7700 {
7701 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7702 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7703 {
7704 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7705 {
7706 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7707 {
7708 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7709
7710 }
7711 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7712 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]);
7713 }
7714 temp[count].cli_AuthenticationState = 0; //TODO
7715 temp[count].cli_Active = 0; //TODO
7716 temp[count].cli_SignalStrength = 0;
7717 }
7718 else //Active wireless clients info
7719 {
7720 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7721 {
7722 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7723 {
7724 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7725
7726 }
7727 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7728 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]);
7729 }
7730 temp[count].cli_Active = 1;
7731 }
7732 }
7733 memset(ipaddr,0,sizeof(ipaddr));
7734 }
7735 pclose(fp);
7736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7737 return RETURN_OK;
7738}
7739//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7740//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7741//To get Band Steering Capability
7742INT wifi_getBandSteeringCapability(BOOL *support)
7743{
7744 *support = FALSE;
7745 return RETURN_OK;
7746}
7747
7748
7749//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7750//To get Band Steering enable status
7751INT wifi_getBandSteeringEnable(BOOL *enable)
7752{
7753 *enable = FALSE;
7754 return RETURN_OK;
7755}
7756
7757//To turn on/off Band steering
7758INT wifi_setBandSteeringEnable(BOOL enable)
7759{
7760 return RETURN_OK;
7761}
7762
7763//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7764//To get Band Steering AP group
7765INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7766{
7767 if (NULL == output_ApGroup)
7768 return RETURN_ERR;
7769
7770 strcpy(output_ApGroup, "1,2");
7771 return RETURN_OK;
7772}
7773
7774//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7775//to set and read the band steering BandUtilizationThreshold parameters
7776INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7777{
7778 return RETURN_ERR;
7779}
7780
7781INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7782{
7783 return RETURN_ERR;
7784}
7785
7786//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7787//to set and read the band steering RSSIThreshold parameters
7788INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7789{
7790 return RETURN_ERR;
7791}
7792
7793INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7794{
7795 return RETURN_ERR;
7796}
7797
7798
7799//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7800//to set and read the band steering physical modulation rate threshold parameters
7801INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7802{
7803 //If chip is not support, return -1
7804 return RETURN_ERR;
7805}
7806
7807INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7808{
7809 //If chip is not support, return -1
7810 return RETURN_ERR;
7811}
7812
7813//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7814//to set and read the inactivity time (in seconds) for steering under overload condition
7815INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7816{
7817 return RETURN_ERR;
7818}
7819
7820INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7821{
7822 return RETURN_ERR;
7823}
7824
7825//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7826//to set and read the inactivity time (in seconds) for steering under Idle condition
7827INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7828{
7829 return RETURN_ERR;
7830}
7831
7832INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7833{
7834 return RETURN_ERR;
7835}
7836
7837//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7838//pClientMAC[64]
7839//pSourceSSIDIndex[64]
7840//pDestSSIDIndex[64]
7841//pSteeringReason[256]
7842INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7843{
7844 //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
7845 *pSteeringTime=time(NULL);
7846 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7847 return RETURN_OK;
7848}
7849
7850INT wifi_ifConfigDown(INT apIndex)
7851{
7852 INT status = RETURN_OK;
7853 char cmd[64];
7854
7855 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7856 printf("%s: %s\n", __func__, cmd);
7857 system(cmd);
7858
7859 return status;
7860}
7861
7862INT wifi_ifConfigUp(INT apIndex)
7863{
7864 char cmd[128];
7865 char buf[1024];
7866
7867 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7868 _syscmd(cmd, buf, sizeof(buf));
7869 return 0;
7870}
7871
7872//>> Deprecated. Replace with wifi_applyRadioSettings
7873INT wifi_pushBridgeInfo(INT apIndex)
7874{
7875 char ip[32];
7876 char subnet[32];
7877 char bridge[32];
7878 int vlanId;
7879 char cmd[128];
7880 char buf[1024];
7881
7882 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7883 wifi_getApVlanID(apIndex,&vlanId);
7884
7885 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7886 _syscmd(cmd,buf, sizeof(buf));
7887
7888 return 0;
7889}
7890
7891INT wifi_pushChannel(INT radioIndex, UINT channel)
7892{
7893 char cmd[128];
7894 char buf[1024];
7895 int apIndex;
7896
7897 apIndex=(radioIndex==0)?0:1;
7898 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7899 _syscmd(cmd,buf, sizeof(buf));
7900
7901 return 0;
7902}
7903
7904INT wifi_pushChannelMode(INT radioIndex)
7905{
7906 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7907 return RETURN_ERR;
7908}
7909
7910INT wifi_pushDefaultValues(INT radioIndex)
7911{
7912 //Apply Comcast specified default radio settings instantly
7913 //AMPDU=1
7914 //AMPDUFrames=32
7915 //AMPDULim=50000
7916 //txqueuelen=1000
7917
7918 return RETURN_ERR;
7919}
7920
7921INT wifi_pushTxChainMask(INT radioIndex)
7922{
7923 //Apply default TxChainMask instantly
7924 return RETURN_ERR;
7925}
7926
7927INT wifi_pushRxChainMask(INT radioIndex)
7928{
7929 //Apply default RxChainMask instantly
7930 return RETURN_ERR;
7931}
7932
7933INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7934{
7935 INT status;
7936
7937 status = wifi_setSSIDName(apIndex,ssid);
7938 wifi_setApEnable(apIndex,FALSE);
7939 wifi_setApEnable(apIndex,TRUE);
7940
7941 return status;
7942}
7943
7944INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7945{
7946 //Apply default Ssid Advertisement instantly
7947 return RETURN_ERR;
7948}
7949
7950INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7951{
7952 INT status = RETURN_ERR;
7953 *output = 0;
7954 return RETURN_ERR;
7955}
7956
7957INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7958{
7959 return RETURN_OK;
7960}
7961
7962INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7963{
7964 return RETURN_OK;
7965}
7966
7967//To-do
7968INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7969{
developereb199ae2022-09-13 14:04:27 +08007970 char output[16]={'\0'};
7971 char config_file[MAX_BUF_SIZE] = {0};
7972
7973 if (!output_string)
7974 return RETURN_ERR;
7975
7976 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7977 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7978
7979 if (strlen(output) == 0)
7980 snprintf(output_string, 64, "Disabled");
7981 else if (strncmp(output, "0", 1) == 0)
7982 snprintf(output_string, 64, "Disabled");
7983 else if (strncmp(output, "1", 1) == 0)
7984 snprintf(output_string, 64, "Optional");
7985 else if (strncmp(output, "2", 1) == 0)
7986 snprintf(output_string, 64, "Required");
7987 else {
7988 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7989 return RETURN_ERR;
7990 }
7991
7992 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007993 return RETURN_OK;
7994}
7995INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7996{
developereb199ae2022-09-13 14:04:27 +08007997 char str[MAX_BUF_SIZE]={'\0'};
7998 char cmd[MAX_CMD_SIZE]={'\0'};
7999 struct params params;
8000 char config_file[MAX_BUF_SIZE] = {0};
8001
8002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8003 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8004 return RETURN_ERR;
8005
8006 params.name = "ieee80211w";
8007 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8008 params.value = "0";
8009 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8010 params.value = "1";
8011 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8012 params.value = "2";
8013 else{
8014 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8015 return RETURN_ERR;
8016 }
8017 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8018 wifi_hostapdWrite(config_file, &params, 1);
8019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008020 return RETURN_OK;
8021}
8022INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8023{
8024 char output[16]={'\0'};
8025 char config_file[MAX_BUF_SIZE] = {0};
8026
8027 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8028 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8029 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8030
8031 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8032 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8033
8034 return RETURN_OK;
8035}
8036
8037INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8038{
8039 return RETURN_OK;
8040}
8041
8042INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8043{
8044 return RETURN_OK;
8045}
8046
8047INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8048{
8049 return RETURN_OK;
8050}
8051
8052INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8053{
8054 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8055 char config_file[MAX_BUF_SIZE] = {0};
8056
8057 if (NULL == output)
8058 return RETURN_ERR;
8059 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8060 wifi_hostapdRead(config_file,"hw_mode",output,64);
8061
8062 if(strcmp(output,"b")==0)
8063 sprintf(output, "%s", "1,2,5.5,11");
8064 else if (strcmp(output,"a")==0)
8065 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8066 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8067 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8068
8069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8070 return RETURN_OK;
8071}
8072
8073INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8074{
8075 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8076 char *temp;
8077 char temp_output[128];
8078 char temp_TransmitRates[128];
8079 char config_file[MAX_BUF_SIZE] = {0};
8080
8081 if (NULL == output)
8082 return RETURN_ERR;
8083
8084 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8085 wifi_hostapdRead(config_file,"supported_rates",output,64);
8086
8087 strcpy(temp_TransmitRates,output);
8088 strcpy(temp_output,"");
8089 temp = strtok(temp_TransmitRates," ");
8090 while(temp!=NULL)
8091 {
8092 temp[strlen(temp)-1]=0;
8093 if((temp[0]=='5') && (temp[1]=='\0'))
8094 {
8095 temp="5.5";
8096 }
8097 strcat(temp_output,temp);
8098 temp = strtok(NULL," ");
8099 if(temp!=NULL)
8100 {
8101 strcat(temp_output,",");
8102 }
8103 }
8104 strcpy(output,temp_output);
8105 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8106
8107 return RETURN_OK;
8108}
8109
8110INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8111{
8112 return RETURN_OK;
8113}
8114
8115
8116INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8117{
8118 int i=0;
8119 char *temp;
developeref938762022-10-19 17:21:01 +08008120 char temp1[128] = {0};
8121 char temp_output[128] = {0};
8122 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008123 struct params params={'\0'};
8124 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008125 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008126
8127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8128 if(NULL == output)
8129 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008130 strcpy(temp_TransmitRates,output);
8131
8132 for(i=0;i<strlen(temp_TransmitRates);i++)
8133 {
developeref938762022-10-19 17:21:01 +08008134 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008135 {
8136 continue;
8137 }
8138 else
8139 {
8140 return RETURN_ERR;
8141 }
8142 }
8143 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008144 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008145 while(temp!=NULL)
8146 {
8147 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008148 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008149 {
developeref938762022-10-19 17:21:01 +08008150 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008151 {
8152 return RETURN_ERR;
8153 }
8154 }
8155
8156 if(strcmp(temp,"5.5")==0)
8157 {
8158 strcpy(temp1,"55");
8159 }
8160 else
8161 {
8162 strcat(temp1,"0");
8163 }
8164 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008165 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008166 if(temp!=NULL)
8167 {
8168 strcat(temp_output," ");
8169 }
8170 }
8171 strcpy(output,temp_output);
8172
developer06a01d92022-09-07 16:32:39 +08008173 params.name = "supported_rates";
8174 params.value = output;
8175
8176 wifi_dbg_printf("\n%s:",__func__);
8177 wifi_dbg_printf("params.value=%s\n",params.value);
8178 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8179 wifi_hostapdWrite(config_file,&params,1);
8180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8181
8182 return RETURN_OK;
8183}
8184
8185
8186static char *sncopy(char *dst, int dst_sz, const char *src)
8187{
8188 if (src && dst && dst_sz > 0) {
8189 strncpy(dst, src, dst_sz);
8190 dst[dst_sz - 1] = '\0';
8191 }
8192 return dst;
8193}
8194
8195static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8196{
8197 if (0 == strcmp(ht_mode, "HT40") ||
8198 0 == strcmp(ht_mode, "HT80") ||
8199 0 == strcmp(ht_mode, "HT160")) {
8200 switch (channel) {
8201 case 1 ... 7:
8202 case 36:
8203 case 44:
8204 case 52:
8205 case 60:
8206 case 100:
8207 case 108:
8208 case 116:
8209 case 124:
8210 case 132:
8211 case 140:
8212 case 149:
8213 case 157:
8214 return 1;
8215 case 8 ... 13:
8216 case 40:
8217 case 48:
8218 case 56:
8219 case 64:
8220 case 104:
8221 case 112:
8222 case 120:
8223 case 128:
8224 case 136:
8225 case 144:
8226 case 153:
8227 case 161:
8228 return -1;
8229 default:
8230 return -EINVAL;
8231 }
8232 }
8233
8234 return -EINVAL;
8235}
8236
developerb7593de2022-10-18 09:51:57 +08008237static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8238{
8239 int idx = channel%8;
8240 if (0 == strcmp(ht_mode, "HT40") ||
8241 0 == strcmp(ht_mode, "HT80") ||
8242 0 == strcmp(ht_mode, "HT160")) {
8243 switch (idx) {
8244 case 1:
8245 return 1;
8246 case 5:
8247 return -1;
8248 default:
8249 return -EINVAL;
8250 }
8251 }
8252
8253 return -EINVAL;
8254}
developer06a01d92022-09-07 16:32:39 +08008255static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8256{
8257 if (NULL == hw_mode) return;
8258
8259 if (0 == strcmp(hw_mode, "ac"))
8260 sncopy(bw_mode, bw_mode_len, "ht vht");
8261
8262 if (0 == strcmp(hw_mode, "n"))
8263 sncopy(bw_mode, bw_mode_len, "ht");
8264
8265 return;
8266}
8267
8268static int util_chan_to_freq(int chan)
8269{
8270 if (chan == 14)
8271 return 2484;
8272 else if (chan < 14)
8273 return 2407 + chan * 5;
8274 else if (chan >= 182 && chan <= 196)
8275 return 4000 + chan * 5;
8276 else
8277 return 5000 + chan * 5;
8278 return 0;
8279}
8280
developerb7593de2022-10-18 09:51:57 +08008281static int util_6G_chan_to_freq(int chan)
8282{
8283 if (chan)
8284 return 5950 + chan * 5;
8285 else
8286 return 0;
8287
8288}
developer06a01d92022-09-07 16:32:39 +08008289const int *util_unii_5g_chan2list(int chan, int width)
8290{
8291 static const int lists[] = {
8292 // <width>, <chan1>, <chan2>..., 0,
8293 20, 36, 0,
8294 20, 40, 0,
8295 20, 44, 0,
8296 20, 48, 0,
8297 20, 52, 0,
8298 20, 56, 0,
8299 20, 60, 0,
8300 20, 64, 0,
8301 20, 100, 0,
8302 20, 104, 0,
8303 20, 108, 0,
8304 20, 112, 0,
8305 20, 116, 0,
8306 20, 120, 0,
8307 20, 124, 0,
8308 20, 128, 0,
8309 20, 132, 0,
8310 20, 136, 0,
8311 20, 140, 0,
8312 20, 144, 0,
8313 20, 149, 0,
8314 20, 153, 0,
8315 20, 157, 0,
8316 20, 161, 0,
8317 20, 165, 0,
8318 40, 36, 40, 0,
8319 40, 44, 48, 0,
8320 40, 52, 56, 0,
8321 40, 60, 64, 0,
8322 40, 100, 104, 0,
8323 40, 108, 112, 0,
8324 40, 116, 120, 0,
8325 40, 124, 128, 0,
8326 40, 132, 136, 0,
8327 40, 140, 144, 0,
8328 40, 149, 153, 0,
8329 40, 157, 161, 0,
8330 80, 36, 40, 44, 48, 0,
8331 80, 52, 56, 60, 64, 0,
8332 80, 100, 104, 108, 112, 0,
8333 80, 116, 120, 124, 128, 0,
8334 80, 132, 136, 140, 144, 0,
8335 80, 149, 153, 157, 161, 0,
8336 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8337 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8338 -1 // final delimiter
8339 };
8340 const int *start;
8341 const int *p;
8342
8343 for (p = lists; *p != -1; p++) {
8344 if (*p == width) {
8345 for (start = ++p; *p != 0; p++) {
8346 if (*p == chan)
8347 return start;
8348 }
8349 }
8350 // move to the end of channel list of given width
8351 while (*p != 0) {
8352 p++;
8353 }
8354 }
8355
8356 return NULL;
8357}
8358
8359static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8360{
8361 if (NULL == ht_mode)
8362 return 0;
8363
8364 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8365 const int *chans = util_unii_5g_chan2list(channel, width);
8366 int sum = 0;
8367 int cnt = 0;
8368
8369 if (NULL == chans)
8370 return 0;
8371
8372 while (*chans) {
8373 sum += *chans;
8374 cnt++;
8375 chans++;
8376 }
8377 return sum / cnt;
8378}
8379
developerb7593de2022-10-18 09:51:57 +08008380static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8381{
8382 if (NULL == ht_mode)
8383 return 0;
8384
8385 int width = strtol((ht_mode + 2), NULL, 10);
8386
8387 int idx = 0 ;
8388 int centerchan = 0;
8389 int chan_ofs = 1;
8390
8391 if (width == 40){
8392 idx = ((channel/4) + chan_ofs)%2;
8393 switch (idx) {
8394 case 0:
8395 centerchan = (channel - 2);
8396 break;
8397 case 1:
8398 centerchan = (channel + 2);
8399 break;
8400 default:
8401 return -EINVAL;
8402 }
8403 }else if (width == 80){
8404 idx = ((channel/4) + chan_ofs)%4;
8405 switch (idx) {
8406 case 0:
8407 centerchan = (channel - 6);
8408 break;
8409 case 1:
8410 centerchan = (channel + 6);
8411 break;
8412 case 2:
8413 centerchan = (channel + 2);
8414 break;
8415 case 3:
8416 centerchan = (channel - 2);
8417 break;
8418 default:
8419 return -EINVAL;
8420 }
8421 }else if (width == 160){
8422 switch (channel) {
8423 case 1 ... 29:
8424 centerchan = 15;
8425 break;
8426 case 33 ... 61:
8427 centerchan = 47;
8428 break;
8429 case 65 ... 93:
8430 centerchan = 79;
8431 break;
8432 case 97 ... 125:
8433 centerchan = 111;
8434 break;
8435 case 129 ... 157:
8436 centerchan = 143;
8437 break;
8438 case 161 ... 189:
8439 centerchan = 175;
8440 break;
8441 case 193 ... 221:
8442 centerchan = 207;
8443 break;
8444 default:
8445 return -EINVAL;
8446 }
8447 }
8448 return centerchan;
8449}
developer06a01d92022-09-07 16:32:39 +08008450static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8451{
8452 BOOL onlyG, onlyN, onlyA;
8453 CHAR tmp[64];
8454 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8455 if (ret == RETURN_OK) {
8456 sncopy(hw_mode, hw_mode_size, tmp);
8457 }
8458 return ret;
8459}
8460
8461INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8462{
8463 // Sample commands:
8464 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8465 // hostapd_cli -i wifi0 chan_switch 30 2437
8466 char cmd[MAX_CMD_SIZE] = {0};
8467 char buf[MAX_BUF_SIZE] = {0};
8468 int freq = 0, ret = 0;
8469 char center_freq1_str[32] = ""; // center_freq1=%d
8470 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8471 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8472 char hw_mode[16] = ""; // n|ac
8473 char bw_mode[16] = ""; // ht|ht vht
8474 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8475 int sec_chan_offset;
8476 int width;
developer4fb0b922022-09-30 14:29:09 +08008477 char config_file[64] = {0};
8478 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008479 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008480 wifi_band band = band_invalid;
8481 int center_chan = 0;
8482 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008483
developer4fb0b922022-09-30 14:29:09 +08008484 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008485
8486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8487
developerb7593de2022-10-18 09:51:57 +08008488 band = wifi_index_to_band(radioIndex);
8489
developer5884e982022-10-06 10:52:50 +08008490 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008491
8492 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008493 if (channel){
developerb7593de2022-10-18 09:51:57 +08008494 if (band == band_6){
8495 freq = util_6G_chan_to_freq(channel);
8496 }else{
8497 freq = util_chan_to_freq(channel);
8498 }
developer5884e982022-10-06 10:52:50 +08008499 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008500
developer5884e982022-10-06 10:52:50 +08008501 // Provide bandwith if specified
8502 if (channel_width_MHz > 20) {
8503 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8504 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8505 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008506
developer5884e982022-10-06 10:52:50 +08008507 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8508 }else if (channel_width_MHz == 20){
8509 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8510 }
developer06a01d92022-09-07 16:32:39 +08008511
developerb7593de2022-10-18 09:51:57 +08008512
developer5884e982022-10-06 10:52:50 +08008513 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008514 if (band == band_6){
8515 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8516 if(center_chan){
8517 center_freq1 = util_6G_chan_to_freq(center_chan);
8518 }
8519 }else{
8520 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8521 if(center_chan){
8522 center_freq1 = util_chan_to_freq(center_chan);
8523 }
developer5884e982022-10-06 10:52:50 +08008524 }
developerb7593de2022-10-18 09:51:57 +08008525
8526 if (center_freq1)
8527 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8528
8529 }
8530
8531 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8532 if (band == band_6){
8533 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8534 }else{
8535 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008536 }
developerb7593de2022-10-18 09:51:57 +08008537 if (sec_chan_offset != -EINVAL)
8538 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008539
developer5884e982022-10-06 10:52:50 +08008540 // Only the first AP, other are hanging on the same radio
8541 int apIndex = radioIndex;
8542 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8543 AP_PREFIX, apIndex, csa_beacon_count, freq,
8544 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8545 wifi_dbg_printf("execute: '%s'\n", cmd);
8546 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008547
developer5884e982022-10-06 10:52:50 +08008548 ret = wifi_setRadioChannel(radioIndex, channel);
8549 if (ret != RETURN_OK) {
8550 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8551 return RETURN_ERR;
8552 }
8553
8554 if (sec_chan_offset == 1) ext_str = "Above";
8555 else if (sec_chan_offset == -1) ext_str = "Below";
8556
8557 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008558
developer5884e982022-10-06 10:52:50 +08008559 } else {
8560 if (channel_width_MHz > 20)
8561 ext_str = "Above";
8562 }
developer4fb0b922022-09-30 14:29:09 +08008563 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8564 _syscmd(cmd, buf, sizeof(buf));
8565 if (strlen(buf) != 0)
8566 stbcEnable = TRUE;
8567
developer06a01d92022-09-07 16:32:39 +08008568 wifi_setRadioExtChannel(radioIndex, ext_str);
8569
developer4fb0b922022-09-30 14:29:09 +08008570 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8571
developer06a01d92022-09-07 16:32:39 +08008572 char mhz_str[16];
8573 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8574 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8575
8576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8577
8578 return RETURN_OK;
8579}
8580
8581INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8582{
developer615510b2022-09-27 10:14:35 +08008583 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008584 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008585 char cmd[256]={0};
8586 char buf[128]={0};
8587 char file_name[32] = {0};
8588 char filter_SSID[32] = {0};
8589 char line[256] = {0};
8590 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008591 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008592 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008593 size_t len=0;
8594 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008595 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008596 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008597 bool filter_enable = false;
8598 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008599 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008600
developer615510b2022-09-27 10:14:35 +08008601 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008602
developer615510b2022-09-27 10:14:35 +08008603 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8604 f = fopen(file_name, "r");
8605 if (f != NULL) {
8606 fgets(filter_SSID, sizeof(file_name), f);
8607 if (strlen(filter_SSID) != 0)
8608 filter_enable = true;
8609 fclose(f);
8610 }
8611
developer033b37b2022-10-18 11:27:46 +08008612 phyId = radio_index_to_phy(radio_index);
8613
8614 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008615 _syscmd(cmd, buf, sizeof(buf));
8616 channels_num = strtol(buf, NULL, 10);
8617
developer615510b2022-09-27 10:14:35 +08008618 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8619 // 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);
8620 fprintf(stderr, "cmd: %s\n", cmd);
8621 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008622 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8623 return RETURN_ERR;
8624 }
developer5550e242022-09-30 09:59:32 +08008625
8626 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8627 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8628
developer615510b2022-09-27 10:14:35 +08008629 ret = fgets(line, sizeof(line), f);
8630 while (ret != NULL) {
8631 if(strstr(line, "BSS") != NULL) { // new neighbor info
8632 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8633 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8634 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8635
8636 if (!filter_BSS) {
8637 index++;
8638 wifi_neighbor_ap2_t *tmp;
8639 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8640 if (tmp == NULL) { // no more memory to use
8641 index--;
8642 wifi_dbg_printf("%s: realloc failed\n", __func__);
8643 break;
8644 }
8645 scan_array = tmp;
8646 }
8647 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008648
developer615510b2022-09-27 10:14:35 +08008649 filter_BSS = false;
8650 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8651 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8652 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8653 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8654 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008655 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008656 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008657
developer615510b2022-09-27 10:14:35 +08008658 if (freq >= 2412 && freq <= 2484) {
8659 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8660 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8661 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8662 }
8663 else if (freq >= 5160 && freq <= 5805) {
8664 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8665 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8666 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8667 }
developer06a01d92022-09-07 16:32:39 +08008668
developer615510b2022-09-27 10:14:35 +08008669 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008670 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008671 for (int i = 0; i < channels_num; i++) {
8672 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8673 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8674 break;
8675 }
8676 }
developer06a01d92022-09-07 16:32:39 +08008677 }
developer615510b2022-09-27 10:14:35 +08008678 } else if (strstr(line, "beacon interval") != NULL) {
8679 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8680 } else if (strstr(line, "signal") != NULL) {
8681 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8682 } else if (strstr(line,"SSID") != NULL) {
8683 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8684 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8685 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008686 }
developer615510b2022-09-27 10:14:35 +08008687 } else if (strstr(line, "Supported rates") != NULL) {
8688 char SRate[80] = {0}, *tmp = NULL;
8689 memset(buf, 0, sizeof(buf));
8690 strcpy(SRate, line);
8691 tmp = strtok(SRate, ":");
8692 tmp = strtok(NULL, ":");
8693 strcpy(buf, tmp);
8694 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008695
developer615510b2022-09-27 10:14:35 +08008696 tmp = strtok(buf, " \n");
8697 while (tmp != NULL) {
8698 strcat(SRate, tmp);
8699 if (SRate[strlen(SRate) - 1] == '*') {
8700 SRate[strlen(SRate) - 1] = '\0';
8701 }
8702 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008703
developer615510b2022-09-27 10:14:35 +08008704 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008705 }
developer615510b2022-09-27 10:14:35 +08008706 SRate[strlen(SRate) - 1] = '\0';
8707 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8708 } else if (strstr(line, "DTIM") != NULL) {
8709 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8710 } else if (strstr(line, "VHT capabilities") != NULL) {
8711 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8712 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8713 } else if (strstr(line, "HT capabilities") != NULL) {
8714 strcat(scan_array[index].ap_SupportedStandards, ",n");
8715 strcpy(scan_array[index].ap_OperatingStandards, "n");
8716 } else if (strstr(line, "VHT operation") != NULL) {
8717 ret = fgets(line, sizeof(line), f);
8718 sscanf(line," * channel width: %d", &vht_channel_width);
8719 if(vht_channel_width == 1) {
8720 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8721 } else {
8722 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8723 }
8724 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8725 continue;
8726 } else if (strstr(line, "HT operation") != NULL) {
8727 ret = fgets(line, sizeof(line), f);
8728 sscanf(line," * secondary channel offset: %s", &buf);
8729 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008730 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008731 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 +08008732 }
developer615510b2022-09-27 10:14:35 +08008733 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008734 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008735 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8736 } else {
8737 //20Mhz
8738 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 +08008739 }
developer615510b2022-09-27 10:14:35 +08008740 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008741 continue;
developer615510b2022-09-27 10:14:35 +08008742 } else if (strstr(line, "HE capabilities") != NULL) {
8743 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8744 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8745 ret = fgets(line, sizeof(line), f);
8746 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8747 if (strstr(line, "HE40/2.4GHz") != NULL)
8748 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8749 else
8750 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8751 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8752 if (strstr(line, "HE80/5GHz") != NULL) {
8753 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8754 ret = fgets(line, sizeof(line), f);
8755 } else
8756 continue;
8757 if (strstr(line, "HE160/5GHz") != NULL)
8758 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008759 }
developer615510b2022-09-27 10:14:35 +08008760 continue;
8761 } else if (strstr(line, "WPA") != NULL) {
8762 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8763 } else if (strstr(line, "RSN") != NULL) {
8764 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8765 } else if (strstr(line, "Group cipher") != NULL) {
8766 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8767 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8768 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008769 }
developer06a01d92022-09-07 16:32:39 +08008770 }
developer615510b2022-09-27 10:14:35 +08008771 ret = fgets(line, sizeof(line), f);
8772 }
8773
8774 if (!filter_BSS) {
8775 *output_array_size = index + 1;
8776 } else {
8777 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8778 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008779 }
developer06a01d92022-09-07 16:32:39 +08008780 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008781 pclose(f);
developer5550e242022-09-30 09:59:32 +08008782 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008784 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008785}
developer615510b2022-09-27 10:14:35 +08008786
developer06a01d92022-09-07 16:32:39 +08008787INT wifi_getApAssociatedDeviceStats(
8788 INT apIndex,
8789 mac_address_t *clientMacAddress,
8790 wifi_associated_dev_stats_t *associated_dev_stats,
8791 u64 *handle)
8792{
8793 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8794 char interface_name[50] = {0};
8795 char cmd[1024] = {0};
8796 char mac_str[18] = {0};
8797 char *key = NULL;
8798 char *val = NULL;
8799 FILE *f = NULL;
8800 char *line = NULL;
8801 size_t len = 0;
8802 ssize_t read = 0;
8803
8804 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8805 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8806 return RETURN_ERR;
8807 }
8808
8809 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8810 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8811 if((f = popen(cmd, "r")) == NULL) {
8812 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8813 return RETURN_ERR;
8814 }
8815
8816 while ((read = getline(&line, &len, f)) != -1) {
8817 key = strtok(line,":");
8818 val = strtok(NULL,":");
8819
8820 if(!strncmp(key,"rx bytes",8))
8821 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8822 if(!strncmp(key,"tx bytes",8))
8823 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8824 if(!strncmp(key,"rx packets",10))
8825 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8826 if(!strncmp(key,"tx packets",10))
8827 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8828 if(!strncmp(key,"tx retries",10))
8829 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8830 if(!strncmp(key,"tx failed",9))
8831 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8832 if(!strncmp(key,"rx drop misc",13))
8833 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8834 if(!strncmp(key,"rx bitrate",10)) {
8835 val = strtok(val, " ");
8836 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8837 }
8838 if(!strncmp(key,"tx bitrate",10)) {
8839 val = strtok(val, " ");
8840 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8841 }
8842 }
8843 free(line);
8844 pclose(f);
8845 return RETURN_OK;
8846}
8847
8848INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8849{
8850 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8851
8852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8853 if (NULL == output_string)
8854 return RETURN_ERR;
8855
8856 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8857 _syscmd(cmd, buf, sizeof(buf));
8858
8859 //size of SSID name restricted to value less than 32 bytes
8860 snprintf(output_string, 32, "%s", buf);
8861 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8862
8863 return RETURN_OK;
8864}
8865
8866INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8867{
8868 //char cmd[MAX_CMD_SIZE] = {0};
8869 char config_file[MAX_BUF_SIZE] = {0};
8870 char buf[32] = {0};
8871
8872 if (!output_filterMode)
8873 return RETURN_ERR;
8874
8875 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8876 //_syscmd(cmd, buf, sizeof(buf));
8877 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8878 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008879 if(strlen(buf) == 0) {
8880 *output_filterMode = 0;
8881 }
8882 else {
8883 int macaddr_acl_mode = strtol(buf, NULL, 10);
8884 if (macaddr_acl_mode == 1) {
8885 *output_filterMode = 1;
8886 } else if (macaddr_acl_mode == 0) {
8887 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8888 if (strlen(buf) == 0) {
8889 *output_filterMode = 0;
8890 } else {
8891 *output_filterMode = 2;
8892 }
8893 } else {
8894 return RETURN_ERR;
8895 }
8896 }
developer06a01d92022-09-07 16:32:39 +08008897
8898 return RETURN_OK;
8899}
8900
8901INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8902{
8903 FILE *fp = NULL;
8904 char str[MAX_BUF_SIZE] = {0};
8905 int wificlientindex = 0 ;
8906 int count = 0;
8907 int signalstrength = 0;
8908 int arr[MACADDRESS_SIZE] = {0};
8909 unsigned char mac[MACADDRESS_SIZE] = {0};
8910 UINT wifi_count = 0;
8911 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8912 char pipeCmd[MAX_CMD_SIZE] = {0};
8913
8914 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8915 *output_array_size = 0;
8916 *associated_dev_array = NULL;
8917 char interface_name[50] = {0};
8918
8919 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8920 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8921 return RETURN_ERR;
8922 }
8923
8924 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8925 fp = popen(pipeCmd, "r");
8926 if (fp == NULL)
8927 {
8928 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8929 return RETURN_ERR;
8930 }
8931
8932 /* Read the output a line at a time - output it. */
8933 fgets(str, sizeof(str)-1, fp);
8934 wifi_count = (unsigned int) atoi ( str );
8935 *output_array_size = wifi_count;
8936 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8937 pclose(fp);
8938
8939 if(wifi_count == 0)
8940 {
8941 return RETURN_OK;
8942 }
8943 else
8944 {
8945 wifi_associated_dev2_t* temp = NULL;
8946 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8947 *associated_dev_array = temp;
8948 if(temp == NULL)
8949 {
8950 printf("Error Statement. Insufficient memory \n");
8951 return RETURN_ERR;
8952 }
8953
8954 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8955 system(pipeCmd);
8956
8957 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8958 if(fp == NULL)
8959 {
8960 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8961 return RETURN_ERR;
8962 }
8963 fclose(fp);
8964
8965 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8966 fp = popen(pipeCmd, "r");
8967 if(fp)
8968 {
8969 for(count =0 ; count < wifi_count; count++)
8970 {
8971 fgets(str, MAX_BUF_SIZE, fp);
8972 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8973 {
8974 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8975 {
8976 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8977
8978 }
8979 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8980 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]);
8981 }
8982 temp[count].cli_AuthenticationState = 1; //TODO
8983 temp[count].cli_Active = 1; //TODO
8984 }
8985 pclose(fp);
8986 }
8987
8988 //Updating RSSI per client
8989 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8990 fp = popen(pipeCmd, "r");
8991 if(fp)
8992 {
8993 pclose(fp);
8994 }
8995 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8996 if(fp)
8997 {
8998 for(count =0 ; count < wifi_count ;count++)
8999 {
9000 fgets(str, MAX_BUF_SIZE, fp);
9001 signalstrength = atoi(str);
9002 temp[count].cli_RSSI = signalstrength;
9003 }
9004 pclose(fp);
9005 }
9006
9007
9008 //LastDataDownlinkRate
9009 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
9010 fp = popen(pipeCmd, "r");
9011 if (fp)
9012 {
9013 pclose(fp);
9014 }
9015 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9016 if (fp)
9017 {
9018 for (count = 0; count < wifi_count; count++)
9019 {
9020 fgets(str, MAX_BUF_SIZE, fp);
9021 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9022 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9023 }
9024 pclose(fp);
9025 }
9026
9027 //LastDataUplinkRate
9028 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
9029 fp = popen(pipeCmd, "r");
9030 if (fp)
9031 {
9032 pclose(fp);
9033 }
9034 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9035 if (fp)
9036 {
9037 for (count = 0; count < wifi_count; count++)
9038 {
9039 fgets(str, MAX_BUF_SIZE, fp);
9040 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9041 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9042 }
9043 pclose(fp);
9044 }
9045 }
9046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9047 return RETURN_OK;
9048
9049}
9050
9051INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9052{
9053#if 0
9054 /*char buf[1024] = {0};
9055 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
9056 _syscmd(cmd, buf, sizeof(buf));*/
9057
9058 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9059 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9060 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9061 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9062
9063 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.
9064 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].
9065 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].
9066 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].
9067 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9068 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9069
9070 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9071 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9072 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9073 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.
9074 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.
9075 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.
9076 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.
9077 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.
9078 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.
9079 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.
9080 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9081#endif
9082
9083 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08009084 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08009085 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009086 char pipeCmd[128] = {0};
9087 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009088 wifi_ssidTrafficStats2_t *out = output_struct;
9089
developerce736392022-09-13 15:24:34 +08009090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009091 if (!output_struct)
9092 return RETURN_ERR;
9093
developerce736392022-09-13 15:24:34 +08009094 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9095 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
9096 GetInterfaceName(interface_name, HConf_file);
9097 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009098
developer06a01d92022-09-07 16:32:39 +08009099 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009100 if (fp == NULL) {
9101 fprintf(stderr, "%s: popen failed\n", __func__);
9102 return RETURN_ERR;
9103 }
9104 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08009105
developerce736392022-09-13 15:24:34 +08009106 if (strlen(str) == 0) // interface not exist
9107 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009108
developerce736392022-09-13 15:24:34 +08009109 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9110 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009111 pclose(fp);
9112
developerce736392022-09-13 15:24:34 +08009113 memset(str, 0, sizeof(str));
9114 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009115 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009116 if (fp == NULL) {
9117 fprintf(stderr, "%s: popen failed\n", __func__);
9118 return RETURN_ERR;
9119 }
9120 fgets(str, sizeof(str), fp);
9121
9122 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9123 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009124 pclose(fp);
developerce736392022-09-13 15:24:34 +08009125
9126 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9127 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9128
9129 // Not supported
9130 output_struct->ssid_RetransCount = 0;
9131 output_struct->ssid_FailedRetransCount = 0;
9132 output_struct->ssid_RetryCount = 0;
9133 output_struct->ssid_MultipleRetryCount = 0;
9134 output_struct->ssid_ACKFailureCount = 0;
9135 output_struct->ssid_AggregatedPacketCount = 0;
9136
developer06a01d92022-09-07 16:32:39 +08009137 return RETURN_OK;
9138}
9139
9140//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).
9141INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9142{
9143 char output_val[16]={'\0'};
9144 char config_file[MAX_BUF_SIZE] = {0};
9145
9146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9147 if (!output)
9148 return RETURN_ERR;
9149 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9150 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9151
9152 if( strcmp(output_val,"1") == 0 )
9153 *output = TRUE;
9154 else
9155 *output = FALSE;
9156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9157
9158 return RETURN_OK;
9159}
9160
9161INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9162{
9163 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9164 char str[MAX_BUF_SIZE]={'\0'};
9165 char string[MAX_BUF_SIZE]={'\0'};
9166 char cmd[MAX_CMD_SIZE]={'\0'};
9167 char *ch;
9168 char config_file[MAX_BUF_SIZE] = {0};
9169 struct params params;
9170
9171 if(enable == TRUE)
9172 strcpy(string,"1");
9173 else
9174 strcpy(string,"0");
9175
9176 params.name = "ap_isolate";
9177 params.value = string;
9178
9179 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9180 wifi_hostapdWrite(config_file,&params,1);
9181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9182
9183 return RETURN_OK;
9184}
9185
9186INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9187{
9188 if (NULL == output_dBm)
9189 return RETURN_ERR;
9190
9191 *output_dBm = 0;
9192 return RETURN_OK;
9193}
9194
9195INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9196{
9197 return RETURN_OK;
9198}
9199INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9200{
9201 return RETURN_OK;
9202}
9203INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9204{
9205 return RETURN_OK;
9206}
9207INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9208{
9209 return RETURN_OK;
9210}
9211INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9212{
9213 return RETURN_OK;
9214}
9215INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9216{
9217 char config_file[MAX_BUF_SIZE] = {0};
9218 struct params list;
9219
9220 list.name = "bss_transition";
9221 list.value = activate?"1":"0";
9222 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9223 wifi_hostapdWrite(config_file, &list, 1);
9224
9225 return RETURN_OK;
9226}
9227wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9228
9229void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9230{
9231 return;
9232}
9233
9234INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9235{
9236 // TODO Implement me!
9237 return RETURN_OK;
9238}
9239
9240INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9241{
developera3c68b92022-09-13 15:27:29 +08009242 char file_name[128] = {0};
9243 char buf[128] = {0};
9244 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009245 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009246
9247 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9248
developer804c64f2022-10-19 13:54:40 +08009249 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009250 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009251 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009252 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9253 f = fopen(file_name, "w");
9254 if (f == NULL)
9255 return RETURN_ERR;
9256 // For mode == 0 is to disable filter, just don't write to the file.
9257 if (mode)
9258 fprintf(f, "%s", essid);
9259
9260 fclose(f);
9261 }
9262 } else { // special case, need to set AP's SSID as filter for each radio.
9263 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9264 f = fopen(file_name, "w");
9265 if (f == NULL)
9266 return RETURN_ERR;
9267
9268 // For mode == 0 is to disable filter, just don't write to the file.
9269 if (mode)
9270 fprintf(f, "%s", essid);
9271
9272 fclose(f);
9273 }
9274
9275 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009276 return RETURN_OK;
9277}
9278
9279INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9280{
9281 // TODO Implement me!
9282 //Apply wifi_pushRadioChannel() instantly
9283 return RETURN_ERR;
9284}
9285
9286INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9287{
9288 // TODO Implement me!
9289 return RETURN_OK;
9290}
9291
9292#ifdef HAL_NETLINK_IMPL
9293static int tidStats_callback(struct nl_msg *msg, void *arg) {
9294 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9295 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9296 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9297 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9298 int rem , tid_index = 0;
9299
9300 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9301 wifi_associated_dev_tid_entry_t *stats_entry;
9302
9303 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9304 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9305 };
9306 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9307 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9308 };
9309
9310 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9311 genlmsg_attrlen(gnlh, 0), NULL);
9312
9313
9314 if (!tb[NL80211_ATTR_STA_INFO]) {
9315 fprintf(stderr, "station stats missing!\n");
9316 return NL_SKIP;
9317 }
9318
9319 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9320 tb[NL80211_ATTR_STA_INFO],
9321 stats_policy)) {
9322 fprintf(stderr, "failed to parse nested attributes!\n");
9323 return NL_SKIP;
9324 }
9325
9326 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9327 {
9328 stats_entry = &out->tid_array[tid_index];
9329
9330 stats_entry->tid = tid_index;
9331 stats_entry->ac = _tid_ac_index_get[tid_index];
9332
9333 if(sinfo[NL80211_STA_INFO_TID_STATS])
9334 {
9335 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9336 printf("failed to parse nested stats attributes!");
9337 return NL_SKIP;
9338 }
9339 }
9340 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9341 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9342
9343 if(tid_index < (PS_MAX_TID - 1))
9344 tid_index++;
9345 }
9346 //ToDo: sum_time_ms, ewma_time_ms
9347 return NL_SKIP;
9348}
9349#endif
9350
9351INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9352{
9353#ifdef HAL_NETLINK_IMPL
9354 Netlink nl;
9355 char if_name[10];
9356
9357 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9358
9359 nl.id = initSock80211(&nl);
9360
9361 if (nl.id < 0) {
9362 fprintf(stderr, "Error initializing netlink \n");
9363 return -1;
9364 }
9365
9366 struct nl_msg* msg = nlmsg_alloc();
9367
9368 if (!msg) {
9369 fprintf(stderr, "Failed to allocate netlink message.\n");
9370 nlfree(&nl);
9371 return -2;
9372 }
9373
9374 genlmsg_put(msg,
9375 NL_AUTO_PORT,
9376 NL_AUTO_SEQ,
9377 nl.id,
9378 0,
9379 0,
9380 NL80211_CMD_GET_STATION,
9381 0);
9382
9383 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9384 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9385 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9386 nl_send_auto(nl.socket, msg);
9387 nl_recvmsgs(nl.socket, nl.cb);
9388 nlmsg_free(msg);
9389 nlfree(&nl);
9390 return RETURN_OK;
9391#else
9392//iw implementation
9393#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9394#define TOTAL_MAX_LINES 50
9395
9396 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9397 char if_name[10];
9398 FILE *fp=NULL;
9399 char pipeCmd[1024]= {'\0'};
9400 int lines,tid_index=0;
9401 char mac_addr[20] = {'\0'};
9402
9403 wifi_associated_dev_tid_entry_t *stats_entry;
9404
9405 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9406 strcpy(mac_addr,clientMacAddress);
9407
9408 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9409 fp= popen(pipeCmd,"r");
9410 if(fp == NULL)
9411 {
9412 perror("popen for station dump failed\n");
9413 return RETURN_ERR;
9414 }
9415 pclose(fp);
9416
9417 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9418 fp=popen(pipeCmd,"r");
9419 if(fp == NULL)
9420 {
9421 perror("popen for grep station failed\n");
9422 return RETURN_ERR;
9423 }
9424 else if(fgets(buf,sizeof(buf),fp) != NULL)
9425 lines=atoi(buf);
9426 else
9427 {
9428 pclose(fp);
9429 fprintf(stderr,"No devices are connected \n");
9430 return RETURN_ERR;
9431 }
9432 pclose(fp);
9433
9434 if(lines == 1)
9435 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9436
9437 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9438 {
9439 stats_entry = &tid_stats->tid_array[tid_index];
9440 stats_entry->tid = tid_index;
9441
9442 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);
9443
9444 fp=popen(pipeCmd,"r");
9445 if(fp ==NULL)
9446 {
9447 perror("Failed to read from tid file \n");
9448 return RETURN_ERR;
9449 }
9450 else if(fgets(buf,sizeof(buf),fp) != NULL)
9451 stats_entry->num_msdus = atol(buf);
9452
9453 pclose(fp);
9454 stats_entry->ac = _tid_ac_index_get[tid_index];
9455// TODO:
9456// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9457// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9458 }
9459 return RETURN_OK;
9460#endif
9461}
9462
9463
9464INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9465{
developer615510b2022-09-27 10:14:35 +08009466 char cmd[128]={0};
9467 char buf[128]={0};
9468 int freq = 0;
9469
9470 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9471
9472 // full mode is used to scan all channels.
9473 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9474 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9475 ieee80211_channel_to_frequency(chan_list[0], &freq);
9476
9477 if (freq)
9478 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9479 else
9480 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9481
9482 _syscmd(cmd, buf, sizeof(buf));
9483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9484
developer06a01d92022-09-07 16:32:39 +08009485 return RETURN_OK;
9486}
9487
9488
9489INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9490{
9491 // TODO Implement me!
9492 return RETURN_ERR;
9493}
9494
9495INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9496{
9497 // TODO Implement me!
9498 return RETURN_ERR;
9499}
9500
9501INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9502{
9503 // TODO Implement me!
9504 return RETURN_ERR;
9505}
9506
9507INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9508{
9509 // TODO Implement me!
9510 return RETURN_ERR;
9511}
9512
9513INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9514{
9515 // TODO Implement me!
9516 return RETURN_ERR;
9517}
9518
9519INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9520{
9521 // TODO Implement me!
9522 return RETURN_ERR;
9523}
9524
9525INT wifi_steering_eventUnregister(void)
9526{
9527 // TODO Implement me!
9528 return RETURN_ERR;
9529}
9530
9531INT wifi_delApAclDevices(INT apIndex)
9532{
9533#if 0
9534 char cmd[MAX_BUF_SIZE] = {0};
9535 char buf[MAX_BUF_SIZE] = {0};
9536
9537 /* Not reset proof solution */
9538 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9539 if(_syscmd(cmd,buf,sizeof(buf)))
9540 return RETURN_ERR;
9541#endif
developere6aafda2022-09-13 14:59:28 +08009542 char cmd[MAX_CMD_SIZE]={0};
9543 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009544
developere6aafda2022-09-13 14:59:28 +08009545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9546 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9547 if(_syscmd(cmd, buf, sizeof(buf)))
9548 return RETURN_ERR;
9549 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009550
9551 return RETURN_OK;
9552}
9553
9554#ifdef HAL_NETLINK_IMPL
9555static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9556 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9557 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9558 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9559 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9560 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9561 char mac_addr[20],dev[20];
9562
9563 nla_parse(tb,
9564 NL80211_ATTR_MAX,
9565 genlmsg_attrdata(gnlh, 0),
9566 genlmsg_attrlen(gnlh, 0),
9567 NULL);
9568
9569 if(!tb[NL80211_ATTR_STA_INFO]) {
9570 fprintf(stderr, "sta stats missing!\n");
9571 return NL_SKIP;
9572 }
9573
9574 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9575 fprintf(stderr, "failed to parse nested attributes!\n");
9576 return NL_SKIP;
9577 }
9578 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9579
9580 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9581
9582 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9583 fprintf(stderr, "failed to parse nested rate attributes!");
9584 return NL_SKIP;
9585 }
9586
9587 if(sinfo[NL80211_STA_INFO_TID_STATS])
9588 {
9589 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9590 printf("failed to parse nested stats attributes!");
9591 return NL_SKIP;
9592 }
9593 }
9594
9595 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9596 {
9597 printf("Type is VHT\n");
9598 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9599 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9600
9601 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9602 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9603 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9604 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9605 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9606 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9607 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9608 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9609 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9610 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9611 }
9612 else
9613 {
9614 printf(" OFDM or CCK \n");
9615 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9616 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9617 }
9618
9619 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9620 if(rinfo[NL80211_RATE_INFO_MCS])
9621 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9622 }
9623 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9624 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9625 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9626 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9627
9628 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9629 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9630
9631 if (sinfo[NL80211_STA_INFO_SIGNAL])
9632 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9633 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9634 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9635 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9636 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9637 //rssi_array need to be filled
9638 return NL_SKIP;
9639}
9640#endif
9641
9642INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9643{
9644#ifdef HAL_NETLINK_IMPL
9645 Netlink nl;
9646 char if_name[10];
9647
9648 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9649
9650 if (*output_array_size <= 0)
9651 return RETURN_OK;
9652
9653 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9654 nl.id = initSock80211(&nl);
9655
9656 if (nl.id < 0) {
9657 fprintf(stderr, "Error initializing netlink \n");
9658 return 0;
9659 }
9660
9661 struct nl_msg* msg = nlmsg_alloc();
9662
9663 if (!msg) {
9664 fprintf(stderr, "Failed to allocate netlink message.\n");
9665 nlfree(&nl);
9666 return 0;
9667 }
9668
9669 genlmsg_put(msg,
9670 NL_AUTO_PORT,
9671 NL_AUTO_SEQ,
9672 nl.id,
9673 0,
9674 0,
9675 NL80211_CMD_GET_STATION,
9676 0);
9677
9678 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9679 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9680 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9681 nl_send_auto(nl.socket, msg);
9682 nl_recvmsgs(nl.socket, nl.cb);
9683 nlmsg_free(msg);
9684 nlfree(&nl);
9685 return RETURN_OK;
9686#else
9687 //TODO Implement me
9688 return RETURN_OK;
9689#endif
9690}
9691
9692#ifdef HAL_NETLINK_IMPL
9693static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9694 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9695 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9696 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9697 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9698 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9699 char mac_addr[20],dev[20];
9700
9701 nla_parse(tb,
9702 NL80211_ATTR_MAX,
9703 genlmsg_attrdata(gnlh, 0),
9704 genlmsg_attrlen(gnlh, 0),
9705 NULL);
9706
9707 if(!tb[NL80211_ATTR_STA_INFO]) {
9708 fprintf(stderr, "sta stats missing!\n");
9709 return NL_SKIP;
9710 }
9711
9712 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9713 fprintf(stderr, "failed to parse nested attributes!\n");
9714 return NL_SKIP;
9715 }
9716
9717 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9718
9719 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9720
9721 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9722 fprintf(stderr, "failed to parse nested rate attributes!");
9723 return NL_SKIP;
9724 }
9725
9726 if(sinfo[NL80211_STA_INFO_TID_STATS])
9727 {
9728 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9729 printf("failed to parse nested stats attributes!");
9730 return NL_SKIP;
9731 }
9732 }
9733 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9734 {
9735 printf("Type is VHT\n");
9736 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9737 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9738
9739 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9740 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9741 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9742 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9743 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9744 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9745 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9746 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9747 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9748 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9749 }
9750 else
9751 {
9752 printf(" OFDM or CCK \n");
9753 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9754 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9755 }
9756
9757 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9758 if(rinfo[NL80211_RATE_INFO_MCS])
9759 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9760 }
9761
9762 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9763 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9764 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9765 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9766
9767 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9768 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9769 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9770
9771 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9772 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9773
9774 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9775 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9776
9777 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9778 ((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]);
9779
9780 return NL_SKIP;
9781}
9782#endif
9783
9784INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9785{
9786#ifdef HAL_NETLINK_IMPL
9787 Netlink nl;
9788 char if_name[10];
9789
9790 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9791
9792 if (*output_array_size <= 0)
9793 return RETURN_OK;
9794
9795 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9796
9797 nl.id = initSock80211(&nl);
9798
9799 if(nl.id < 0) {
9800 fprintf(stderr, "Error initializing netlink \n");
9801 return 0;
9802 }
9803
9804 struct nl_msg* msg = nlmsg_alloc();
9805
9806 if(!msg) {
9807 fprintf(stderr, "Failed to allocate netlink message.\n");
9808 nlfree(&nl);
9809 return 0;
9810 }
9811
9812 genlmsg_put(msg,
9813 NL_AUTO_PORT,
9814 NL_AUTO_SEQ,
9815 nl.id,
9816 0,
9817 0,
9818 NL80211_CMD_GET_STATION,
9819 0);
9820
9821 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9822 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9823 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9824 nl_send_auto(nl.socket, msg);
9825 nl_recvmsgs(nl.socket, nl.cb);
9826 nlmsg_free(msg);
9827 nlfree(&nl);
9828 return RETURN_OK;
9829#else
9830 //TODO Implement me
9831 return RETURN_OK;
9832#endif
9833}
9834
9835INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9836{
9837 // TODO Implement me!
9838 char buf[MAX_BUF_SIZE] = {0};
9839 char config_file[MAX_BUF_SIZE] = {0};
9840
9841 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9842 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9843 *activate = (strncmp("1",buf,1) == 0);
9844
9845 return RETURN_OK;
9846}
9847
9848INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9849{
9850 char config_file[MAX_BUF_SIZE] = {0};
9851 struct params list;
9852
9853 list.name = "rrm_neighbor_report";
9854 list.value = activate?"1":"0";
9855 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9856 wifi_hostapdWrite(config_file, &list, 1);
9857
9858 return RETURN_OK;
9859}
9860
9861INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9862{
9863 char buf[32] = {0};
9864 char config_file[MAX_BUF_SIZE] = {0};
9865
9866 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9867 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9868 *activate = (strncmp("1",buf,1) == 0);
9869
9870 return RETURN_OK;
9871}
9872#undef HAL_NETLINK_IMPL
9873#ifdef HAL_NETLINK_IMPL
9874static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9875 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9876 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9877 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9878 char dev[20];
9879 int freq =0 ;
9880 static int i=0;
9881
9882 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9883
9884 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9885 };
9886
9887 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9888
9889 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9890
9891 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9892 fprintf(stderr, "survey data missing!\n");
9893 return NL_SKIP;
9894 }
9895
9896 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9897 {
9898 fprintf(stderr, "failed to parse nested attributes!\n");
9899 return NL_SKIP;
9900 }
9901
9902
9903 if(out[0].array_size == 1 )
9904 {
9905 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9906 {
9907 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9908 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9909 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9910
9911 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9912 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9913 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9914 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9915 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9916 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9917 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9918 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9919 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9920 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9921 if (sinfo[NL80211_SURVEY_INFO_TIME])
9922 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9923 return NL_STOP;
9924 }
9925 }
9926 else
9927 {
9928 if ( i <= out[0].array_size )
9929 {
9930 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9931 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9932 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9933
9934 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9935 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9936 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9937 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9938 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9939 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9940 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9941 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9942 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9943 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9944 if (sinfo[NL80211_SURVEY_INFO_TIME])
9945 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9946 }
9947 }
9948
9949 i++;
9950 return NL_SKIP;
9951}
9952#endif
9953
9954static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9955{
9956 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9957 FILE *fp;
9958
9959 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9960 {
9961 printf("Creating Frequency-Channel Map\n");
9962 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9963 }
9964 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9965 if((fp = popen(command, "r")))
9966 {
9967 fgets(output, sizeof(output), fp);
9968 *freqMHz = atoi(output);
9969 fclose(fp);
9970 }
9971
9972 return 0;
9973}
9974
9975static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9976{
9977 int freqMHz = -1;
9978 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +08009979 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009980
9981 ieee80211_channel_to_frequency(channel, &freqMHz);
9982 if (freqMHz == -1) {
9983 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9984 return -1;
9985 }
9986
developer033b37b2022-10-18 11:27:46 +08009987 phyId = radio_index_to_phy(radioIndex);
9988 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 +08009989 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9990 radioIndex, freqMHz);
9991 return -1;
9992 }
9993
9994 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9995 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9996 return -1;
9997 }
9998
9999 return 0;
10000}
10001
10002static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10003{
10004 const char *ptr = buf;
10005 char *key = NULL;
10006 char *val = NULL;
10007 char line[256] = { '\0' };
10008
10009 while (ptr = get_line_from_str_buf(ptr, line)) {
10010 if (strstr(line, "Frequency")) continue;
10011
10012 key = strtok(line, ":");
10013 val = strtok(NULL, " ");
10014 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10015
10016 if (!strcmp(key, "noise")) {
10017 sscanf(val, "%d", &stats->ch_noise);
10018 if (stats->ch_noise == 0) {
10019 // Workaround for missing noise information.
10020 // Assume -95 for 2.4G and -103 for 5G
10021 if (radioIndex == 0) stats->ch_noise = -95;
10022 if (radioIndex == 1) stats->ch_noise = -103;
10023 }
10024 }
10025 else if (!strcmp(key, "channel active time")) {
10026 sscanf(val, "%llu", &stats->ch_utilization_total);
10027 }
10028 else if (!strcmp(key, "channel busy time")) {
10029 sscanf(val, "%llu", &stats->ch_utilization_busy);
10030 }
10031 else if (!strcmp(key, "channel receive time")) {
10032 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10033 }
10034 else if (!strcmp(key, "channel transmit time")) {
10035 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10036 }
10037 };
10038
10039 return 0;
10040}
10041
10042INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10043{
10044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10045#ifdef HAL_NETLINK_IMPL
10046 Netlink nl;
10047 wifi_channelStats_t_loc local[array_size];
10048 char if_name[10];
10049
10050 local[0].array_size = array_size;
10051
10052 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
10053
10054 nl.id = initSock80211(&nl);
10055
10056 if (nl.id < 0) {
10057 fprintf(stderr, "Error initializing netlink \n");
10058 return -1;
10059 }
10060
10061 struct nl_msg* msg = nlmsg_alloc();
10062
10063 if (!msg) {
10064 fprintf(stderr, "Failed to allocate netlink message.\n");
10065 nlfree(&nl);
10066 return -2;
10067 }
10068
10069 genlmsg_put(msg,
10070 NL_AUTO_PORT,
10071 NL_AUTO_SEQ,
10072 nl.id,
10073 0,
10074 NLM_F_DUMP,
10075 NL80211_CMD_GET_SURVEY,
10076 0);
10077
10078 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10079 nl_send_auto(nl.socket, msg);
10080 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10081 nl_recvmsgs(nl.socket, nl.cb);
10082 nlmsg_free(msg);
10083 nlfree(&nl);
10084 //Copying the Values
10085 for(int i=0;i<array_size;i++)
10086 {
10087 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10088 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10089 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10090 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10091 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10092 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10093 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10094 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10095 }
10096#else
10097 ULONG channel = 0;
10098 int i;
10099 int number_of_channels = array_size;
10100 char buf[512];
10101 INT ret;
10102 wifi_channelStats_t tmp_stats;
10103
10104 if (number_of_channels == 0) {
10105 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10106 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10107 return RETURN_ERR;
10108 }
10109 number_of_channels = 1;
10110 input_output_channelStats_array[0].ch_number = channel;
10111 }
10112
10113 for (i = 0; i < number_of_channels; i++) {
10114
10115 input_output_channelStats_array[i].ch_noise = 0;
10116 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10117 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10118 input_output_channelStats_array[i].ch_utilization_busy = 0;
10119 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10120 input_output_channelStats_array[i].ch_utilization_total = 0;
10121
10122 memset(buf, 0, sizeof(buf));
10123 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10124 return RETURN_ERR;
10125 }
10126 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10127 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10128 return RETURN_ERR;
10129 }
10130
10131 // XXX: fake missing 'self' counter which is not available in iw survey output
10132 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10133 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10134
10135 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10136 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10137 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10138 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10139 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10140
10141 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",
10142 __func__,
10143 input_output_channelStats_array[i].ch_number,
10144 input_output_channelStats_array[i].ch_noise,
10145 input_output_channelStats_array[i].ch_utilization_total,
10146 input_output_channelStats_array[i].ch_utilization_busy,
10147 input_output_channelStats_array[i].ch_utilization_busy_rx,
10148 input_output_channelStats_array[i].ch_utilization_busy_tx,
10149 input_output_channelStats_array[i].ch_utilization_busy_self,
10150 input_output_channelStats_array[i].ch_utilization_busy_ext);
10151 }
10152#endif
10153 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10154 return RETURN_OK;
10155}
10156#define HAL_NETLINK_IMPL
10157
10158/* Hostapd events */
10159
10160#ifndef container_of
10161#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10162#define container_of(ptr, type, member) \
10163 ((type *)((char *)ptr - offset_of(type, member)))
10164#endif /* container_of */
10165
10166struct ctrl {
10167 char sockpath[128];
10168 char sockdir[128];
10169 char bss[IFNAMSIZ];
10170 char reply[4096];
10171 int ssid_index;
10172 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10173 void (*overrun)(struct ctrl *ctrl);
10174 struct wpa_ctrl *wpa;
10175 unsigned int ovfl;
10176 size_t reply_len;
10177 int initialized;
10178 ev_timer retry;
10179 ev_timer watchdog;
10180 ev_stat stat;
10181 ev_io io;
10182};
10183static wifi_newApAssociatedDevice_callback clients_connect_cb;
10184static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10185static struct ctrl wpa_ctrl[MAX_APS];
10186static int initialized;
10187
10188static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10189{
10190 char cbuf[256] = {};
10191 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10192 struct cmsghdr *cmsg;
10193 unsigned int ovfl = ctrl->ovfl;
10194 unsigned int drop;
10195
10196 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10197 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10198 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10199 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10200
10201 drop = ovfl - ctrl->ovfl;
10202 ctrl->ovfl = ovfl;
10203
10204 return drop;
10205}
10206
10207static void ctrl_close(struct ctrl *ctrl)
10208{
10209 if (ctrl->io.cb)
10210 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10211 if (ctrl->retry.cb)
10212 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10213 if (!ctrl->wpa)
10214 return;
10215
10216 wpa_ctrl_detach(ctrl->wpa);
10217 wpa_ctrl_close(ctrl->wpa);
10218 ctrl->wpa = NULL;
10219 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10220}
10221
10222static void ctrl_process(struct ctrl *ctrl)
10223{
10224 const char *str;
10225 int drops;
10226 int level;
10227 int err;
10228
10229 /* Example events:
10230 *
10231 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10232 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10233 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10234 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10235 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10236 */
10237 if (!(str = index(ctrl->reply, '>')))
10238 return;
10239 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10240 return;
10241
10242 str++;
10243
10244 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10245 if (!(str = index(ctrl->reply, ' ')))
10246 return;
10247 wifi_associated_dev_t sta;
10248 memset(&sta, 0, sizeof(sta));
10249
10250 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10251 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10252 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10253
10254 sta.cli_Active=true;
10255
10256 (clients_connect_cb)(ctrl->ssid_index, &sta);
10257 goto handled;
10258 }
10259
10260 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10261 if (!(str = index(ctrl->reply, ' ')))
10262 return;
10263
10264 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10265 goto handled;
10266 }
10267
10268 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10269 printf("CTRL_WPA: handle TERMINATING event\n");
10270 goto retry;
10271 }
10272
10273 if (strncmp("AP-DISABLED", str, 11) == 0) {
10274 printf("CTRL_WPA: handle AP-DISABLED\n");
10275 goto retry;
10276 }
10277
10278 printf("Event not supported!!\n");
10279
10280handled:
10281
10282 if ((drops = ctrl_get_drops(ctrl))) {
10283 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10284 if (ctrl->overrun)
10285 ctrl->overrun(ctrl);
10286 }
10287
10288 return;
10289
10290retry:
10291 printf("WPA_CTRL: closing\n");
10292 ctrl_close(ctrl);
10293 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10294 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10295}
10296
10297static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10298{
10299 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10300 int err;
10301
10302 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10303 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10304 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10305 ctrl->reply[ctrl->reply_len] = 0;
10306 if (err < 0) {
10307 if (errno == EAGAIN || errno == EWOULDBLOCK)
10308 return;
10309 ctrl_close(ctrl);
10310 ev_timer_again(EV_A_ &ctrl->retry);
10311 return;
10312 }
10313
10314 ctrl_process(ctrl);
10315}
10316
10317static int ctrl_open(struct ctrl *ctrl)
10318{
10319 int fd;
10320
10321 if (ctrl->wpa)
10322 return 0;
10323
10324 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10325 if (!ctrl->wpa)
10326 goto err;
10327
10328 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10329 goto err_close;
10330
10331 fd = wpa_ctrl_get_fd(ctrl->wpa);
10332 if (fd < 0)
10333 goto err_detach;
10334
10335 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10336 goto err_detach;
10337
10338 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10339 ev_io_start(EV_DEFAULT_ &ctrl->io);
10340
10341 return 0;
10342
10343err_detach:
10344 wpa_ctrl_detach(ctrl->wpa);
10345err_close:
10346 wpa_ctrl_close(ctrl->wpa);
10347err:
10348 ctrl->wpa = NULL;
10349 return -1;
10350}
10351
10352static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10353{
10354 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10355
10356 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10357 ctrl_open(ctrl);
10358}
10359
10360static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10361{
10362 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10363
10364 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10365 if (ctrl_open(ctrl) == 0) {
10366 printf("WPA_CTRL: retry successful\n");
10367 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10368 }
10369}
10370
10371int ctrl_enable(struct ctrl *ctrl)
10372{
10373 if (ctrl->wpa)
10374 return 0;
10375
10376 if (!ctrl->stat.cb) {
10377 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10378 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10379 }
10380
10381 if (!ctrl->retry.cb) {
10382 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10383 }
10384
10385 return ctrl_open(ctrl);
10386}
10387
10388static void
10389ctrl_msg_cb(char *buf, size_t len)
10390{
10391 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10392
10393 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10394 ctrl_process(ctrl);
10395}
10396
10397static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10398{
10399 int err;
10400
10401 if (!ctrl->wpa)
10402 return -1;
10403 if (*reply_len < 2)
10404 return -1;
10405
10406 (*reply_len)--;
10407 ctrl->reply_len = sizeof(ctrl->reply);
10408 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10409 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10410 if (err < 0)
10411 return err;
10412
10413 if (ctrl->reply_len > *reply_len)
10414 ctrl->reply_len = *reply_len;
10415
10416 *reply_len = ctrl->reply_len;
10417 memcpy(reply, ctrl->reply, *reply_len);
10418 reply[*reply_len - 1] = 0;
10419 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10420 return 0;
10421}
10422
10423static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10424{
10425 const char *pong = "PONG";
10426 const char *ping = "PING";
10427 char reply[1024];
10428 size_t len = sizeof(reply);
10429 int err;
10430 ULONG s, snum;
10431 INT ret;
10432 BOOL status;
10433
10434 printf("WPA_CTRL: watchdog cb\n");
10435
10436 ret = wifi_getSSIDNumberOfEntries(&snum);
10437 if (ret != RETURN_OK) {
10438 printf("%s: failed to get SSID count", __func__);
10439 return;
10440 }
10441
10442 if (snum > MAX_APS) {
10443 printf("more ssid than supported! %lu\n", snum);
10444 return;
10445 }
10446
10447 for (s = 0; s < snum; s++) {
10448 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10449 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10450 continue;
10451 }
10452 if (status == false) continue;
10453
10454 memset(reply, 0, sizeof(reply));
10455 len = sizeof(reply);
10456 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10457 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10458 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10459 continue;
10460
10461 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10462 ctrl_close(&wpa_ctrl[s]);
10463 printf("WPA_CTRL: ev_timer_again %d\n", s);
10464 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10465 }
10466}
10467
10468static int init_wpa()
10469{
10470 int ret = 0, i = 0;
10471 ULONG s, snum;
10472
10473 ret = wifi_getSSIDNumberOfEntries(&snum);
10474 if (ret != RETURN_OK) {
10475 printf("%s: failed to get SSID count", __func__);
10476 return RETURN_ERR;
10477 }
10478
10479 if (snum > MAX_APS) {
10480 printf("more ssid than supported! %lu\n", snum);
10481 return RETURN_ERR;
10482 }
10483
10484 for (s = 0; s < snum; s++) {
10485 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10486 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10487 wpa_ctrl[s].ssid_index = s;
10488 ctrl_enable(&wpa_ctrl[s]);
10489 }
10490
10491 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10492 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10493
10494 initialized = 1;
10495 printf("WPA_CTRL: initialized\n");
10496
10497 return RETURN_OK;
10498}
10499
10500void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10501{
10502 clients_connect_cb = callback_proc;
10503 if (!initialized)
10504 init_wpa();
10505}
10506
10507void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10508{
10509 clients_disconnect_cb = callback_proc;
10510 if (!initialized)
10511 init_wpa();
10512}
10513
10514INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10515{
10516 // TODO Implement me!
10517 return RETURN_ERR;
10518}
10519
10520INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10521{
10522 // TODO Implement me!
10523 return RETURN_ERR;
10524}
10525
10526INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10527{
10528 int i;
10529 char cmd[256];
10530 char channel_numbers_buf[256];
10531 char dfs_state_buf[256];
10532 char line[256];
10533 const char *ptr;
10534
10535 memset(cmd, 0, sizeof(cmd));
10536 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10537 memset(line, 0, sizeof(line));
10538 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10539 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10540
10541 if (radioIndex == 0) { // 2.4G - all allowed
10542 if (outputMapSize < 11) {
10543 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10544 return RETURN_ERR;
10545 }
10546
10547 for (i = 0; i < 11; i++) {
10548 outputMap[i].ch_number = i + 1;
10549 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10550 }
10551
10552 return RETURN_OK;
10553 }
10554
10555 if (radioIndex == 1) { // 5G
10556// Example output of iw list:
10557//
10558// Frequencies:
10559// * 5180 MHz [36] (17.0 dBm)
10560// * 5200 MHz [40] (17.0 dBm)
10561// * 5220 MHz [44] (17.0 dBm)
10562// * 5240 MHz [48] (17.0 dBm)
10563// * 5260 MHz [52] (23.0 dBm) (radar detection)
10564// DFS state: usable (for 78930 sec)
10565// DFS CAC time: 60000 ms
10566// * 5280 MHz [56] (23.0 dBm) (radar detection)
10567// DFS state: usable (for 78930 sec)
10568// DFS CAC time: 60000 ms
10569// * 5300 MHz [60] (23.0 dBm) (radar detection)
10570// DFS state: usable (for 78930 sec)
10571// DFS CAC time: 60000 ms
10572// * 5320 MHz [64] (23.0 dBm) (radar detection)
10573// DFS state: usable (for 78930 sec)
10574// DFS CAC time: 60000 ms
10575// * 5500 MHz [100] (disabled)
10576// * 5520 MHz [104] (disabled)
10577// * 5540 MHz [108] (disabled)
10578// * 5560 MHz [112] (disabled)
10579//
10580// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10581 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10582 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10583 return RETURN_ERR;
10584 }
10585
10586 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10587 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10588 return RETURN_ERR;
10589 }
10590
10591 ptr = channel_numbers_buf;
10592 i = 0;
10593 while (ptr = get_line_from_str_buf(ptr, line)) {
10594 if (i >= outputMapSize) {
10595 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10596 return RETURN_ERR;
10597 }
10598 sscanf(line, "%d", &outputMap[i].ch_number);
10599
10600 memset(cmd, 0, sizeof(cmd));
10601 // Below command should fetch string for DFS state (usable, available or unavailable)
10602 // Example line: "DFS state: usable (for 78930 sec)"
10603 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) {
10604 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10605 return RETURN_ERR;
10606 }
10607
10608 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10609 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10610 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10611 return RETURN_ERR;
10612 }
10613
10614 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10615
10616 if (!strcmp(dfs_state_buf, "usable")) {
10617 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10618 } else if (!strcmp(dfs_state_buf, "available")) {
10619 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10620 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10621 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10622 } else {
10623 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10624 }
10625 i++;
10626 }
10627
10628 return RETURN_OK;
10629 }
10630
10631 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10632 return RETURN_ERR;
10633}
10634
10635INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10636{
10637 // TODO Implement me!
10638 return RETURN_ERR;
10639}
10640
10641INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10642{
10643 return RETURN_OK;
10644}
10645
10646INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10647{
10648 // TODO Implement me!
10649 return RETURN_ERR;
10650}
10651
10652INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10653{
10654 // TODO API refrence Implementaion is present on RPI hal
10655 return RETURN_ERR;
10656}
10657
10658INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10659{
developera5005b62022-09-13 15:43:35 +080010660 char cmd[128]={'\0'};
10661 char buf[128]={'\0'};
10662 char *support;
10663 int maximum_tx = 0, current_tx = 0;
10664
10665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10666 if(txpwr_pcntg == NULL)
10667 return RETURN_ERR;
10668
10669 // Get the maximum tx power of the device
10670 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10671 _syscmd(cmd, buf, sizeof(buf));
10672 maximum_tx = strtol(buf, NULL, 10);
10673
10674 // Get the current tx power
10675 memset(cmd, 0, sizeof(cmd));
10676 memset(buf, 0, sizeof(buf));
10677 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10678 _syscmd(cmd, buf, sizeof(buf));
10679 current_tx = strtol(buf, NULL, 10);
10680
10681 // Get the power supported list and find the current power percentage in supported list
10682 memset(buf, 0, sizeof(buf));
10683 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10684 support = strtok(buf, ",");
10685 while(true)
10686 {
10687 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 +080010688 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010689 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010690 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010691 }
10692 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10693 if (tmp == current_tx) {
10694 *txpwr_pcntg = strtol(support, NULL, 10);
10695 break;
10696 }
10697 support = strtok(NULL, ",");
10698 }
10699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010700 return RETURN_OK;
10701}
10702
10703INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10704{
developer58599c22022-09-13 16:40:34 +080010705 // TODO precac feature.
10706 struct params params = {0};
10707 char config_file[128] = {0};
10708
10709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10710
10711 params.name = "enable_background_radar";
10712 params.value = enable?"1":"0";
10713 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10714 wifi_hostapdWrite(config_file, &params, 1);
10715 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10716
10717 /* TODO precac feature */
10718
10719 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10720 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010721}
10722
10723INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10724{
developer58599c22022-09-13 16:40:34 +080010725 char config_file[128] = {0};
10726 char buf[64] = {0};
10727
10728 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10729 if (NULL == enable || NULL == precac)
10730 return RETURN_ERR;
10731
10732 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10733 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10734 if (strncmp(enable, "1", 1) == 0)
10735 *enable = true;
10736 else
10737 *enable = false;
10738
10739 /* TODO precac feature */
10740
10741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10742 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010743}
10744
10745INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10746{
developer58599c22022-09-13 16:40:34 +080010747 *supported = TRUE;
10748 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010749}
10750
developer3e6b1692022-09-30 18:04:05 +080010751INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10752{
10753 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10754 struct params params = {0};
10755 char config_file[64] = {0};
10756 char buf[64] = {0};
10757 unsigned int set_mu_type = 0;
10758 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10759
10760 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10761 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10762
10763 if (strlen(buf) > 0)
10764 set_mu_type = strtol(buf, NULL, 10);
10765
10766 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10767 set_mu_type &= ~0x05; // unset bit 0, 2
10768 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10769 set_mu_type |= 0x01;
10770 set_mu_type &= ~0x04;
10771 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10772 set_mu_type &= ~0x01;
10773 set_mu_type |= 0x04;
10774 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10775 set_mu_type |= 0x05; // set bit 0, 2
10776 }
10777
10778 params.name = "hemu_onoff";
10779 sprintf(buf, "%u", set_mu_type);
10780 params.value = buf;
10781 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10782 wifi_hostapdWrite(config_file, &params, 1);
10783 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10784
10785 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10786 return RETURN_OK;
10787}
10788
10789INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10790{
10791 struct params params={0};
10792 char config_file[64] = {0};
10793 char buf[64] = {0};
10794 unsigned int get_mu_type = 0;
10795
10796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10797
10798 if (mu_type == NULL)
10799 return RETURN_ERR;
10800
10801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10802 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10803 get_mu_type = strtol(buf, NULL, 10);
10804
10805 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10806 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10807 else if (get_mu_type & 0x04)
10808 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10809 else if (get_mu_type & 0x01)
10810 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10811 else
10812 *mu_type = WIFI_DL_MU_TYPE_NONE;
10813
10814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10815 return RETURN_OK;
10816}
10817
10818INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10819{
10820 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10821 struct params params={0};
10822 char config_file[64] = {0};
10823 char buf[64] = {0};
10824 unsigned int set_mu_type = 0;
10825 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10826
10827 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10828 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10829
10830 if (strlen(buf) > 0)
10831 set_mu_type = strtol(buf, NULL, 10);
10832
10833 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10834 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10835 set_mu_type &= ~0x0a;
10836 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10837 set_mu_type |= 0x02;
10838 set_mu_type &= ~0x08;
10839 }
10840
10841 params.name = "hemu_onoff";
10842 sprintf(buf, "%u", set_mu_type);
10843 params.value = buf;
10844 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10845 wifi_hostapdWrite(config_file, &params, 1);
10846 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10847
10848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10849 return RETURN_OK;
10850}
10851
10852INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10853{
10854 struct params params={0};
10855 char config_file[64] = {0};
10856 char buf[64] = {0};
10857 unsigned int get_mu_type = 0;
10858
10859 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10860
10861 if (mu_type == NULL)
10862 return RETURN_ERR;
10863
10864 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10865 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10866
10867 get_mu_type = strtol(buf, NULL, 10);
10868 if (get_mu_type & 0x02)
10869 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10870 else
10871 *mu_type = WIFI_DL_MU_TYPE_NONE;
10872
10873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10874 return RETURN_OK;
10875}
10876
10877
developer454b9462022-09-13 15:29:16 +080010878INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10879{
10880 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010881 char buf[256] = {0};
10882 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010883 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010884 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010885 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010886 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010887
10888 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10889
developer254882b2022-09-30 17:12:31 +080010890 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010891 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10892 return RETURN_ERR;
10893 }
developer454b9462022-09-13 15:29:16 +080010894
developer254882b2022-09-30 17:12:31 +080010895 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010896 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010897
developer254882b2022-09-30 17:12:31 +080010898 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10899 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080010900 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010901 _syscmd(cmd, buf, sizeof(buf));
10902 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10903 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10904 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010905 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 +080010906 _syscmd(cmd, buf, sizeof(buf));
10907 }
10908 if (band == band_5) {
10909 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10910 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010911 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 +080010912 _syscmd(cmd, buf, sizeof(buf));
10913 }
10914 }
10915 }
10916 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010917
developer254882b2022-09-30 17:12:31 +080010918 if (guard_interval == wifi_guard_interval_400)
10919 strcpy(GI, "0.4");
10920 else if (guard_interval == wifi_guard_interval_800)
10921 strcpy(GI, "0.8");
10922 else if (guard_interval == wifi_guard_interval_1600)
10923 strcpy(GI, "1.6");
10924 else if (guard_interval == wifi_guard_interval_3200)
10925 strcpy(GI, "3.2");
10926 else if (guard_interval == wifi_guard_interval_auto)
10927 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010928 // Record GI for get GI function
10929 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10930 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010931 if (f == NULL)
10932 return RETURN_ERR;
10933 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010934 fclose(f);
10935 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10936 return RETURN_OK;
10937}
10938
10939INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10940{
10941 char buf[32] = {0};
10942 char cmd[64] = {0};
10943
10944 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10945
10946 if (guard_interval == NULL)
10947 return RETURN_ERR;
10948
10949 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10950 _syscmd(cmd, buf, sizeof(buf));
10951
10952 if (strncmp(buf, "0.4", 3) == 0)
10953 *guard_interval = wifi_guard_interval_400;
10954 else if (strncmp(buf, "0.8", 3) == 0)
10955 *guard_interval = wifi_guard_interval_800;
10956 else if (strncmp(buf, "1.6", 3) == 0)
10957 *guard_interval = wifi_guard_interval_1600;
10958 else if (strncmp(buf, "3.2", 3) == 0)
10959 *guard_interval = wifi_guard_interval_3200;
10960 else
10961 *guard_interval = wifi_guard_interval_auto;
10962
10963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10964 return RETURN_OK;
10965}
10966
developer3cc61d12022-09-13 16:36:05 +080010967INT wifi_setBSSColor(INT radio_index, UCHAR color)
10968{
10969 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10970 struct params params = {0};
10971 char config_file[128] = {0};
10972 char bss_color[4] ={0};
10973
10974 params.name = "he_bss_color";
10975 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10976 params.value = bss_color;
10977 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10978 wifi_hostapdWrite(config_file, &params, 1);
10979 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10980
10981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10982 return RETURN_OK;
10983}
10984
10985INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10986{
10987 char config_file[128] = {0};
10988 char buf[64] = {0};
10989 char temp_output[128] = {'\0'};
10990
10991 wifi_dbg_printf("\nFunc=%s\n", __func__);
10992 if (NULL == color)
10993 return RETURN_ERR;
10994
10995 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10996 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10997
10998 if(strlen(buf) > 0) {
10999 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11000 } else {
11001 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11002 }
11003
11004 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11005 wifi_dbg_printf("\noutput_string=%s\n", color);
11006
11007 return RETURN_OK;
11008}
11009
developer06a01d92022-09-07 16:32:39 +080011010/* multi-psk support */
11011INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11012{
11013 char cmd[256];
11014
11015 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11016 AP_PREFIX,
11017 apIndex,
11018 mac[0],
11019 mac[1],
11020 mac[2],
11021 mac[3],
11022 mac[4],
11023 mac[5]
11024 );
11025 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11026 _syscmd(cmd, key->wifi_keyId, 64);
11027
11028
11029 return RETURN_OK;
11030}
11031
11032INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11033{
11034 FILE *fd = NULL;
11035 char fname[100];
11036 char cmd[128] = {0};
11037 char out[64] = {0};
11038 wifi_key_multi_psk_t * key = NULL;
11039 if(keysNumber < 0)
11040 return RETURN_ERR;
11041
11042 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11043 fd = fopen(fname, "w");
11044 if (!fd) {
11045 return RETURN_ERR;
11046 }
11047 key= (wifi_key_multi_psk_t *) keys;
11048 for(int i=0; i<keysNumber; ++i, key++) {
11049 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11050 }
11051 fclose(fd);
11052
11053 //reload file
11054 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
11055 _syscmd(cmd, out, 64);
11056 return RETURN_OK;
11057}
11058
11059INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11060{
11061 FILE *fd = NULL;
11062 char fname[100];
11063 char * line = NULL;
11064 char * pos = NULL;
11065 size_t len = 0;
11066 ssize_t read = 0;
11067 INT ret = RETURN_OK;
11068 wifi_key_multi_psk_t *keys_it = NULL;
11069
11070 if (keysNumber < 1) {
11071 return RETURN_ERR;
11072 }
11073
11074 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11075 fd = fopen(fname, "r");
11076 if (!fd) {
11077 return RETURN_ERR;
11078 }
11079
11080 if (keys == NULL) {
11081 ret = RETURN_ERR;
11082 goto close;
11083 }
11084
11085 keys_it = keys;
11086 while ((read = getline(&line, &len, fd)) != -1) {
11087 //Strip trailing new line if present
11088 if (read > 0 && line[read-1] == '\n') {
11089 line[read-1] = '\0';
11090 }
11091
11092 if(strcmp(line,"keyid=")) {
11093 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11094 if (!(pos = index(line, ' '))) {
11095 ret = RETURN_ERR;
11096 goto close;
11097 }
11098 pos++;
11099 //Here should be 00:00:00:00:00:00
11100 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11101 printf("Not supported MAC: %s\n", pos);
11102 }
11103 if (!(pos = index(pos, ' '))) {
11104 ret = RETURN_ERR;
11105 goto close;
11106 }
11107 pos++;
11108
11109 //The rest is PSK
11110 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11111 keys_it++;
11112
11113 if(--keysNumber <= 0)
11114 break;
11115 }
11116 }
11117
11118close:
11119 free(line);
11120 fclose(fd);
11121 return ret;
11122}
11123/* end of multi-psk support */
11124
11125INT wifi_setNeighborReports(UINT apIndex,
11126 UINT numNeighborReports,
11127 wifi_NeighborReport_t *neighborReports)
11128{
11129 char cmd[256] = { 0 };
11130 char hex_bssid[13] = { 0 };
11131 char bssid[18] = { 0 };
11132 char nr[256] = { 0 };
11133 char ssid[256];
11134 char hex_ssid[256];
11135 INT ret;
11136
11137 /*rmeove all neighbors*/
11138 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
11139 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);
11140 system(cmd);
11141
11142 for(unsigned int i = 0; i < numNeighborReports; i++)
11143 {
11144 memset(ssid, 0, sizeof(ssid));
11145 ret = wifi_getSSIDName(apIndex, ssid);
11146 if (ret != RETURN_OK)
11147 return RETURN_ERR;
11148
11149 memset(hex_ssid, 0, sizeof(hex_ssid));
11150 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11151 sprintf(hex_ssid + k,"%02x", ssid[j]);
11152
11153 snprintf(hex_bssid, sizeof(hex_bssid),
11154 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11155 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11156 snprintf(bssid, sizeof(bssid),
11157 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11158 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11159
11160 snprintf(nr, sizeof(nr),
11161 "%s" // bssid
11162 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11163 "%02hhx" // operclass
11164 "%02hhx" // channel
11165 "%02hhx", // phy_mode
11166 hex_bssid,
11167 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11168 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11169 neighborReports[i].opClass,
11170 neighborReports[i].channel,
11171 neighborReports[i].phyTable);
11172
11173 snprintf(cmd, sizeof(cmd),
11174 "hostapd_cli set_neighbor "
11175 "%s " // bssid
11176 "ssid=%s " // ssid
11177 "nr=%s " // nr
11178 "-i %s%d",
11179 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
11180
11181 if (WEXITSTATUS(system(cmd)) != 0)
11182 {
11183 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11184 }
11185 }
11186
11187 return RETURN_OK;
11188}
11189
11190INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11191{
11192 return RETURN_OK;
11193}
11194
11195#ifdef _WIFI_HAL_TEST_
11196int main(int argc,char **argv)
11197{
11198 int index;
11199 INT ret=0;
11200 char buf[1024]="";
11201
11202 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11203 if(argc<3)
11204 {
11205 if(argc==2)
11206 {
11207 if(!strcmp(argv[1], "init"))
11208 return wifi_init();
11209 if(!strcmp(argv[1], "reset"))
11210 return wifi_reset();
11211 if(!strcmp(argv[1], "wifi_getHalVersion"))
11212 {
11213 char buffer[64];
11214 if(wifi_getHalVersion(buffer)==RETURN_OK)
11215 printf("Version: %s\n", buffer);
11216 else
11217 printf("Error in wifi_getHalVersion\n");
11218 return RETURN_OK;
11219 }
11220 }
11221 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11222 exit(-1);
11223 }
11224
11225 index = atoi(argv[2]);
11226 if(strstr(argv[1], "wifi_getApName")!=NULL)
11227 {
11228 wifi_getApName(index,buf);
11229 printf("Ap name is %s \n",buf);
11230 return 0;
11231 }
11232 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11233 {
11234 BOOL b = FALSE;
11235 BOOL *output_bool = &b;
11236 wifi_getRadioAutoChannelEnable(index,output_bool);
11237 printf("Channel enabled = %d \n",b);
11238 return 0;
11239 }
11240 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11241 {
11242 wifi_getApWpaEncryptionMode(index,buf);
11243 printf("encryption enabled = %s\n",buf);
11244 return 0;
11245 }
11246 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11247 {
11248 BOOL b = FALSE;
11249 BOOL *output_bool = &b;
11250 wifi_getApSsidAdvertisementEnable(index,output_bool);
11251 printf("advertisment enabled = %d\n",b);
11252 return 0;
11253 }
11254 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11255 {
11256 if(argc <= 3 )
11257 {
11258 printf("Insufficient arguments \n");
11259 exit(-1);
11260 }
11261
11262 char sta[20] = {'\0'};
11263 ULLONG handle= 0;
11264 strcpy(sta,argv[3]);
11265 mac_address_t st;
11266 mac_addr_aton(st,sta);
11267
11268 wifi_associated_dev_tid_stats_t tid_stats;
11269 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11270 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11271 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);
11272 }
11273
11274 if(strstr(argv[1], "getApEnable")!=NULL) {
11275 BOOL enable;
11276 ret=wifi_getApEnable(index, &enable);
11277 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11278 }
11279 else if(strstr(argv[1], "setApEnable")!=NULL) {
11280 BOOL enable = atoi(argv[3]);
11281 ret=wifi_setApEnable(index, enable);
11282 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11283 }
11284 else if(strstr(argv[1], "getApStatus")!=NULL) {
11285 char status[64];
11286 ret=wifi_getApStatus(index, status);
11287 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11288 }
11289 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11290 {
11291 wifi_getSSIDNameStatus(index,buf);
11292 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11293 return 0;
11294 }
11295 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11296 wifi_ssidTrafficStats2_t stats={0};
11297 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11298 printf("%s %d: returns %d\n", argv[1], index, ret);
11299 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11300 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11301 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11302 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11303 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11304 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11305 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11306 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11307 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11308 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11309 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11310 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11311 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11312 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11313 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11314 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11315 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11316 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11317 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11318 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11319 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11320 }
11321 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11322 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11323 UINT array_size=0;
11324 UINT i=0;
11325 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11326 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11327 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11328 printf(" neighbor %d:\n", i);
11329 printf(" ap_SSID =%s\n", pt->ap_SSID);
11330 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11331 printf(" ap_Mode =%s\n", pt->ap_Mode);
11332 printf(" ap_Channel =%d\n", pt->ap_Channel);
11333 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11334 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11335 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11336 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11337 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11338 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11339 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11340 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11341 printf(" ap_Noise =%d\n", pt->ap_Noise);
11342 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11343 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11344 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11345 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11346 }
11347 if(neighbor_ap_array)
11348 free(neighbor_ap_array); //make sure to free the list
11349 }
11350 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11351 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11352 UINT array_size=0;
11353 UINT i=0;
11354 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11355 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11356 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11357 printf(" associated_dev %d:\n", i);
11358 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11359 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11360 printf(" cli_SNR =%d\n", pt->cli_SNR);
11361 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11362 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11363 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11364 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11365 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11366 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11367 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11368 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11369 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11370 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11371 }
11372 if(associated_dev_array)
11373 free(associated_dev_array); //make sure to free the list
11374 }
11375
11376 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11377 {
11378#define MAX_ARRAY_SIZE 64
11379 int i, array_size;
11380 char *p, *ch_str;
11381 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11382
11383 if(argc != 5)
11384 {
11385 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11386 exit(-1);
11387 }
11388 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11389
11390 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11391 {
11392 strtok_r(ch_str, ",", &p);
11393 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11394 }
11395 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11396 if(!array_size)
11397 array_size=1;//Need to print current channel statistics
11398 for(i=0; i<array_size; i++)
11399 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11400 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11401 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11402 input_output_channelStats_array[i].ch_number,\
11403 input_output_channelStats_array[i].ch_noise,\
11404 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11405 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11406 input_output_channelStats_array[i].ch_utilization_busy,\
11407 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11408 input_output_channelStats_array[i].ch_utilization_total);
11409 }
11410
11411 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11412 {
11413 if(argc <= 3 )
11414 {
11415 printf("Insufficient arguments \n");
11416 exit(-1);
11417 }
11418 char mac_addr[20] = {'\0'};
11419 wifi_device_t output_struct;
11420 int dev_index = atoi(argv[3]);
11421
11422 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11423 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11424 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);
11425 }
11426
11427 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11428 {
11429 if (argc <= 3)
11430 {
11431 printf("Insufficient arguments\n");
11432 exit(-1);
11433 }
11434 char args[256];
11435 wifi_NeighborReport_t *neighborReports;
11436
11437 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11438 if (!neighborReports)
11439 {
11440 printf("Failed to allocate memory");
11441 exit(-1);
11442 }
11443
11444 for (int i = 3; i < argc; ++i)
11445 {
11446 char *val;
11447 int j = 0;
11448 memset(args, 0, sizeof(args));
11449 strncpy(args, argv[i], sizeof(args));
11450 val = strtok(args, ";");
11451 while (val != NULL)
11452 {
11453 if (j == 0)
11454 {
11455 mac_addr_aton(neighborReports[i - 3].bssid, val);
11456 } else if (j == 1)
11457 {
11458 neighborReports[i - 3].info = strtol(val, NULL, 16);
11459 } else if (j == 2)
11460 {
11461 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11462 } else if (j == 3)
11463 {
11464 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11465 } else if (j == 4)
11466 {
11467 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11468 } else {
11469 printf("Insufficient arguments]n\n");
11470 exit(-1);
11471 }
11472 val = strtok(NULL, ";");
11473 j++;
11474 }
11475 }
11476
11477 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11478 if (ret != RETURN_OK)
11479 {
11480 printf("wifi_setNeighborReports ret = %d", ret);
11481 exit(-1);
11482 }
11483 }
11484 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11485 {
11486 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11487 printf("%s.\n", buf);
11488 else
11489 printf("Error returned\n");
11490 }
11491 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11492 {
11493 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11494 printf("%s.\n", buf);
11495 else
11496 printf("Error returned\n");
11497 }
11498 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11499 {
11500 if (argc <= 2)
11501 {
11502 printf("Insufficient arguments\n");
11503 exit(-1);
11504 }
11505 char buf[64]= {'\0'};
11506 wifi_getRadioOperatingChannelBandwidth(index,buf);
11507 printf("Current bandwidth is %s \n",buf);
11508 return 0;
11509 }
11510 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11511 {
11512 if (argc <= 5)
11513 {
11514 printf("Insufficient arguments\n");
11515 exit(-1);
11516 }
11517 UINT channel = atoi(argv[3]);
11518 UINT width = atoi(argv[4]);
11519 UINT beacon = atoi(argv[5]);
11520 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11521 printf("Result = %d", ret);
11522 }
11523
11524 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11525 return 0;
11526}
11527
11528#endif
11529
11530#ifdef WIFI_HAL_VERSION_3
11531
developer1e5aa162022-09-13 16:06:24 +080011532INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11533{
11534 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11535 if (bitMap & WIFI_BITRATE_1MBPS)
11536 strcat(BasicRate, "1,");
11537 if (bitMap & WIFI_BITRATE_2MBPS)
11538 strcat(BasicRate, "2,");
11539 if (bitMap & WIFI_BITRATE_5_5MBPS)
11540 strcat(BasicRate, "5.5,");
11541 if (bitMap & WIFI_BITRATE_6MBPS)
11542 strcat(BasicRate, "6,");
11543 if (bitMap & WIFI_BITRATE_9MBPS)
11544 strcat(BasicRate, "9,");
11545 if (bitMap & WIFI_BITRATE_11MBPS)
11546 strcat(BasicRate, "11,");
11547 if (bitMap & WIFI_BITRATE_12MBPS)
11548 strcat(BasicRate, "12,");
11549 if (bitMap & WIFI_BITRATE_18MBPS)
11550 strcat(BasicRate, "18,");
11551 if (bitMap & WIFI_BITRATE_24MBPS)
11552 strcat(BasicRate, "24,");
11553 if (bitMap & WIFI_BITRATE_36MBPS)
11554 strcat(BasicRate, "36,");
11555 if (bitMap & WIFI_BITRATE_48MBPS)
11556 strcat(BasicRate, "48,");
11557 if (bitMap & WIFI_BITRATE_54MBPS)
11558 strcat(BasicRate, "54,");
11559 if (strlen(BasicRate) != 0) // remove last comma
11560 BasicRate[strlen(BasicRate) - 1] = '\0';
11561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11562 return RETURN_OK;
11563}
11564
11565INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11566{
11567 UINT BitMap = 0;
11568 char *rate;
11569
11570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11571 rate = strtok(BasicRatesList, ",");
11572 while(rate != NULL)
11573 {
11574 if (strcmp(rate, "1") == 0)
11575 BitMap |= WIFI_BITRATE_1MBPS;
11576 else if (strcmp(rate, "2") == 0)
11577 BitMap |= WIFI_BITRATE_2MBPS;
11578 else if (strcmp(rate, "5.5") == 0)
11579 BitMap |= WIFI_BITRATE_5_5MBPS;
11580 else if (strcmp(rate, "6") == 0)
11581 BitMap |= WIFI_BITRATE_6MBPS;
11582 else if (strcmp(rate, "9") == 0)
11583 BitMap |= WIFI_BITRATE_9MBPS;
11584 else if (strcmp(rate, "11") == 0)
11585 BitMap |= WIFI_BITRATE_11MBPS;
11586 else if (strcmp(rate, "12") == 0)
11587 BitMap |= WIFI_BITRATE_12MBPS;
11588 else if (strcmp(rate, "18") == 0)
11589 BitMap |= WIFI_BITRATE_18MBPS;
11590 else if (strcmp(rate, "24") == 0)
11591 BitMap |= WIFI_BITRATE_24MBPS;
11592 else if (strcmp(rate, "36") == 0)
11593 BitMap |= WIFI_BITRATE_36MBPS;
11594 else if (strcmp(rate, "48") == 0)
11595 BitMap |= WIFI_BITRATE_48MBPS;
11596 else if (strcmp(rate, "54") == 0)
11597 BitMap |= WIFI_BITRATE_54MBPS;
11598 rate = strtok(NULL, ",");
11599 }
11600 *basicRateBitMap = BitMap;
11601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11602 return RETURN_OK;
11603}
11604
11605// 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 +080011606INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11607{
developer1e5aa162022-09-13 16:06:24 +080011608 char buf[128] = {0};
11609 char cmd[128] = {0};
11610 char config_file[64] = {0};
11611 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011612 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011613 wifi_radio_operationParam_t current_param;
11614
11615 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11616
11617 multiple_set = TRUE;
11618 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11619 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11620 return RETURN_ERR;
11621 }
11622 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11623 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11624 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11625 return RETURN_ERR;
11626 }
11627 }
developer5884e982022-10-06 10:52:50 +080011628
11629 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11630 bandwidth = 20;
11631 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11632 bandwidth = 40;
11633 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11634 bandwidth = 80;
11635 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11636 bandwidth = 160;
11637 if (operationParam->autoChannelEnabled){
11638 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11639 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11640 return RETURN_ERR;
11641 }
11642 }else{
developer1e5aa162022-09-13 16:06:24 +080011643 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11644 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11645 return RETURN_ERR;
11646 }
11647 }
developer5884e982022-10-06 10:52:50 +080011648
developer1e5aa162022-09-13 16:06:24 +080011649 if (current_param.variant != operationParam->variant) {
11650 // Two different definition bit map, so need to check every bit.
11651 if (operationParam->variant & WIFI_80211_VARIANT_A)
11652 set_mode |= WIFI_MODE_A;
11653 if (operationParam->variant & WIFI_80211_VARIANT_B)
11654 set_mode |= WIFI_MODE_B;
11655 if (operationParam->variant & WIFI_80211_VARIANT_G)
11656 set_mode |= WIFI_MODE_G;
11657 if (operationParam->variant & WIFI_80211_VARIANT_N)
11658 set_mode |= WIFI_MODE_N;
11659 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11660 set_mode |= WIFI_MODE_AC;
11661 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11662 set_mode |= WIFI_MODE_AX;
11663 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11664 memset(buf, 0, sizeof(buf));
11665 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11666 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11667 return RETURN_ERR;
11668 }
11669 }
11670 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11671 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11672 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11673 return RETURN_ERR;
11674 }
11675 }
11676 if (current_param.beaconInterval != operationParam->beaconInterval) {
11677 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11678 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11679 return RETURN_ERR;
11680 }
11681 }
11682 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11683 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11684 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11685 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11686 return RETURN_ERR;
11687 }
11688 }
11689 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11690 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11691 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11692 return RETURN_ERR;
11693 }
11694 }
11695 if (current_param.guardInterval != operationParam->guardInterval) {
11696 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11697 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11698 return RETURN_ERR;
11699 }
11700 }
11701 if (current_param.transmitPower != operationParam->transmitPower) {
11702 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11703 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11704 return RETURN_ERR;
11705 }
11706 }
11707 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11708 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11709 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11710 return RETURN_ERR;
11711 }
11712 }
11713 if (current_param.obssCoex != operationParam->obssCoex) {
11714 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11715 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11716 return RETURN_ERR;
11717 }
11718 }
11719 if (current_param.stbcEnable != operationParam->stbcEnable) {
11720 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11721 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11722 return RETURN_ERR;
11723 }
11724 }
11725 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11726 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11727 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11728 return RETURN_ERR;
11729 }
11730 }
11731
11732 // if enable is true, then restart the radio
11733 wifi_setRadioEnable(index, FALSE);
11734 if (operationParam->enable == TRUE)
11735 wifi_setRadioEnable(index, TRUE);
11736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11737
developer06a01d92022-09-07 16:32:39 +080011738 return RETURN_OK;
11739}
11740
11741INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11742{
developer1e5aa162022-09-13 16:06:24 +080011743 char band[64] = {0};
11744 char buf[256] = {0};
11745 char config_file[64] = {0};
11746 char cmd[128] = {0};
11747 int ret = RETURN_ERR;
11748 int mode = 0;
11749 ULONG channel = 0;
11750 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011751
11752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11753 printf("Entering %s index = %d\n", __func__, (int)index);
11754
developer1e5aa162022-09-13 16:06:24 +080011755 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11756 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11757 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011758 {
developer1e5aa162022-09-13 16:06:24 +080011759 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011760 return RETURN_ERR;
11761 }
11762 operationParam->enable = enabled;
11763
11764 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011765 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011766 {
developer1e5aa162022-09-13 16:06:24 +080011767 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011768 return RETURN_ERR;
11769 }
11770
11771 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011772 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011773 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011774 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011775 else if (!strcmp(band, "6GHz"))
11776 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011777 else
11778 {
developer1e5aa162022-09-13 16:06:24 +080011779 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011780 band);
11781 }
11782
developer1e5aa162022-09-13 16:06:24 +080011783 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11784 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11785 operationParam->channel = 0;
11786 operationParam->autoChannelEnabled = TRUE;
11787 } else {
11788 operationParam->channel = strtol(buf, NULL, 10);
11789 operationParam->autoChannelEnabled = FALSE;
11790 }
11791
developer06a01d92022-09-07 16:32:39 +080011792 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011793 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11794 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11795 return RETURN_ERR;
11796 }
developer06a01d92022-09-07 16:32:39 +080011797 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11798 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11799 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011800 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11801 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011802 else
11803 {
developer1e5aa162022-09-13 16:06:24 +080011804 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11805 return false;
developer06a01d92022-09-07 16:32:39 +080011806 }
11807
developer1e5aa162022-09-13 16:06:24 +080011808 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11809 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11810 return RETURN_ERR;
11811 }
11812 // Two different definition bit map, so need to check every bit.
11813 if (mode & WIFI_MODE_A)
11814 operationParam->variant |= WIFI_80211_VARIANT_A;
11815 if (mode & WIFI_MODE_B)
11816 operationParam->variant |= WIFI_80211_VARIANT_B;
11817 if (mode & WIFI_MODE_G)
11818 operationParam->variant |= WIFI_80211_VARIANT_G;
11819 if (mode & WIFI_MODE_N)
11820 operationParam->variant |= WIFI_80211_VARIANT_N;
11821 if (mode & WIFI_MODE_AC)
11822 operationParam->variant |= WIFI_80211_VARIANT_AC;
11823 if (mode & WIFI_MODE_AX)
11824 operationParam->variant |= WIFI_80211_VARIANT_AX;
11825 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11826 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11827 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011828 }
developer1e5aa162022-09-13 16:06:24 +080011829 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11830 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11831 return RETURN_ERR;
11832 }
11833 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11834 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11835 return RETURN_ERR;
11836 }
developer06a01d92022-09-07 16:32:39 +080011837
developer1e5aa162022-09-13 16:06:24 +080011838 memset(buf, 0, sizeof(buf));
11839 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11840 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11841 return RETURN_ERR;
11842 }
11843 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11844
11845 memset(buf, 0, sizeof(buf));
11846 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11847 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11848 return RETURN_ERR;
11849 }
11850 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11851
11852 memset(buf, 0, sizeof(buf));
11853 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11854 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11855
11856 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11857 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11858 return RETURN_ERR;
11859 }
11860 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11861 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11862 return RETURN_ERR;
11863 }
11864
11865 memset(buf, 0, sizeof(buf));
11866 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11867 if (strcmp(buf, "-1") == 0) {
11868 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11869 operationParam->ctsProtection = FALSE;
11870 } else {
11871 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11872 operationParam->ctsProtection = TRUE;
11873 }
11874
11875 memset(buf, 0, sizeof(buf));
11876 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11877 if (strcmp(buf, "0") == 0)
11878 operationParam->obssCoex = FALSE;
11879 else
11880 operationParam->obssCoex = TRUE;
11881
11882 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11883 _syscmd(cmd, buf, sizeof(buf));
11884 if (strlen(buf) != 0)
11885 operationParam->stbcEnable = TRUE;
11886 else
11887 operationParam->stbcEnable = FALSE;
11888
11889 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11890 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11891 return RETURN_ERR;
11892 }
11893
11894 // Below value is hardcoded
11895
11896 operationParam->numSecondaryChannels = 0;
11897 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11898 operationParam->channelSecondary[i] = 0;
11899 }
11900 operationParam->csa_beacon_count = 15;
11901 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011902
11903 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11904 return RETURN_OK;
11905}
11906
11907static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11908{
developerc086fb72022-10-04 10:18:22 +080011909 int max_radio_num = 0;
11910
11911 wifi_getMaxRadioNumber(&max_radio_num);
11912 if (radioIndex >= max_radio_num || radioIndex < 0) {
11913 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11914 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011915 }
11916
developerc086fb72022-10-04 10:18:22 +080011917 return (arrayIndex * max_radio_num) + radioIndex;
11918}
developer06a01d92022-09-07 16:32:39 +080011919
developerc086fb72022-10-04 10:18:22 +080011920wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11921 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11922 return WIFI_BITRATE_1MBPS;
11923 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11924 return WIFI_BITRATE_2MBPS;
11925 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11926 return WIFI_BITRATE_5_5MBPS;
11927 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11928 return WIFI_BITRATE_6MBPS;
11929 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11930 return WIFI_BITRATE_9MBPS;
11931 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11932 return WIFI_BITRATE_11MBPS;
11933 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11934 return WIFI_BITRATE_12MBPS;
11935 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11936 return WIFI_BITRATE_18MBPS;
11937 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11938 return WIFI_BITRATE_24MBPS;
11939 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11940 return WIFI_BITRATE_36MBPS;
11941 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11942 return WIFI_BITRATE_48MBPS;
11943 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11944 return WIFI_BITRATE_54MBPS;
11945 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011946}
11947
developer1d57d002022-10-12 18:03:15 +080011948INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
11949{
11950 if (beacon == WIFI_BITRATE_1MBPS)
11951 strcpy(beacon_str, "1Mbps");
11952 else if (beacon == WIFI_BITRATE_2MBPS)
11953 strcpy(beacon_str, "2Mbps");
11954 else if (beacon == WIFI_BITRATE_5_5MBPS)
11955 strcpy(beacon_str, "5.5Mbps");
11956 else if (beacon == WIFI_BITRATE_6MBPS)
11957 strcpy(beacon_str, "6Mbps");
11958 else if (beacon == WIFI_BITRATE_9MBPS)
11959 strcpy(beacon_str, "9Mbps");
11960 else if (beacon == WIFI_BITRATE_11MBPS)
11961 strcpy(beacon_str, "11Mbps");
11962 else if (beacon == WIFI_BITRATE_12MBPS)
11963 strcpy(beacon_str, "12Mbps");
11964 else if (beacon == WIFI_BITRATE_18MBPS)
11965 strcpy(beacon_str, "18Mbps");
11966 else if (beacon == WIFI_BITRATE_24MBPS)
11967 strcpy(beacon_str, "24Mbps");
11968 else if (beacon == WIFI_BITRATE_36MBPS)
11969 strcpy(beacon_str, "36Mbps");
11970 else if (beacon == WIFI_BITRATE_48MBPS)
11971 strcpy(beacon_str, "48Mbps");
11972 else if (beacon == WIFI_BITRATE_54MBPS)
11973 strcpy(beacon_str, "54Mbps");
11974 return RETURN_OK;
11975}
11976
developer06a01d92022-09-07 16:32:39 +080011977INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11978{
developerc086fb72022-10-04 10:18:22 +080011979 INT mode = 0;
11980 INT ret = -1;
11981 INT output = 0;
11982 int i = 0;
11983 int vap_index = 0;
11984 BOOL enabled = FALSE;
11985 char buf[256] = {0};
11986 wifi_vap_security_t security;
11987 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011988
11989 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11990 printf("Entering %s index = %d\n", __func__, (int)index);
11991
developer06a01d92022-09-07 16:32:39 +080011992 for (i = 0; i < 5; i++)
11993 {
developerc086fb72022-10-04 10:18:22 +080011994 map->vap_array[i].radio_index = index;
11995
developer06a01d92022-09-07 16:32:39 +080011996 vap_index = array_index_to_vap_index(index, i);
11997 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011998 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011999
developerc086fb72022-10-04 10:18:22 +080012000 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012001
12002 map->vap_array[i].vap_index = vap_index;
12003
12004 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012005 ret = wifi_getApName(vap_index, buf);
12006 if (ret != RETURN_OK) {
12007 printf("%s: wifi_getApName return error\n", __func__);
12008 return RETURN_ERR;
12009 }
12010 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12011
12012 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012013 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012014 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012015 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012016 return RETURN_ERR;
12017 }
12018 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 +080012019
12020 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012021 if (ret != RETURN_OK) {
12022 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012023 return RETURN_ERR;
12024 }
12025 map->vap_array[i].u.bss_info.enabled = enabled;
12026
developerc086fb72022-10-04 10:18:22 +080012027 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12028 if (ret != RETURN_OK) {
12029 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12030 return RETURN_ERR;
12031 }
developer06a01d92022-09-07 16:32:39 +080012032 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012033
12034 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12035 if (ret != RETURN_OK) {
12036 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12037 return RETURN_ERR;
12038 }
12039 map->vap_array[i].u.bss_info.isolation = enabled;
12040
12041 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12042 if (ret != RETURN_OK) {
12043 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12044 return RETURN_ERR;
12045 }
12046 map->vap_array[i].u.bss_info.bssMaxSta = output;
12047
12048 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12049 if (ret != RETURN_OK) {
12050 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12051 return RETURN_ERR;
12052 }
12053 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012054
developerc086fb72022-10-04 10:18:22 +080012055 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12056 if (ret != RETURN_OK) {
12057 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12058 return RETURN_ERR;
12059 }
12060 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012061
developerc086fb72022-10-04 10:18:22 +080012062 ret = wifi_getApSecurity(vap_index, &security);
12063 if (ret != RETURN_OK) {
12064 printf("%s: wifi_getApSecurity return error\n", __func__);
12065 return RETURN_ERR;
12066 }
12067 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012068
developerc086fb72022-10-04 10:18:22 +080012069 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12070 if (ret != RETURN_OK) {
12071 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12072 return RETURN_ERR;
12073 }
12074 if (mode == 0)
12075 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12076 else
12077 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12078 if (mode == 1)
12079 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12080 else if (mode == 2)
12081 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012082
developerc086fb72022-10-04 10:18:22 +080012083 ret = wifi_getApWmmEnable(vap_index, &enabled);
12084 if (ret != RETURN_OK) {
12085 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12086 return RETURN_ERR;
12087 }
12088 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012089
developerc086fb72022-10-04 10:18:22 +080012090 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12091 if (ret != RETURN_OK) {
12092 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012093 return RETURN_ERR;
12094 }
developerc086fb72022-10-04 10:18:22 +080012095 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012096
12097 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012098 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012099 if (ret != RETURN_OK) {
12100 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12101 return RETURN_ERR;
12102 }
12103 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012104
developerc086fb72022-10-04 10:18:22 +080012105 memset(buf, 0, sizeof(buf));
12106 ret = wifi_getBaseBSSID(vap_index, buf);
12107 if (ret != RETURN_OK) {
12108 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12109 return RETURN_ERR;
12110 }
12111 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12112 &map->vap_array[i].u.bss_info.bssid[0],
12113 &map->vap_array[i].u.bss_info.bssid[1],
12114 &map->vap_array[i].u.bss_info.bssid[2],
12115 &map->vap_array[i].u.bss_info.bssid[3],
12116 &map->vap_array[i].u.bss_info.bssid[4],
12117 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012118 // 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]);
12119
12120 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12121 if (ret != RETURN_OK) {
12122 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12123 return RETURN_ERR;
12124 }
12125 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012126
developerc086fb72022-10-04 10:18:22 +080012127 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012128 }
12129 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12130 return RETURN_OK;
12131}
12132
12133INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12134{
12135 unsigned int i;
12136 wifi_vap_info_t *vap_info = NULL;
12137 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012138 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012139 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012140 char buf[256] = {0};
12141 char cmd[128] = {0};
12142 char config_file[64] = {0};
12143 char bssid[32] = {0};
12144 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012145
12146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12147 printf("Entering %s index = %d\n", __func__, (int)index);
12148 for (i = 0; i < map->num_vaps; i++)
12149 {
developer1d57d002022-10-12 18:03:15 +080012150 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012151 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012152 if (vap_info->u.bss_info.enabled == FALSE)
12153 continue;
developer06a01d92022-09-07 16:32:39 +080012154
developer1d57d002022-10-12 18:03:15 +080012155 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12156
12157 // multi-ap need to copy current radio config
12158 if (vap_info->radio_index != vap_info->vap_index) {
12159 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12160 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012161 }
developer06a01d92022-09-07 16:32:39 +080012162
developer1d57d002022-10-12 18:03:15 +080012163 struct params params[3];
12164 snprintf(vap_info->vap_name, 64, "%s%d", AP_PREFIX, vap_info->vap_index);
12165 params[0].name = "interface";
12166 params[0].value = vap_info->vap_name;
12167 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12168 params[1].name = "bssid";
12169 params[1].value = bssid;
12170 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12171 params[2].name = "wpa_psk_file";
12172 params[2].value = psk_file;
12173
12174 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12175 wifi_hostapdWrite(config_file, params, 3);
12176
12177 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12178 _syscmd(cmd, buf, sizeof(buf));
12179
12180 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12181 if (ret != RETURN_OK) {
12182 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12183 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012184 }
developer1d57d002022-10-12 18:03:15 +080012185
12186 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12187 if (ret != RETURN_OK) {
12188 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12189 return RETURN_ERR;
12190 }
12191
12192 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12193 if (ret != RETURN_OK) {
12194 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12195 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012196 }
12197
developer1d57d002022-10-12 18:03:15 +080012198 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12199 if (ret != RETURN_OK) {
12200 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12201 return RETURN_ERR;
12202 }
developer06a01d92022-09-07 16:32:39 +080012203
developer1d57d002022-10-12 18:03:15 +080012204 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12205 if (ret != RETURN_OK) {
12206 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12207 return RETURN_ERR;
12208 }
developer06a01d92022-09-07 16:32:39 +080012209
developer1d57d002022-10-12 18:03:15 +080012210 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12211 if (ret != RETURN_OK) {
12212 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12213 return RETURN_ERR;
12214 }
12215
developer804c64f2022-10-19 13:54:40 +080012216 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012217 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012218 }else {
12219 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012220 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012221 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12222 _syscmd(cmd, buf, sizeof(buf));
12223 }else{
developer1d57d002022-10-12 18:03:15 +080012224 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012225 }
developer1d57d002022-10-12 18:03:15 +080012226 }
12227
12228 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12229 if (ret != RETURN_OK) {
12230 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12231 return RETURN_ERR;
12232 }
12233
12234 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12235 if (ret != RETURN_OK) {
12236 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12237 return RETURN_ERR;
12238 }
12239
12240 memset(buf, 0, sizeof(buf));
12241 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12242 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12243 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12244 if (ret != RETURN_OK) {
12245 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12246 return RETURN_ERR;
12247 }
12248
12249 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12250 if (ret != RETURN_OK) {
12251 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12252 return RETURN_ERR;
12253 }
12254
12255 wifi_setApEnable(vap_info->vap_index, TRUE);
12256 multiple_set = FALSE;
12257
12258 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12259 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12260 if (ret != RETURN_OK) {
12261 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12262 return RETURN_ERR;
12263 }
12264
12265 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12266 if (ret != RETURN_OK) {
12267 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12268 return RETURN_ERR;
12269 }
developer06a01d92022-09-07 16:32:39 +080012270
developer1d57d002022-10-12 18:03:15 +080012271 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012272 }
12273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12274 return RETURN_OK;
12275}
12276
12277int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12278{
12279 char *token, *next;
12280 const char s[2] = ",";
12281 int count =0;
12282
12283 /* get the first token */
12284 token = strtok_r(pchannels, s, &next);
12285
12286 /* walk through other tokens */
12287 while( token != NULL && count < MAX_CHANNELS) {
12288 chlistptr->channels_list[count++] = atoi(token);
12289 token = strtok_r(NULL, s, &next);
12290 }
12291
12292 return count;
12293}
12294
12295static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12296{
12297 INT status;
12298 wifi_channels_list_t *chlistp;
12299 CHAR output_string[64];
12300 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012301 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012302 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012303
12304 if(rcap == NULL)
12305 {
12306 return RETURN_ERR;
12307 }
12308
12309 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012310 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012311
developer1e5aa162022-09-13 16:06:24 +080012312 if (band == band_2_4)
12313 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12314 else if (band == band_5)
12315 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12316 else if (band == band_6)
12317 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012318
12319 chlistp = &(rcap->channel_list[0]);
12320 memset(pchannels, 0, sizeof(pchannels));
12321
12322 /* possible number of radio channels */
12323 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12324 {
12325 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12326 }
12327 /* Number of channels and list*/
12328 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12329
12330 /* autoChannelSupported */
12331 /* always ON with wifi_getRadioAutoChannelSupported */
12332 rcap->autoChannelSupported = TRUE;
12333
12334 /* DCSSupported */
12335 /* always ON with wifi_getRadioDCSSupported */
12336 rcap->DCSSupported = TRUE;
12337
12338 /* zeroDFSSupported - TBD */
12339 rcap->zeroDFSSupported = FALSE;
12340
12341 /* Supported Country List*/
12342 memset(output_string, 0, sizeof(output_string));
12343 status = wifi_getRadioCountryCode(radioIndex, output_string);
12344 if( status != 0 ) {
12345 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12346 return RETURN_ERR;
12347 } else {
12348 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12349 }
12350 if(!strcmp(output_string,"US")){
12351 rcap->countrySupported[0] = wifi_countrycode_US;
12352 rcap->countrySupported[1] = wifi_countrycode_CA;
12353 } else if (!strcmp(output_string,"CA")) {
12354 rcap->countrySupported[0] = wifi_countrycode_CA;
12355 rcap->countrySupported[1] = wifi_countrycode_US;
12356 } else {
12357 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12358 }
12359
12360 rcap->numcountrySupported = 2;
12361
12362 /* csi */
12363 rcap->csi.maxDevices = 8;
12364 rcap->csi.soudingFrameSupported = TRUE;
12365
developer033b37b2022-10-18 11:27:46 +080012366 phyId = radio_index_to_phy(radioIndex);
12367 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012368
12369 /* channelWidth - all supported bandwidths */
12370 int i=0;
12371 rcap->channelWidth[i] = 0;
12372 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12373 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12374 WIFI_CHANNELBANDWIDTH_40MHZ);
12375
12376 }
developer1e5aa162022-09-13 16:06:24 +080012377 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012378 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12379 WIFI_CHANNELBANDWIDTH_40MHZ |
12380 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12381 }
12382
12383
12384 /* mode - all supported variants */
12385 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12386 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012387 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 +080012388 }
12389 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012390 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12391 }
12392 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12393 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012394 }
12395 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12396 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12397
12398 /* supportedBitRate - all supported bitrates */
12399 rcap->supportedBitRate[i] = 0;
12400 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12401 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12402 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12403 }
developer1e5aa162022-09-13 16:06:24 +080012404 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012405 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12406 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12407 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12408 }
12409
12410
12411 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12412 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12413 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12414 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12415 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12416 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12417 rcap->cipherSupported = 0;
12418 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12419 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12420
12421 return RETURN_OK;
12422}
12423
12424INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12425{
12426 INT status, radioIndex;
12427 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12428 int iter = 0;
12429 unsigned int j;
12430 wifi_interface_name_idex_map_t *iface_info;
12431
12432 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12433
12434 memset(cap, 0, sizeof(wifi_hal_capability_t));
12435
12436 /* version */
12437 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12438 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12439
12440 /* number of radios platform property */
12441 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12442 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012443 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012444
12445 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12446 {
12447 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12448 if (status != 0) {
12449 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12450 return RETURN_ERR;
12451 }
12452
12453 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12454 {
developer804c64f2022-10-19 13:54:40 +080012455 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012456 {
12457 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12458 return RETURN_ERR;
12459 }
12460 iface_info = &cap->wifi_prop.interface_map[iter];
12461 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12462 iface_info->rdk_radio_index = radioIndex;
12463 memset(output, 0, sizeof(output));
12464 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12465 {
12466 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12467 }
12468 // TODO: bridge name
12469 // TODO: vlan id
12470 // TODO: primary
12471 iface_info->index = array_index_to_vap_index(radioIndex, j);
12472 memset(output, 0, sizeof(output));
12473 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12474 {
12475 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12476 }
12477 iter++;
12478 }
12479 }
12480
12481 cap->BandSteeringSupported = FALSE;
12482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12483 return RETURN_OK;
12484}
12485
developer9df4e652022-10-11 11:27:38 +080012486INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12487{
12488 struct params h_config={0};
12489 char config_file[64] = {0};
12490
12491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12492
12493 h_config.name = "okc";
12494 h_config.value = okc_enable?"1":"0";
12495
12496 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12497 wifi_hostapdWrite(config_file, &h_config, 1);
12498 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12499
12500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12501 return RETURN_OK;
12502}
12503
12504INT wifi_setSAEMFP(int ap_index, BOOL enable)
12505{
12506 struct params h_config={0};
12507 char config_file[64] = {0};
12508 char buf[128] = {0};
12509
12510 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12511
12512 h_config.name = "sae_require_mfp";
12513 h_config.value = enable?"1":"0";
12514
12515 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12516 wifi_hostapdWrite(config_file, &h_config, 1);
12517 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12518
12519 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12520 return RETURN_OK;
12521}
12522
12523INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12524{
12525 struct params h_config={0};
12526 char config_file[64] = {0};
12527 char buf[128] = {0};
12528
12529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12530
12531 h_config.name = "sae_pwe";
12532 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12533 h_config.value = buf;
12534
12535 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12536 wifi_hostapdWrite(config_file, &h_config, 1);
12537 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12538
12539 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12540 return RETURN_OK;
12541}
12542
12543INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12544{
12545 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12546 struct params h_config={0};
12547 char config_file[64] = {0};
12548
12549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12550
12551 h_config.name = "wpa_disable_eapol_key_retries";
12552 h_config.value = disable_EAPOL_retries?"1":"0";
12553
12554 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12555 wifi_hostapdWrite(config_file, &h_config, 1);
12556 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12557
12558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12559 return RETURN_OK;
12560}
12561
developer06a01d92022-09-07 16:32:39 +080012562INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12563{
developer587c1b62022-09-27 15:58:59 +080012564 char buf[128] = {0};
12565 char config_file[128] = {0};
12566 char password[64] = {0};
12567 char mfp[32] = {0};
12568 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012569 BOOL okc_enable = FALSE;
12570 BOOL sae_MFP = FALSE;
12571 BOOL disable_EAPOL_retries = TRUE;
12572 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012573 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012574 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012575
12576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12577
12578 multiple_set = TRUE;
12579 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12580 if (security->mode == wifi_security_mode_none) {
12581 strcpy(wpa_mode, "None");
12582 } else if (security->mode == wifi_security_mode_wpa_personal)
12583 strcpy(wpa_mode, "WPA-Personal");
12584 else if (security->mode == wifi_security_mode_wpa2_personal)
12585 strcpy(wpa_mode, "WPA2-Personal");
12586 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12587 strcpy(wpa_mode, "WPA-WPA2-Personal");
12588 else if (security->mode == wifi_security_mode_wpa_enterprise)
12589 strcpy(wpa_mode, "WPA-Enterprise");
12590 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12591 strcpy(wpa_mode, "WPA2-Enterprise");
12592 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12593 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012594 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012595 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012596 okc_enable = TRUE;
12597 sae_MFP = TRUE;
12598 sae_pwe = 2;
12599 disable_EAPOL_retries = FALSE;
12600 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012601 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012602 okc_enable = TRUE;
12603 sae_MFP = TRUE;
12604 sae_pwe = 2;
12605 disable_EAPOL_retries = FALSE;
12606 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012607 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012608 sae_MFP = TRUE;
12609 sae_pwe = 2;
12610 disable_EAPOL_retries = FALSE;
12611 }
12612
12613 band = wifi_index_to_band(ap_index);
12614 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12615 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12616 return RETURN_ERR;
12617 }
developer587c1b62022-09-27 15:58:59 +080012618
12619 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012620 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012621 wifi_setSAEMFP(ap_index, sae_MFP);
12622 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012623 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012624
developer9df4e652022-10-11 11:27:38 +080012625 if (security->mode != wifi_security_mode_none) {
12626 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12627 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12628 password[63] = '\0';
12629 wifi_setApSecurityKeyPassphrase(ap_index, password);
12630 }
12631 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12632 params.name = "sae_password";
12633 params.value = security->u.key.key;
12634 wifi_hostapdWrite(config_file, &params, 1);
12635 }
12636 }
developer587c1b62022-09-27 15:58:59 +080012637
12638 if (security->mode != wifi_security_mode_none) {
12639 memset(&params, 0, sizeof(params));
12640 params.name = "wpa_pairwise";
12641 if (security->encr == wifi_encryption_tkip)
12642 params.value = "TKIP";
12643 else if (security->encr == wifi_encryption_aes)
12644 params.value = "CCMP";
12645 else if (security->encr == wifi_encryption_aes_tkip)
12646 params.value = "TKIP CCMP";
12647 wifi_hostapdWrite(config_file, &params, 1);
12648 }
12649
12650 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012651 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012652 else if (security->mfp == wifi_mfp_cfg_optional)
12653 strcpy(mfp, "Optional");
12654 else if (security->mfp == wifi_mfp_cfg_required)
12655 strcpy(mfp, "Required");
12656 wifi_setApSecurityMFPConfig(ap_index, mfp);
12657
12658 memset(&params, 0, sizeof(params));
12659 params.name = "transition_disable";
12660 if (security->wpa3_transition_disable == TRUE)
12661 params.value = "0x01";
12662 else
12663 params.value = "0x00";
12664 wifi_hostapdWrite(config_file, &params, 1);
12665
12666 memset(&params, 0, sizeof(params));
12667 params.name = "wpa_group_rekey";
12668 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12669 params.value = buf;
12670 wifi_hostapdWrite(config_file, &params, 1);
12671
12672 memset(&params, 0, sizeof(params));
12673 params.name = "wpa_strict_rekey";
12674 params.value = security->strict_rekey?"1":"0";
12675 wifi_hostapdWrite(config_file, &params, 1);
12676
12677 memset(&params, 0, sizeof(params));
12678 params.name = "wpa_pairwise_update_count";
12679 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12680 params.value = buf;
12681 wifi_hostapdWrite(config_file, &params, 1);
12682
12683 memset(&params, 0, sizeof(params));
12684 params.name = "disable_pmksa_caching";
12685 params.value = security->disable_pmksa_caching?"1":"0";
12686 wifi_hostapdWrite(config_file, &params, 1);
12687
12688 wifi_setApEnable(ap_index, FALSE);
12689 wifi_setApEnable(ap_index, TRUE);
12690
12691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12692
developer06a01d92022-09-07 16:32:39 +080012693 return RETURN_OK;
12694}
12695
12696INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12697{
developer9df4e652022-10-11 11:27:38 +080012698 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012699 char config_file[128] = {0};
12700 int disable = 0;
12701 // struct params params = {0};
12702
12703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12704 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12705 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12706 security->mode = wifi_security_mode_none;
12707 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012708 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012709 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012710 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012711 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012712 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012713 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012714 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012715 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012716 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012717 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012718 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012719 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012720 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012721 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012722 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012723 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012724 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012725 security->mode = wifi_security_mode_wpa3_enterprise;
12726 }
12727
12728 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12729 if (security->mode == wifi_security_mode_none)
12730 security->encr = wifi_encryption_none;
12731 else {
12732 if (strcmp(buf, "TKIP") == 0)
12733 security->encr = wifi_encryption_tkip;
12734 else if (strcmp(buf, "CCMP") == 0)
12735 security->encr = wifi_encryption_aes;
12736 else
12737 security->encr = wifi_encryption_aes_tkip;
12738 }
12739
developer9df4e652022-10-11 11:27:38 +080012740 if (security->mode != wifi_encryption_none) {
12741 memset(buf, 0, sizeof(buf));
12742 // wpa3 can use one or both configs as password, so we check sae_password first.
12743 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12744 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12745 security->u.key.type = wifi_security_key_type_sae;
12746 } else {
12747 security->u.key.type = wifi_security_key_type_psk;
12748 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12749 }
12750 strncpy(security->u.key.key, buf, sizeof(buf));
12751 security->u.key.key[255] = '\0';
12752 }
12753
developer587c1b62022-09-27 15:58:59 +080012754 memset(buf, 0, sizeof(buf));
12755 wifi_getApSecurityMFPConfig(ap_index, buf);
12756 if (strcmp(buf, "Disabled") == 0)
12757 security->mfp = wifi_mfp_cfg_disabled;
12758 else if (strcmp(buf, "Optional") == 0)
12759 security->mfp = wifi_mfp_cfg_optional;
12760 else if (strcmp(buf, "Required") == 0)
12761 security->mfp = wifi_mfp_cfg_required;
12762
12763 memset(buf, 0, sizeof(buf));
12764 security->wpa3_transition_disable = FALSE;
12765 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12766 disable = strtol(buf, NULL, 16);
12767 if (disable != 0)
12768 security->wpa3_transition_disable = TRUE;
12769
12770 memset(buf, 0, sizeof(buf));
12771 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12772 if (strlen(buf) == 0)
12773 security->rekey_interval = 86400;
12774 else
12775 security->rekey_interval = strtol(buf, NULL, 10);
12776
12777 memset(buf, 0, sizeof(buf));
12778 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12779 if (strlen(buf) == 0)
12780 security->strict_rekey = 1;
12781 else
12782 security->strict_rekey = strtol(buf, NULL, 10);
12783
12784 memset(buf, 0, sizeof(buf));
12785 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12786 if (strlen(buf) == 0)
12787 security->eapol_key_retries = 4;
12788 else
12789 security->eapol_key_retries = strtol(buf, NULL, 10);
12790
12791 memset(buf, 0, sizeof(buf));
12792 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12793 if (strlen(buf) == 0)
12794 security->disable_pmksa_caching = FALSE;
12795 else
12796 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12797
12798 /* TODO
12799 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12800 */
12801 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12802 security->eap_identity_req_timeout = 0;
12803 security->eap_identity_req_retries = 0;
12804 security->eap_req_timeout = 0;
12805 security->eap_req_retries = 0;
12806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012807 return RETURN_OK;
12808}
12809
12810#endif /* WIFI_HAL_VERSION_3 */
12811
12812#ifdef WIFI_HAL_VERSION_3_PHASE2
12813INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12814{
developer13df9332022-09-27 16:53:22 +080012815 char cmd[128] = {0};
12816 char buf[128] = {0};
12817 char *mac_addr = NULL;
12818 BOOL status = FALSE;
12819 size_t len = 0;
12820
12821 if(ap_index > MAX_APS)
12822 return RETURN_ERR;
12823
12824 *output_numDevices = 0;
12825 wifi_getApEnable(ap_index, &status);
12826 if (status == FALSE)
12827 return RETURN_OK;
12828
12829 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12830 _syscmd(cmd, buf, sizeof(buf));
12831
12832 mac_addr = strtok(buf, "\n");
12833 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12834 *output_numDevices = i + 1;
12835 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12836 addr_ptr = output_deviceMacAddressArray[i];
12837 mac_addr_aton(addr_ptr, mac_addr);
12838 mac_addr = strtok(NULL, "\n");
12839 }
12840
12841 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012842}
12843#else
12844INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12845{
12846 char cmd[128];
12847 BOOL status = false;
12848
12849 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12850 return RETURN_ERR;
12851
12852 output_buf[0] = '\0';
12853
12854 wifi_getApEnable(ap_index,&status);
12855 if (!status)
12856 return RETURN_OK;
12857
12858 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12859 _syscmd(cmd, output_buf, output_buf_size);
12860
12861 return RETURN_OK;
12862}
12863#endif
developer2f513ab2022-09-13 14:26:06 +080012864
12865INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12866{
12867 char output[16]={'\0'};
12868 char config_file[MAX_BUF_SIZE] = {0};
12869
12870 if (!enable)
12871 return RETURN_ERR;
12872
12873 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12874 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12875
12876 if (strlen(output) == 0)
12877 *enable = FALSE;
12878 else if (strncmp(output, "1", 1) == 0)
12879 *enable = TRUE;
12880 else
12881 *enable = FALSE;
12882
12883 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12884 return RETURN_OK;
12885}
developer2d9c30f2022-09-13 15:06:14 +080012886
12887INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12888{
developer804c64f2022-10-19 13:54:40 +080012889 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080012890 return RETURN_ERR;
12891 *output_enable=TRUE;
12892 return RETURN_OK;
12893}
developerfd7d2892022-09-13 16:44:53 +080012894
12895INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12896{
12897 char cmd[128] = {0};
12898 char buf[128] = {0};
12899 char line[128] = {0};
12900 size_t len = 0;
12901 ssize_t read = 0;
12902 FILE *f = NULL;
12903 int index = 0;
12904 int exp = 0;
12905 int mantissa = 0;
12906 int duration = 0;
12907 int radio_index = 0;
12908 int max_radio_num = 0;
12909 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080012910 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080012911 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12912
12913 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080012914
developerfd7d2892022-09-13 16:44:53 +080012915 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080012916
12917 phyId = radio_index_to_phy(radio_index);
12918 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080012919 _syscmd(cmd, buf, sizeof(buf));
12920 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12921 if (*numSessionReturned > maxNumberSessions)
12922 *numSessionReturned = maxNumberSessions;
12923 else if (*numSessionReturned < 1) {
12924 *numSessionReturned = 0;
12925 return RETURN_OK;
12926 }
12927
developer033b37b2022-10-18 11:27:46 +080012928 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 +080012929 if ((f = popen(cmd, "r")) == NULL) {
12930 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12931 return RETURN_ERR;
12932 }
12933
12934 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12935 while((read = fgets(line, sizeof(line), f)) != NULL) {
12936 char *tmp = NULL;
12937 strcpy(buf, line);
12938 tmp = strtok(buf, " ");
12939 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12940 tmp = strtok(NULL, " ");
12941 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12942 tmp = strtok(NULL, " ");
12943 if (strstr(tmp, "t")) {
12944 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12945 }
12946 if (strstr(tmp, "a")) {
12947 twtSessions[index].twtParameters.operation.announced = TRUE;
12948 }
12949 tmp = strtok(NULL, " ");
12950 exp = strtol(tmp, NULL, 10);
12951 tmp = strtok(NULL, " ");
12952 mantissa = strtol(tmp, NULL, 10);
12953 tmp = strtok(NULL, " ");
12954 duration = strtol(tmp, NULL, 10);
12955
12956 // only implicit supported
12957 twtSessions[index].twtParameters.operation.implicit = TRUE;
12958 // only individual agreement supported
12959 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12960
12961 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12962 twt_wake_interval = mantissa * (1 << exp);
12963 if (twt_wake_interval/mantissa != (1 << exp)) {
12964 // Overflow handling
12965 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12966 } else {
12967 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12968 }
12969 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12970 index++;
12971 }
12972
12973 pclose(f);
12974 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12975 return RETURN_OK;
12976}