blob: 43de89459b9645c6381d6708920bc35253e7dc80 [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
66#define MAX_BUF_SIZE 128
67#define MAX_CMD_SIZE 1024
68#define MAX_POSSIBLE_CHANNEL_STRING_BUF 512
69#define IF_NAME_SIZE 50
70#define CONFIG_PREFIX "/nvram/hostapd"
71#define ACL_PREFIX "/tmp/hostapd-acl"
developer10adcc12022-09-13 14:39:17 +080072#define DENY_PREFIX "/tmp/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080073//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
75#define VAP_STATUS_FILE "/tmp/vap-status"
developera3c68b92022-09-13 15:27:29 +080076#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080077#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
100#define MAX_APS 10
101#define NUMBER_OF_RADIOS 2
102
103#ifndef AP_PREFIX
104#define AP_PREFIX "wifi"
105#endif
106
107#ifndef RADIO_PREFIX
108#define RADIO_PREFIX "wlan"
109#endif
110
111#define MAX_BUF_SIZE 128
112#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800113#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800114
115//Uncomment to enable debug logs
116//#define WIFI_DEBUG
117
118#ifdef WIFI_DEBUG
119#define wifi_dbg_printf printf
120#define WIFI_ENTRY_EXIT_DEBUG printf
121#else
122#define wifi_dbg_printf(format, args...) printf("")
123#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
124#endif
125
126#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
127#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
128#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
129#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
130#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
131#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
132#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
133#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
134#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
135#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
136
developer4fb0b922022-09-30 14:29:09 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800138
139#define BW_FNAME "/nvram/bw_file.txt"
140
141#define PS_MAX_TID 16
142
143static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
145 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
148 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
150 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
153 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
156 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
158 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
160};
161
162typedef unsigned long long u64;
163
164/* Enum to define WiFi Bands */
165typedef enum
166{
167 band_invalid = -1,
168 band_2_4 = 0,
169 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800170 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800171} wifi_band;
172
developerdb744382022-09-13 15:34:54 +0800173typedef enum {
174 WIFI_MODE_A = 0x01,
175 WIFI_MODE_B = 0x02,
176 WIFI_MODE_G = 0x04,
177 WIFI_MODE_N = 0x08,
178 WIFI_MODE_AC = 0x10,
179 WIFI_MODE_AX = 0x20,
180} wifi_ieee80211_Mode;
181
developer06a01d92022-09-07 16:32:39 +0800182#ifdef WIFI_HAL_VERSION_3
183
184// Return number of elements in array
185#ifndef ARRAY_SIZE
186#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187#endif /* ARRAY_SIZE */
188
189#ifndef ARRAY_AND_SIZE
190#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
191#endif /* ARRAY_AND_SIZE */
192
193#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
194
195typedef struct {
196 int32_t value;
197 int32_t param;
198 intptr_t key;
199 intptr_t data;
200} wifi_secur_list;
201
202wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
203wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
204char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800205static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800206
207static wifi_secur_list map_security[] =
208{
209 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
219 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Transition"),
220 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]={};
273 sscanf(arg, "%x:%x:%x:%x:%x:%x", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
274 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];
292 snprintf(mac_addr, 20, "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
293 return;
294}
295
296static int ieee80211_frequency_to_channel(int freq)
297{
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800299 if (freq == 2484)
300 return 14;
developerf5745ee2022-10-05 16:09:53 +0800301 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
302 else if (freq == 5935)
303 return 2;
developer06a01d92022-09-07 16:32:39 +0800304 else if (freq < 2484)
305 return (freq - 2407) / 5;
306 else if (freq >= 4910 && freq <= 4980)
307 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800308 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800309 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800310 else if (freq <= 45000) /* DMG band lower limit */
311 /* see 802.11ax D6.1 27.3.23.2 */
312 return (freq - 5950) / 5;
313 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800314 return (freq - 56160) / 2160;
315 else
316 return 0;
317}
318
319static int initSock80211(Netlink* nl) {
320 nl->socket = nl_socket_alloc();
321 if (!nl->socket) {
322 fprintf(stderr, "Failing to allocate the sock\n");
323 return -ENOMEM;
324 }
325
326 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
327
328 if (genl_connect(nl->socket)) {
329 fprintf(stderr, "Failed to connect\n");
330 nl_close(nl->socket);
331 nl_socket_free(nl->socket);
332 return -ENOLINK;
333 }
334
335 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
336 if (nl->id< 0) {
337 fprintf(stderr, "interface not found.\n");
338 nl_close(nl->socket);
339 nl_socket_free(nl->socket);
340 return -ENOENT;
341 }
342
343 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
344 if ((!nl->cb)) {
345 fprintf(stderr, "Failed to allocate netlink callback.\n");
346 nl_close(nl->socket);
347 nl_socket_free(nl->socket);
348 return ENOMEM;
349 }
350
351 return nl->id;
352}
353
354static int nlfree(Netlink *nl)
355{
356 nl_cb_put(nl->cb);
357 nl_close(nl->socket);
358 nl_socket_free(nl->socket);
359 return 0;
360}
361
362static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
363 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
364 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
365 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
366};
367
368static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
369};
370
371static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
372};
373
374typedef struct _wifi_channelStats_loc {
375 INT array_size;
376 INT ch_number;
377 BOOL ch_in_pool;
378 INT ch_noise;
379 BOOL ch_radar_noise;
380 INT ch_max_80211_rssi;
381 INT ch_non_80211_noise;
382 INT ch_utilization;
383 ULLONG ch_utilization_total;
384 ULLONG ch_utilization_busy;
385 ULLONG ch_utilization_busy_tx;
386 ULLONG ch_utilization_busy_rx;
387 ULLONG ch_utilization_busy_self;
388 ULLONG ch_utilization_busy_ext;
389} wifi_channelStats_t_loc;
390
391typedef struct wifi_device_info {
392 INT wifi_devIndex;
393 UCHAR wifi_devMacAddress[6];
394 CHAR wifi_devIPAddress[64];
395 BOOL wifi_devAssociatedDeviceAuthentiationState;
396 INT wifi_devSignalStrength;
397 INT wifi_devTxRate;
398 INT wifi_devRxRate;
399} wifi_device_info_t;
400
401#endif
402
403//For 5g Alias Interfaces
404static BOOL priv_flag = TRUE;
405static BOOL pub_flag = TRUE;
406static BOOL Radio_flag = TRUE;
407//wifi_setApBeaconRate(1, beaconRate);
408
developer1e5aa162022-09-13 16:06:24 +0800409BOOL multiple_set = FALSE;
410
developer06a01d92022-09-07 16:32:39 +0800411struct params
412{
413 char * name;
414 char * value;
415};
416
417static int _syscmd(char *cmd, char *retBuf, int retBufSize)
418{
419 FILE *f;
420 char *ptr = retBuf;
421 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
422
423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
424 if((f = popen(cmd, "r")) == NULL) {
425 fprintf(stderr,"\npopen %s error\n", cmd);
426 return RETURN_ERR;
427 }
428
429 while(!feof(f))
430 {
431 *ptr = 0;
432 if(bufSize>=128) {
433 bufbytes=128;
434 } else {
435 bufbytes=bufSize-1;
436 }
437
438 fgets(ptr,bufbytes,f);
439 readbytes=strlen(ptr);
440
441 if(!readbytes)
442 break;
443
444 bufSize-=readbytes;
445 ptr += readbytes;
446 }
447 cmd_ret = pclose(f);
448 retBuf[retBufSize-1]=0;
449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
450
451 return cmd_ret >> 8;
452}
453
developerc707e972022-09-13 15:38:02 +0800454wifi_band wifi_index_to_band(int apIndex)
455{
456 char cmd[128] = {0};
457 char buf[64] = {0};
458 int freq = 0;
developer5884e982022-10-06 10:52:50 +0800459 int i = 0;
developerc707e972022-09-13 15:38:02 +0800460 wifi_band band = band_invalid;
461
462 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5884e982022-10-06 10:52:50 +0800463 while(i < 10){
464 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
465 _syscmd(cmd, buf, sizeof(buf));
466 freq = strtol(buf, NULL, 10);
467 if (freq > 2401 && freq < 2495)
468 band = band_2_4;
469 else if (freq > 5160 && freq < 5915)
470 band = band_5;
471 else if (freq > 5955 && freq < 7125)
472 band = band_6;
473
474 if(band != band_invalid)
475 break;
476
477 i++;
478 sleep(1);
479 }
developerc707e972022-09-13 15:38:02 +0800480
481 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
482 return band;
483}
484
developer06a01d92022-09-07 16:32:39 +0800485static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
486{
487 char cmd[MAX_CMD_SIZE]={'\0'};
488 char buf[MAX_BUF_SIZE]={'\0'};
489 int ret = 0;
490
491 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
492 ret = _syscmd(cmd, buf, sizeof(buf));
493 if ((ret != 0) && (strlen(buf) == 0))
494 return -1;
495 snprintf(output, output_size, "%s", buf);
496
497 return 0;
498}
499
500static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
501{
502 char cmd[MAX_CMD_SIZE]={'\0'};
503 char buf[MAX_BUF_SIZE]={'\0'};
504
505 for(int i=0;i<item_count;i++)
506 {
507 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
508 if (strlen(buf) == 0) //Insert
509 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
510 else //Update
511 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developer5884e982022-10-06 10:52:50 +0800512
developer06a01d92022-09-07 16:32:39 +0800513 if(_syscmd(cmd, buf, sizeof(buf)))
514 return -1;
515 }
516
517 return 0;
518}
519
520static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
521{
developer1e5aa162022-09-13 16:06:24 +0800522 if (multiple_set == TRUE)
523 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800524 char cmd[MAX_CMD_SIZE]="", output[32]="";
525 FILE *fp;
526 int i;
527 //NOTE RELOAD should be done in ApplySSIDSettings
528
529 for(i=0; i<item_count; i++, list++)
530 {
531 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
532 if((fp = popen(cmd, "r"))==NULL)
533 {
534 perror("popen failed");
535 return -1;
536 }
537 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
538 {
539 pclose(fp);
540 perror("fgets failed");
541 return -1;
542 }
543 pclose(fp);
544 }
545 return 0;
546}
547
548static int wifi_reloadAp(int apIndex)
549{
developer1e5aa162022-09-13 16:06:24 +0800550 if (multiple_set == TRUE)
551 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800552 char cmd[MAX_CMD_SIZE]="";
553 char buf[MAX_BUF_SIZE]="";
554
555 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
556 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
557 return RETURN_ERR;
558
559 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
560 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
561 return RETURN_ERR;
562
563 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
564 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
565 return RETURN_ERR;
566
567 return RETURN_OK;
568}
569
570
571//For Getting Current Interface Name from corresponding hostapd configuration
572void GetInterfaceName(char *interface_name, char *conf_file)
573{
574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
575 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
577}
578
579INT File_Reading(CHAR *file, char *Value)
580{
581 FILE *fp = NULL;
582 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
583 int count = 0;
584
585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
586 fp = popen(file,"r");
587 if(fp == NULL)
588 return RETURN_ERR;
589
590 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
591 {
592 for(count=0;buf[count]!='\n';count++)
593 copy_buf[count]=buf[count];
594 copy_buf[count]='\0';
595 }
596 strcpy(Value,copy_buf);
597 pclose(fp);
598 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
599
600 return RETURN_OK;
601}
602
603void wifi_RestartHostapd_2G()
604{
605 int Public2GApIndex = 4;
606
607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
608 wifi_setApEnable(Public2GApIndex, FALSE);
609 wifi_setApEnable(Public2GApIndex, TRUE);
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611}
612
613void wifi_RestartHostapd_5G()
614{
615 int Public5GApIndex = 5;
616
617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
618 wifi_setApEnable(Public5GApIndex, FALSE);
619 wifi_setApEnable(Public5GApIndex, TRUE);
620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
621}
622
623void wifi_RestartPrivateWifi_2G()
624{
625 int PrivateApIndex = 0;
626
627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
628 wifi_setApEnable(PrivateApIndex, FALSE);
629 wifi_setApEnable(PrivateApIndex, TRUE);
630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
631}
632
633void wifi_RestartPrivateWifi_5G()
634{
635 int Private5GApIndex = 1;
636
637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
638 wifi_setApEnable(Private5GApIndex, FALSE);
639 wifi_setApEnable(Private5GApIndex, TRUE);
640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
641}
642
643static int writeBandWidth(int radioIndex,char *bw_value)
644{
645 char buf[MAX_BUF_SIZE];
646 char cmd[MAX_CMD_SIZE];
647
648 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
649 if(_syscmd(cmd, buf, sizeof(buf)))
650 {
651 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
652 _syscmd(cmd, buf, sizeof(buf));
653 return RETURN_OK;
654 }
655
656 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
657 _syscmd(cmd,buf,sizeof(buf));
658 return RETURN_OK;
659}
660
661static int readBandWidth(int radioIndex,char *bw_value)
662{
663 char buf[MAX_BUF_SIZE];
664 char cmd[MAX_CMD_SIZE];
665 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
666 _syscmd(cmd,buf,sizeof(buf));
667 if(NULL!=strstr(buf,"20MHz"))
668 {
669 strcpy(bw_value,"20MHz");
670 }
671 else if(NULL!=strstr(buf,"40MHz"))
672 {
673 strcpy(bw_value,"40MHz");
674 }
675 else if(NULL!=strstr(buf,"80MHz"))
676 {
677 strcpy(bw_value,"80MHz");
678 }
679 else
680 {
681 return RETURN_ERR;
682 }
683 return RETURN_OK;
684}
685
developer39a5efb2022-09-13 16:09:06 +0800686INT wifi_getMaxRadioNumber(INT *max_radio_num)
687{
688 char cmd[64] = {0};
689 char buf[4] = {0};
690
691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
692
693 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
694 _syscmd(cmd, buf, sizeof(buf));
695 *max_radio_num = strtoul(buf, NULL, 10);
696
697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
698
699 return RETURN_OK;
700}
701
developer5f222492022-09-13 15:21:52 +0800702// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800703INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
704{
developer5f222492022-09-13 15:21:52 +0800705 struct params params={'\0'};
706 char config_file[MAX_BUF_SIZE] = {0};
707 char buf[MAX_BUF_SIZE] = {'\0'};
708
709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
710 if (strlen (beaconRate) < 5)
711 return RETURN_ERR;
712 // Copy the numeric value
713 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
714 buf[strlen(beaconRate) - 4] = '\0';
715
716 params.name = "beacon_rate";
717 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
718 if (strncmp(buf, "5.5", 3) == 0) {
719 snprintf(buf, sizeof(buf), "55");
720 params.value = buf;
721 } else {
722 strcat(buf, "0");
723 params.value = buf;
724 }
725
726 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
727 wifi_hostapdWrite(config_file, &params, 1);
728 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
729 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
730
731 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800732}
733
734INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
735{
developer5f222492022-09-13 15:21:52 +0800736 char config_file[MAX_BUF_SIZE] = {'\0'};
737 char temp_output[MAX_BUF_SIZE] = {'\0'};
738 char buf[MAX_BUF_SIZE] = {'\0'};
739 float rate = 0;
740
741 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
742 if (NULL == beaconRate)
743 return RETURN_ERR;
744
745 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
746 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
747 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
748 if(strlen(buf) > 0) {
749 rate = atof(buf)/10;
750 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
751 } else {
752 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
753 }
754 strncpy(beaconRate, temp_output, sizeof(temp_output));
755 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
756
757 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800758}
759
760INT wifi_setLED(INT radioIndex, BOOL enable)
761{
762 return 0;
763}
764INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
765{
766 return RETURN_OK;
767}
768/**********************************************************************************
769 *
770 * Wifi Subsystem level function prototypes
771 *
772**********************************************************************************/
773//---------------------------------------------------------------------------------------------------
774//Wifi system api
775//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
776INT wifi_getHalVersion(CHAR *output_string) //RDKB
777{
778 if(!output_string)
779 return RETURN_ERR;
780 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
781
782 return RETURN_OK;
783}
784
785
786/* wifi_factoryReset() function */
787/**
788* @description Clears internal variables to implement a factory reset of the Wi-Fi
789* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
790*
791* @param None
792*
793* @return The status of the operation.
794* @retval RETURN_OK if successful.
795* @retval RETURN_ERR if any error is detected
796*
797* @execution Synchronous
798* @sideeffect None
799*
800* @note This function must not suspend and must not invoke any blocking system
801* calls. It should probably just send a message to a driver event handler task.
802*
803*/
804INT wifi_factoryReset()
805{
806 char cmd[128];
807
808 /*delete running hostapd conf files*/
809 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
810 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
811 system(cmd);
812 system("systemctl restart hostapd.service");
813
814 return RETURN_OK;
815}
816
817/* wifi_factoryResetRadios() function */
818/**
819* @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.
820*
821* @param None
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*
828* @sideeffect None
829*
830* @note This function must not suspend and must not invoke any blocking system
831* calls. It should probably just send a message to a driver event handler task.
832*
833*/
834INT wifi_factoryResetRadios()
835{
836 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
837 return RETURN_OK;
838
839 return RETURN_ERR;
840}
841
842
843/* wifi_factoryResetRadio() function */
844/**
845* @description Restore selected radio parameters without touching access point parameters
846*
847* @param radioIndex - Index of Wi-Fi Radio channel
848*
849* @return The status of the operation.
850* @retval RETURN_OK if successful.
851* @retval RETURN_ERR if any error is detected
852*
853* @execution Synchronous.
854* @sideeffect None.
855*
856* @note This function must not suspend and must not invoke any blocking system
857* calls. It should probably just send a message to a driver event handler task.
858*
859*/
860INT wifi_factoryResetRadio(int radioIndex) //RDKB
861{
developer5ff7f5f2022-09-13 15:12:16 +0800862 system("systemctl stop hostapd.service");
863
developer06a01d92022-09-07 16:32:39 +0800864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
865 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800866 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800867 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800868 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800869 else
870 return RETURN_ERR;
871
developer5ff7f5f2022-09-13 15:12:16 +0800872 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
874 return RETURN_OK;
875}
876
877/* wifi_initRadio() function */
878/**
879* Description: This function call initializes the specified radio.
880* Implementation specifics may dictate the functionality since
881* different hardware implementations may have different initilization requirements.
882* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
883*
884* @return The status of the operation.
885* @retval RETURN_OK if successful.
886* @retval RETURN_ERR if any error is detected
887*
888* @execution Synchronous.
889* @sideeffect None.
890*
891* @note This function must not suspend and must not invoke any blocking system
892* calls. It should probably just send a message to a driver event handler task.
893*
894*/
895INT wifi_initRadio(INT radioIndex)
896{
897 //TODO: Initializes the wifi subsystem (for specified radio)
898 return RETURN_OK;
899}
900void macfilter_init()
901{
902 char count[4]={'\0'};
903 char buf[253]={'\0'};
904 char tmp[19]={'\0'};
905 int dev_count,block,mac_entry=0;
906 char res[4]={'\0'};
907 char acl_file_path[64] = {'\0'};
908 FILE *fp = NULL;
909 int index=0;
910 char iface[10]={'\0'};
911 char config_file[MAX_BUF_SIZE] = {0};
912
913
914 sprintf(acl_file_path,"/tmp/mac_filter.sh");
915
916 fp=fopen(acl_file_path,"w+");
917 sprintf(buf,"#!/bin/sh \n");
918 fprintf(fp,"%s\n",buf);
919
920 system("chmod 0777 /tmp/mac_filter.sh");
921
922 for(index=0;index<=1;index++)
923 {
924 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
925 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
926 sprintf(buf,"syscfg get %dcountfilter",index);
927 _syscmd(buf,count,sizeof(count));
928 mac_entry=atoi(count);
929
930 sprintf(buf,"syscfg get %dblockall",index);
931 _syscmd(buf,res,sizeof(res));
932 block = atoi(res);
933
934 //Allow only those macs mentioned in ACL
935 if(block==1)
936 {
937 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
938 fprintf(fp,"%s\n",buf);
939 for(dev_count=1;dev_count<=mac_entry;dev_count++)
940 {
941 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
942 _syscmd(buf,tmp,sizeof(tmp));
943 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
944 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
945 fprintf(fp,"%s\n",buf);
946 }
947 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
948 fprintf(fp,"%s\n",buf);
949 }
950
951 //Block all the macs mentioned in ACL
952 else if(block==2)
953 {
954 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
955 fprintf(fp,"%s\n",buf);
956
957 for(dev_count=1;dev_count<=mac_entry;dev_count++)
958 {
959 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
960 _syscmd(buf,tmp,sizeof(tmp));
961 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
962 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
963 fprintf(fp,"%s\n",buf);
964 }
965 }
966 }
967 fclose(fp);
968}
969
970// Initializes the wifi subsystem (all radios)
971INT wifi_init() //RDKB
972{
973 char interface[MAX_BUF_SIZE]={'\0'};
974 char bridge_name[MAX_BUF_SIZE]={'\0'};
975 INT len=0;
976
977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
978 //Not intitializing macfilter for Turris-Omnia Platform for now
979 //macfilter_init();
980
981 system("/usr/sbin/iw reg set US");
982 system("systemctl start hostapd.service");
983 sleep(2);//sleep to wait for hostapd to start
984
985 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
986
987 return RETURN_OK;
988}
989
990/* wifi_reset() function */
991/**
992* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
993* Implementation specifics may dictate what is actualy reset since
994* different hardware implementations may have different requirements.
995* Parameters : None
996*
997* @return The status of the operation.
998* @retval RETURN_OK if successful.
999* @retval RETURN_ERR if any error is detected
1000*
1001* @execution Synchronous.
1002* @sideeffect None.
1003*
1004* @note This function must not suspend and must not invoke any blocking system
1005* calls. It should probably just send a message to a driver event handler task.
1006*
1007*/
1008INT wifi_reset()
1009{
1010 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001011 system("systemctl stop hostapd.service");
1012 sleep(2);
1013 system("systemctl start hostapd.service");
1014 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001015 return RETURN_OK;
1016}
1017
1018/* wifi_down() function */
1019/**
1020* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1021* Implementation specifics may dictate some functionality since
1022* different hardware implementations may have different requirements.
1023*
1024* @param 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_down()
1038{
1039 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001040 system("systemctl stop hostapd.service");
1041 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001042 return RETURN_OK;
1043}
1044
1045
1046/* wifi_createInitialConfigFiles() function */
1047/**
1048* @description This function creates wifi configuration files. The format
1049* and content of these files are implementation dependent. This function call is
1050* used to trigger this task if necessary. Some implementations may not need this
1051* function. If an implementation does not need to create config files the function call can
1052* do nothing and return RETURN_OK.
1053*
1054* @param None
1055*
1056* @return The status of the operation
1057* @retval RETURN_OK if successful
1058* @retval RETURN_ERR if any error is detected
1059*
1060* @execution Synchronous
1061* @sideeffect None
1062*
1063* @note This function must not suspend and must not invoke any blocking system
1064* calls. It should probably just send a message to a driver event handler task.
1065*
1066*/
1067INT wifi_createInitialConfigFiles()
1068{
1069 //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)
1070 return RETURN_OK;
1071}
1072
1073// outputs the country code to a max 64 character string
1074INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1075{
developer7543b3b2022-09-13 13:47:17 +08001076 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1077 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001078 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001079
1080 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1081 _syscmd(cmd, buf, sizeof(buf));
1082 if(strlen(buf) > 0)
1083 snprintf(output_string, 64, "%s", buf);
1084 else
1085 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001086
1087 return RETURN_OK;
1088}
1089
1090INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1091{
1092 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001093 char str[MAX_BUF_SIZE]={'\0'};
1094 char cmd[MAX_CMD_SIZE]={'\0'};
1095 struct params params;
1096 char config_file[MAX_BUF_SIZE] = {0};
1097
1098 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1099 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1100 return RETURN_ERR;
1101
developerb86c6f32022-10-07 14:34:58 +08001102 if (strlen(CountryCode) == 0)
1103 strcpy(CountryCode, "US");
1104
developer7543b3b2022-09-13 13:47:17 +08001105 params.name = "country_code";
1106 params.value = CountryCode;
1107 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1108 int ret = wifi_hostapdWrite(config_file, &params, 1);
1109 if (ret) {
1110 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1111 ,__func__, ret);
1112 }
1113
1114 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1115 if (ret) {
1116 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1117 ,__func__, ret);
1118 }
1119 wifi_reloadAp(radioIndex);
1120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1121
developer06a01d92022-09-07 16:32:39 +08001122 return RETURN_OK;
1123}
1124
developera748dcf2022-09-13 15:56:48 +08001125INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1126{
1127 char channel_util_file[64] = {0};
1128 char cmd[128] = {0};
1129 char buf[128] = {0};
1130 char line[128] = {0};
1131 char *param = NULL, *value = NULL;
1132 int read = 0;
1133 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1134 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1135 size_t len = 0;
1136 FILE *f = NULL;
1137
1138 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1139
1140 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1141 _syscmd(cmd, buf, sizeof(buf));
1142 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1143
1144 memset(cmd, 0, sizeof(cmd));
1145 memset(buf, 0, sizeof(buf));
1146 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1147 if ((f = popen(cmd, "r")) == NULL) {
1148 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1149 return RETURN_ERR;
1150 }
1151
1152 read = getline(&line, &len, f);
1153 while (read != -1) {
1154 param = strtok(line, ":\t");
1155 value = strtok(NULL, " ");
1156 if(strstr(param, "frequency") != NULL) {
1157 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1158 }
1159 if(strstr(param, "noise") != NULL) {
1160 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1161 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1162 }
1163 if(strstr(param, "channel active time") != NULL) {
1164 ActiveTime = strtol(value, NULL, 10);
1165 }
1166 if(strstr(param, "channel busy time") != NULL) {
1167 BusyTime = strtol(value, NULL, 10);
1168 }
1169 if(strstr(param, "channel transmit time") != NULL) {
1170 TransmitTime = strtol(value, NULL, 10);
1171 }
1172 read = getline(&line, &len, f);
1173 }
1174 pclose(f);
1175
1176 // The file should store the last active, busy and transmit time
1177 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1178 f = fopen(channel_util_file, "r");
1179 if (f != NULL) {
1180 read = getline(&line, &len, f);
1181 preActiveTime = strtol(line, NULL, 10);
1182 read = getline(&line, &len, f);
1183 preBusyTime = strtol(line, NULL, 10);
1184 read = getline(&line, &len, f);
1185 preTransmitTime = strtol(line, NULL, 10);
1186 fclose(f);
1187 }
1188
1189 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1190 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1191
1192 f = fopen(channel_util_file, "w");
1193 if (f != NULL) {
1194 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1195 fclose(f);
1196 }
1197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1198 return RETURN_OK;
1199}
1200
developer06a01d92022-09-07 16:32:39 +08001201/**********************************************************************************
1202 *
1203 * Wifi radio level function prototypes
1204 *
1205**********************************************************************************/
1206
1207//Get the total number of radios in this wifi subsystem
1208INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1209{
1210 if (NULL == output)
1211 return RETURN_ERR;
1212 *output = 2;
1213
1214 return RETURN_OK;
1215}
1216
1217//Get the total number of SSID entries in this wifi subsystem
1218INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1219{
1220 if (NULL == output)
1221 return RETURN_ERR;
1222 *output = MAX_APS;
1223
1224 return RETURN_OK;
1225}
1226
1227//Get the Radio enable config parameter
1228INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1229{
1230 char interface_path[MAX_CMD_SIZE] = {0};
1231 FILE *fp = NULL;
1232
1233 if (NULL == output_bool)
1234 return RETURN_ERR;
1235
1236 *output_bool = FALSE;
1237 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1238 return RETURN_ERR;
1239
1240 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1241 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001242 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001243 {
developercf48e482022-09-13 14:49:50 +08001244 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001245 }
1246 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001247 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1248 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1249 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001250
developercf48e482022-09-13 14:49:50 +08001251 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1252 *output_bool = TRUE;
1253 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001254 return RETURN_OK;
1255}
1256
1257INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1258{
1259 char cmd[MAX_CMD_SIZE] = {0};
1260 char buf[MAX_CMD_SIZE] = {0};
1261 int apIndex, ret;
1262 FILE *fp = NULL;
1263
1264 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1265 if(enable==FALSE)
1266 {
1267 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1268 {
1269 //Detaching %s%d from hostapd daemon
1270 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1271 _syscmd(cmd, buf, sizeof(buf));
1272 if(strncmp(buf, "OK", 2))
1273 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1274 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1275 _syscmd(cmd, buf, sizeof(buf));
1276 }
developer456aa3e2022-09-13 14:27:36 +08001277 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001278 _syscmd(cmd, buf, sizeof(buf));
1279 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001280 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001281 }
1282 else
1283 {
developer456aa3e2022-09-13 14:27:36 +08001284 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001285 _syscmd(cmd, buf, sizeof(buf));
1286 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001287 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001288 sleep(1);
1289 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1290 {
1291 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1292 fp = fopen(cmd, "r");
1293 if(!fp)
1294 {
1295 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1296 _syscmd(cmd, buf, sizeof(buf));
1297 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1298 _syscmd(cmd, buf, sizeof(buf));
1299 }
1300 if(fp)
1301 fclose(fp);
1302 }
1303 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1304 {
1305 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1306 ret = _syscmd(cmd, buf, sizeof(buf));
1307 if ( ret == RETURN_ERR)
1308 {
1309 fprintf(stderr, "VAP interface creation failed\n");
1310 continue;
1311 }
1312 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1313 _syscmd(cmd, buf, sizeof(buf));
1314 if(*buf == '1')
1315 {
1316 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1317 radioIndex, apIndex);
1318 _syscmd(cmd, buf, sizeof(buf));
1319 if(strncmp(buf, "OK", 2))
1320 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1321 }
1322 }
1323 }
1324
1325 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1326 return RETURN_OK;
1327}
1328
1329//Get the Radio enable status
1330INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1331{
1332 if (NULL == output_bool)
1333 return RETURN_ERR;
1334
1335 return wifi_getRadioEnable(radioIndex, output_bool);
1336}
1337
1338//Get the Radio Interface name from platform, eg "wlan0"
1339INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1340{
1341 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1342 return RETURN_ERR;
1343 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1344
1345 return RETURN_OK;
1346}
1347
1348//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1349//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.
1350INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1351{
developerbcc556a2022-09-22 20:02:45 +08001352 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1353 // For max bit rate, we should always choose the best MCS
1354 char mode[64] = {0};
1355 char channel_bandwidth_str[16] = {0};
1356 char *tmp = NULL;
1357 UINT mode_map = 0;
1358 UINT num_subcarrier = 0;
1359 UINT code_bits = 0;
1360 float code_rate = 0; // use max code rate
1361 int NSS = 0;
1362 UINT Symbol_duration = 0;
1363 UINT GI_duration = 0;
1364 wifi_band band = band_invalid;
1365 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1366 BOOL enable = FALSE;
1367 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001368
1369 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1370 if (NULL == output_string)
1371 return RETURN_ERR;
1372
developerbcc556a2022-09-22 20:02:45 +08001373 wifi_getRadioEnable(radioIndex, &enable);
1374 if (enable == FALSE) {
1375 snprintf(output_string, 64, "0 Mb/s");
1376 return RETURN_OK;
1377 }
1378
1379 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1380 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1381 return RETURN_ERR;
1382 }
1383
1384 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1385 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1386 return RETURN_ERR;
1387 }
1388
1389 if (gi == wifi_guard_interval_3200)
1390 GI_duration = 32;
1391 else if (gi == wifi_guard_interval_1600)
1392 GI_duration = 16;
1393 else if (gi == wifi_guard_interval_800)
1394 GI_duration = 8;
1395 else // auto, 400
1396 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001397
developerbcc556a2022-09-22 20:02:45 +08001398 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1399 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1400 return RETURN_ERR;
1401 }
1402
1403 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1404 strcpy(channel_bandwidth_str, "160");
1405
1406 if (mode_map & WIFI_MODE_AX) {
1407 if (strstr(channel_bandwidth_str, "160") != NULL)
1408 num_subcarrier = 1960;
1409 else if (strstr(channel_bandwidth_str, "80") != NULL)
1410 num_subcarrier = 980;
1411 else if (strstr(channel_bandwidth_str, "40") != NULL)
1412 num_subcarrier = 468;
1413 else if (strstr(channel_bandwidth_str, "20") != NULL)
1414 num_subcarrier = 234;
1415 code_bits = 10;
1416 code_rate = (float)5/6;
1417 Symbol_duration = 128;
1418 } else if (mode_map & WIFI_MODE_AC) {
1419 if (strstr(channel_bandwidth_str, "160") != NULL)
1420 num_subcarrier = 468;
1421 else if (strstr(channel_bandwidth_str, "80") != NULL)
1422 num_subcarrier = 234;
1423 else if (strstr(channel_bandwidth_str, "40") != NULL)
1424 num_subcarrier = 108;
1425 else if (strstr(channel_bandwidth_str, "20") != NULL)
1426 num_subcarrier = 52;
1427 code_bits = 8;
1428 code_rate = (float)5/6;
1429 Symbol_duration = 32;
1430 } else if (mode_map & WIFI_MODE_N) {
1431 if (strstr(channel_bandwidth_str, "160") != NULL)
1432 num_subcarrier = 468;
1433 else if (strstr(channel_bandwidth_str, "80") != NULL)
1434 num_subcarrier = 234;
1435 else if (strstr(channel_bandwidth_str, "40") != NULL)
1436 num_subcarrier = 108;
1437 else if (strstr(channel_bandwidth_str, "20") != NULL)
1438 num_subcarrier = 52;
1439 code_bits = 6;
1440 code_rate = (float)3/4;
1441 Symbol_duration = 32;
1442 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1443 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1444 snprintf(output_string, 64, "65 Mb/s");
1445 return RETURN_OK;
1446 } else {
1447 snprintf(output_string, 64, "0 Mb/s");
1448 return RETURN_OK;
1449 }
developer06a01d92022-09-07 16:32:39 +08001450
developerbcc556a2022-09-22 20:02:45 +08001451 // Spatial streams
1452 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1453 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1454 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001455 }
developerbcc556a2022-09-22 20:02:45 +08001456
1457 // multiple 10 is to align duration unit (0.1 us)
1458 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1459 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1460
developer06a01d92022-09-07 16:32:39 +08001461 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1462
1463 return RETURN_OK;
1464}
1465#if 0
1466INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1467{
1468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1469 char cmd[64];
1470 char buf[1024];
1471 int apIndex;
1472
1473 if (NULL == output_string)
1474 return RETURN_ERR;
1475
1476 apIndex=(radioIndex==0)?0:1;
1477
1478 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1479 _syscmd(cmd,buf, sizeof(buf));
1480
1481 snprintf(output_string, 64, "%s", buf);
1482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1483 return RETURN_OK;
1484}
1485#endif
1486
1487
1488//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1489//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.
1490INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1491{
developer963da0c2022-09-13 15:58:27 +08001492 wifi_band band = band_invalid;
1493
developer06a01d92022-09-07 16:32:39 +08001494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1495 if (NULL == output_string)
1496 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001497
1498 band = wifi_index_to_band(radioIndex);
1499
1500 memset(output_string, 0, 10);
1501 if (band == band_2_4)
1502 strcpy(output_string, "2.4GHz");
1503 else if (band == band_5)
1504 strcpy(output_string, "5GHz");
1505 else if (band == band_6)
1506 strcpy(output_string, "6GHz");
1507 else
1508 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1510
1511 return RETURN_OK;
1512#if 0
1513 char buf[MAX_BUF_SIZE]={'\0'};
1514 char str[MAX_BUF_SIZE]={'\0'};
1515 char cmd[MAX_CMD_SIZE]={'\0'};
1516 char *ch=NULL;
1517 char *ch2=NULL;
1518
1519 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1520 if (NULL == output_string)
1521 return RETURN_ERR;
1522
1523
1524 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1525
1526 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1527 {
1528 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1529 return RETURN_ERR;
1530 }
1531 ch=strchr(buf,'\n');
1532 *ch='\0';
1533 ch=strchr(buf,'=');
1534 if(ch==NULL)
1535 return RETURN_ERR;
1536
1537
1538 ch++;
1539
1540 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1541 strcpy(buf,"0");
1542 if(strlen(ch) == 1)
1543 ch=strcat(buf,ch);
1544
1545
1546 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1547
1548 if(_syscmd(cmd,str,64) == RETURN_ERR)
1549 {
1550 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1551 return RETURN_ERR;
1552 }
1553
1554
1555 ch2=strchr(str,'\n');
1556 //replace \n with \0
1557 *ch2='\0';
1558 ch2=strchr(str,'=');
1559 if(ch2==NULL)
1560 {
1561 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1562 return RETURN_ERR;
1563 }
1564 else
1565 wifi_dbg_printf("%s",ch2+1);
1566
1567
1568 ch2++;
1569
1570
1571 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1572
1573 memset(buf,'\0',sizeof(buf));
1574 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1575 {
1576 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1577 return RETURN_ERR;
1578 }
1579 if (strstr(buf,"2.4") != NULL )
1580 strcpy(output_string,"2.4GHz");
1581 else if(strstr(buf,"5.") != NULL )
1582 strcpy(output_string,"5GHz");
1583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1584
1585 return RETURN_OK;
1586#endif
1587}
1588
1589//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1590//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.
1591INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1592{
1593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1594 if (NULL == output_string)
1595 return RETURN_ERR;
1596 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1598
1599 return RETURN_OK;
1600#if 0
1601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1602 char buf[MAX_BUF_SIZE]={'\0'};
1603 char str[MAX_BUF_SIZE]={'\0'};
1604 char cmd[MAX_CMD_SIZE]={'\0'};
1605 char *ch=NULL;
1606 char *ch2=NULL;
1607 char ch1[5]="0";
1608
1609 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1610
1611 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1612 {
1613 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1614 return RETURN_ERR;
1615 }
1616
1617 ch=strchr(buf,'\n');
1618 *ch='\0';
1619 ch=strchr(buf,'=');
1620 if(ch==NULL)
1621 return RETURN_ERR;
1622 ch++;
1623
1624 if(strlen(ch)==1)
1625 {
1626 strcat(ch1,ch);
1627
1628 }
1629 else
1630 {
1631 strcpy(ch1,ch);
1632 }
1633
1634
1635
1636 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1637 if(_syscmd(cmd,str,64) == RETURN_ERR)
1638 {
1639 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1640 return RETURN_ERR;
1641 }
1642
1643
1644 ch2=strchr(str,'\n');
1645 //replace \n with \0
1646 *ch2='\0';
1647 ch2=strchr(str,'=');
1648 if(ch2==NULL)
1649 {
1650 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1651 return RETURN_ERR;
1652 }
1653 else
1654 wifi_dbg_printf("%s",ch2+1);
1655 ch2++;
1656
1657
1658 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1659 memset(buf,'\0',sizeof(buf));
1660 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1661 {
1662 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1663 return RETURN_ERR;
1664 }
1665
1666
1667 if(strstr(buf,"2.4")!=NULL)
1668 {
1669 strcpy(output_string,"2.4GHz");
1670 }
1671 if(strstr(buf,"5.")!=NULL)
1672 {
1673 strcpy(output_string,"5GHz");
1674 }
1675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1676 return RETURN_OK;
1677#endif
1678}
1679
1680//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1681//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.
1682INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1683{
developer963da0c2022-09-13 15:58:27 +08001684 char cmd[128]={0};
1685 char buf[128]={0};
1686 char temp_output[128] = {0};
1687 wifi_band band;
1688
1689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001690 if (NULL == output_string)
1691 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001692
1693 band = wifi_index_to_band(radioIndex);
1694 if (band == band_2_4) {
1695 strcat(temp_output, "b,g,");
1696 } else if (band == band_5) {
1697 strcat(temp_output, "a,");
1698 }
1699
1700 // ht capabilities
1701 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
1702 _syscmd(cmd, buf, sizeof(buf));
1703 if (strncmp(buf, "0x00", 4) != 0) {
1704 strcat(temp_output, "n,");
1705 }
developer06a01d92022-09-07 16:32:39 +08001706
developer963da0c2022-09-13 15:58:27 +08001707 // vht capabilities
1708 if (band == band_5) {
1709 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1710 _syscmd(cmd, buf, sizeof(buf));
1711 if (strncmp(buf, "0x00000000", 10) != 0) {
1712 strcat(temp_output, "ac,");
1713 }
1714 }
1715
1716 // he capabilities
1717 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", radioIndex);
1718 _syscmd(cmd, buf, sizeof(buf));
1719 if (strncmp (buf, "0x0000", 6) != 0) {
1720 strcat(temp_output, "ax,");
1721 }
1722
1723 // Remove the last comma
1724 if (strlen(temp_output) != 0)
1725 temp_output[strlen(temp_output)-1] = '\0';
1726 strncpy(output_string, temp_output, strlen(temp_output));
1727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001728 return RETURN_OK;
1729}
1730
1731//Get the radio operating mode, and pure mode flag. eg: "ac"
1732//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.
1733INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1734{
1735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1736 if (NULL == output_string)
1737 return RETURN_ERR;
1738
1739 if (radioIndex == 0) {
1740 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1741 *gOnly = FALSE;
1742 *nOnly = TRUE;
1743 *acOnly = FALSE;
1744 } else {
1745 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1746 *gOnly = FALSE;
1747 *nOnly = FALSE;
1748 *acOnly = FALSE;
1749 }
1750 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1751
1752 return RETURN_OK;
1753#if 0
1754 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1755 char buf[64] = {0};
1756 char config_file[MAX_BUF_SIZE] = {0};
1757
1758 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1759 return RETURN_ERR;
1760
1761 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1762 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1763
1764 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1765 if (strlen(buf) == 0)
1766 {
1767 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1768 return RETURN_ERR;
1769 }
1770 if(strcmp(buf,"g")==0)
1771 {
1772 wifi_dbg_printf("\nG\n");
1773 *gOnly=TRUE;
1774 *nOnly=FALSE;
1775 *acOnly=FALSE;
1776 }
1777 else if(strcmp(buf,"n")==0)
1778 {
1779 wifi_dbg_printf("\nN\n");
1780 *gOnly=FALSE;
1781 *nOnly=TRUE;
1782 *acOnly=FALSE;
1783 }
1784 else if(strcmp(buf,"ac")==0)
1785 {
1786 wifi_dbg_printf("\nac\n");
1787 *gOnly=FALSE;
1788 *nOnly=FALSE;
1789 *acOnly=TRUE;
1790 }
1791 /* hostapd-5G.conf has "a" as hw_mode */
1792 else if(strcmp(buf,"a")==0)
1793 {
1794 wifi_dbg_printf("\na\n");
1795 *gOnly=FALSE;
1796 *nOnly=FALSE;
1797 *acOnly=FALSE;
1798 }
1799 else
1800 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1801
1802 //for a,n mode
1803 if(radioIndex == 1)
1804 {
1805 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1806 if(strcmp(buf,"1")==0)
1807 {
1808 strncpy(output_string, "n", 1);
1809 *nOnly=FALSE;
1810 }
1811 }
1812
1813 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1815 return RETURN_OK;
1816#endif
1817}
1818
developerdb744382022-09-13 15:34:54 +08001819INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1820{
1821 char cmd[128] = {0};
1822 char buf[64] = {0};
1823 char config_file[64] = {0};
1824 wifi_band band;
1825
1826 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1827 if(NULL == output_string || NULL == pureMode)
1828 return RETURN_ERR;
1829
1830 // grep all of the ieee80211 protocol config set to 1
1831 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1832 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1833 _syscmd(cmd, buf, sizeof(buf));
1834
1835 band = wifi_index_to_band(radioIndex);
1836 // puremode is a bit map
1837 *pureMode = 0;
1838 if (band == band_2_4) {
1839 strcat(output_string, "b,g");
1840 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1841 if (strstr(buf, "n") != NULL) {
1842 strcat(output_string, ",n");
1843 *pureMode |= WIFI_MODE_N;
1844 }
1845 if (strstr(buf, "ax") != NULL) {
1846 strcat(output_string, ",ax");
1847 *pureMode |= WIFI_MODE_AX;
1848 }
1849 } else if (band == band_5) {
1850 strcat(output_string, "a");
1851 *pureMode |= WIFI_MODE_A;
1852 if (strstr(buf, "n") != NULL) {
1853 strcat(output_string, ",n");
1854 *pureMode |= WIFI_MODE_N;
1855 }
1856 if (strstr(buf, "ac") != NULL) {
1857 strcat(output_string, ",ac");
1858 *pureMode |= WIFI_MODE_AC;
1859 }
1860 if (strstr(buf, "ax") != NULL) {
1861 strcat(output_string, ",ax");
1862 *pureMode |= WIFI_MODE_AX;
1863 }
1864 } else if (band == band_6) {
1865 if (strstr(buf, "ax") != NULL) {
1866 strcat(output_string, "ax");
1867 *pureMode |= WIFI_MODE_AX;
1868 }
1869 }
1870
1871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1872 return RETURN_OK;
1873}
1874
1875// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001876INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1877{
1878 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1879 if (strcmp (channelMode,"11A") == 0)
1880 {
1881 writeBandWidth(radioIndex,"20MHz");
1882 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1883 printf("\nChannel Mode is 802.11a (5GHz)\n");
1884 }
1885 else if (strcmp (channelMode,"11NAHT20") == 0)
1886 {
1887 writeBandWidth(radioIndex,"20MHz");
1888 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1889 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1890 }
1891 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1892 {
1893 writeBandWidth(radioIndex,"40MHz");
1894 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1895 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1896 }
1897 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1898 {
1899 writeBandWidth(radioIndex,"40MHz");
1900 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1901 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1902 }
1903 else if (strcmp (channelMode,"11ACVHT20") == 0)
1904 {
1905 writeBandWidth(radioIndex,"20MHz");
1906 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1907 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1908 }
1909 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1910 {
1911 writeBandWidth(radioIndex,"40MHz");
1912 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1913 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1914 }
1915 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1916 {
1917 writeBandWidth(radioIndex,"40MHz");
1918 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1919 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1920 }
1921 else if (strcmp (channelMode,"11ACVHT80") == 0)
1922 {
1923 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1924 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1925 }
1926 else if (strcmp (channelMode,"11ACVHT160") == 0)
1927 {
1928 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1929 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1930 }
1931 else if (strcmp (channelMode,"11B") == 0)
1932 {
1933 writeBandWidth(radioIndex,"20MHz");
1934 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1935 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1936 }
1937 else if (strcmp (channelMode,"11G") == 0)
1938 {
1939 writeBandWidth(radioIndex,"20MHz");
1940 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1941 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1942 }
1943 else if (strcmp (channelMode,"11NGHT20") == 0)
1944 {
1945 writeBandWidth(radioIndex,"20MHz");
1946 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1947 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1948 }
1949 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1950 {
1951 writeBandWidth(radioIndex,"40MHz");
1952 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1953 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1954 }
1955 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1956 {
1957 writeBandWidth(radioIndex,"40MHz");
1958 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1959 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1960 }
1961 else
1962 {
1963 return RETURN_ERR;
1964 }
1965 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1966
1967 return RETURN_OK;
1968}
1969
developerdb744382022-09-13 15:34:54 +08001970// Set the radio operating mode, and pure mode flag.
1971INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1972{
1973 int num_hostapd_support_mode = 3; // n, ac, ax
1974 struct params list[num_hostapd_support_mode];
1975 char config_file[64] = {0};
1976 char bandwidth[16] = {0};
1977 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08001978
developerdb744382022-09-13 15:34:54 +08001979
1980 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1981 // Set radio mode
1982 list[0].name = "ieee80211n";
1983 list[1].name = "ieee80211ac";
1984 list[2].name = "ieee80211ax";
1985 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1986
1987 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08001988 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08001989 list[0].value = "1";
1990 else
1991 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08001992 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08001993 list[1].value = "1";
1994 else
1995 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08001996 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08001997 list[2].value = "1";
1998 else
1999 list[2].value = "0";
2000 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2001
2002 if (channelMode == NULL || strlen(channelMode) == 0)
2003 return RETURN_OK;
2004 // Set bandwidth
2005 if (strstr(channelMode, "40") != NULL)
2006 strcpy(bandwidth, "40MHz");
2007 else if (strstr(channelMode, "80") != NULL)
2008 strcpy(bandwidth, "80MHz");
2009 else if (strstr(channelMode, "160") != NULL)
2010 strcpy(bandwidth, "160MHz");
2011 else // 11A, 11B, 11G....
2012 strcpy(bandwidth, "20MHz");
2013
2014 writeBandWidth(radioIndex, bandwidth);
2015 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2016
2017 wifi_reloadAp(radioIndex);
2018 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2019
2020 return RETURN_OK;
2021}
2022
developer1d12ebf2022-10-04 15:13:38 +08002023INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2024
2025 char config_file[64] = {0};
2026 struct params params = {0};
2027 wifi_band band = band_invalid;
2028
2029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2030
2031 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002032
2033 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002034 return RETURN_ERR;
2035 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2036 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002037 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2038 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002039
2040 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2041 params.name = "hw_mode";
2042 params.value = hw_mode;
2043 wifi_hostapdWrite(config_file, &params, 1);
2044 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2045
2046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2047 return RETURN_OK;
2048}
2049
developer06a01d92022-09-07 16:32:39 +08002050//Get the list of supported channel. eg: "1-11"
2051//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.
2052INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2053{
developer6318ed52022-09-13 15:17:58 +08002054 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002055 if (NULL == output_string)
2056 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002057 char cmd[256] = {0};
2058 char buf[128] = {0};
2059 BOOL dfs_enable = false;
2060 // Parse possible channel number and separate them with commas.
2061 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer76989232022-10-04 14:13:19 +08002062 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002063 if (dfs_enable)
developer76989232022-10-04 14:13:19 +08002064 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
developer6318ed52022-09-13 15:17:58 +08002065 else
developer76989232022-10-04 14:13:19 +08002066 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
developer6318ed52022-09-13 15:17:58 +08002067
2068 _syscmd(cmd,buf,sizeof(buf));
2069 strncpy(output_string, buf, sizeof(buf));
2070
2071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2072 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002073}
2074
2075//Get the list for used channel. eg: "1,6,9,11"
2076//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.
2077INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2078{
developerf5745ee2022-10-05 16:09:53 +08002079 char cmd[128] = {0};
2080 char buf[128] = {0};
2081 char config_file[64] = {0};
2082 int channel = 0;
2083 int freq = 0;
2084 int bandwidth = 0;
2085 int center_freq = 0;
2086 int center_channel = 0;
2087 int channel_delta = 0;
2088 wifi_band band = band_invalid;
2089
2090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2091
developer06a01d92022-09-07 16:32:39 +08002092 if (NULL == output_string)
2093 return RETURN_ERR;
2094
developerf5745ee2022-10-05 16:09:53 +08002095 sprintf(cmd, "iw %s%d info | grep channel | sed -e 's/[^0-9 ]//g'", AP_PREFIX, radioIndex);
2096 _syscmd(cmd, buf, sizeof(buf));
2097 if (strlen(buf) == 0) {
2098 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2099 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002100 }
developerf5745ee2022-10-05 16:09:53 +08002101 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2102
2103 if (bandwidth == 20) {
2104 snprintf(output_string, 256, "%d", channel);
2105 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002106 }
developerf5745ee2022-10-05 16:09:53 +08002107
2108 center_channel = ieee80211_frequency_to_channel(center_freq);
2109
2110 band = wifi_index_to_band(radioIndex);
2111 if (band == band_2_4 && bandwidth == 40) {
2112 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2113 memset(buf, 0, sizeof(buf));
2114 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2115
2116 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2117 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2118 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2119 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2120 } else {
2121 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2122 return RETURN_ERR;
2123 }
2124 } else if (band == band_5 || band == band_6){
2125 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2126 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2127 channel_delta = (bandwidth-20)/10;
2128 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2129 } else
2130 return RETURN_ERR;
2131
2132 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002133 return RETURN_OK;
2134}
2135
2136//Get the running channel number
2137INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2138{
developerda1ed692022-09-13 13:59:20 +08002139#ifdef MTK_IMPL
2140 if(!wifi_getApChannel(radioIndex, output_ulong))
2141 return RETURN_OK;
2142 else
2143 return RETURN_ERR;
2144#else
developer06a01d92022-09-07 16:32:39 +08002145 char cmd[1024] = {0}, buf[5] = {0};
2146
2147 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2148 if (NULL == output_ulong)
2149 return RETURN_ERR;
2150
2151 snprintf(cmd, sizeof(cmd),
2152 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2153 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2154 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2155 _syscmd(cmd, buf, sizeof(buf));
2156
2157 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2158 if (*output_ulong <= 0) {
2159 *output_ulong = 0;
2160 return RETURN_ERR;
2161 }
2162
2163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2164 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002165#endif
developer06a01d92022-09-07 16:32:39 +08002166}
2167
2168
2169INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2170{
2171 char cmd[1024] = {0}, buf[5] = {0};
2172 char interface_name[50] = {0};
2173
2174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2175 if (NULL == output_ulong)
2176 return RETURN_ERR;
2177
2178 wifi_getApName(apIndex,interface_name);
2179 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2180 _syscmd(cmd,buf,sizeof(buf));
2181 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2182 if (*output_ulong == 0) {
2183 return RETURN_ERR;
2184 }
2185
2186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2187 return RETURN_OK;
2188}
2189
2190//Storing the previous channel value
2191INT wifi_storeprevchanval(INT radioIndex)
2192{
2193 char buf[256] = {0};
2194 char output[4]={'\0'};
2195 char config_file[MAX_BUF_SIZE] = {0};
2196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2197 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2198 if(radioIndex == 0)
2199 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2200 else if(radioIndex == 1)
2201 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2202 system(buf);
2203 Radio_flag = FALSE;
2204 return RETURN_OK;
2205}
2206
2207//Set the running channel number
2208INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2209{
developer76989232022-10-04 14:13:19 +08002210 // We only write hostapd config here
2211 char str_channel[8]={0};
2212 char *list_channel;
2213 char config_file[128] = {0};
2214 char possible_channels[256] = {0};
2215 int max_radio_num = 0;
2216 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002217
developer76989232022-10-04 14:13:19 +08002218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002219
developer76989232022-10-04 14:13:19 +08002220 // Check valid
2221 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002222
developer76989232022-10-04 14:13:19 +08002223 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2224 list_channel = strtok(possible_channels, ",");
2225 while(true)
developer06a01d92022-09-07 16:32:39 +08002226 {
developer76989232022-10-04 14:13:19 +08002227 if(list_channel == NULL) { // input not in the list
2228 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2229 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002230 }
developer76989232022-10-04 14:13:19 +08002231 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2232 break;
2233 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002234 }
2235
developer76989232022-10-04 14:13:19 +08002236 list.name = "channel";
2237 list.value = str_channel;
2238 wifi_getMaxRadioNumber(&max_radio_num);
2239 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002240 {
developer76989232022-10-04 14:13:19 +08002241 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2242 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002243 }
2244
developer76989232022-10-04 14:13:19 +08002245 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002246 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002247}
developer06a01d92022-09-07 16:32:39 +08002248
2249INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2250{
developer76989232022-10-04 14:13:19 +08002251 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002252 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002253 char config_file[64];
2254 int max_num_radios = 0;
2255 wifi_band band = band_invalid;
2256
2257 band = wifi_index_to_band(radioIndex);
2258 if (band == band_2_4)
2259 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002260
developer06a01d92022-09-07 16:32:39 +08002261 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002262 list[0].name = "vht_oper_centr_freq_seg0_idx";
2263 list[0].value = str_idx;
2264 list[1].name = "he_oper_centr_freq_seg0_idx";
2265 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002266
developer76989232022-10-04 14:13:19 +08002267 wifi_getMaxRadioNumber(&max_num_radios);
2268 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002269 {
developer76989232022-10-04 14:13:19 +08002270 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2271 if (band == band_6)
2272 wifi_hostapdWrite(config_file, &list[1], 1);
2273 else
2274 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002275 }
2276
2277 return RETURN_OK;
2278}
2279
2280//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2281//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2282INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2283{
2284 //Set to wifi config only. Wait for wifi reset to apply.
2285 char buf[256] = {0};
2286 char str_channel[256] = {0};
2287 int count = 0;
2288 ULONG Value = 0;
2289 FILE *fp = NULL;
2290 if(enable == TRUE)
2291 {
developer06a01d92022-09-07 16:32:39 +08002292 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002293 }
developer5884e982022-10-06 10:52:50 +08002294 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002295}
2296
developer0b246d12022-09-30 15:24:20 +08002297INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2298{
2299 if (output_bool == NULL)
2300 return RETURN_ERR;
2301
2302 *output_bool = TRUE;
2303
2304 return RETURN_OK;
2305}
2306
developer06a01d92022-09-07 16:32:39 +08002307INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2308{
2309 if (NULL == output_bool)
2310 return RETURN_ERR;
2311 *output_bool=FALSE;
2312 return RETURN_OK;
2313}
2314
2315INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2316{
2317 if (NULL == output_bool)
2318 return RETURN_ERR;
2319 *output_bool=FALSE;
2320 return RETURN_OK;
2321}
2322
2323INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2324{
2325 //Set to wifi config only. Wait for wifi reset to apply.
2326 return RETURN_OK;
2327}
2328
2329INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2330{
2331 return RETURN_OK;
2332}
2333
2334INT wifi_factoryResetAP(int apIndex)
2335{
developer838cca92022-10-03 13:19:57 +08002336 char ap_config_file[64] = {0};
2337 char cmd[128] = {0};
2338
developer06a01d92022-09-07 16:32:39 +08002339 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002340
2341 wifi_setApEnable(apIndex, FALSE);
2342 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2343 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2344 wifi_setApEnable(apIndex, TRUE);
2345
developer06a01d92022-09-07 16:32:39 +08002346 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002347
developer06a01d92022-09-07 16:32:39 +08002348 return RETURN_OK;
2349}
2350
2351//To set Band Steering AP group
2352//To-do
2353INT wifi_setBandSteeringApGroup(char *ApGroup)
2354{
2355 return RETURN_OK;
2356}
2357
developer1e5aa162022-09-13 16:06:24 +08002358INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2359{
2360 char config_file[128] = {'\0'};
2361 char buf[128] = {'\0'};
2362
2363 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2364 if (dtimInterval == NULL)
2365 return RETURN_ERR;
2366
2367 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2368 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2369
2370 if (strlen(buf) == 0) {
2371 *dtimInterval = 2;
2372 } else {
2373 *dtimInterval = strtoul(buf, NULL, 10);
2374 }
2375
2376 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2377 return RETURN_OK;
2378}
2379
developer06a01d92022-09-07 16:32:39 +08002380INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2381{
developer5f222492022-09-13 15:21:52 +08002382 struct params params={0};
2383 char config_file[MAX_BUF_SIZE] = {'\0'};
2384 char buf[MAX_BUF_SIZE] = {'\0'};
2385
2386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2387 if (dtimInterval < 1 || dtimInterval > 255) {
2388 return RETURN_ERR;
2389 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2390 }
2391
2392 params.name = "dtim_period";
2393 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2394 params.value = buf;
2395
2396 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2397 wifi_hostapdWrite(config_file, &params, 1);
2398 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2399
2400 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2401 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002402}
2403
2404//Check if the driver support the Dfs
2405INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2406{
2407 if (NULL == output_bool)
2408 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002409 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002410 return RETURN_OK;
2411}
2412
2413//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.
2414//The value of this parameter is a comma seperated list of channel number
2415INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2416{
2417 if (NULL == output_pool)
2418 return RETURN_ERR;
2419 if (radioIndex==1)
2420 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2421 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2422
2423 return RETURN_OK;
2424}
2425
2426INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2427{
2428 //Set to wifi config. And apply instantly.
2429 return RETURN_OK;
2430}
2431
2432INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2433{
2434 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2435 return RETURN_ERR;
2436 *output_interval_seconds=1800;
2437 *output_dwell_milliseconds=40;
2438
2439 return RETURN_OK;
2440}
2441
2442INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2443{
2444 //Set to wifi config. And apply instantly.
2445 return RETURN_OK;
2446}
2447
developerbfc18512022-10-05 17:54:28 +08002448INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2449{
2450 if (output_bool == NULL)
2451 return RETURN_ERR;
2452 *output_bool = true;
2453 return RETURN_OK;
2454}
2455
2456INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2457{
2458 return RETURN_OK;
2459}
2460
developer06a01d92022-09-07 16:32:39 +08002461//Get the Dfs enable status
2462INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2463{
developer9964b5b2022-09-13 15:59:34 +08002464 char buf[16] = {0};
2465 FILE *f = NULL;
2466 wifi_band band;
2467
2468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2469
2470 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002471 if (NULL == output_bool)
2472 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002473
2474 band = wifi_index_to_band(radioIndex);
2475 if (band != band_5)
2476 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002477
developer9964b5b2022-09-13 15:59:34 +08002478 f = fopen(DFS_ENABLE_FILE, "r");
2479 if (f != NULL) {
2480 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002481 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002482 *output_bool = FALSE;
2483 fclose(f);
2484 }
2485 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002486 return RETURN_OK;
2487}
2488
2489//Set the Dfs enable status
2490INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2491{
developer9964b5b2022-09-13 15:59:34 +08002492 char config_file[128] = {0};
2493 FILE *f = NULL;
2494 struct params params={0};
2495 wifi_band band;
2496
2497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2498
2499 band = wifi_index_to_band(radioIndex);
2500 if (band != band_5)
2501 return RETURN_OK;
2502
2503 f = fopen(DFS_ENABLE_FILE, "w");
2504 if (f == NULL)
2505 return RETURN_ERR;
2506 fprintf(f, "%d", enable);
2507 fclose(f);
2508
2509 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002510 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002511 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2512 wifi_hostapdWrite(config_file, &params, 1);
2513 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2514
2515 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2516
developer9964b5b2022-09-13 15:59:34 +08002517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002518 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002519}
2520
2521//Check if the driver support the AutoChannelRefreshPeriod
2522INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2523{
2524 if (NULL == output_bool)
2525 return RETURN_ERR;
2526 *output_bool=FALSE; //not support
2527
2528 return RETURN_OK;
2529}
2530
2531//Get the ACS refresh period in seconds
2532INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2533{
2534 if (NULL == output_ulong)
2535 return RETURN_ERR;
2536 *output_ulong=300;
2537
2538 return RETURN_OK;
2539}
2540
2541//Set the ACS refresh period in seconds
2542INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2543{
2544 return RETURN_ERR;
2545}
2546
2547//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2548//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.
2549INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2550{
developer70490032022-09-13 15:45:20 +08002551 char cmd[128] = {0}, buf[64] = {0};
2552 char interface_name[64] = {0};
2553 int ret = 0, len=0;
2554 BOOL radio_enable = FALSE;
2555
2556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2557
developer06a01d92022-09-07 16:32:39 +08002558 if (NULL == output_string)
2559 return RETURN_ERR;
2560
developer70490032022-09-13 15:45:20 +08002561 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2562 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002563
developer70490032022-09-13 15:45:20 +08002564 if (radio_enable != TRUE)
2565 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002566
developer70490032022-09-13 15:45:20 +08002567 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002568 ret = _syscmd(cmd, buf, sizeof(buf));
2569 len = strlen(buf);
2570 if((ret != 0) || (len == 0))
2571 {
2572 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2573 return RETURN_ERR;
2574 }
2575
2576 buf[len-1] = '\0';
2577 snprintf(output_string, 64, "%sMHz", buf);
2578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2579
2580#if 0
2581 //TODO: revisit below implementation
2582 char output_buf[8]={0};
2583 char bw_value[10];
2584 char config_file[MAX_BUF_SIZE] = {0};
2585
2586 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2587 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2588 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2589 readBandWidth(radioIndex,bw_value);
2590
2591 if(strstr (output_buf,"0") != NULL )
2592 {
2593 strcpy(output_string,bw_value);
2594 }
2595 else if (strstr (output_buf,"1") != NULL)
2596 {
2597 strcpy(output_string,"80MHz");
2598 }
2599 else if (strstr (output_buf,"2") != NULL)
2600 {
2601 strcpy(output_string,"160MHz");
2602 }
2603 else if (strstr (output_buf,"3") != NULL)
2604 {
2605 strcpy(output_string,"80+80");
2606 }
2607 else
2608 {
2609 strcpy(output_string,"Auto");
2610 }
2611 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2612#endif
2613
2614 return RETURN_OK;
2615}
2616
2617//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002618INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002619{
developerf7a466e2022-09-29 11:55:56 +08002620 char config_file[128];
2621 char set_value[16];
2622 struct params params[2];
2623 int max_radio_num = 0;
2624
developer06a01d92022-09-07 16:32:39 +08002625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002626
developerf7a466e2022-09-29 11:55:56 +08002627 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002628 return RETURN_ERR;
2629
developerf7a466e2022-09-29 11:55:56 +08002630 if(strstr(bandwidth,"80+80") != NULL)
2631 strcpy(set_value, "3");
2632 else if(strstr(bandwidth,"160") != NULL)
2633 strcpy(set_value, "2");
2634 else if(strstr(bandwidth,"80") != NULL)
2635 strcpy(set_value, "1");
2636 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2637 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002638 else
2639 {
developerf7a466e2022-09-29 11:55:56 +08002640 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002641 return RETURN_ERR;
2642 }
2643
developerf7a466e2022-09-29 11:55:56 +08002644 params[0].name = "vht_oper_chwidth";
2645 params[0].value = set_value;
2646 params[1].name = "he_oper_chwidth";
2647 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002648
developerf7a466e2022-09-29 11:55:56 +08002649 wifi_getMaxRadioNumber(&max_radio_num);
2650 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002651 {
developerf7a466e2022-09-29 11:55:56 +08002652 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2653 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002654 }
2655
2656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2657 return RETURN_OK;
2658}
2659
2660//Getting current radio extension channel
2661INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2662{
2663 CHAR buf[150] = {0};
2664 CHAR cmd[150] = {0};
2665 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2666 _syscmd(cmd, buf, sizeof(buf));
2667 if(NULL != strstr(buf,"HT40+"))
2668 strcpy(Value,"AboveControlChannel");
2669 else if(NULL != strstr(buf,"HT40-"))
2670 strcpy(Value,"BelowControlChannel");
2671 return RETURN_OK;
2672}
2673
2674//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2675//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.
2676INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2677{
2678 if (NULL == output_string)
2679 return RETURN_ERR;
2680
2681 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2682#if 0
2683 CHAR Value[100] = {0};
2684 if (NULL == output_string)
2685 return RETURN_ERR;
2686 if(radioIndex == 0)
2687 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2688 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2689 {
2690 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2691 if(strcmp(Value,"40MHz") == 0)
2692 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2693 else
2694 strcpy(Value,"Auto");
2695 }
2696 strcpy(output_string,Value);
2697#endif
2698
2699 return RETURN_OK;
2700}
2701
2702//Set the extension channel.
2703INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2704{
2705 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2706 struct params params={'\0'};
2707 char config_file[MAX_BUF_SIZE] = {0};
2708 char ext_channel[127]={'\0'};
2709
2710 params.name = "ht_capab";
2711
2712 if(radioIndex == 0)
2713 {
2714 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002715 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002716 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002717 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002718 else
developer3cc0f2e2022-09-15 18:25:39 +08002719 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002720 }
2721 else if(radioIndex == 1)
2722 {
2723 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002724 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002725 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002726 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002727 else
developer3cc0f2e2022-09-15 18:25:39 +08002728 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002729 }
2730
2731 params.value = ext_channel;
2732 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2733 {
2734 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2735 wifi_hostapdWrite(config_file, &params, 1);
2736 }
2737
2738 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2739 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2740 return RETURN_OK;
2741}
2742
2743//Get the guard interval value. eg "400nsec" or "800nsec"
2744//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.
2745INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2746{
developer454b9462022-09-13 15:29:16 +08002747 wifi_guard_interval_t GI;
2748
2749 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2750
2751 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002752 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002753
2754 if (GI == wifi_guard_interval_400)
2755 strcpy(output_string, "400nsec");
2756 else if (GI == wifi_guard_interval_800)
2757 strcpy(output_string, "800nsec");
2758 else if (GI == wifi_guard_interval_1600)
2759 strcpy(output_string, "1600nsec");
2760 else if (GI == wifi_guard_interval_3200)
2761 strcpy(output_string, "3200nsec");
2762 else
2763 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002764
developer454b9462022-09-13 15:29:16 +08002765 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002766 return RETURN_OK;
2767}
2768
2769//Set the guard interval value.
2770INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2771{
developer454b9462022-09-13 15:29:16 +08002772 wifi_guard_interval_t GI;
2773 int ret = 0;
2774
2775 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2776
2777 if (strcmp(string, "400nsec") == 0)
2778 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002779 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002780 GI = wifi_guard_interval_800;
2781 else if (strcmp(string , "1600nsec") == 0)
2782 GI = wifi_guard_interval_1600;
2783 else if (strcmp(string , "3200nsec") == 0)
2784 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002785 else
2786 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002787
2788 ret = wifi_setGuardInterval(radioIndex, GI);
2789
2790 if (ret == RETURN_ERR) {
2791 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2792 return RETURN_ERR;
2793 }
2794
2795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2796 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002797}
2798
2799//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2800INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2801{
developerf49437e2022-09-29 19:58:21 +08002802 char buf[32]={0};
2803 char mcs_file[64] = {0};
2804 char cmd[64] = {0};
2805 int mode_bitmap = 0;
2806
2807 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2808 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002809 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002810 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2811
2812 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2813 _syscmd(cmd, buf, sizeof(buf));
2814 if (strlen(buf) > 0)
2815 *output_int = strtol(buf, NULL, 10);
2816 else {
2817 // output the max MCS for the current radio mode
2818 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2819 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2820 return RETURN_ERR;
2821 }
2822 if (mode_bitmap & WIFI_MODE_AX) {
2823 *output_int = 11;
2824 } else if (mode_bitmap & WIFI_MODE_AC) {
2825 *output_int = 9;
2826 } else if (mode_bitmap & WIFI_MODE_N) {
2827 *output_int = 7;
2828 }
2829 }
2830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002831
2832 return RETURN_OK;
2833}
2834
2835//Set the Modulation Coding Scheme index
2836INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2837{
developerf49437e2022-09-29 19:58:21 +08002838 // 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).
2839 char config_file[64] = {0};
2840 char set_value[16] = {0};
2841 char mcs_file[32] = {0};
2842 wifi_band band = band_invalid;
2843 struct params set_config = {0};
2844 FILE *f = NULL;
2845
2846 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2847
2848 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2849
2850 if (MCS > 11 || MCS < 0) {
2851 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2852 return RETURN_ERR;
2853 }
2854
2855 if (MCS <= 7)
2856 strcpy(set_value, "0");
2857 else if (MCS <= 9)
2858 strcpy(set_value, "1");
2859 else
2860 strcpy(set_value, "2");
2861
2862 set_config.name = "he_basic_mcs_nss_set";
2863 set_config.value = set_value;
2864
2865 wifi_hostapdWrite(config_file, &set_config, 1);
2866 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2867
2868 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2869 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2870 f = fopen(mcs_file, "w");
2871 if (f == NULL) {
2872 fprintf(stderr, "%s: fopen failed\n", __func__);
2873 return RETURN_ERR;
2874 }
2875 fprintf(f, "%d", MCS);
2876 fclose(f);
2877
2878 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2879 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002880}
2881
2882//Get supported Transmit Power list, eg : "0,25,50,75,100"
2883//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.
2884INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2885{
2886 if (NULL == output_list)
2887 return RETURN_ERR;
2888 snprintf(output_list, 64,"0,25,50,75,100");
2889 return RETURN_OK;
2890}
2891
developera5005b62022-09-13 15:43:35 +08002892//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002893//The transmite power level is in units of full power for this radio.
2894INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2895{
2896 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002897 char buf[16]={0};
2898 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002899
developera5005b62022-09-13 15:43:35 +08002900 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002901 return RETURN_ERR;
2902
developera5005b62022-09-13 15:43:35 +08002903 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 +08002904 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002905
developera5005b62022-09-13 15:43:35 +08002906 *output_ulong = strtol(buf, NULL, 10);
2907
2908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002909 return RETURN_OK;
2910}
2911
2912//Set Transmit Power
2913//The transmite power level is in units of full power for this radio.
2914INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2915{
developera5005b62022-09-13 15:43:35 +08002916 char *support;
developer06a01d92022-09-07 16:32:39 +08002917 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002918 char buf[128]={0};
2919 char txpower_str[64] = {0};
2920 int txpower = 0;
2921 int maximum_tx = 0;
2922
2923 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002924
developera5005b62022-09-13 15:43:35 +08002925 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 +08002926 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002927 maximum_tx = strtol(buf, NULL, 10);
2928
2929 // Get the Tx power supported list and check that is the input in the list
2930 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2931 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2932 support = strtok(buf, ",");
2933 while(true)
2934 {
2935 if(support == NULL) { // input not in the list
2936 wifi_dbg_printf("Input value is invalid.\n");
2937 return RETURN_ERR;
2938 }
2939 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2940 break;
2941 }
2942 support = strtok(NULL, ",");
2943 }
2944 txpower = TransmitPower*maximum_tx/100;
2945 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2946 _syscmd(cmd, buf, sizeof(buf));
2947 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002948
2949 return RETURN_OK;
2950}
2951
2952//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2953INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2954{
2955 if (NULL == Supported)
2956 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002957 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002958
2959 return RETURN_OK;
2960}
2961
2962//Get 80211h feature enable
2963INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2964{
developer3885fec2022-09-13 15:13:47 +08002965 char buf[64]={'\0'};
2966 char config_file[64] = {'\0'};
2967
2968 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2969 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002970 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002971
2972 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2973 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002974
developer3885fec2022-09-13 15:13:47 +08002975 if (strncmp(buf, "1", 1) == 0)
2976 *enable = TRUE;
2977 else
2978 *enable = FALSE;
2979
2980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002981 return RETURN_OK;
2982}
2983
2984//Set 80211h feature enable
2985INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2986{
developer3885fec2022-09-13 15:13:47 +08002987 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2988 struct params params={'\0'};
2989 char config_file[MAX_BUF_SIZE] = {0};
2990
2991 params.name = "ieee80211h";
2992
2993 if (enable) {
2994 params.value = "1";
2995 } else {
2996 params.value = "0";
2997 }
2998
2999 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3000 wifi_hostapdWrite(config_file, &params, 1);
3001
3002 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3003 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3004 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003005}
3006
3007//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.
3008INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3009{
3010 if (NULL == output)
3011 return RETURN_ERR;
3012 *output=100;
3013
3014 return RETURN_OK;
3015}
3016
3017//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.
3018INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3019{
3020 if (NULL == output)
3021 return RETURN_ERR;
3022 *output = -99;
3023
3024 return RETURN_OK;
3025}
3026
3027INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3028{
3029 return RETURN_ERR;
3030}
3031
3032
3033//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3034INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3035{
developer5f222492022-09-13 15:21:52 +08003036 char cmd[MAX_BUF_SIZE]={'\0'};
3037 char buf[MAX_CMD_SIZE]={'\0'};
3038
3039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3040 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003041 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003042
3043 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3044 _syscmd(cmd, buf, sizeof(buf));
3045 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003046
developer5f222492022-09-13 15:21:52 +08003047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003048 return RETURN_OK;
3049}
3050
3051INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3052{
developer5f222492022-09-13 15:21:52 +08003053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3054 struct params params={'\0'};
3055 char buf[MAX_BUF_SIZE] = {'\0'};
3056 char config_file[MAX_BUF_SIZE] = {'\0'};
3057
3058 params.name = "beacon_int";
3059 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3060 params.value = buf;
3061
3062 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3063 wifi_hostapdWrite(config_file, &params, 1);
3064
3065 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3066 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3067 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003068}
3069
3070//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.
3071INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3072{
developer06a01d92022-09-07 16:32:39 +08003073 //TODO: need to revisit below implementation
3074 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003075 char temp_output[128] = {0};
3076 char temp_TransmitRates[64] = {0};
3077 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003078
3079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3080 if (NULL == output)
3081 return RETURN_ERR;
3082 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003083 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3084
3085 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3086 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3087 } else {
3088 temp = strtok(temp_TransmitRates," ");
3089 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003090 {
developere9d0abd2022-09-13 15:40:57 +08003091 // Convert 100 kbps to Mbps
3092 temp[strlen(temp)-1]=0;
3093 if((temp[0]=='5') && (temp[1]=='\0'))
3094 {
3095 temp="5.5";
3096 }
3097 strcat(temp_output,temp);
3098 temp = strtok(NULL," ");
3099 if(temp!=NULL)
3100 {
3101 strcat(temp_output,",");
3102 }
developer06a01d92022-09-07 16:32:39 +08003103 }
developere9d0abd2022-09-13 15:40:57 +08003104 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003105 }
developer06a01d92022-09-07 16:32:39 +08003106 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003107 return RETURN_OK;
3108}
3109
3110INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3111{
3112 char *temp;
3113 char temp1[128];
3114 char temp_output[128];
3115 char temp_TransmitRates[128];
3116 char set[128];
3117 char sub_set[128];
3118 int set_count=0,subset_count=0;
3119 int set_index=0,subset_index=0;
3120 char *token;
3121 int flag=0, i=0;
3122 struct params params={'\0'};
3123 char config_file[MAX_BUF_SIZE] = {0};
3124
3125 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3126 if(NULL == TransmitRates)
3127 return RETURN_ERR;
3128 strcpy(sub_set,TransmitRates);
3129
3130 //Allow only supported Data transmit rate to be set
3131 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3132 token = strtok(sub_set,",");
3133 while( token != NULL ) /* split the basic rate to be set, by comma */
3134 {
3135 sub_set[subset_count]=atoi(token);
3136 subset_count++;
3137 token=strtok(NULL,",");
3138 }
3139 token=strtok(set,",");
3140 while(token!=NULL) /* split the supported rate by comma */
3141 {
3142 set[set_count]=atoi(token);
3143 set_count++;
3144 token=strtok(NULL,",");
3145 }
3146 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3147 {
3148 for(set_index=0;set_index < set_count;set_index++)
3149 {
3150 flag=0;
3151 if(sub_set[subset_index]==set[set_index])
3152 break;
3153 else
3154 flag=1; /* No match found */
3155 }
3156 if(flag==1)
3157 return RETURN_ERR; //If value not found return Error
3158 }
3159 strcpy(temp_TransmitRates,TransmitRates);
3160
3161 for(i=0;i<strlen(temp_TransmitRates);i++)
3162 {
3163 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3164 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3165 {
3166 continue;
3167 }
3168 else
3169 {
3170 return RETURN_ERR;
3171 }
3172 }
3173 strcpy(temp_output,"");
3174 temp = strtok(temp_TransmitRates,",");
3175 while(temp!=NULL)
3176 {
3177 strcpy(temp1,temp);
3178 if(radioIndex==1)
3179 {
3180 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3181 {
3182 return RETURN_ERR;
3183 }
3184 }
3185
3186 if(strcmp(temp,"5.5")==0)
3187 {
3188 strcpy(temp1,"55");
3189 }
3190 else
3191 {
3192 strcat(temp1,"0");
3193 }
3194 strcat(temp_output,temp1);
3195 temp = strtok(NULL,",");
3196 if(temp!=NULL)
3197 {
3198 strcat(temp_output," ");
3199 }
3200 }
3201 strcpy(TransmitRates,temp_output);
3202
3203 params.name= "basic_rates";
3204 params.value =TransmitRates;
3205
3206 wifi_dbg_printf("\n%s:",__func__);
3207 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3208 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3209 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3210 wifi_hostapdWrite(config_file,&params,1);
3211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3212 return RETURN_OK;
3213}
3214
3215//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3216INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3217{
3218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3219 FILE *fp = NULL;
3220 char path[256] = {0}, output_string[256] = {0};
3221 int count = 0;
3222 char *interface = NULL;
3223
3224 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3225 if (fp == NULL)
3226 {
3227 printf("Failed to run command in Function %s\n", __FUNCTION__);
3228 return RETURN_ERR;
3229 }
3230 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3231 {
3232 interface = strchr(path, '=');
3233
3234 if (interface != NULL)
3235 {
3236 strcpy(output_string, interface + 1);
3237 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3238 interface_name[count] = output_string[count];
3239
3240 interface_name[count] = '\0';
3241 }
3242 }
3243 pclose(fp);
3244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3245 return RETURN_OK;
3246}
3247
3248INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3249{
3250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3251 output_struct->radio_BytesSent = 0;
3252 output_struct->radio_BytesReceived = 0;
3253 output_struct->radio_PacketsSent = 0;
3254 output_struct->radio_PacketsReceived = 0;
3255 output_struct->radio_ErrorsSent = 0;
3256 output_struct->radio_ErrorsReceived = 0;
3257 output_struct->radio_DiscardPacketsSent = 0;
3258 output_struct->radio_DiscardPacketsReceived = 0;
3259 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3260 return RETURN_OK;
3261}
3262
3263
3264INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3265{
3266 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3267 CHAR buf[MAX_CMD_SIZE] = {0};
3268 CHAR Value[MAX_BUF_SIZE] = {0};
3269 FILE *fp = NULL;
3270
3271 if (ifname == NULL || strlen(ifname) <= 1)
3272 return RETURN_OK;
3273
3274 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3275 system(buf);
3276
3277 fp = fopen("/tmp/Radio_Stats.txt", "r");
3278 if(fp == NULL)
3279 {
3280 printf("/tmp/Radio_Stats.txt not exists \n");
3281 return RETURN_ERR;
3282 }
3283 fclose(fp);
3284
3285 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3286 File_Reading(buf, Value);
3287 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3288
3289 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3290 File_Reading(buf, Value);
3291 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3292
3293 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3294 File_Reading(buf, Value);
3295 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3296
3297 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3298 File_Reading(buf, Value);
3299 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3300
3301 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3302 File_Reading(buf, Value);
3303 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3304
3305 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3306 File_Reading(buf, Value);
3307 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3308
3309 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3310 File_Reading(buf, Value);
3311 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3312
3313 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3314 File_Reading(buf, Value);
3315 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3316
3317 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3318 return RETURN_OK;
3319}
3320
3321INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3322{
3323 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3324 CHAR buf[MAX_CMD_SIZE] = {0};
3325 FILE *fp = NULL;
3326 INT count = 0;
3327
3328 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3329 {
3330 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3331 File_Reading(buf, status);
3332 }
3333 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3334 return RETURN_OK;
3335}
3336
3337//Get detail radio traffic static info
3338INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3339{
3340
3341#if 0
3342 //ifconfig radio_x
3343 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3344 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3345 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3346 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3347
3348 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3349 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3350 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.
3351 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.
3352
3353 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3354 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].
3355 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3356 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.
3357 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
3358 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
3359 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
3360 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
3361 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
3362
3363 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
3364 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
3365 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
3366 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.
3367
3368 return RETURN_OK;
3369#endif
3370
developera91d99f2022-09-29 15:59:10 +08003371 CHAR interface_name[64] = {0};
3372 CHAR config_path[64] = {0};
3373 BOOL iface_status = FALSE;
3374 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003375
3376 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3377 if (NULL == output_struct)
3378 return RETURN_ERR;
3379
developera91d99f2022-09-29 15:59:10 +08003380 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3381 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003382
developera91d99f2022-09-29 15:59:10 +08003383 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003384
developera91d99f2022-09-29 15:59:10 +08003385 if (iface_status == TRUE)
3386 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3387 else
3388 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003389
developera91d99f2022-09-29 15:59:10 +08003390 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3391 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3392 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3393 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3394 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3395 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3396 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3397 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003398
3399 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3400 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].
3401 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3402 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.
3403 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
3404 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
3405 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
3406 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
3407 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
3408
3409 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
3410 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
3411 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
3412 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.
3413
3414 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3415
3416 return RETURN_OK;
3417}
3418
3419//Set radio traffic static Measureing rules
3420INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3421{
3422 //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
3423 // Else, save the MeasuringRate and MeasuringInterval for future usage
3424
3425 return RETURN_OK;
3426}
3427
3428//To start or stop RadioTrafficStats
3429INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3430{
3431 //zqiu: If the RadioTrafficStats process running
3432 // if(enable)
3433 // return RETURN_OK.
3434 // else
3435 // Stop RadioTrafficStats process
3436 // Else
3437 // if(enable)
3438 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3439 // else
3440 // return RETURN_OK.
3441
3442 return RETURN_OK;
3443}
3444
3445//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
3446INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3447{
3448 //zqiu: Please ignor signalIndex.
3449 if (NULL == SignalLevel)
3450 return RETURN_ERR;
3451 *SignalLevel=(radioIndex==0)?-19:-19;
3452
3453 return RETURN_OK;
3454}
3455
3456//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3457INT wifi_applyRadioSettings(INT radioIndex)
3458{
3459 return RETURN_OK;
3460}
3461
3462//Get the radio index assocated with this SSID entry
3463INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3464{
3465 if (NULL == radioIndex)
3466 return RETURN_ERR;
3467 *radioIndex=ssidIndex%2;
3468
3469 return RETURN_OK;
3470}
3471
3472//Device.WiFi.SSID.{i}.Enable
3473//Get SSID enable configuration parameters (not the SSID enable status)
3474INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3475{
3476 if (NULL == output_bool)
3477 return RETURN_ERR;
3478
3479 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3480 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3481 return wifi_getApEnable(ssidIndex, output_bool);
3482}
3483
3484//Device.WiFi.SSID.{i}.Enable
3485//Set SSID enable configuration parameters
3486INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3487{
3488 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3489 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3490 return wifi_setApEnable(ssidIndex, enable);
3491}
3492
3493//Device.WiFi.SSID.{i}.Status
3494//Get the SSID enable status
3495INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3496{
3497 char cmd[MAX_CMD_SIZE]={0};
3498 char buf[MAX_BUF_SIZE]={0};
3499 BOOL output_bool;
3500
3501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3502 if (NULL == output_string)
3503 return RETURN_ERR;
3504 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3505 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3506
3507 wifi_getApEnable(ssidIndex,&output_bool);
3508 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3509
3510 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3511 return RETURN_OK;
3512}
3513
3514// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3515INT wifi_getSSIDName(INT apIndex, CHAR *output)
3516{
3517 char config_file[MAX_BUF_SIZE] = {0};
3518
3519 if (NULL == output)
3520 return RETURN_ERR;
3521
3522 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3523 wifi_hostapdRead(config_file,"ssid",output,32);
3524
3525 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3526 return RETURN_OK;
3527}
3528
3529// Set a max 32 byte string and sets an internal variable to the SSID name
3530INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3531{
3532 char str[MAX_BUF_SIZE]={'\0'};
3533 char cmd[MAX_CMD_SIZE]={'\0'};
3534 struct params params;
3535 char config_file[MAX_BUF_SIZE] = {0};
3536
3537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3538 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3539 return RETURN_ERR;
3540
3541 params.name = "ssid";
3542 params.value = ssid_string;
3543 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3544 wifi_hostapdWrite(config_file, &params, 1);
3545 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3547
3548 return RETURN_OK;
3549}
3550
3551//Get the BSSID
3552INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3553{
3554 char cmd[MAX_CMD_SIZE]="";
3555
3556 if (NULL == output_string)
3557 return RETURN_ERR;
3558
3559 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3560 {
3561 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3562 _syscmd(cmd, output_string, 64);
3563 return RETURN_OK;
3564 }
3565 strncpy(output_string, "\0", 1);
3566
3567 return RETURN_ERR;
3568}
3569
3570//Get the MAC address associated with this Wifi SSID
3571INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3572{
3573 wifi_getBaseBSSID(ssidIndex,output_string);
3574 return RETURN_OK;
3575}
3576
3577//Get the basic SSID traffic static info
3578//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3579//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3580INT wifi_applySSIDSettings(INT ssidIndex)
3581{
3582 BOOL status = false;
3583 char cmd[MAX_CMD_SIZE] = {0};
3584 char buf[MAX_CMD_SIZE] = {0};
3585 int apIndex, ret;
3586 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3587
3588 wifi_getApEnable(ssidIndex,&status);
3589 // Do not apply when ssid index is disabled
3590 if (status == false)
3591 return RETURN_OK;
3592
3593 /* Doing full remove and add for ssid Index
3594 * Not all hostapd options are supported with reload
3595 * for example macaddr_acl
3596 */
3597 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3598 return RETURN_ERR;
3599
3600 ret = wifi_setApEnable(ssidIndex,true);
3601
3602 /* Workaround for hostapd issue with multiple bss definitions
3603 * when first created interface will be removed
3604 * then all vaps other vaps on same phy are removed
3605 * after calling setApEnable to false readd all enabled vaps */
3606 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3607 apIndex = 2*i+radioIndex;
3608 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3609 _syscmd(cmd, buf, sizeof(buf));
3610 if(*buf == '1')
3611 wifi_setApEnable(apIndex, true);
3612 }
3613
3614 return ret;
3615}
3616
developera3c68b92022-09-13 15:27:29 +08003617struct channels_noise {
3618 int channel;
3619 int noise;
3620};
3621
3622// Return noise array for each channel
3623int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3624{
3625 FILE *f = NULL;
3626 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003627 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003628 size_t len = 0;
3629 ssize_t read = 0;
3630 int tmp = 0, arr_index = -1;
3631
3632 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3633
3634 if ((f = popen(cmd, "r")) == NULL) {
3635 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3636 return RETURN_ERR;
3637 }
developer5550e242022-09-30 09:59:32 +08003638
3639 while(fgets(line, sizeof(line), f) != NULL) {
3640 if(arr_index < channels_num){
3641 sscanf(line, "%d", &tmp);
3642 if (tmp > 0) { // channel frequency, the first line must be frequency
3643 arr_index++;
3644 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3645 } else { // noise
3646 channels_noise_arr[arr_index].noise = tmp;
3647 }
3648 }else{
3649 break;
developera3c68b92022-09-13 15:27:29 +08003650 }
3651 }
developera3c68b92022-09-13 15:27:29 +08003652 pclose(f);
3653 return RETURN_OK;
3654}
3655
developer06a01d92022-09-07 16:32:39 +08003656//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3657//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3658INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3659{
developera3c68b92022-09-13 15:27:29 +08003660 int index = -1;
3661 wifi_neighbor_ap2_t *scan_array = NULL;
3662 char cmd[256]={0};
3663 char buf[128]={0};
3664 char file_name[32] = {0};
3665 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003666 char line[256] = {0};
3667 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003668 int freq=0;
3669 FILE *f = NULL;
3670 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003671 int channels_num = 0;
3672 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003673 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003674 bool filter_enable = false;
3675 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003676
developer615510b2022-09-27 10:14:35 +08003677 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003678
3679 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3680 f = fopen(file_name, "r");
3681 if (f != NULL) {
3682 fgets(filter_SSID, sizeof(file_name), f);
3683 if (strlen(filter_SSID) != 0)
3684 filter_enable = true;
3685 fclose(f);
3686 }
3687
3688 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003689 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003690 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003691
developer5550e242022-09-30 09:59:32 +08003692
developer06a01d92022-09-07 16:32:39 +08003693
developera3c68b92022-09-13 15:27:29 +08003694 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 +08003695 // 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 +08003696 fprintf(stderr, "cmd: %s\n", cmd);
3697 if ((f = popen(cmd, "r")) == NULL) {
3698 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3699 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003700 }
developer5550e242022-09-30 09:59:32 +08003701
3702 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3703 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3704
developer615510b2022-09-27 10:14:35 +08003705 ret = fgets(line, sizeof(line), f);
3706 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003707 if(strstr(line, "BSS") != NULL) { // new neighbor info
3708 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3709 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3710 // 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 +08003711
developera3c68b92022-09-13 15:27:29 +08003712 if (!filter_BSS) {
3713 index++;
3714 wifi_neighbor_ap2_t *tmp;
3715 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3716 if (tmp == NULL) { // no more memory to use
3717 index--;
3718 wifi_dbg_printf("%s: realloc failed\n", __func__);
3719 break;
3720 }
3721 scan_array = tmp;
3722 }
3723 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3724
3725 filter_BSS = false;
3726 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3727 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3728 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3729 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3730 } else if (strstr(line, "freq") != NULL) {
3731 sscanf(line," freq: %d", &freq);
3732 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3733
3734 if (freq >= 2412 && freq <= 2484) {
3735 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3736 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3737 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3738 }
3739 else if (freq >= 5160 && freq <= 5805) {
3740 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3741 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3742 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3743 }
3744
3745 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003746 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003747 for (int i = 0; i < channels_num; i++) {
3748 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3749 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3750 break;
3751 }
3752 }
3753 }
3754 } else if (strstr(line, "beacon interval") != NULL) {
3755 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3756 } else if (strstr(line, "signal") != NULL) {
3757 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3758 } else if (strstr(line,"SSID") != NULL) {
3759 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3760 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3761 filter_BSS = true;
3762 }
3763 } else if (strstr(line, "Supported rates") != NULL) {
3764 char SRate[80] = {0}, *tmp = NULL;
3765 memset(buf, 0, sizeof(buf));
3766 strcpy(SRate, line);
3767 tmp = strtok(SRate, ":");
3768 tmp = strtok(NULL, ":");
3769 strcpy(buf, tmp);
3770 memset(SRate, 0, sizeof(SRate));
3771
3772 tmp = strtok(buf, " \n");
3773 while (tmp != NULL) {
3774 strcat(SRate, tmp);
3775 if (SRate[strlen(SRate) - 1] == '*') {
3776 SRate[strlen(SRate) - 1] = '\0';
3777 }
3778 strcat(SRate, ",");
3779
3780 tmp = strtok(NULL, " \n");
3781 }
3782 SRate[strlen(SRate) - 1] = '\0';
3783 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3784 } else if (strstr(line, "DTIM") != NULL) {
3785 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3786 } else if (strstr(line, "VHT capabilities") != NULL) {
3787 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3788 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3789 } else if (strstr(line, "HT capabilities") != NULL) {
3790 strcat(scan_array[index].ap_SupportedStandards, ",n");
3791 strcpy(scan_array[index].ap_OperatingStandards, "n");
3792 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003793 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003794 sscanf(line," * channel width: %d", &vht_channel_width);
3795 if(vht_channel_width == 1) {
3796 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3797 } else {
3798 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3799 }
3800 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3801 continue;
3802 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003803 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003804 sscanf(line," * secondary channel offset: %s", &buf);
3805 if (!strcmp(buf, "above")) {
3806 //40Mhz +
3807 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3808 }
3809 else if (!strcmp(buf, "below")) {
3810 //40Mhz -
3811 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3812 } else {
3813 //20Mhz
3814 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3815 }
3816 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3817 continue;
3818 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003819 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3820 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3821 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003822 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3823 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003824 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003825 else
developer615510b2022-09-27 10:14:35 +08003826 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003827 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003828 if (strstr(line, "HE80/5GHz") != NULL) {
3829 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3830 ret = fgets(line, sizeof(line), f);
3831 } else
3832 continue;
developera3c68b92022-09-13 15:27:29 +08003833 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003834 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003835 }
developer615510b2022-09-27 10:14:35 +08003836 continue;
developera3c68b92022-09-13 15:27:29 +08003837 } else if (strstr(line, "WPA") != NULL) {
3838 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3839 } else if (strstr(line, "RSN") != NULL) {
3840 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3841 } else if (strstr(line, "Group cipher") != NULL) {
3842 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3843 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3844 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3845 }
3846 }
developer615510b2022-09-27 10:14:35 +08003847 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003848 }
3849
3850 if (!filter_BSS) {
3851 *output_array_size = index + 1;
3852 } else {
3853 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3854 *output_array_size = index;
3855 }
3856 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003857 pclose(f);
developer5550e242022-09-30 09:59:32 +08003858 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003860 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003861}
3862
3863//>> Deprecated: used for old RDKB code.
3864INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3865{
3866 INT status = RETURN_ERR;
3867
3868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3869 output_struct->wifi_PLCPErrorCount = 0;
3870 output_struct->wifi_FCSErrorCount = 0;
3871 output_struct->wifi_InvalidMACCount = 0;
3872 output_struct->wifi_PacketsOtherReceived = 0;
3873 output_struct->wifi_Noise = 0;
3874 status = RETURN_OK;
3875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3876 return status;
3877}
3878
3879INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3880{
3881 char cmd[128];
3882 char buf[1280];
3883 char *pos = NULL;
3884
3885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3886 if (NULL == output_struct)
3887 return RETURN_ERR;
3888
3889 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3890
3891 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3892 _syscmd(cmd, buf, sizeof(buf));
3893
3894 pos = buf;
3895 if ((pos = strstr(pos, "RX packets:")) == NULL)
3896 return RETURN_ERR;
3897 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3898
3899 if ((pos = strstr(pos, "TX packets:")) == NULL)
3900 return RETURN_ERR;
3901 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3902
3903 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3904 return RETURN_ERR;
3905 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3906
3907 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3908 return RETURN_ERR;
3909 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3910
3911 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3912 _syscmd(cmd, buf, sizeof(buf));
3913 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3914
3915#if 0
3916 //TODO: need to revisit below implementation
3917 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3918 char interface_name[MAX_BUF_SIZE] = {0};
3919 char interface_status[MAX_BUF_SIZE] = {0};
3920 char Value[MAX_BUF_SIZE] = {0};
3921 char buf[MAX_CMD_SIZE] = {0};
3922 char cmd[MAX_CMD_SIZE] = {0};
3923 FILE *fp = NULL;
3924
3925 if (NULL == output_struct) {
3926 return RETURN_ERR;
3927 }
3928
3929 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3930
3931 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3932 {
3933 if(apIndex == 0) //private_wifi for 2.4G
3934 {
3935 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3936 }
3937 else if(apIndex == 1) //private_wifi for 5G
3938 {
3939 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3940 }
3941 else if(apIndex == 4) //public_wifi for 2.4G
3942 {
3943 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3944 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3945 {
3946 return RETURN_ERR;
3947 }
3948 if(buf[0] == '#')//tp-link
3949 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3950 else//tenda
3951 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3952 }
3953 else if(apIndex == 5) //public_wifi for 5G
3954 {
3955 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3956 }
3957
3958 GetIfacestatus(interface_name, interface_status);
3959
3960 if(0 != strcmp(interface_status, "1"))
3961 return RETURN_ERR;
3962
3963 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3964 system(cmd);
3965
3966 fp = fopen("/tmp/SSID_Stats.txt", "r");
3967 if(fp == NULL)
3968 {
3969 printf("/tmp/SSID_Stats.txt not exists \n");
3970 return RETURN_ERR;
3971 }
3972 fclose(fp);
3973
3974 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3975 File_Reading(buf, Value);
3976 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3977
3978 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3979 File_Reading(buf, Value);
3980 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3981
3982 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3983 File_Reading(buf, Value);
3984 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3985
3986 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3987 File_Reading(buf, Value);
3988 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3989
3990 /* There is no specific parameter from caller to associate the value wifi_Associations */
3991 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3992 //_syscmd(cmd, buf, sizeof(buf));
3993 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3994 }
3995#endif
3996 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3997 return RETURN_OK;
3998}
3999
4000INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4001{
4002 char interface_name[MAX_BUF_SIZE] = {0};
4003 char interface_status[MAX_BUF_SIZE] = {0};
4004 char Value[MAX_BUF_SIZE] = {0};
4005 char buf[MAX_CMD_SIZE] = {0};
4006 char cmd[MAX_CMD_SIZE] = {0};
4007 FILE *fp = NULL;
4008
4009 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4010 if (NULL == output_struct)
4011 return RETURN_ERR;
4012
4013 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4014
4015 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4016 {
4017 if(apIndex == 0) //private_wifi for 2.4G
4018 {
4019 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4020 }
4021 else if(apIndex == 1) //private_wifi for 5G
4022 {
4023 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4024 }
4025 else if(apIndex == 4) //public_wifi for 2.4G
4026 {
4027 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4028 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4029 {
4030 return RETURN_ERR;
4031 }
4032 if(buf[0] == '#')
4033 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4034 else
4035 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4036 }
4037 else if(apIndex == 5) //public_wifi for 5G
4038 {
4039 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4040 }
4041
4042 GetIfacestatus(interface_name, interface_status);
4043
4044 if(0 != strcmp(interface_status, "1"))
4045 return RETURN_ERR;
4046
4047 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4048 system(cmd);
4049
4050 fp = fopen("/tmp/SSID_Stats.txt", "r");
4051 if(fp == NULL)
4052 {
4053 printf("/tmp/SSID_Stats.txt not exists \n");
4054 return RETURN_ERR;
4055 }
4056 fclose(fp);
4057
4058 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4059 File_Reading(buf, Value);
4060 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4061
4062 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4063 File_Reading(buf, Value);
4064 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4065
4066 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4067 File_Reading(buf, Value);
4068 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4069
4070 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4071 File_Reading(buf, Value);
4072 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4073 }
4074
4075 output_struct->wifi_UnicastPacketsSent = 0;
4076 output_struct->wifi_UnicastPacketsReceived = 0;
4077 output_struct->wifi_MulticastPacketsSent = 0;
4078 output_struct->wifi_MulticastPacketsReceived = 0;
4079 output_struct->wifi_BroadcastPacketsSent = 0;
4080 output_struct->wifi_BroadcastPacketsRecevied = 0;
4081 output_struct->wifi_UnknownPacketsReceived = 0;
4082
4083 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4084 return RETURN_OK;
4085}
4086
4087INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4088{
4089 INT status = RETURN_ERR;
4090
4091 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4092 //Below values should get updated from hal
4093 output_struct->wifi_RetransCount=0;
4094 output_struct->wifi_FailedRetransCount=0;
4095 output_struct->wifi_RetryCount=0;
4096 output_struct->wifi_MultipleRetryCount=0;
4097 output_struct->wifi_ACKFailureCount=0;
4098 output_struct->wifi_AggregatedPacketCount=0;
4099
4100 status = RETURN_OK;
4101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4102
4103 return status;
4104}
4105
4106INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4107{
4108 INT status = RETURN_ERR;
4109 UINT index;
4110 wifi_neighbor_ap_t *pt=NULL;
4111
4112 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4113 *output_array_size=2;
4114 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4115 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4116 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4117 strcpy(pt->ap_Radio,"");
4118 strcpy(pt->ap_SSID,"");
4119 strcpy(pt->ap_BSSID,"");
4120 strcpy(pt->ap_Mode,"");
4121 pt->ap_Channel=1;
4122 pt->ap_SignalStrength=0;
4123 strcpy(pt->ap_SecurityModeEnabled,"");
4124 strcpy(pt->ap_EncryptionMode,"");
4125 strcpy(pt->ap_OperatingFrequencyBand,"");
4126 strcpy(pt->ap_SupportedStandards,"");
4127 strcpy(pt->ap_OperatingStandards,"");
4128 strcpy(pt->ap_OperatingChannelBandwidth,"");
4129 pt->ap_BeaconPeriod=1;
4130 pt->ap_Noise=0;
4131 strcpy(pt->ap_BasicDataTransferRates,"");
4132 strcpy(pt->ap_SupportedDataTransferRates,"");
4133 pt->ap_DTIMPeriod=1;
4134 pt->ap_ChannelUtilization = 1;
4135 }
4136
4137 status = RETURN_OK;
4138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4139
4140 return status;
4141}
4142
4143//----------------- AP HAL -------------------------------
4144
4145//>> Deprecated: used for old RDKB code.
4146INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4147{
4148 if (NULL == output_ulong || NULL == output_struct)
4149 return RETURN_ERR;
4150 *output_ulong = 0;
4151 *output_struct = NULL;
4152 return RETURN_OK;
4153}
4154
4155#ifdef HAL_NETLINK_IMPL
4156static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4157 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4158 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4159 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4160 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4161 char mac_addr[20];
4162 static int count=0;
4163 int rate=0;
4164
4165 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4166
4167 nla_parse(tb,
4168 NL80211_ATTR_MAX,
4169 genlmsg_attrdata(gnlh, 0),
4170 genlmsg_attrlen(gnlh, 0),
4171 NULL);
4172
4173 if(!tb[NL80211_ATTR_STA_INFO]) {
4174 fprintf(stderr, "sta stats missing!\n");
4175 return NL_SKIP;
4176 }
4177
4178
4179 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4180 fprintf(stderr, "failed to parse nested attributes!\n");
4181 return NL_SKIP;
4182 }
4183
4184 //devIndex starts from 1
4185 if( ++count == out->wifi_devIndex )
4186 {
4187 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4188 //Getting the mac addrress
4189 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4190
4191 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4192 fprintf(stderr, "failed to parse nested rate attributes!");
4193 return NL_SKIP;
4194 }
4195
4196 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4197 if(rinfo[NL80211_RATE_INFO_BITRATE])
4198 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4199 out->wifi_devTxRate = rate/10;
4200 }
4201
4202 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4203 fprintf(stderr, "failed to parse nested rate attributes!");
4204 return NL_SKIP;
4205 }
4206
4207 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4208 if(rinfo[NL80211_RATE_INFO_BITRATE])
4209 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4210 out->wifi_devRxRate = rate/10;
4211 }
4212 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4213 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4214
4215 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4216 count = 0; //starts the count for next cycle
4217 return NL_STOP;
4218 }
4219
4220 return NL_SKIP;
4221
4222}
4223#endif
4224
4225INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4226{
4227#ifdef HAL_NETLINK_IMPL
4228 Netlink nl;
4229 char if_name[10];
4230
4231 wifi_device_info_t info;
4232 info.wifi_devIndex = devIndex;
4233
4234 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4235
4236 nl.id = initSock80211(&nl);
4237
4238 if (nl.id < 0) {
4239 fprintf(stderr, "Error initializing netlink \n");
4240 return -1;
4241 }
4242
4243 struct nl_msg* msg = nlmsg_alloc();
4244
4245 if (!msg) {
4246 fprintf(stderr, "Failed to allocate netlink message.\n");
4247 nlfree(&nl);
4248 return -2;
4249 }
4250
4251 genlmsg_put(msg,
4252 NL_AUTO_PORT,
4253 NL_AUTO_SEQ,
4254 nl.id,
4255 0,
4256 NLM_F_DUMP,
4257 NL80211_CMD_GET_STATION,
4258 0);
4259
4260 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4261 nl_send_auto(nl.socket, msg);
4262 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4263 nl_recvmsgs(nl.socket, nl.cb);
4264 nlmsg_free(msg);
4265 nlfree(&nl);
4266
4267 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4268 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4269 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4270 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4271 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4272 return RETURN_OK;
4273#else
4274 //iw utility to retrieve station information
4275#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4276#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4277#define MACFILE "/tmp/wifi_AssoMac.txt"
4278#define TXRATEFILE "/tmp/wifi_txrate.txt"
4279#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4280 FILE *file = NULL;
4281 char if_name[10] = {'\0'};
4282 char pipeCmd[256] = {'\0'};
4283 char line[256];
4284 int count,device = 0;
4285
4286 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4287
4288 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4289 file = popen(pipeCmd, "r");
4290
4291 if(file == NULL)
4292 return RETURN_ERR; //popen failed
4293
4294 fgets(line, sizeof line, file);
4295 device = atoi(line);
4296 pclose(file);
4297
4298 if(device == 0)
4299 return RETURN_ERR; //No devices are connected
4300
4301 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4302 system(pipeCmd);
4303
4304 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4305
4306 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4307
4308 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4309
4310 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4311
4312 //devIndex starts from 1, ++count
4313 if((file = fopen(SIGNALFILE, "r")) != NULL )
4314 {
4315 for(count =0;fgets(line, sizeof line, file) != NULL;)
4316 {
4317 if (++count == devIndex)
4318 {
4319 output_struct->wifi_devSignalStrength = atoi(line);
4320 break;
4321 }
4322 }
4323 fclose(file);
4324 }
4325 else
4326 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4327
4328 if((file = fopen(MACFILE, "r")) != NULL )
4329 {
4330 for(count =0;fgets(line, sizeof line, file) != NULL;)
4331 {
4332 if (++count == devIndex)
4333 {
4334 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]);
4335 break;
4336 }
4337 }
4338 fclose(file);
4339 }
4340 else
4341 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4342
4343 if((file = fopen(TXRATEFILE, "r")) != NULL )
4344 {
4345 for(count =0;fgets(line, sizeof line, file) != NULL;)
4346 {
4347 if (++count == devIndex)
4348 {
4349 output_struct->wifi_devTxRate = atoi(line);
4350 break;
4351 }
4352 }
4353 fclose(file);
4354 }
4355 else
4356 fprintf(stderr,"fopen wifi_txrate.txt failed");
4357
4358 if((file = fopen(RXRATEFILE, "r")) != NULL)
4359 {
4360 for(count =0;fgets(line, sizeof line, file) != NULL;)
4361 {
4362 if (++count == devIndex)
4363 {
4364 output_struct->wifi_devRxRate = atoi(line);
4365 break;
4366 }
4367 }
4368 fclose(file);
4369 }
4370 else
4371 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4372
4373 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4374
4375 return RETURN_OK;
4376#endif
4377}
4378
4379INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4380{
4381 if (NULL == device)
4382 return RETURN_ERR;
4383 return RETURN_OK;
4384}
4385//<<
4386
4387
4388//--------------wifi_ap_hal-----------------------------
4389//enables CTS protection for the radio used by this AP
4390INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4391{
4392 //save config and Apply instantly
4393 return RETURN_ERR;
4394}
4395
4396// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4397INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4398{
developer463d39a2022-09-13 15:32:51 +08004399 char config_file[64] = {'\0'};
4400 char buf[64] = {'\0'};
4401 struct params list;
4402
4403 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4404 list.name = "ht_coex";
4405 snprintf(buf, sizeof(buf), "%d", enable);
4406 list.value = buf;
4407
4408 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4409 wifi_hostapdWrite(config_file, &list, 1);
4410 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4411
4412 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4413
4414 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004415}
4416
4417//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4418INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4419{
developerea4bcce2022-09-13 15:26:13 +08004420 char config_file[MAX_BUF_SIZE] = {'\0'};
4421 char buf[MAX_BUF_SIZE] = {'\0'};
4422 struct params list;
4423
4424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4425 if (threshold < 256 || threshold > 2346 )
4426 return RETURN_ERR;
4427 list.name = "fragm_threshold";
4428 snprintf(buf, sizeof(buf), "%d", threshold);
4429 list.value = buf;
4430
4431 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4432 wifi_hostapdWrite(config_file, &list, 1);
4433 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004434
developerea4bcce2022-09-13 15:26:13 +08004435 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004436
4437 return RETURN_OK;
4438}
4439
4440// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4441INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4442{
developer51a927d2022-09-13 15:42:22 +08004443 char config_file[64] = {'\0'};
4444 char cmd[128] = {'\0'};
4445 char buf[64] = {'\0'};
4446 char stbc_config[16] = {'\0'};
4447 wifi_band band;
4448 int iterator = 0;
4449 BOOL current_stbc = FALSE;
4450
4451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4452
4453 band = wifi_index_to_band(radioIndex);
4454 if (band == band_invalid)
4455 return RETURN_ERR;
4456
4457 if (band == band_2_4)
4458 iterator = 1;
4459 else if (band == band_5)
4460 iterator = 2;
4461 else
4462 return RETURN_OK;
4463
4464 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4465
4466 // set ht and vht config
4467 for (int i = 0; i < iterator; i++) {
4468 memset(stbc_config, 0, sizeof(stbc_config));
4469 memset(cmd, 0, sizeof(cmd));
4470 memset(buf, 0, sizeof(buf));
4471 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4472 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4473 _syscmd(cmd, buf, sizeof(buf));
4474 if (strlen(buf) != 0)
4475 current_stbc = TRUE;
4476 if (current_stbc == STBC_Enable)
4477 continue;
4478
4479 if (STBC_Enable == TRUE) {
4480 // Append the STBC flags in capab config
4481 memset(cmd, 0, sizeof(cmd));
4482 if (i == 0)
4483 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4484 else
4485 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4486 _syscmd(cmd, buf, sizeof(buf));
4487 } else if (STBC_Enable == FALSE) {
4488 // Remove the STBC flags and remain other flags in capab
4489 memset(cmd, 0, sizeof(cmd));
4490 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4491 _syscmd(cmd, buf, sizeof(buf));
4492 memset(cmd, 0, sizeof(cmd));
4493 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4494 _syscmd(cmd, buf, sizeof(buf));
4495 }
4496 }
4497
4498 wifi_reloadAp(radioIndex);
4499
4500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4501 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004502}
4503
4504// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4505INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4506{
developer54e6b9f2022-09-28 14:41:20 +08004507 char AMSDU_file_path[64] = {0};
4508
4509 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4510
4511 if(output_bool == NULL)
4512 return RETURN_ERR;
4513
4514 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4515
4516 if (access(AMSDU_file_path, F_OK) == 0)
4517 *output_bool = TRUE;
4518 else
4519 *output_bool = FALSE;
4520
4521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4522 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004523}
4524
4525// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4526INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4527{
developer54e6b9f2022-09-28 14:41:20 +08004528 char cmd[64]={0};
4529 char buf[64]={0};
4530 char AMSDU_file_path[64] = {0};
4531
4532 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4533
4534 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4535 _syscmd(cmd, buf, sizeof(buf));
4536
4537 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4538 memset(cmd, 0, sizeof(cmd));
4539 if (amsduEnable == TRUE)
4540 sprintf(cmd, "touch %s", AMSDU_file_path);
4541 else
4542 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4543 _syscmd(cmd, buf, sizeof(buf));
4544
4545 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4546 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004547}
4548
4549//P2 // outputs the number of Tx streams
4550INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4551{
developer2de97692022-09-26 14:00:03 +08004552 char buf[8] = {0};
4553 char cmd[128] = {0};
4554
4555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4556
4557 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4558 _syscmd(cmd, buf, sizeof(buf));
4559
4560 // if there is no record, output the max number of spatial streams
4561 if (strlen(buf) == 0) {
4562 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4563 _syscmd(cmd, buf, sizeof(buf));
4564 }
4565
4566 *output_int = (INT)strtol(buf, NULL, 10);
4567
4568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4569
4570 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004571}
4572
4573//P2 // sets the number of Tx streams to an enviornment variable
4574INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4575{
developer2de97692022-09-26 14:00:03 +08004576 char cmd[128] = {0};
4577 char buf[128] = {0};
4578 char chain_mask_file[128] = {0};
4579 FILE *f = NULL;
4580
4581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4582
4583 if (numStreams == 0) {
4584 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4585 return RETURN_ERR;
4586 }
4587 wifi_setRadioEnable(radioIndex, FALSE);
4588 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4589 _syscmd(cmd, buf, sizeof(buf));
4590
4591 if (strlen(buf) > 0) {
4592 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4593 return RETURN_ERR;
4594 }
4595 wifi_setRadioEnable(radioIndex, TRUE);
4596
4597 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4598 f = fopen(chain_mask_file, "w");
4599 if (f == NULL) {
4600 fprintf(stderr, "%s: fopen failed.\n", __func__);
4601 return RETURN_ERR;
4602 }
4603 fprintf(f, "%d", numStreams);
4604 fclose(f);
4605 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4606 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004607}
4608
4609//P2 // outputs the number of Rx streams
4610INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4611{
developer2de97692022-09-26 14:00:03 +08004612 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4613 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4614 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004615 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004616 }
4617 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004618 return RETURN_OK;
4619}
4620
4621//P2 // sets the number of Rx streams to an enviornment variable
4622INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4623{
developer2de97692022-09-26 14:00:03 +08004624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4625 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4626 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4627 return RETURN_ERR;
4628 }
4629 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004630 return RETURN_ERR;
4631}
4632
4633//Get radio RDG enable setting
4634INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4635{
4636 if (NULL == output_bool)
4637 return RETURN_ERR;
4638 *output_bool = TRUE;
4639 return RETURN_OK;
4640}
4641
4642//Get radio RDG enable setting
4643INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4644{
4645 if (NULL == output_bool)
4646 return RETURN_ERR;
4647 *output_bool = TRUE;
4648 return RETURN_OK;
4649}
4650
4651//Set radio RDG enable setting
4652INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4653{
4654 return RETURN_ERR;
4655}
4656
4657//Get radio ADDBA enable setting
4658INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4659{
4660 if (NULL == output_bool)
4661 return RETURN_ERR;
4662 *output_bool = TRUE;
4663 return RETURN_OK;
4664}
4665
4666//Set radio ADDBA enable setting
4667INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4668{
4669 return RETURN_ERR;
4670}
4671
4672//Get radio auto block ack enable setting
4673INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4674{
4675 if (NULL == output_bool)
4676 return RETURN_ERR;
4677 *output_bool = TRUE;
4678 return RETURN_OK;
4679}
4680
4681//Set radio auto block ack enable setting
4682INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4683{
4684 return RETURN_ERR;
4685}
4686
4687//Get radio 11n pure mode enable support
4688INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4689{
4690 if (NULL == output_bool)
4691 return RETURN_ERR;
4692 *output_bool = TRUE;
4693 return RETURN_OK;
4694}
4695
4696//Get radio 11n pure mode enable setting
4697INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4698{
4699 if (NULL == output_bool)
4700 return RETURN_ERR;
4701 *output_bool = TRUE;
4702 return RETURN_OK;
4703}
4704
4705//Set radio 11n pure mode enable setting
4706INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4707{
4708 return RETURN_ERR;
4709}
4710
4711//Get radio IGMP snooping enable setting
4712INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4713{
developer81bf2ed2022-09-13 15:31:14 +08004714 char cmd[128]={0};
4715 char buf[4]={0};
4716 bool bridge = FALSE, mac80211 = FALSE;
4717 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4718
4719 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004720 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004721
4722 *output_bool = FALSE;
4723
4724 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4725 _syscmd(cmd, buf, sizeof(buf));
4726 if (strncmp(buf, "1", 1) == 0)
4727 bridge = TRUE;
4728
4729 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4730 _syscmd(cmd, buf, sizeof(buf));
4731 if (strncmp(buf, "1", 1) == 0)
4732 mac80211 = TRUE;
4733
4734 if (bridge && mac80211)
4735 *output_bool = TRUE;
4736
4737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004738 return RETURN_OK;
4739}
4740
4741//Set radio IGMP snooping enable setting
4742INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4743{
developer81bf2ed2022-09-13 15:31:14 +08004744 char cmd[128]={0};
4745 char buf[4]={0};
4746
4747 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4748
4749 // bridge
4750 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4751 _syscmd(cmd, buf, sizeof(buf));
4752
4753 // mac80211
4754 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4755 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4756 _syscmd(cmd, buf, sizeof(buf));
4757 }
4758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4759 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004760}
4761
4762//Get the Reset count of radio
4763INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4764{
4765 if (NULL == output_int)
4766 return RETURN_ERR;
4767 *output_int = (radioIndex==0)? 1: 3;
4768
4769 return RETURN_OK;
4770}
4771
4772
4773//---------------------------------------------------------------------------------------------------
4774//
4775// Additional Wifi AP level APIs used for Access Point devices
4776//
4777//---------------------------------------------------------------------------------------------------
4778
4779// creates a new ap and pushes these parameters to the hardware
4780INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4781{
4782 char buf[1024];
4783 char cmd[128];
4784
4785 if (NULL == essid)
4786 return RETURN_ERR;
4787
4788 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4789 _syscmd(cmd, buf, sizeof(buf));
4790
4791 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4792 _syscmd(cmd, buf, sizeof(buf));
4793
4794 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4795
4796 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4797 _syscmd(cmd, buf, sizeof(buf));
4798
4799 return RETURN_OK;
4800}
4801
4802// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4803INT wifi_deleteAp(INT apIndex)
4804{
4805 char buf[1024];
4806 char cmd[128];
4807
4808 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4809 _syscmd(cmd, buf, sizeof(buf));
4810
4811 wifi_removeApSecVaribles(apIndex);
4812
4813 return RETURN_OK;
4814}
4815
4816// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4817INT wifi_getApName(INT apIndex, CHAR *output_string)
4818{
4819 if(NULL == output_string)
4820 return RETURN_ERR;
4821
4822 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4823 return RETURN_OK;
4824}
4825
4826// Outputs the index number in that corresponds to the SSID string
4827INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4828{
4829 CHAR *pos = NULL;
4830
4831 *output_int = -1;
4832 pos = strstr(inputSsidString, AP_PREFIX);
4833 if(pos)
4834 {
4835 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4836 return RETURN_OK;
4837 }
4838 return RETURN_ERR;
4839}
4840
4841INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4842{
4843 return wifi_getIndexFromName(inputSsidString, output_int);
4844}
4845
4846// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4847INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4848{
4849 char buf[MAX_BUF_SIZE] = {0};
4850 char cmd[MAX_CMD_SIZE] = {0};
4851 char config_file[MAX_BUF_SIZE] = {0};
4852
4853 if(NULL == output_string)
4854 return RETURN_ERR;
4855
4856 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4857 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4858 if((strcmp(buf,"3")==0))
4859 snprintf(output_string, 32, "WPAand11i");
4860 else if((strcmp(buf,"2")==0))
4861 snprintf(output_string, 32, "11i");
4862 else if((strcmp(buf,"1")==0))
4863 snprintf(output_string, 32, "WPA");
4864 else
4865 snprintf(output_string, 32, "None");
4866
4867 return RETURN_OK;
4868}
4869
4870// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4871INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4872{
4873 char config_file[MAX_BUF_SIZE] = {0};
4874 struct params list;
4875
4876 if (NULL == beaconTypeString)
4877 return RETURN_ERR;
4878 list.name = "wpa";
4879 list.value = "0";
4880
4881 if((strcmp(beaconTypeString,"WPAand11i")==0))
4882 list.value="3";
4883 else if((strcmp(beaconTypeString,"11i")==0))
4884 list.value="2";
4885 else if((strcmp(beaconTypeString,"WPA")==0))
4886 list.value="1";
4887
4888 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4889 wifi_hostapdWrite(config_file, &list, 1);
4890 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4891 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4892 return RETURN_OK;
4893}
4894
4895// sets the beacon interval on the hardware for this AP
4896INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4897{
developer5f222492022-09-13 15:21:52 +08004898 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4899 struct params params={'\0'};
4900 char buf[MAX_BUF_SIZE] = {'\0'};
4901 char config_file[MAX_BUF_SIZE] = {'\0'};
4902
4903 params.name = "beacon_int";
4904 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4905 params.value = buf;
4906
4907 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4908 wifi_hostapdWrite(config_file, &params, 1);
4909
4910 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4912 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004913}
4914
4915INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4916{
4917 //save config and apply instantly
4918 return RETURN_ERR;
4919}
4920
4921// Get the packet size threshold supported.
4922INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4923{
4924 //save config and apply instantly
4925 if (NULL == output_bool)
4926 return RETURN_ERR;
4927 *output_bool = FALSE;
4928 return RETURN_OK;
4929}
4930
4931// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4932INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4933{
4934 char cmd[128];
4935 char buf[512];
4936
4937 if (threshold > 0)
4938 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4939 else
4940 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4941 _syscmd(cmd, buf, sizeof(buf));
4942
4943 return RETURN_OK;
4944}
4945
4946// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4947INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4948{
4949 if (NULL == output_string)
4950 return RETURN_ERR;
4951 snprintf(output_string, 32, "TKIPandAESEncryption");
4952 return RETURN_OK;
4953
4954}
4955
4956// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4957INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4958{
4959 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4960 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4961
4962 if(NULL == output_string)
4963 return RETURN_ERR;
4964
4965 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4966 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4967
4968 if(strcmp(buf,"0")==0)
4969 {
4970 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4971 snprintf(output_string, 32, "None");
4972 return RETURN_OK;
4973 }
4974 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4975 param_name = "rsn_pairwise";
4976 else if((strcmp(buf,"1")==0))
4977 param_name = "wpa_pairwise";
4978 else
4979 return RETURN_ERR;
4980 memset(output_string,'\0',32);
4981 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4982 wifi_hostapdRead(config_file,param_name,output_string,32);
4983 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4984
4985 if(strcmp(output_string,"TKIP") == 0)
4986 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4987 else if(strcmp(output_string,"CCMP") == 0)
4988 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4989 else if(strcmp(output_string,"TKIP CCMP") == 0)
4990 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4991
4992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4993 return RETURN_OK;
4994}
4995
4996// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4997INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4998{
4999 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5000 struct params params={'\0'};
5001 char output_string[32];
5002 char config_file[MAX_BUF_SIZE] = {0};
5003
5004 memset(output_string,'\0',32);
5005 wifi_getApWpaEncryptionMode(apIndex,output_string);
5006
5007 if(strcmp(encMode, "TKIPEncryption") == 0)
5008 params.value = "TKIP";
5009 else if(strcmp(encMode,"AESEncryption") == 0)
5010 params.value = "CCMP";
5011 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5012 params.value = "TKIP CCMP";
5013
5014 if((strcmp(output_string,"WPAand11i")==0))
5015 {
5016 params.name = "wpa_pairwise";
5017 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5018 wifi_hostapdWrite(config_file, &params, 1);
5019 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5020
5021 params.name,"rsn_pairwise";
5022 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5023 wifi_hostapdWrite(config_file, &params, 1);
5024 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5025
5026 return RETURN_OK;
5027 }
5028 else if((strcmp(output_string,"11i")==0))
5029 {
5030 params.name = "rsn_pairwise";
5031 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5032 wifi_hostapdWrite(config_file, &params, 1);
5033 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5034 return RETURN_OK;
5035 }
5036 else if((strcmp(output_string,"WPA")==0))
5037 {
5038 params.name = "wpa_pairwise";
5039 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5040 wifi_hostapdWrite(config_file, &params, 1);
5041 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5042 return RETURN_OK;
5043 }
5044
5045 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5046 return RETURN_OK;
5047}
5048
5049// deletes internal security varable settings for this ap
5050INT wifi_removeApSecVaribles(INT apIndex)
5051{
5052 //TODO: remove the entry in hostapd config file
5053 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5054 //_syscmd(cmd, buf, sizeof(buf));
5055
5056 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5057 //_syscmd(cmd, buf, sizeof(buf));
5058 return RETURN_ERR;
5059}
5060
5061// changes the hardware settings to disable encryption on this ap
5062INT wifi_disableApEncryption(INT apIndex)
5063{
5064 //Apply instantly
5065 return RETURN_ERR;
5066}
5067
5068// set the authorization mode on this ap
5069// mode mapping as: 1: open, 2: shared, 4:auto
5070INT wifi_setApAuthMode(INT apIndex, INT mode)
5071{
developeraf95c502022-09-13 16:18:22 +08005072 struct params params={0};
5073 char config_file[64] = {0};
5074 int ret;
5075
5076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5077
5078 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5079 params.name = "auth_algs";
5080
5081 if (mode & 1 && mode & 2)
5082 params.value = "3";
5083 else if (mode & 2)
5084 params.value = "2";
5085 else if (mode & 1)
5086 params.value = "1";
5087 else
5088 params.value = "0";
5089
5090 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5091 wifi_hostapdWrite(config_file, &params, 1);
5092 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5094
5095 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005096}
5097
5098// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5099INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5100{
5101 //save to wifi config, and wait for wifi restart to apply
5102 struct params params={'\0'};
5103 char config_file[MAX_BUF_SIZE] = {0};
5104 int ret;
5105
5106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5107 if(authMode == NULL)
5108 return RETURN_ERR;
5109
5110 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5111 params.name = "wpa_key_mgmt";
5112
5113 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5114 params.value = "WPA-PSK";
5115 else if(strcmp(authMode,"EAPAuthentication") == 0)
5116 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005117 else if (strcmp(authMode, "SAEAuthentication") == 0)
5118 params.value = "SAE";
5119 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5120 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005121 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5122 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005123 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5124 return RETURN_OK; //This is taken careof in beaconType
5125
5126 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5127 ret=wifi_hostapdWrite(config_file,&params,1);
5128 if(!ret)
5129 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5131
5132 return ret;
5133}
5134
5135// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5136INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5137{
5138 //save to wifi config, and wait for wifi restart to apply
5139 char BeaconType[50] = {0};
5140 char config_file[MAX_BUF_SIZE] = {0};
5141
5142 *authMode = 0;
5143 wifi_getApBeaconType(apIndex,BeaconType);
5144 printf("%s____%s \n",__FUNCTION__,BeaconType);
5145
5146 if(strcmp(BeaconType,"None") == 0)
5147 strcpy(authMode,"None");
5148 else
5149 {
5150 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5151 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5152 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5153 if(strcmp(authMode,"WPA-PSK") == 0)
5154 strcpy(authMode,"SharedAuthentication");
5155 else if(strcmp(authMode,"WPA-EAP") == 0)
5156 strcpy(authMode,"EAPAuthentication");
5157 }
5158
5159 return RETURN_OK;
5160}
5161
5162// Outputs the number of stations associated per AP
5163INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5164{
5165 char cmd[128]={0};
5166 char buf[128]={0};
5167 BOOL status = false;
5168
5169 if(apIndex > MAX_APS)
5170 return RETURN_ERR;
5171
5172 wifi_getApEnable(apIndex,&status);
5173 if (!status)
5174 return RETURN_OK;
5175
5176 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5177 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5178 _syscmd(cmd, buf, sizeof(buf));
5179 sscanf(buf,"%lu", output_ulong);
5180
5181 return RETURN_OK;
5182}
5183
5184// manually removes any active wi-fi association with the device specified on this ap
5185INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5186{
5187 char buf[126]={'\0'};
5188
5189 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5190 system(buf);
5191
5192 return RETURN_OK;
5193}
5194
5195// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5196INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5197{
5198 if(NULL == output_int)
5199 return RETURN_ERR;
5200 *output_int = apIndex%2;
5201 return RETURN_OK;
5202}
5203
5204// sets the radio index for the specific ap
5205INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5206{
5207 //set to config only and wait for wifi reset to apply settings
5208 return RETURN_ERR;
5209}
5210
5211// Get the ACL MAC list per AP
5212INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5213{
5214 char cmd[MAX_CMD_SIZE]={'\0'};
5215 int ret = 0;
5216
5217 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5218 ret = _syscmd(cmd,macArray,buf_size);
5219 if (ret != 0)
5220 return RETURN_ERR;
5221
5222 return RETURN_OK;
5223}
5224
developere6aafda2022-09-13 14:59:28 +08005225INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5226{
5227 char cmd[MAX_CMD_SIZE]={'\0'};
5228 int ret = 0;
5229
5230 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5231 ret = _syscmd(cmd,macArray,buf_size);
5232 if (ret != 0)
5233 return RETURN_ERR;
5234
5235 return RETURN_OK;
5236}
5237
5238
developer06a01d92022-09-07 16:32:39 +08005239// Get the list of stations associated per AP
5240INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5241{
5242 char cmd[128];
5243
5244 if(apIndex > 3) //Currently supporting apIndex upto 3
5245 return RETURN_ERR;
5246 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5247 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5248 _syscmd(cmd, macArray, buf_size);
5249
5250 return RETURN_OK;
5251}
5252
5253// adds the mac address to the filter list
5254//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5255INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5256{
5257 char cmd[MAX_CMD_SIZE]={'\0'};
5258 char buf[MAX_BUF_SIZE]={'\0'};
5259
5260#if 0
5261 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5262 if(_syscmd(cmd,buf,sizeof(buf)))
5263 return RETURN_ERR;
5264#endif
5265 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5266 if(_syscmd(cmd,buf,sizeof(buf)))
5267 return RETURN_ERR;
5268
5269 return RETURN_OK;
5270}
5271
5272// deletes the mac address from the filter list
5273//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5274INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5275{
5276 char cmd[MAX_CMD_SIZE]={'\0'};
5277 char buf[MAX_BUF_SIZE]={'\0'};
5278
5279#if 0
5280 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5281 if(_syscmd(cmd,buf,sizeof(buf)))
5282 return RETURN_ERR;
5283
5284#endif
5285 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5286 if(_syscmd(cmd,buf,sizeof(buf)))
5287 return RETURN_ERR;
5288
5289 return RETURN_OK;
5290}
5291
5292// outputs the number of devices in the filter list
5293INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5294{
developere6aafda2022-09-13 14:59:28 +08005295 char cmd[MAX_BUF_SIZE]={0};
5296 char buf[MAX_CMD_SIZE]={0};
5297
5298 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5299 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005300 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005301
5302 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5303 _syscmd(cmd, buf, sizeof(buf));
5304
5305 *output_uint = atoi(buf);
5306
5307 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5308 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005309}
5310
5311INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5312{
5313 char cmd[128]={'\0'};
5314 char buf[128]={'\0'};
5315
5316 if(strcmp(action,"DENY")==0)
5317 {
5318 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5319 system(buf);
5320 return RETURN_OK;
5321 }
5322
5323 if(strcmp(action,"ALLOW")==0)
5324 {
5325 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5326 system(buf);
5327 return RETURN_OK;
5328 }
5329
5330 return RETURN_ERR;
5331
5332}
5333
5334// enable kick for devices on acl black list
5335INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5336{
5337 char aclArray[512] = {0}, *acl = NULL;
5338 char assocArray[512] = {0}, *asso = NULL;
5339
developere6aafda2022-09-13 14:59:28 +08005340 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005341 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5342
5343 // if there are no devices connected there is nothing to do
5344 if (strlen(assocArray) < 17)
5345 return RETURN_OK;
5346
5347 if (enable == TRUE)
5348 {
5349 //kick off the MAC which is in ACL array (deny list)
5350 acl = strtok(aclArray, "\r\n");
5351 while (acl != NULL) {
5352 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5353 wifi_kickApAssociatedDevice(apIndex, acl);
5354
5355 acl = strtok(NULL, "\r\n");
5356 }
developere6aafda2022-09-13 14:59:28 +08005357 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005358 }
5359 else
5360 {
developere6aafda2022-09-13 14:59:28 +08005361 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005362 }
5363
5364#if 0
5365 //TODO: need to revisit below implementation
5366 char aclArray[512]={0}, *acl=NULL;
5367 char assocArray[512]={0}, *asso=NULL;
5368 char buf[256]={'\0'};
5369 char action[10]={'\0'};
5370 FILE *fr=NULL;
5371 char interface[10]={'\0'};
5372 char config_file[MAX_BUF_SIZE] = {0};
5373
5374 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5375 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5376 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5377 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5378
5379 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5380 system(buf);
5381 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5382 system(buf);
5383 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5384 system(buf);
5385 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5386 system(buf);
5387 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5388 system(buf);
5389
5390 if ( enable == TRUE )
5391 {
5392 int device_count=0;
5393 strcpy(action,"DENY");
5394 //kick off the MAC which is in ACL array (deny list)
5395 acl = strtok (aclArray,",");
5396 while (acl != NULL) {
5397 if(strlen(acl)>=17)
5398 {
5399 apply_rules(apIndex, acl,action,interface);
5400 device_count++;
5401 //Register mac to be blocked ,in syscfg.db persistent storage
5402 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5403 system(buf);
5404 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5405 system(buf);
5406 system("syscfg commit");
5407
5408 wifi_kickApAssociatedDevice(apIndex, acl);
5409 }
5410 acl = strtok (NULL, ",");
5411 }
5412 }
5413 else
5414 {
5415 int device_count=0;
5416 char cmdmac[20]={'\0'};
5417 strcpy(action,"ALLOW");
5418 //kick off the MAC which is not in ACL array (allow list)
5419 acl = strtok (aclArray,",");
5420 while (acl != NULL) {
5421 if(strlen(acl)>=17)
5422 {
5423 apply_rules(apIndex, acl,action,interface);
5424 device_count++;
5425 //Register mac to be Allowed ,in syscfg.db persistent storage
5426 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5427 system(buf);
5428 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5429 system(buf);
5430 sprintf(cmdmac,"%s",acl);
5431 }
5432 acl = strtok (NULL, ",");
5433 }
5434 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5435 system(buf);
5436
5437 //Disconnect the mac which is not in ACL
5438 asso = strtok (assocArray,",");
5439 while (asso != NULL) {
5440 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5441 wifi_kickApAssociatedDevice(apIndex, asso);
5442 asso = strtok (NULL, ",");
5443 }
5444 }
5445#endif
5446 return RETURN_OK;
5447}
5448
5449INT wifi_setPreferPrivateConnection(BOOL enable)
5450{
5451 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5452 char buf[1024] = {0};
5453
5454 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5455 if(enable == TRUE)
5456 {
5457 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5458 sprintf(buf,"ifconfig %s down" ,interface_name);
5459 system(buf);
5460 memset(buf,0,sizeof(buf));
5461 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5462 sprintf(buf,"ifconfig %s down" ,interface_name);
5463 system(buf);
5464 }
5465 else
5466 {
5467 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5468 if(strcmp(ssid_cur_value,"1") == 0)
5469 wifi_RestartPrivateWifi_5G();
5470 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5471 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5472 if(strcmp(ssid_cur_value,"1") == 0)
5473 wifi_RestartHostapd_2G();
5474 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5475 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5476 if(strcmp(ssid_cur_value,"1") == 0)
5477 wifi_RestartHostapd_5G();
5478 }
5479 return RETURN_OK;
5480}
5481
5482// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5483INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5484{
5485 int items = 1;
5486 struct params list[2];
5487 char buf[MAX_BUF_SIZE] = {0};
5488 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005489 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005490
5491 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005492
developer10adcc12022-09-13 14:39:17 +08005493 if (filterMode == 0) {
5494 sprintf(buf, "%d", 0);
5495 list[0].value = buf;
5496
5497 char cmd[128], rtn[128];
5498 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5499 _syscmd(cmd, rtn, sizeof(rtn));
5500 memset(cmd,0,sizeof(cmd));
5501 // Delete deny_mac_file in hostapd configuration
5502 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5503 _syscmd(cmd, rtn, sizeof(rtn));
5504 }
5505 else if (filterMode == 1) {
5506 sprintf(buf, "%d", filterMode);
5507 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005508 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5509 list[1].name = "accept_mac_file";
5510 list[1].value = acl_file;
5511 items = 2;
developer10adcc12022-09-13 14:39:17 +08005512 } else if (filterMode == 2) {
5513 //TODO: deny_mac_file
5514 sprintf(buf, "%d", 0);
5515 list[0].value = buf;
5516 list[1].name = "deny_mac_file";
5517 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5518 list[1].value = deny_file;
5519 items = 2;
5520 } else {
5521 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005522 }
developer10adcc12022-09-13 14:39:17 +08005523
developer06a01d92022-09-07 16:32:39 +08005524 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5525 wifi_hostapdWrite(config_file, list, items);
5526
5527 return RETURN_OK;
5528
5529#if 0
5530 if(apIndex==0 || apIndex==1)
5531 {
5532 //set the filtermode
5533 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5534 system(buf);
5535 system("syscfg commit");
5536
5537 if(filterMode==0)
5538 {
5539 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5540 system(buf);
5541 return RETURN_OK;
5542 }
5543 }
5544 return RETURN_OK;
5545#endif
5546}
5547
5548// 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.
5549INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5550{
5551 return RETURN_ERR;
5552}
5553
5554// gets the vlan ID for this ap from an internal enviornment variable
5555INT wifi_getApVlanID(INT apIndex, INT *output_int)
5556{
5557 if(apIndex=0)
5558 {
5559 *output_int=100;
5560 return RETURN_OK;
5561 }
5562
5563 return RETURN_ERR;
5564}
5565
5566// sets the vlan ID for this ap to an internal enviornment variable
5567INT wifi_setApVlanID(INT apIndex, INT vlanId)
5568{
5569 //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)
5570 return RETURN_ERR;
5571}
5572
5573// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5574INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5575{
5576 snprintf(bridgeName, 32, "brlan0");
5577 snprintf(IP, 32, "10.0.0.1");
5578 snprintf(subnet, 32, "255.255.255.0");
5579
5580 return RETURN_OK;
5581}
5582
5583//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5584INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5585{
5586 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5587 return RETURN_ERR;
5588}
5589
5590// reset the vlan configuration for this ap
5591INT wifi_resetApVlanCfg(INT apIndex)
5592{
developerf5fef612022-09-20 19:38:26 +08005593 char original_config_file[64] = {0};
5594 char current_config_file[64] = {0};
5595 char buf[64] = {0};
5596 char cmd[64] = {0};
5597 char vlan_file[64] = {0};
5598 char vlan_tagged_interface[16] = {0};
5599 char vlan_bridge[16] = {0};
5600 char vlan_naming[16] = {0};
5601 struct params list[4] = {0};
5602 wifi_band band;
5603
5604 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5605
5606 band = wifi_index_to_band(apIndex);
5607 if (band == band_2_4)
5608 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5609 else if (band = band_5)
5610 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5611 else if (band = band_6)
5612 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5613
5614 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5615
5616 if (strlen(vlan_file) == 0)
5617 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005618
developerf5fef612022-09-20 19:38:26 +08005619 // The file should exist or this vap would not work.
5620 if (access(vlan_file, F_OK) != 0) {
5621 sprintf(cmd, "touch %s", vlan_file);
5622 _syscmd(cmd, buf, sizeof(buf));
5623 }
5624 list[0].name = "vlan_file";
5625 list[0].value = vlan_file;
5626
5627 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5628 list[1].name = "vlan_tagged_interface";
5629 list[1].value = vlan_tagged_interface;
5630
5631 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5632 list[2].name = "vlan_bridge";
5633 list[2].value = vlan_bridge;
5634
5635 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5636 list[3].name = "vlan_naming";
5637 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005638
developerf5fef612022-09-20 19:38:26 +08005639 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5640 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005641 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005642 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005643
developerf5fef612022-09-20 19:38:26 +08005644 // restart this ap
5645 wifi_setApEnable(apIndex, FALSE);
5646 wifi_setApEnable(apIndex, TRUE);
5647
5648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5649
5650 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005651}
5652
5653// 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.
5654INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5655{
5656 return RETURN_ERR;
5657}
5658
5659// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5660INT wifi_startHostApd()
5661{
5662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5663 system("systemctl start hostapd.service");
5664 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5665 return RETURN_OK;
5666 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5667}
5668
5669// stops hostapd
5670INT wifi_stopHostApd()
5671{
5672 char cmd[128] = {0};
5673 char buf[128] = {0};
5674
5675 sprintf(cmd,"systemctl stop hostapd");
5676 _syscmd(cmd, buf, sizeof(buf));
5677
5678 return RETURN_OK;
5679}
5680
5681// restart hostapd dummy function
5682INT wifi_restartHostApd()
5683{
5684 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5685 system("systemctl restart hostapd-global");
5686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5687
5688 return RETURN_OK;
5689}
5690
5691static int align_hostapd_config(int index)
5692{
5693 ULONG lval;
5694 wifi_getRadioChannel(index%2, &lval);
5695 wifi_setRadioChannel(index%2, lval);
5696}
5697
5698// sets the AP enable status variable for the specified ap.
5699INT wifi_setApEnable(INT apIndex, BOOL enable)
5700{
5701 char config_file[MAX_BUF_SIZE] = {0};
5702 char cmd[MAX_CMD_SIZE] = {0};
5703 char buf[MAX_BUF_SIZE] = {0};
5704 BOOL status;
5705
5706 wifi_getApEnable(apIndex,&status);
5707 if (enable == status)
5708 return RETURN_OK;
5709
5710 if (enable == TRUE) {
5711 int radioIndex = apIndex % NUMBER_OF_RADIOS;
developer06a01d92022-09-07 16:32:39 +08005712 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5713 //Hostapd will bring up this interface
5714 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5715 _syscmd(cmd, buf, sizeof(buf));
5716 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5717 _syscmd(cmd, buf, sizeof(buf));
5718 }
5719 else {
5720 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5721 _syscmd(cmd, buf, sizeof(buf));
5722 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5723 _syscmd(cmd, buf, sizeof(buf));
5724 }
5725 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5726 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5727 _syscmd(cmd, buf, sizeof(buf));
5728 //Wait for wifi up/down to apply
5729 return RETURN_OK;
5730}
5731
5732// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5733INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5734{
5735 char cmd[MAX_CMD_SIZE] = {'\0'};
5736 char buf[MAX_BUF_SIZE] = {'\0'};
5737
5738 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5739 return RETURN_ERR;
5740
5741 *output_bool = 0;
5742
5743 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5744 {
developer70490032022-09-13 15:45:20 +08005745 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005746 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5747 }
5748
5749 return RETURN_OK;
5750}
5751
5752// Outputs the AP "Enabled" "Disabled" status from driver
5753INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5754{
5755 char cmd[128] = {0};
5756 char buf[128] = {0};
5757 BOOL output_bool;
5758
5759 if ( NULL == output_string)
5760 return RETURN_ERR;
5761 wifi_getApEnable(apIndex,&output_bool);
5762
5763 if(output_bool == 1)
5764 snprintf(output_string, 32, "Up");
5765 else
5766 snprintf(output_string, 32, "Disable");
5767
5768 return RETURN_OK;
5769}
5770
5771//Indicates whether or not beacons include the SSID name.
5772// outputs a 1 if SSID on the AP is enabled, else outputs 0
5773INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5774{
5775 //get the running status
5776 char config_file[MAX_BUF_SIZE] = {0};
5777 char buf[16] = {0};
5778
5779 if (!output)
5780 return RETURN_ERR;
5781
5782 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5783 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5784 *output = (strncmp("0",buf,1) == 0);
5785
5786 return RETURN_OK;
5787}
5788
5789// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5790INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5791{
5792 //store the config, apply instantly
5793 char config_file[MAX_BUF_SIZE] = {0};
5794 struct params list;
5795
5796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5797 list.name = "ignore_broadcast_ssid";
5798 list.value = enable?"0":"1";
5799
5800 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5801 wifi_hostapdWrite(config_file, &list, 1);
5802 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5803 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005804 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5806
5807 return RETURN_OK;
5808}
5809
5810//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5811INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5812{
5813 //get the running status
5814 if(!output_uint)
5815 return RETURN_ERR;
5816 *output_uint=16;
5817 return RETURN_OK;
5818}
5819
5820INT wifi_setApRetryLimit(INT apIndex, UINT number)
5821{
5822 //apply instantly
5823 return RETURN_ERR;
5824}
5825
5826//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5827INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5828{
5829 if(!output)
5830 return RETURN_ERR;
5831 *output=TRUE;
5832 return RETURN_OK;
5833}
5834
5835//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5836INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5837{
5838 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005839 char cmd[128] = {0};
5840 char buf[128] = {0};
5841 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005842
developer0b246d12022-09-30 15:24:20 +08005843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005844
developer0b246d12022-09-30 15:24:20 +08005845 wifi_getMaxRadioNumber(&max_radio_num);
5846 radioIndex = apIndex % max_radio_num;
5847 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5848 _syscmd(cmd,buf, sizeof(buf));
5849
5850 if (strlen(buf) > 0)
5851 *output = true;
5852
5853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005854
developer06a01d92022-09-07 16:32:39 +08005855 return RETURN_OK;
5856}
5857
5858//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5859INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5860{
5861 //get the running status from driver
5862 if(!output)
5863 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005864
5865 char config_file[MAX_BUF_SIZE] = {0};
5866 char buf[16] = {0};
5867
5868 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5869 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5870 if (strncmp("1",buf,1) == 0)
5871 *output = TRUE;
5872 else
5873 *output = FALSE;
5874
developer06a01d92022-09-07 16:32:39 +08005875 return RETURN_OK;
5876}
5877
5878// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5879INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5880{
5881 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005882 char config_file[MAX_BUF_SIZE] = {0};
5883 struct params list;
5884
5885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5886 list.name = "wmm_enabled";
5887 list.value = enable?"1":"0";
5888
5889 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5890 wifi_hostapdWrite(config_file, &list, 1);
5891 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5892 wifi_reloadAp(apIndex);
5893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5894
5895 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005896}
5897
5898//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.
5899INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5900{
5901 //get the running status from driver
5902 if(!output)
5903 return RETURN_ERR;
5904 *output=TRUE;
5905 return RETURN_OK;
5906}
5907
5908// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5909INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5910{
5911 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005912 char config_file[MAX_BUF_SIZE] = {0};
5913 struct params list;
5914
5915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5916 list.name = "uapsd_advertisement_enabled";
5917 list.value = enable?"1":"0";
5918
5919 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5920 wifi_hostapdWrite(config_file, &list, 1);
5921 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5922 wifi_reloadAp(apIndex);
5923 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5924
5925 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005926}
5927
developer6daeb3f2022-09-30 13:36:39 +08005928// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005929INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5930{
developer6daeb3f2022-09-30 13:36:39 +08005931 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5932 char cmd[128] = {0};
5933 char buf[128] = {0};
5934 char ack_filepath[128] = {0};
5935 uint16_t bitmap = 0;
5936 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5937 FILE *f = NULL;
5938
5939 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5940
5941 // Get current setting
5942 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5943 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5944 _syscmd(cmd, buf, sizeof(buf));
5945 if (strlen(buf) > 0)
5946 bitmap = strtoul(buf, NULL, 10);
5947
5948 bitmap = strtoul(buf, NULL, 10);
5949
5950 if (ackPolicy == TRUE) { // True, unset this class
5951 bitmap &= ~class_map[class];
5952 } else { // False, set this class
5953 bitmap |= class_map[class];
5954 }
5955
5956 f = fopen(ack_filepath, "w");
5957 if (f == NULL) {
5958 fprintf(stderr, "%s: fopen failed\n", __func__);
5959 return RETURN_ERR;
5960 }
5961 fprintf(f, "%hu", bitmap);
5962 fclose(f);
5963
5964 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5965 _syscmd(cmd, buf, sizeof(buf));
5966
5967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5968 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005969}
5970
5971//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.
5972INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5973{
5974 //get the running status from driver
5975 if(!output_uint)
5976 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005977
5978 char output[16]={'\0'};
5979 char config_file[MAX_BUF_SIZE] = {0};
5980
5981 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5982 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5983 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5984 else {
5985 int device_num = atoi(output);
5986 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5987 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5988 return RETURN_ERR;
5989 }
5990 else {
5991 *output_uint = device_num;
5992 }
5993 }
5994
developer06a01d92022-09-07 16:32:39 +08005995 return RETURN_OK;
5996}
5997
5998INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5999{
6000 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006001 char str[MAX_BUF_SIZE]={'\0'};
6002 char cmd[MAX_CMD_SIZE]={'\0'};
6003 struct params params;
6004 char config_file[MAX_BUF_SIZE] = {0};
6005
6006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6007 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6008 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6009 return RETURN_ERR;
6010 }
6011 sprintf(str, "%d", number);
6012 params.name = "max_num_sta";
6013 params.value = str;
6014
6015 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6016 int ret = wifi_hostapdWrite(config_file, &params, 1);
6017 if (ret) {
6018 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6019 ,__func__, ret);
6020 }
6021
6022 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6023 if (ret) {
6024 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6025 ,__func__, ret);
6026 }
6027 wifi_reloadAp(apIndex);
6028 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6029
6030 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006031}
6032
6033//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.
6034INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6035{
6036 //get the current threshold
6037 if(!output_uint)
6038 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006039 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6040 if (*output_uint == 0)
6041 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006042 return RETURN_OK;
6043}
6044
6045INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6046{
6047 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006048 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6049 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006050 return RETURN_ERR;
6051}
6052
6053//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.
6054INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6055{
6056 if(!output_uint)
6057 return RETURN_ERR;
6058 *output_uint = 3;
6059 return RETURN_OK;
6060}
6061
6062//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6063INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6064{
6065 if(!output_uint)
6066 return RETURN_ERR;
6067 *output_uint = 3;
6068 return RETURN_OK;
6069}
6070
6071//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.
6072INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6073{
6074 if(!output_in_seconds)
6075 return RETURN_ERR;
6076 *output_in_seconds = 0;
6077 return RETURN_OK;
6078}
6079
6080//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
6081INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6082{
6083 if(!output || apIndex>=MAX_APS)
6084 return RETURN_ERR;
6085 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006086 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006087 return RETURN_OK;
6088}
6089
6090//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6091INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6092{
developer587c1b62022-09-27 15:58:59 +08006093 char config_file[128] = {0};
6094 char wpa[16] = {0};
6095 char key_mgmt[64] = {0};
6096 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006097 if (!output)
6098 return RETURN_ERR;
6099
6100 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006101 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006102
developer587c1b62022-09-27 15:58:59 +08006103 strcpy(output, "None");//Copying "None" to output string for default case
6104 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6105 if (strstr(key_mgmt, "WPA-PSK")) {
developer517a9792022-10-05 19:37:42 +08006106 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006107 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006108 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006109 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006110 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006111 snprintf(output, 32, "WPA-WPA2-Personal");
6112
6113 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006114 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006115 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006116 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006117 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006118 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006119 snprintf(output, 32, "WPA-WPA2-Enterprise");
6120 } else if (strstr(key_mgmt, "SAE")) {
6121 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6122 int disable = strtol(buf, NULL, 16);
6123 if (disable & 0x1)
6124 snprintf(output, 32, "WPA3-Personal");
6125 else
6126 snprintf(output, 32, "WPA3-Transition");
6127 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6128 snprintf(output, 32, "WPA3-Enterprise");
6129 }
developer06a01d92022-09-07 16:32:39 +08006130
6131 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6132 return RETURN_OK;
6133#if 0
6134 //TODO: need to revisit below implementation
6135 char securityType[32], authMode[32];
6136 int enterpriseMode=0;
6137
6138 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6139 if(!output)
6140 return RETURN_ERR;
6141
6142 wifi_getApBeaconType(apIndex, securityType);
6143 strcpy(output,"None");//By default, copying "None" to output string
6144 if (strncmp(securityType,"None", strlen("None")) == 0)
6145 return RETURN_OK;
6146
6147 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6148 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6149
6150 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6151 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6152 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6153 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6154 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6155 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6157
6158 return RETURN_OK;
6159#endif
6160}
6161
6162INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6163{
6164 char securityType[32];
6165 char authMode[32];
6166
6167 //store settings and wait for wifi up to apply
6168 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6169 if(!encMode)
6170 return RETURN_ERR;
6171
developer06a01d92022-09-07 16:32:39 +08006172 if (strcmp(encMode, "None")==0)
6173 {
6174 strcpy(securityType,"None");
6175 strcpy(authMode,"None");
6176 }
6177 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6178 {
6179 strcpy(securityType,"WPAand11i");
6180 strcpy(authMode,"PSKAuthentication");
6181 }
6182 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6183 {
6184 strcpy(securityType,"WPAand11i");
6185 strcpy(authMode,"EAPAuthentication");
6186 }
6187 else if (strcmp(encMode, "WPA-Personal")==0)
6188 {
6189 strcpy(securityType,"WPA");
6190 strcpy(authMode,"PSKAuthentication");
6191 }
6192 else if (strcmp(encMode, "WPA-Enterprise")==0)
6193 {
6194 strcpy(securityType,"WPA");
6195 strcpy(authMode,"EAPAuthentication");
6196 }
6197 else if (strcmp(encMode, "WPA2-Personal")==0)
6198 {
6199 strcpy(securityType,"11i");
6200 strcpy(authMode,"PSKAuthentication");
6201 }
6202 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6203 {
6204 strcpy(securityType,"11i");
6205 strcpy(authMode,"EAPAuthentication");
6206 }
developer587c1b62022-09-27 15:58:59 +08006207 else if (strcmp(encMode, "WPA3-Personal") == 0)
6208 {
6209 strcpy(securityType,"11i");
6210 strcpy(authMode,"SAEAuthentication");
6211 }
developer9df4e652022-10-11 11:27:38 +08006212 else if (strcmp(encMode, "WPA3-Transition") == 0)
6213 {
6214 strcpy(securityType, "11i");
6215 strcpy(authMode, "PSK-SAEAuthentication");
6216 }
developer587c1b62022-09-27 15:58:59 +08006217 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6218 {
6219 strcpy(securityType,"11i");
6220 strcpy(authMode,"EAP_192-bit_Authentication");
6221 }
developer06a01d92022-09-07 16:32:39 +08006222 else
6223 {
6224 strcpy(securityType,"None");
6225 strcpy(authMode,"None");
6226 }
6227 wifi_setApBeaconType(apIndex, securityType);
6228 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6229 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6230
6231 return RETURN_OK;
6232}
6233
6234
6235//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6236// output_string must be pre-allocated as 64 character string by caller
6237// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6238INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6239{
6240 char buf[16];
6241 char config_file[MAX_BUF_SIZE] = {0};
6242
6243 if(output_string==NULL)
6244 return RETURN_ERR;
6245
6246 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6247 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6248
6249 if(strcmp(buf,"0")==0)
6250 {
6251 printf("wpa_mode is %s ......... \n",buf);
6252 return RETURN_ERR;
6253 }
6254
6255 wifi_dbg_printf("\nFunc=%s\n",__func__);
6256 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6257 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6258 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6259
6260 return RETURN_OK;
6261}
6262
6263// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6264// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6265INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6266{
6267 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6268 struct params params={'\0'};
6269 int ret;
6270 char config_file[MAX_BUF_SIZE] = {0};
6271
6272 if(NULL == preSharedKey)
6273 return RETURN_ERR;
6274
6275 params.name = "wpa_passphrase";
6276
6277 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6278 {
6279 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6280 return RETURN_ERR;
6281 }
6282 params.value = preSharedKey;
6283 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6284 ret = wifi_hostapdWrite(config_file, &params, 1);
6285 if(!ret)
6286 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6287 return ret;
6288 //TODO: call hostapd_cli for dynamic_config_control
6289}
6290
6291//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6292// outputs the passphrase, maximum 63 characters
6293INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6294{
6295 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6296
6297 wifi_dbg_printf("\nFunc=%s\n",__func__);
6298 if (NULL == output_string)
6299 return RETURN_ERR;
6300
6301 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6302 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6303 if(strcmp(buf,"0")==0)
6304 {
6305 printf("wpa_mode is %s ......... \n",buf);
6306 return RETURN_ERR;
6307 }
6308
6309 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6310 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6311
6312 return RETURN_OK;
6313}
6314
6315// sets the passphrase enviornment variable, max 63 characters
6316INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6317{
6318 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6319 struct params params={'\0'};
6320 char config_file[MAX_BUF_SIZE] = {0};
6321 int ret;
6322
6323 if(NULL == passPhrase)
6324 return RETURN_ERR;
6325
6326 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6327 {
6328 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6329 return RETURN_ERR;
6330 }
6331 params.name = "wpa_passphrase";
6332 params.value = passPhrase;
6333 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6334 ret=wifi_hostapdWrite(config_file,&params,1);
6335 if(!ret)
6336 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6337
6338 return ret;
6339}
6340
6341//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.
6342INT wifi_setApSecurityReset(INT apIndex)
6343{
developer8d583982022-09-20 11:28:22 +08006344 char original_config_file[64] = {0};
6345 char current_config_file[64] = {0};
6346 char buf[64] = {0};
6347 char cmd[64] = {0};
6348 char wpa[4] = {0};
6349 char wpa_psk[64] = {0};
6350 char wpa_passphrase[64] = {0};
6351 char wpa_psk_file[128] = {0};
6352 char wpa_key_mgmt[64] = {0};
6353 char wpa_pairwise[32] = {0};
6354 wifi_band band;
6355 struct params list[6];
6356
6357 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6358
6359 band = wifi_index_to_band(apIndex);
6360 if (band == band_2_4)
6361 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6362 else if (band = band_5)
6363 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6364 else if (band = band_6)
6365 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6366 else
6367 return RETURN_ERR;
6368
6369 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6370 list[0].name = "wpa";
6371 list[0].value = wpa;
6372
6373 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6374 list[1].name = "wpa_psk";
6375 list[1].value = wpa_psk;
6376
6377 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6378 list[2].name = "wpa_passphrase";
6379 list[2].value = wpa_passphrase;
6380
6381 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6382
6383 if (strlen(wpa_psk_file) == 0)
6384 strcpy(wpa_psk_file, PSK_FILE);
6385
6386 if (access(wpa_psk_file, F_OK) != 0) {
6387 sprintf(cmd, "touch %s", wpa_psk_file);
6388 _syscmd(cmd, buf, sizeof(buf));
6389 }
6390 list[3].name = "wpa_psk_file";
6391 list[3].value = wpa_psk_file;
6392
6393 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6394 list[4].name = "wpa_key_mgmt";
6395 list[4].value = wpa_key_mgmt;
6396
6397 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6398 list[5].name = "wpa_pairwise";
6399 list[5].value = wpa_pairwise;
6400
6401 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6402 wifi_hostapdWrite(current_config_file, list, 6);
6403
6404 wifi_setApEnable(apIndex, FALSE);
6405 wifi_setApEnable(apIndex, TRUE);
6406
6407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6408 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006409}
6410
6411//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).
6412INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6413{
developer8f2ddd52022-09-13 15:39:24 +08006414 char config_file[64] = {0};
6415 char buf[64] = {0};
6416 char cmd[256] = {0};
6417
6418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6419
developer06a01d92022-09-07 16:32:39 +08006420 if(!IP_output || !Port_output || !RadiusSecret_output)
6421 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006422
developer8f2ddd52022-09-13 15:39:24 +08006423 // Read the first matched config
6424 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6425 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6426 _syscmd(cmd, buf, sizeof(buf));
6427 strncpy(IP_output, buf, 64);
6428
6429 memset(buf, 0, sizeof(buf));
6430 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6431 _syscmd(cmd, buf, sizeof(buf));
6432 *Port_output = atoi(buf);
6433
6434 memset(buf, 0, sizeof(buf));
6435 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6436 _syscmd(cmd, buf, sizeof(buf));
6437 strncpy(RadiusSecret_output, buf, 64);
6438
6439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006440 return RETURN_OK;
6441}
6442
6443INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6444{
developer8f2ddd52022-09-13 15:39:24 +08006445 char config_file[64] = {0};
6446 char port_str[8] = {0};
6447 char cmd[256] = {0};
6448 char buf[128] = {0};
6449
6450 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6451
6452 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6453
6454 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6455 _syscmd(cmd, buf, sizeof(buf));
6456 memset(cmd, 0, sizeof(cmd));
6457
6458 snprintf(port_str, sizeof(port_str), "%d", port);
6459 if (strlen(buf) == 0)
6460 // Append
6461 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6462 "auth_server_addr=%s\\n"
6463 "auth_server_port=%s\\n"
6464 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6465 else {
6466 // Delete the three lines setting after the "# radius 1" comment
6467 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6468 _syscmd(cmd, buf, sizeof(buf));
6469 memset(cmd, 0, sizeof(cmd));
6470 // Use "# radius 1" comment to find the location to insert the radius setting
6471 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6472 "# radius 1\\n"
6473 "auth_server_addr=%s\\n"
6474 "auth_server_port=%s\\n"
6475 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6476 }
6477 if(_syscmd(cmd, buf, sizeof(buf))) {
6478 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6479 return RETURN_ERR;
6480 }
6481
6482 wifi_reloadAp(apIndex);
6483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6484 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006485}
6486
6487INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6488{
developer8f2ddd52022-09-13 15:39:24 +08006489 char config_file[64] = {0};
6490 char buf[64] = {0};
6491 char cmd[256] = {0};
6492
6493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6494
developer06a01d92022-09-07 16:32:39 +08006495 if(!IP_output || !Port_output || !RadiusSecret_output)
6496 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006497
6498 // Read the second matched config
6499 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6500 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6501 _syscmd(cmd, buf, sizeof(buf));
6502 strncpy(IP_output, buf, 64);
6503
6504 memset(buf, 0, sizeof(buf));
6505 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6506 _syscmd(cmd, buf, sizeof(buf));
6507 *Port_output = atoi(buf);
6508
6509 memset(buf, 0, sizeof(buf));
6510 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6511 _syscmd(cmd, buf, sizeof(buf));
6512 strncpy(RadiusSecret_output, buf, 64);
6513
6514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006515 return RETURN_OK;
6516}
6517
6518INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6519{
developer8f2ddd52022-09-13 15:39:24 +08006520 char config_file[64] = {0};
6521 char port_str[8] = {0};
6522 char cmd[256] = {0};
6523 char buf[128] = {0};
6524
6525 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6526
6527 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6528
6529 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6530 _syscmd(cmd, buf, sizeof(buf));
6531 memset(cmd, 0, sizeof(cmd));
6532
6533 snprintf(port_str, sizeof(port_str), "%d", port);
6534 if (strlen(buf) == 0)
6535 // Append
6536 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6537 "auth_server_addr=%s\\n"
6538 "auth_server_port=%s\\n"
6539 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6540 else {
6541 // Delete the three lines setting after the "# radius 2" comment
6542 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6543 _syscmd(cmd, buf, sizeof(buf));
6544 memset(cmd, 0, sizeof(cmd));
6545 // Use "# radius 2" comment to find the location to insert the radius setting
6546 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6547 "# radius 2\\n"
6548 "auth_server_addr=%s\\n"
6549 "auth_server_port=%s\\n"
6550 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6551 }
6552 if(_syscmd(cmd, buf, sizeof(buf))) {
6553 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6554 return RETURN_ERR;
6555 }
6556
6557 wifi_reloadAp(apIndex);
6558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6559 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006560}
6561
6562//RadiusSettings
6563INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6564{
6565 if(!output)
6566 return RETURN_ERR;
6567
6568 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6569 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6570 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6571 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6572 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6573 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.
6574 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6575 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6576 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6577 //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.
6578
6579 return RETURN_OK;
6580}
6581
6582INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6583{
6584 //store the paramters, and apply instantly
6585 return RETURN_ERR;
6586}
6587
6588//Device.WiFi.AccessPoint.{i}.WPS.Enable
6589//Enables or disables WPS functionality for this access point.
6590// outputs the WPS enable state of this ap in output_bool
6591INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6592{
6593 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6594 if(!output_bool || !(apIndex==0 || apIndex==1))
6595 return RETURN_ERR;
6596 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6597 _syscmd(cmd, buf, sizeof(buf));
6598 if(strstr(buf, "configured"))
6599 *output_bool=TRUE;
6600 else
6601 *output_bool=FALSE;
6602
6603 return RETURN_OK;
6604}
6605
6606//Device.WiFi.AccessPoint.{i}.WPS.Enable
6607// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6608INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6609{
6610 char config_file[MAX_BUF_SIZE] = {0};
6611 struct params params;
6612
6613 if(!(apIndex==0 || apIndex==1))
6614 return RETURN_ERR;
6615 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6616 //store the paramters, and wait for wifi up to apply
6617 params.name = "wps_state";
6618 params.value = enable ? "2":"0";
6619
6620 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6621 wifi_hostapdWrite(config_file, &params, 1);
6622 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6623 wifi_reloadAp(apIndex);
6624
6625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6626 return RETURN_OK;
6627}
6628
6629//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
6630INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6631{
6632 if(!output)
6633 return RETURN_ERR;
6634 snprintf(output, 128, "PushButton,PIN");
6635 return RETURN_OK;
6636}
6637
6638//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6639//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.
6640// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6641INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6642{
6643 if(!output)
6644 return RETURN_ERR;
6645 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6646
6647 return RETURN_OK;
6648}
6649
6650//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6651// 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
6652INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6653{
6654 //apply instantly. No setting need to be stored.
6655 char methods[MAX_BUF_SIZE], *token, *next_token;
6656 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6657 struct params params;
6658
6659 if(!methodString || !(apIndex==0 || apIndex==1))
6660 return RETURN_ERR;
6661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6662 //store the paramters, and wait for wifi up to apply
6663
6664 snprintf(methods, sizeof(methods), "%s", methodString);
6665 for(token=methods; *token; token=next_token)
6666 {
6667 strtok_r(token, ",", &next_token);
6668 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6669 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6670 else if(*token=='E')
6671 {
6672 if(!strcmp(methods, "Ethernet"))
6673 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6674 else if(!strcmp(methods, "ExternalNFCToken"))
6675 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6676 else
6677 printf("%s: Unknown WpsConfigMethod\n", __func__);
6678 }
6679 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6680 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6681 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6682 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6683 else if(*token=='P' )
6684 {
6685 if(!strcmp(token, "PushButton"))
6686 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6687 else if(!strcmp(token, "PIN"))
6688 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6689 else
6690 printf("%s: Unknown WpsConfigMethod\n", __func__);
6691 }
6692 else
6693 printf("%s: Unknown WpsConfigMethod\n", __func__);
6694 }
6695 params.name = "config_methods";
6696 params.value = config_methods;
6697 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6698 wifi_hostapdWrite(config_file, &params, 1);
6699 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6701
6702 return RETURN_OK;
6703}
6704
6705// outputs the pin value, ulong_pin must be allocated by the caller
6706INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6707{
6708 char buf[MAX_BUF_SIZE] = {0};
6709 char cmd[MAX_CMD_SIZE] = {0};
6710
6711 if(!output_ulong || !(apIndex==0 || apIndex==1))
6712 return RETURN_ERR;
6713 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6714 _syscmd(cmd, buf, sizeof(buf));
6715 if(strlen(buf) > 0)
6716 *output_ulong=strtoul(buf, NULL, 10);
6717
6718 return RETURN_OK;
6719}
6720
6721// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6722INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6723{
6724 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6725 char ap_pin[16] = {0};
6726 char buf[MAX_BUF_SIZE] = {0};
6727 char config_file[MAX_BUF_SIZE] = {0};
6728 ULONG prev_pin = 0;
6729 struct params params;
6730
6731 if(!(apIndex==0 || apIndex==1))
6732 return RETURN_ERR;
6733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6734 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6735 params.name = "ap_pin";
6736 params.value = ap_pin;
6737 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6738 wifi_hostapdWrite(config_file, &params, 1);
6739 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6740 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6741
6742 return RETURN_OK;
6743}
6744
6745// Output string is either Not configured or Configured, max 32 characters
6746INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6747{
6748 char cmd[MAX_CMD_SIZE];
6749 char buf[MAX_BUF_SIZE]={0};
6750
6751 if(!output_string || !(apIndex==0 || apIndex==1))
6752 return RETURN_ERR;
6753 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6754 snprintf(output_string, 32, "Not configured");
6755 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6756 _syscmd(cmd, buf, sizeof(buf));
6757
developer348e3d92022-09-13 14:48:41 +08006758 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006759 snprintf(output_string, 32, "Configured");
6760 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6761
6762 return RETURN_OK;
6763}
6764
6765// sets the WPS pin for this AP
6766INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6767{
6768 char cmd[MAX_CMD_SIZE];
6769 char buf[MAX_BUF_SIZE]={0};
6770 BOOL enable;
6771
6772 if(!(apIndex==0 || apIndex==1))
6773 return RETURN_ERR;
6774 wifi_getApEnable(apIndex, &enable);
6775 if (!enable)
6776 return RETURN_ERR;
6777 wifi_getApWpsEnable(apIndex, &enable);
6778 if (!enable)
6779 return RETURN_ERR;
6780
6781 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6782 _syscmd(cmd, buf, sizeof(buf));
6783 if((strstr(buf, "OK"))!=NULL)
6784 return RETURN_OK;
6785
6786 return RETURN_ERR;
6787}
6788
6789// This function is called when the WPS push button has been pressed for this AP
6790INT wifi_setApWpsButtonPush(INT apIndex)
6791{
6792 char cmd[MAX_CMD_SIZE];
6793 char buf[MAX_BUF_SIZE]={0};
6794 BOOL enable=FALSE;
6795
6796 if(!(apIndex==0 || apIndex==1))
6797 return RETURN_ERR;
6798 wifi_getApEnable(apIndex, &enable);
6799 if (!enable)
6800 return RETURN_ERR;
6801
6802 wifi_getApWpsEnable(apIndex, &enable);
6803 if (!enable)
6804 return RETURN_ERR;
6805
6806 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6807 _syscmd(cmd, buf, sizeof(buf));
6808
6809 if((strstr(buf, "OK"))!=NULL)
6810 return RETURN_OK;
6811 return RETURN_ERR;
6812}
6813
6814// cancels WPS mode for this AP
6815INT wifi_cancelApWPS(INT apIndex)
6816{
6817 char cmd[MAX_CMD_SIZE];
6818 char buf[MAX_BUF_SIZE]={0};
6819
6820 if(!(apIndex==0 || apIndex==1))
6821 return RETURN_ERR;
6822 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6823 _syscmd(cmd,buf, sizeof(buf));
6824
6825 if((strstr(buf, "OK"))!=NULL)
6826 return RETURN_OK;
6827 return RETURN_ERR;
6828}
6829
6830//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6831//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6832INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6833{
6834 FILE *f;
6835 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6836 char cmd[256], buf[2048];
6837 char *param , *value, *line=NULL;
6838 size_t len = 0;
6839 ssize_t nread;
6840 wifi_associated_dev_t *dev=NULL;
6841
6842 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6843 *associated_dev_array = NULL;
6844 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6845 _syscmd(cmd,buf,sizeof(buf));
6846 *output_array_size = atoi(buf);
6847
6848 if (*output_array_size <= 0)
6849 return RETURN_OK;
6850
6851 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6852 *associated_dev_array = dev;
6853 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6854 _syscmd(cmd,buf,sizeof(buf));
6855 f = fopen("/tmp/connected_devices.txt", "r");
6856 if (f==NULL)
6857 {
6858 *output_array_size=0;
6859 return RETURN_ERR;
6860 }
6861 while ((nread = getline(&line, &len, f)) != -1)
6862 {
6863 param = strtok(line,"=");
6864 value = strtok(NULL,"=");
6865
6866 if( strcmp("flags",param) == 0 )
6867 {
6868 value[strlen(value)-1]='\0';
6869 if(strstr (value,"AUTHORIZED") != NULL )
6870 {
6871 dev[auth_temp].cli_AuthenticationState = 1;
6872 dev[auth_temp].cli_Active = 1;
6873 auth_temp++;
6874 read_flag=1;
6875 }
6876 }
6877 if(read_flag==1)
6878 {
6879 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6880 {
6881 value[strlen(value)-1]='\0';
6882 sscanf(value, "%x:%x:%x:%x:%x:%x",
6883 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6884 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6885 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6886 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6887 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6888 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6889 mac_temp++;
6890 read_flag=0;
6891 }
6892 }
6893 }
6894 *output_array_size = auth_temp;
6895 auth_temp=0;
6896 mac_temp=0;
6897 free(line);
6898 fclose(f);
6899 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6900 return RETURN_OK;
6901}
6902
6903#define MACADDRESS_SIZE 6
6904
6905INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6906{
6907 FILE *fp = NULL;
6908 char str[MAX_BUF_SIZE] = {0};
6909 int wificlientindex = 0 ;
6910 int count = 0;
6911 int signalstrength = 0;
6912 int arr[MACADDRESS_SIZE] = {0};
6913 unsigned char mac[MACADDRESS_SIZE] = {0};
6914 UINT wifi_count = 0;
6915 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6916 char pipeCmd[MAX_CMD_SIZE] = {0};
6917
6918 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6919 *output_array_size = 0;
6920 *associated_dev_array = NULL;
6921
6922 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6923 fp = popen(pipeCmd, "r");
6924 if (fp == NULL)
6925 {
6926 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6927 return RETURN_ERR;
6928 }
6929
6930 /* Read the output a line at a time - output it. */
6931 fgets(str, sizeof(str)-1, fp);
6932 wifi_count = (unsigned int) atoi ( str );
6933 *output_array_size = wifi_count;
6934 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6935 pclose(fp);
6936
6937 if(wifi_count == 0)
6938 {
6939 return RETURN_OK;
6940 }
6941 else
6942 {
6943 wifi_associated_dev3_t* temp = NULL;
6944 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6945 if(temp == NULL)
6946 {
6947 printf("Error Statement. Insufficient memory \n");
6948 return RETURN_ERR;
6949 }
6950
6951 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6952 system(pipeCmd);
6953 memset(pipeCmd,0,sizeof(pipeCmd));
6954 if(apIndex == 0)
6955 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6956 else if(apIndex == 1)
6957 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6958 system(pipeCmd);
6959
6960 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6961 if(fp == NULL)
6962 {
6963 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6964 return RETURN_ERR;
6965 }
6966 fclose(fp);
6967
6968 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6969 fp = popen(pipeCmd, "r");
6970 if(fp)
6971 {
6972 for(count =0 ; count < wifi_count; count++)
6973 {
6974 fgets(str, MAX_BUF_SIZE, fp);
6975 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6976 {
6977 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6978 {
6979 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6980
6981 }
6982 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6983 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]);
6984 }
6985 temp[count].cli_AuthenticationState = 1; //TODO
6986 temp[count].cli_Active = 1; //TODO
6987 }
6988 pclose(fp);
6989 }
6990
6991 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6992 fp = popen(pipeCmd, "r");
6993 if(fp)
6994 {
6995 pclose(fp);
6996 }
6997 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6998 if(fp)
6999 {
7000 for(count =0 ; count < wifi_count ;count++)
7001 {
7002 fgets(str, MAX_BUF_SIZE, fp);
7003 signalstrength = atoi(str);
7004 temp[count].cli_SignalStrength = signalstrength;
7005 temp[count].cli_RSSI = signalstrength;
7006 temp[count].cli_SNR = signalstrength + 95;
7007 }
7008 pclose(fp);
7009 }
7010
7011
7012 if((apIndex == 0) || (apIndex == 4))
7013 {
7014 for(count =0 ; count < wifi_count ;count++)
7015 {
7016 strcpy(temp[count].cli_OperatingStandard,"g");
7017 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7018 }
7019
7020 //BytesSent
7021 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7022 fp = popen(pipeCmd, "r");
7023 if(fp)
7024 {
7025 pclose(fp);
7026 }
7027 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7028 if(fp)
7029 {
7030 for (count = 0; count < wifi_count; count++)
7031 {
7032 fgets(str, MAX_BUF_SIZE, fp);
7033 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7034 }
7035 pclose(fp);
7036 }
7037
7038 //BytesReceived
7039 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7040 fp = popen(pipeCmd, "r");
7041 if (fp)
7042 {
7043 pclose(fp);
7044 }
7045 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7046 if (fp)
7047 {
7048 for (count = 0; count < wifi_count; count++)
7049 {
7050 fgets(str, MAX_BUF_SIZE, fp);
7051 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7052 }
7053 pclose(fp);
7054 }
7055
7056 //PacketsSent
7057 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7058 fp = popen(pipeCmd, "r");
7059 if (fp)
7060 {
7061 pclose(fp);
7062 }
7063
7064 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7065 if (fp)
7066 {
7067 for (count = 0; count < wifi_count; count++)
7068 {
7069 fgets(str, MAX_BUF_SIZE, fp);
7070 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7071 }
7072 pclose(fp);
7073 }
7074
7075 //PacketsReceived
7076 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7077 fp = popen(pipeCmd, "r");
7078 if (fp)
7079 {
7080 pclose(fp);
7081 }
7082 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7083 if (fp)
7084 {
7085 for (count = 0; count < wifi_count; count++)
7086 {
7087 fgets(str, MAX_BUF_SIZE, fp);
7088 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7089 }
7090 pclose(fp);
7091 }
7092
7093 //ErrorsSent
7094 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7095 fp = popen(pipeCmd, "r");
7096 if (fp)
7097 {
7098 pclose(fp);
7099 }
7100 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7101 if (fp)
7102 {
7103 for (count = 0; count < wifi_count; count++)
7104 {
7105 fgets(str, MAX_BUF_SIZE, fp);
7106 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7107 }
7108 pclose(fp);
7109 }
7110
7111 //ErrorsSent
7112 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7113 fp = popen(pipeCmd, "r");
7114 if (fp)
7115 {
7116 pclose(fp);
7117 }
7118 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7119 if (fp)
7120 {
7121 for (count = 0; count < wifi_count; count++)
7122 {
7123 fgets(str, MAX_BUF_SIZE, fp);
7124 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7125 }
7126 pclose(fp);
7127 }
7128
7129 //LastDataDownlinkRate
7130 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7131 fp = popen(pipeCmd, "r");
7132 if (fp)
7133 {
7134 pclose(fp);
7135 }
7136 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7137 if (fp)
7138 {
7139 for (count = 0; count < wifi_count; count++)
7140 {
7141 fgets(str, MAX_BUF_SIZE, fp);
7142 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7143 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7144 }
7145 pclose(fp);
7146 }
7147
7148 //LastDataUplinkRate
7149 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7150 fp = popen(pipeCmd, "r");
7151 if (fp)
7152 {
7153 pclose(fp);
7154 }
7155 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7156 if (fp)
7157 {
7158 for (count = 0; count < wifi_count; count++)
7159 {
7160 fgets(str, MAX_BUF_SIZE, fp);
7161 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7162 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7163 }
7164 pclose(fp);
7165 }
7166
7167 }
7168 else if ((apIndex == 1) || (apIndex == 5))
7169 {
7170 for (count = 0; count < wifi_count; count++)
7171 {
7172 strcpy(temp[count].cli_OperatingStandard, "a");
7173 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7174 temp[count].cli_BytesSent = 0;
7175 temp[count].cli_BytesReceived = 0;
7176 temp[count].cli_LastDataUplinkRate = 0;
7177 temp[count].cli_LastDataDownlinkRate = 0;
7178 temp[count].cli_PacketsSent = 0;
7179 temp[count].cli_PacketsReceived = 0;
7180 temp[count].cli_ErrorsSent = 0;
7181 }
7182 }
7183
7184 for (count = 0; count < wifi_count; count++)
7185 {
7186 temp[count].cli_Retransmissions = 0;
7187 temp[count].cli_DataFramesSentAck = 0;
7188 temp[count].cli_DataFramesSentNoAck = 0;
7189 temp[count].cli_MinRSSI = 0;
7190 temp[count].cli_MaxRSSI = 0;
7191 strncpy(temp[count].cli_InterferenceSources, "", 64);
7192 memset(temp[count].cli_IPAddress, 0, 64);
7193 temp[count].cli_RetransCount = 0;
7194 temp[count].cli_FailedRetransCount = 0;
7195 temp[count].cli_RetryCount = 0;
7196 temp[count].cli_MultipleRetryCount = 0;
7197 }
7198 *associated_dev_array = temp;
7199 }
7200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7201 return RETURN_OK;
7202}
7203
7204int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7205{
7206 FILE *fp = NULL;
7207 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7208 char cmd[MAX_CMD_SIZE];
7209 int count = 0;
7210
7211 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7212 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7213 fp = popen(cmd,"r");
7214 if(fp == NULL)
7215 {
7216 printf("Failed to run command in Function %s\n",__FUNCTION__);
7217 return 0;
7218 }
7219 if(fgets(path, sizeof(path)-1, fp) != NULL)
7220 {
7221 for(count=0;path[count]!='\n';count++)
7222 status[count]=path[count];
7223 status[count]='\0';
7224 }
7225 strcpy(wifi_status,status);
7226 pclose(fp);
7227 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7228 return RETURN_OK;
7229}
7230
7231/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7232struct hostapd_sta_param {
7233 char key[50];
7234 char value[100];
7235}
7236
7237static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7238 int i = 0;
7239
7240 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7241 if (strncmp(params[i].key,key,50) == 0){
7242 return &params[i].value;
7243 }
7244 i++;
7245 }
7246 return NULL;
7247
7248} */
7249
7250static unsigned int count_occurences(const char *buf, const char *word)
7251{
7252 unsigned int n = 0;
7253 char *ptr = strstr(buf, word);
7254
7255 while (ptr++) {
7256 n++;
7257 ptr = strstr(ptr, word);
7258 }
7259
7260 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7261 return n;
7262}
7263
7264static const char *get_line_from_str_buf(const char *buf, char *line)
7265{
7266 int i;
7267 int n = strlen(buf);
7268
7269 for (i = 0; i < n; i++) {
7270 line[i] = buf[i];
7271 if (buf[i] == '\n') {
7272 line[i] = '\0';
7273 return &buf[i + 1];
7274 }
7275 }
7276
7277 return NULL;
7278}
7279
7280INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7281{
7282 unsigned int assoc_cnt = 0;
7283 char interface_name[50] = {0};
7284 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7285 char cmd[MAX_CMD_SIZE] = {'\0'};
7286 char line[256] = {'\0'};
7287 int i = 0;
7288 int ret = 0;
7289 const char *ptr = NULL;
7290 char *key = NULL;
7291 char *val = NULL;
7292 wifi_associated_dev3_t *temp = NULL;
7293 int rssi;
7294
7295 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7296
7297 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7298 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7299 return RETURN_ERR;
7300 }
7301
7302 // Example filtered output of 'iw dev' command:
7303 // Station 0a:69:72:10:d2:fa (on wifi0)
7304 // signal avg:-67 [-71, -71] dBm
7305 // Station 28:c2:1f:25:5f:99 (on wifi0)
7306 // signal avg:-67 [-71, -70] dBm
7307 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7308 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7309 return RETURN_ERR;
7310 }
7311
7312 ret = _syscmd(cmd, buf, sizeof(buf));
7313 if (ret == RETURN_ERR) {
7314 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7315 return RETURN_ERR;
7316 }
7317
7318 *output_array_size = count_occurences(buf, "Station");
7319 if (*output_array_size == 0) return RETURN_OK;
7320
7321 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7322 if (temp == NULL) {
7323 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7324 return RETURN_ERR;
7325 }
7326 *associated_dev_array = temp;
7327
7328 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7329 ptr = get_line_from_str_buf(buf, line);
7330 i = -1;
7331 while (ptr) {
7332 if (strstr(line, "Station")) {
7333 i++;
7334 key = strtok(line, " ");
7335 val = strtok(NULL, " ");
7336 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7337 &temp[i].cli_MACAddress[0],
7338 &temp[i].cli_MACAddress[1],
7339 &temp[i].cli_MACAddress[2],
7340 &temp[i].cli_MACAddress[3],
7341 &temp[i].cli_MACAddress[4],
7342 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7343 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7344 free(*associated_dev_array);
7345 return RETURN_ERR;
7346 }
7347 }
7348 else if (i < 0) {
7349 ptr = get_line_from_str_buf(ptr, line);
7350 continue; // We didn't detect 'station' entry yet
7351 }
7352 else if (strstr(line, "signal avg")) {
7353 key = strtok(line, ":");
7354 val = strtok(NULL, " ");
7355 if (sscanf(val, "%d", &rssi) <= 0 ) {
7356 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7357 free(*associated_dev_array);
7358 return RETURN_ERR;
7359 }
7360 temp[i].cli_RSSI = rssi;
7361 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7362 }
7363 // Here other fields can be parsed if added to filter of 'iw dev' command
7364
7365 ptr = get_line_from_str_buf(ptr, line);
7366 };
7367
7368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7369
7370 return RETURN_OK;
7371}
7372
7373#if 0
7374//To-do
7375INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7376{
7377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7378
7379 //Using different approach to get required WiFi Parameters from system available commands
7380#if 0
7381 FILE *f;
7382 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7383 char cmd[256], buf[2048];
7384 char *param , *value, *line=NULL;
7385 size_t len = 0;
7386 ssize_t nread;
7387 wifi_associated_dev3_t *dev=NULL;
7388 *associated_dev_array = NULL;
7389 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7390 _syscmd(cmd,buf,sizeof(buf));
7391 *output_array_size = atoi(buf);
7392
7393 if (*output_array_size <= 0)
7394 return RETURN_OK;
7395
7396 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7397 *associated_dev_array = dev;
7398 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7399 _syscmd(cmd,buf,sizeof(buf));
7400 f = fopen("/tmp/connected_devices.txt", "r");
7401 if (f==NULL)
7402 {
7403 *output_array_size=0;
7404 return RETURN_ERR;
7405 }
7406 while ((nread = getline(&line, &len, f)) != -1)
7407 {
7408 param = strtok(line,"=");
7409 value = strtok(NULL,"=");
7410
7411 if( strcmp("flags",param) == 0 )
7412 {
7413 value[strlen(value)-1]='\0';
7414 if(strstr (value,"AUTHORIZED") != NULL )
7415 {
7416 dev[auth_temp].cli_AuthenticationState = 1;
7417 dev[auth_temp].cli_Active = 1;
7418 auth_temp++;
7419 read_flag=1;
7420 }
7421 }
7422 if(read_flag==1)
7423 {
7424 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7425 {
7426 value[strlen(value)-1]='\0';
7427 sscanf(value, "%x:%x:%x:%x:%x:%x",
7428 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7429 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7430 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7431 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7432 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7433 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7434
7435 }
7436 else if( strcmp("rx_packets",param) == 0 )
7437 {
7438 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7439 }
7440
7441 else if( strcmp("tx_packets",param) == 0 )
7442 {
7443 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7444 }
7445
7446 else if( strcmp("rx_bytes",param) == 0 )
7447 {
7448 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7449 }
7450
7451 else if( strcmp("tx_bytes",param) == 0 )
7452 {
7453 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7454 mac_temp++;
7455 read_flag=0;
7456 }
7457 }
7458 }
7459
7460 *output_array_size = auth_temp;
7461 auth_temp=0;
7462 mac_temp=0;
7463 free(line);
7464 fclose(f);
7465#endif
7466 char interface_name[MAX_BUF_SIZE] = {0};
7467 char wifi_status[MAX_BUF_SIZE] = {0};
7468 char hostapdconf[MAX_BUF_SIZE] = {0};
7469
7470 wifi_associated_dev3_t *dev_array = NULL;
7471 ULONG wifi_count = 0;
7472
7473 *associated_dev_array = NULL;
7474 *output_array_size = 0;
7475
7476 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7477 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7478 {
7479 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7480
7481 GetInterfaceName(interface_name, hostapdconf);
7482
7483 if(strlen(interface_name) > 1)
7484 {
7485 wifihal_interfacestatus(wifi_status,interface_name);
7486 if(strcmp(wifi_status,"RUNNING") == 0)
7487 {
7488 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7489
7490 *associated_dev_array = dev_array;
7491 *output_array_size = wifi_count;
7492 }
7493 else
7494 {
7495 *associated_dev_array = NULL;
7496 }
7497 }
7498 }
7499
7500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7501 return RETURN_OK;
7502}
7503#endif
7504
7505/* getIPAddress function */
7506/**
7507* @description Returning IpAddress of the Matched String
7508*
7509* @param
7510* @str Having MacAddress
7511* @ipaddr Having ipaddr
7512* @return The status of the operation
7513* @retval RETURN_OK if successful
7514* @retval RETURN_ERR if any error is detected
7515*
7516*/
7517
7518INT getIPAddress(char *str,char *ipaddr)
7519{
7520 FILE *fp = NULL;
7521 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7522 int LeaseTime = 0,ret = 0;
7523 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7524 {
7525 return RETURN_ERR;
7526 }
7527
7528 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7529 {
7530 /*
7531 Sample:sss
7532 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7533 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7534 */
7535 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7536 &(LeaseTime),
7537 phyAddr,
7538 ipAddr,
7539 hostName
7540 );
7541 if(ret != 4)
7542 continue;
7543 if(strcmp(str,phyAddr) == 0)
7544 strcpy(ipaddr,ipAddr);
7545 }
7546 return RETURN_OK;
7547}
7548
7549/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7550/**
7551* @description Returning Inactive wireless connected clients informations
7552*
7553* @param
7554* @filename Holding private_wifi 2g/5g content files
7555* @associated_dev_array Having inactiv wireless clients informations
7556* @output_array_size Returning Inactive wireless counts
7557* @return The status of the operation
7558* @retval RETURN_OK if successful
7559* @retval RETURN_ERR if any error is detected
7560*
7561*/
7562
7563INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7564{
7565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7566 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7567 FILE *fp = NULL;
7568 int arr[MACADDRESS_SIZE] = {0};
7569 unsigned char mac[MACADDRESS_SIZE] = {0};
7570 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7571 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7572 fp = popen(buf,"r");
7573 if(fp == NULL)
7574 return RETURN_ERR;
7575 else
7576 {
7577 fgets(path,sizeof(path),fp);
7578 maccount = atoi(path);
7579 }
7580 pclose(fp);
7581 *output_array_size = maccount;
7582 wifi_associated_dev3_t* temp = NULL;
7583 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7584 *associated_dev_array = temp;
7585 if(temp == NULL)
7586 {
7587 printf("Error Statement. Insufficient memory \n");
7588 return RETURN_ERR;
7589 }
7590 memset(buf,0,sizeof(buf));
7591 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7592 fp = popen(buf,"r");
7593 for(count = 0; count < maccount ; count++)
7594 {
7595 fgets(path,sizeof(path),fp);
7596 for(i = 0; path[i]!='\n';i++)
7597 str[i]=path[i];
7598 str[i]='\0';
7599 getIPAddress(str,ipaddr);
7600 memset(buf,0,sizeof(buf));
7601 if(strlen(ipaddr) > 0)
7602 {
7603 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7604 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7605 {
7606 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7607 {
7608 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7609 {
7610 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7611
7612 }
7613 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7614 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]);
7615 }
7616 temp[count].cli_AuthenticationState = 0; //TODO
7617 temp[count].cli_Active = 0; //TODO
7618 temp[count].cli_SignalStrength = 0;
7619 }
7620 else //Active wireless clients info
7621 {
7622 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7623 {
7624 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7625 {
7626 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7627
7628 }
7629 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7630 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]);
7631 }
7632 temp[count].cli_Active = 1;
7633 }
7634 }
7635 memset(ipaddr,0,sizeof(ipaddr));
7636 }
7637 pclose(fp);
7638 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7639 return RETURN_OK;
7640}
7641//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7642//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7643//To get Band Steering Capability
7644INT wifi_getBandSteeringCapability(BOOL *support)
7645{
7646 *support = FALSE;
7647 return RETURN_OK;
7648}
7649
7650
7651//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7652//To get Band Steering enable status
7653INT wifi_getBandSteeringEnable(BOOL *enable)
7654{
7655 *enable = FALSE;
7656 return RETURN_OK;
7657}
7658
7659//To turn on/off Band steering
7660INT wifi_setBandSteeringEnable(BOOL enable)
7661{
7662 return RETURN_OK;
7663}
7664
7665//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7666//To get Band Steering AP group
7667INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7668{
7669 if (NULL == output_ApGroup)
7670 return RETURN_ERR;
7671
7672 strcpy(output_ApGroup, "1,2");
7673 return RETURN_OK;
7674}
7675
7676//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7677//to set and read the band steering BandUtilizationThreshold parameters
7678INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7679{
7680 return RETURN_ERR;
7681}
7682
7683INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7684{
7685 return RETURN_ERR;
7686}
7687
7688//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7689//to set and read the band steering RSSIThreshold parameters
7690INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7691{
7692 return RETURN_ERR;
7693}
7694
7695INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7696{
7697 return RETURN_ERR;
7698}
7699
7700
7701//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7702//to set and read the band steering physical modulation rate threshold parameters
7703INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7704{
7705 //If chip is not support, return -1
7706 return RETURN_ERR;
7707}
7708
7709INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7710{
7711 //If chip is not support, return -1
7712 return RETURN_ERR;
7713}
7714
7715//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7716//to set and read the inactivity time (in seconds) for steering under overload condition
7717INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7718{
7719 return RETURN_ERR;
7720}
7721
7722INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7723{
7724 return RETURN_ERR;
7725}
7726
7727//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7728//to set and read the inactivity time (in seconds) for steering under Idle condition
7729INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7730{
7731 return RETURN_ERR;
7732}
7733
7734INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7735{
7736 return RETURN_ERR;
7737}
7738
7739//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7740//pClientMAC[64]
7741//pSourceSSIDIndex[64]
7742//pDestSSIDIndex[64]
7743//pSteeringReason[256]
7744INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7745{
7746 //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
7747 *pSteeringTime=time(NULL);
7748 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7749 return RETURN_OK;
7750}
7751
7752INT wifi_ifConfigDown(INT apIndex)
7753{
7754 INT status = RETURN_OK;
7755 char cmd[64];
7756
7757 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7758 printf("%s: %s\n", __func__, cmd);
7759 system(cmd);
7760
7761 return status;
7762}
7763
7764INT wifi_ifConfigUp(INT apIndex)
7765{
7766 char cmd[128];
7767 char buf[1024];
7768
7769 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7770 _syscmd(cmd, buf, sizeof(buf));
7771 return 0;
7772}
7773
7774//>> Deprecated. Replace with wifi_applyRadioSettings
7775INT wifi_pushBridgeInfo(INT apIndex)
7776{
7777 char ip[32];
7778 char subnet[32];
7779 char bridge[32];
7780 int vlanId;
7781 char cmd[128];
7782 char buf[1024];
7783
7784 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7785 wifi_getApVlanID(apIndex,&vlanId);
7786
7787 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7788 _syscmd(cmd,buf, sizeof(buf));
7789
7790 return 0;
7791}
7792
7793INT wifi_pushChannel(INT radioIndex, UINT channel)
7794{
7795 char cmd[128];
7796 char buf[1024];
7797 int apIndex;
7798
7799 apIndex=(radioIndex==0)?0:1;
7800 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7801 _syscmd(cmd,buf, sizeof(buf));
7802
7803 return 0;
7804}
7805
7806INT wifi_pushChannelMode(INT radioIndex)
7807{
7808 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7809 return RETURN_ERR;
7810}
7811
7812INT wifi_pushDefaultValues(INT radioIndex)
7813{
7814 //Apply Comcast specified default radio settings instantly
7815 //AMPDU=1
7816 //AMPDUFrames=32
7817 //AMPDULim=50000
7818 //txqueuelen=1000
7819
7820 return RETURN_ERR;
7821}
7822
7823INT wifi_pushTxChainMask(INT radioIndex)
7824{
7825 //Apply default TxChainMask instantly
7826 return RETURN_ERR;
7827}
7828
7829INT wifi_pushRxChainMask(INT radioIndex)
7830{
7831 //Apply default RxChainMask instantly
7832 return RETURN_ERR;
7833}
7834
7835INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7836{
7837 INT status;
7838
7839 status = wifi_setSSIDName(apIndex,ssid);
7840 wifi_setApEnable(apIndex,FALSE);
7841 wifi_setApEnable(apIndex,TRUE);
7842
7843 return status;
7844}
7845
7846INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7847{
7848 //Apply default Ssid Advertisement instantly
7849 return RETURN_ERR;
7850}
7851
7852INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7853{
7854 INT status = RETURN_ERR;
7855 *output = 0;
7856 return RETURN_ERR;
7857}
7858
7859INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7860{
7861 return RETURN_OK;
7862}
7863
7864INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7865{
7866 return RETURN_OK;
7867}
7868
7869//To-do
7870INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7871{
developereb199ae2022-09-13 14:04:27 +08007872 char output[16]={'\0'};
7873 char config_file[MAX_BUF_SIZE] = {0};
7874
7875 if (!output_string)
7876 return RETURN_ERR;
7877
7878 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7879 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7880
7881 if (strlen(output) == 0)
7882 snprintf(output_string, 64, "Disabled");
7883 else if (strncmp(output, "0", 1) == 0)
7884 snprintf(output_string, 64, "Disabled");
7885 else if (strncmp(output, "1", 1) == 0)
7886 snprintf(output_string, 64, "Optional");
7887 else if (strncmp(output, "2", 1) == 0)
7888 snprintf(output_string, 64, "Required");
7889 else {
7890 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7891 return RETURN_ERR;
7892 }
7893
7894 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007895 return RETURN_OK;
7896}
7897INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7898{
developereb199ae2022-09-13 14:04:27 +08007899 char str[MAX_BUF_SIZE]={'\0'};
7900 char cmd[MAX_CMD_SIZE]={'\0'};
7901 struct params params;
7902 char config_file[MAX_BUF_SIZE] = {0};
7903
7904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7905 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7906 return RETURN_ERR;
7907
7908 params.name = "ieee80211w";
7909 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7910 params.value = "0";
7911 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7912 params.value = "1";
7913 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7914 params.value = "2";
7915 else{
7916 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7917 return RETURN_ERR;
7918 }
7919 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7920 wifi_hostapdWrite(config_file, &params, 1);
7921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007922 return RETURN_OK;
7923}
7924INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7925{
7926 char output[16]={'\0'};
7927 char config_file[MAX_BUF_SIZE] = {0};
7928
7929 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7930 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7931 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7932
7933 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7934 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7935
7936 return RETURN_OK;
7937}
7938
7939INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7940{
7941 return RETURN_OK;
7942}
7943
7944INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7945{
7946 return RETURN_OK;
7947}
7948
7949INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7950{
7951 return RETURN_OK;
7952}
7953
7954INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7955{
7956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7957 char config_file[MAX_BUF_SIZE] = {0};
7958
7959 if (NULL == output)
7960 return RETURN_ERR;
7961 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7962 wifi_hostapdRead(config_file,"hw_mode",output,64);
7963
7964 if(strcmp(output,"b")==0)
7965 sprintf(output, "%s", "1,2,5.5,11");
7966 else if (strcmp(output,"a")==0)
7967 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7968 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7969 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7970
7971 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7972 return RETURN_OK;
7973}
7974
7975INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7976{
7977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7978 char *temp;
7979 char temp_output[128];
7980 char temp_TransmitRates[128];
7981 char config_file[MAX_BUF_SIZE] = {0};
7982
7983 if (NULL == output)
7984 return RETURN_ERR;
7985
7986 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7987 wifi_hostapdRead(config_file,"supported_rates",output,64);
7988
7989 strcpy(temp_TransmitRates,output);
7990 strcpy(temp_output,"");
7991 temp = strtok(temp_TransmitRates," ");
7992 while(temp!=NULL)
7993 {
7994 temp[strlen(temp)-1]=0;
7995 if((temp[0]=='5') && (temp[1]=='\0'))
7996 {
7997 temp="5.5";
7998 }
7999 strcat(temp_output,temp);
8000 temp = strtok(NULL," ");
8001 if(temp!=NULL)
8002 {
8003 strcat(temp_output,",");
8004 }
8005 }
8006 strcpy(output,temp_output);
8007 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8008
8009 return RETURN_OK;
8010}
8011
8012INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8013{
8014 return RETURN_OK;
8015}
8016
8017
8018INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8019{
8020 int i=0;
8021 char *temp;
8022 char temp1[128];
8023 char temp_output[128];
8024 char temp_TransmitRates[128];
8025 struct params params={'\0'};
8026 char config_file[MAX_BUF_SIZE] = {0};
8027
8028 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8029 if(NULL == output)
8030 return RETURN_ERR;
8031
8032 strcpy(temp_TransmitRates,output);
8033
8034 for(i=0;i<strlen(temp_TransmitRates);i++)
8035 {
8036 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
8037 {
8038 continue;
8039 }
8040 else
8041 {
8042 return RETURN_ERR;
8043 }
8044 }
8045 strcpy(temp_output,"");
8046 temp = strtok(temp_TransmitRates," ");
8047 while(temp!=NULL)
8048 {
8049 strcpy(temp1,temp);
8050 if(wlanIndex==1)
8051 {
8052 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8053 {
8054 return RETURN_ERR;
8055 }
8056 }
8057
8058 if(strcmp(temp,"5.5")==0)
8059 {
8060 strcpy(temp1,"55");
8061 }
8062 else
8063 {
8064 strcat(temp1,"0");
8065 }
8066 strcat(temp_output,temp1);
8067 temp = strtok(NULL," ");
8068 if(temp!=NULL)
8069 {
8070 strcat(temp_output," ");
8071 }
8072 }
8073 strcpy(output,temp_output);
8074
8075
8076 params.name = "supported_rates";
8077 params.value = output;
8078
8079 wifi_dbg_printf("\n%s:",__func__);
8080 wifi_dbg_printf("params.value=%s\n",params.value);
8081 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8082 wifi_hostapdWrite(config_file,&params,1);
8083 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8084
8085 return RETURN_OK;
8086}
8087
8088
8089static char *sncopy(char *dst, int dst_sz, const char *src)
8090{
8091 if (src && dst && dst_sz > 0) {
8092 strncpy(dst, src, dst_sz);
8093 dst[dst_sz - 1] = '\0';
8094 }
8095 return dst;
8096}
8097
8098static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8099{
8100 if (0 == strcmp(ht_mode, "HT40") ||
8101 0 == strcmp(ht_mode, "HT80") ||
8102 0 == strcmp(ht_mode, "HT160")) {
8103 switch (channel) {
8104 case 1 ... 7:
8105 case 36:
8106 case 44:
8107 case 52:
8108 case 60:
8109 case 100:
8110 case 108:
8111 case 116:
8112 case 124:
8113 case 132:
8114 case 140:
8115 case 149:
8116 case 157:
8117 return 1;
8118 case 8 ... 13:
8119 case 40:
8120 case 48:
8121 case 56:
8122 case 64:
8123 case 104:
8124 case 112:
8125 case 120:
8126 case 128:
8127 case 136:
8128 case 144:
8129 case 153:
8130 case 161:
8131 return -1;
8132 default:
8133 return -EINVAL;
8134 }
8135 }
8136
8137 return -EINVAL;
8138}
8139
8140static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8141{
8142 if (NULL == hw_mode) return;
8143
8144 if (0 == strcmp(hw_mode, "ac"))
8145 sncopy(bw_mode, bw_mode_len, "ht vht");
8146
8147 if (0 == strcmp(hw_mode, "n"))
8148 sncopy(bw_mode, bw_mode_len, "ht");
8149
8150 return;
8151}
8152
8153static int util_chan_to_freq(int chan)
8154{
8155 if (chan == 14)
8156 return 2484;
8157 else if (chan < 14)
8158 return 2407 + chan * 5;
8159 else if (chan >= 182 && chan <= 196)
8160 return 4000 + chan * 5;
8161 else
8162 return 5000 + chan * 5;
8163 return 0;
8164}
8165
8166const int *util_unii_5g_chan2list(int chan, int width)
8167{
8168 static const int lists[] = {
8169 // <width>, <chan1>, <chan2>..., 0,
8170 20, 36, 0,
8171 20, 40, 0,
8172 20, 44, 0,
8173 20, 48, 0,
8174 20, 52, 0,
8175 20, 56, 0,
8176 20, 60, 0,
8177 20, 64, 0,
8178 20, 100, 0,
8179 20, 104, 0,
8180 20, 108, 0,
8181 20, 112, 0,
8182 20, 116, 0,
8183 20, 120, 0,
8184 20, 124, 0,
8185 20, 128, 0,
8186 20, 132, 0,
8187 20, 136, 0,
8188 20, 140, 0,
8189 20, 144, 0,
8190 20, 149, 0,
8191 20, 153, 0,
8192 20, 157, 0,
8193 20, 161, 0,
8194 20, 165, 0,
8195 40, 36, 40, 0,
8196 40, 44, 48, 0,
8197 40, 52, 56, 0,
8198 40, 60, 64, 0,
8199 40, 100, 104, 0,
8200 40, 108, 112, 0,
8201 40, 116, 120, 0,
8202 40, 124, 128, 0,
8203 40, 132, 136, 0,
8204 40, 140, 144, 0,
8205 40, 149, 153, 0,
8206 40, 157, 161, 0,
8207 80, 36, 40, 44, 48, 0,
8208 80, 52, 56, 60, 64, 0,
8209 80, 100, 104, 108, 112, 0,
8210 80, 116, 120, 124, 128, 0,
8211 80, 132, 136, 140, 144, 0,
8212 80, 149, 153, 157, 161, 0,
8213 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8214 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8215 -1 // final delimiter
8216 };
8217 const int *start;
8218 const int *p;
8219
8220 for (p = lists; *p != -1; p++) {
8221 if (*p == width) {
8222 for (start = ++p; *p != 0; p++) {
8223 if (*p == chan)
8224 return start;
8225 }
8226 }
8227 // move to the end of channel list of given width
8228 while (*p != 0) {
8229 p++;
8230 }
8231 }
8232
8233 return NULL;
8234}
8235
8236static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8237{
8238 if (NULL == ht_mode)
8239 return 0;
8240
8241 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8242 const int *chans = util_unii_5g_chan2list(channel, width);
8243 int sum = 0;
8244 int cnt = 0;
8245
8246 if (NULL == chans)
8247 return 0;
8248
8249 while (*chans) {
8250 sum += *chans;
8251 cnt++;
8252 chans++;
8253 }
8254 return sum / cnt;
8255}
8256
8257static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8258{
8259 BOOL onlyG, onlyN, onlyA;
8260 CHAR tmp[64];
8261 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8262 if (ret == RETURN_OK) {
8263 sncopy(hw_mode, hw_mode_size, tmp);
8264 }
8265 return ret;
8266}
8267
8268INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8269{
8270 // Sample commands:
8271 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8272 // hostapd_cli -i wifi0 chan_switch 30 2437
8273 char cmd[MAX_CMD_SIZE] = {0};
8274 char buf[MAX_BUF_SIZE] = {0};
8275 int freq = 0, ret = 0;
8276 char center_freq1_str[32] = ""; // center_freq1=%d
8277 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8278 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8279 char hw_mode[16] = ""; // n|ac
8280 char bw_mode[16] = ""; // ht|ht vht
8281 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8282 int sec_chan_offset;
8283 int width;
developer4fb0b922022-09-30 14:29:09 +08008284 char config_file[64] = {0};
8285 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008286 char *ext_str = "None";
8287
developer4fb0b922022-09-30 14:29:09 +08008288 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008289
8290 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8291
developer5884e982022-10-06 10:52:50 +08008292 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008293
8294 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008295 if (channel){
8296 freq = util_chan_to_freq(channel);
8297 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8298 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8299 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8300 if (sec_chan_offset != -EINVAL)
8301 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008302
8303
developer5884e982022-10-06 10:52:50 +08008304 // Provide bandwith if specified
8305 if (channel_width_MHz > 20) {
8306 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8307 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8308 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008309
developer5884e982022-10-06 10:52:50 +08008310 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8311 }else if (channel_width_MHz == 20){
8312 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8313 }
developer06a01d92022-09-07 16:32:39 +08008314
developer5884e982022-10-06 10:52:50 +08008315 int center_chan = 0;
8316 if (channel_width_MHz > 20) {
8317 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8318 if (center_chan > 0) {
8319 int center_freq1 = util_chan_to_freq(center_chan);
8320 if (center_freq1)
8321 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8322 }
developer06a01d92022-09-07 16:32:39 +08008323 }
developer06a01d92022-09-07 16:32:39 +08008324
developer5884e982022-10-06 10:52:50 +08008325 // Only the first AP, other are hanging on the same radio
8326 int apIndex = radioIndex;
8327 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8328 AP_PREFIX, apIndex, csa_beacon_count, freq,
8329 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8330 wifi_dbg_printf("execute: '%s'\n", cmd);
8331 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008332
developer5884e982022-10-06 10:52:50 +08008333 ret = wifi_setRadioChannel(radioIndex, channel);
8334 if (ret != RETURN_OK) {
8335 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8336 return RETURN_ERR;
8337 }
8338
8339 if (sec_chan_offset == 1) ext_str = "Above";
8340 else if (sec_chan_offset == -1) ext_str = "Below";
8341
8342 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008343
developer5884e982022-10-06 10:52:50 +08008344 } else {
8345 if (channel_width_MHz > 20)
8346 ext_str = "Above";
8347 }
developer4fb0b922022-09-30 14:29:09 +08008348 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8349 _syscmd(cmd, buf, sizeof(buf));
8350 if (strlen(buf) != 0)
8351 stbcEnable = TRUE;
8352
developer06a01d92022-09-07 16:32:39 +08008353 wifi_setRadioExtChannel(radioIndex, ext_str);
8354
developer4fb0b922022-09-30 14:29:09 +08008355 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8356
developer06a01d92022-09-07 16:32:39 +08008357 char mhz_str[16];
8358 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8359 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8360
8361 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8362
8363 return RETURN_OK;
8364}
8365
8366INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8367{
developer615510b2022-09-27 10:14:35 +08008368 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008369 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008370 char cmd[256]={0};
8371 char buf[128]={0};
8372 char file_name[32] = {0};
8373 char filter_SSID[32] = {0};
8374 char line[256] = {0};
8375 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008376 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008377 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008378 size_t len=0;
8379 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008380 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008381 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008382 bool filter_enable = false;
8383 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008384
developer615510b2022-09-27 10:14:35 +08008385 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008386
developer615510b2022-09-27 10:14:35 +08008387 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8388 f = fopen(file_name, "r");
8389 if (f != NULL) {
8390 fgets(filter_SSID, sizeof(file_name), f);
8391 if (strlen(filter_SSID) != 0)
8392 filter_enable = true;
8393 fclose(f);
8394 }
8395
8396 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8397 _syscmd(cmd, buf, sizeof(buf));
8398 channels_num = strtol(buf, NULL, 10);
8399
developer615510b2022-09-27 10:14:35 +08008400 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8401 // 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);
8402 fprintf(stderr, "cmd: %s\n", cmd);
8403 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008404 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8405 return RETURN_ERR;
8406 }
developer5550e242022-09-30 09:59:32 +08008407
8408 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8409 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8410
developer615510b2022-09-27 10:14:35 +08008411 ret = fgets(line, sizeof(line), f);
8412 while (ret != NULL) {
8413 if(strstr(line, "BSS") != NULL) { // new neighbor info
8414 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8415 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8416 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8417
8418 if (!filter_BSS) {
8419 index++;
8420 wifi_neighbor_ap2_t *tmp;
8421 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8422 if (tmp == NULL) { // no more memory to use
8423 index--;
8424 wifi_dbg_printf("%s: realloc failed\n", __func__);
8425 break;
8426 }
8427 scan_array = tmp;
8428 }
8429 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008430
developer615510b2022-09-27 10:14:35 +08008431 filter_BSS = false;
8432 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8433 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8434 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8435 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8436 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008437 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008438 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008439
developer615510b2022-09-27 10:14:35 +08008440 if (freq >= 2412 && freq <= 2484) {
8441 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8442 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8443 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8444 }
8445 else if (freq >= 5160 && freq <= 5805) {
8446 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8447 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8448 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8449 }
developer06a01d92022-09-07 16:32:39 +08008450
developer615510b2022-09-27 10:14:35 +08008451 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008452 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008453 for (int i = 0; i < channels_num; i++) {
8454 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8455 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8456 break;
8457 }
8458 }
developer06a01d92022-09-07 16:32:39 +08008459 }
developer615510b2022-09-27 10:14:35 +08008460 } else if (strstr(line, "beacon interval") != NULL) {
8461 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8462 } else if (strstr(line, "signal") != NULL) {
8463 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8464 } else if (strstr(line,"SSID") != NULL) {
8465 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8466 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8467 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008468 }
developer615510b2022-09-27 10:14:35 +08008469 } else if (strstr(line, "Supported rates") != NULL) {
8470 char SRate[80] = {0}, *tmp = NULL;
8471 memset(buf, 0, sizeof(buf));
8472 strcpy(SRate, line);
8473 tmp = strtok(SRate, ":");
8474 tmp = strtok(NULL, ":");
8475 strcpy(buf, tmp);
8476 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008477
developer615510b2022-09-27 10:14:35 +08008478 tmp = strtok(buf, " \n");
8479 while (tmp != NULL) {
8480 strcat(SRate, tmp);
8481 if (SRate[strlen(SRate) - 1] == '*') {
8482 SRate[strlen(SRate) - 1] = '\0';
8483 }
8484 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008485
developer615510b2022-09-27 10:14:35 +08008486 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008487 }
developer615510b2022-09-27 10:14:35 +08008488 SRate[strlen(SRate) - 1] = '\0';
8489 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8490 } else if (strstr(line, "DTIM") != NULL) {
8491 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8492 } else if (strstr(line, "VHT capabilities") != NULL) {
8493 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8494 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8495 } else if (strstr(line, "HT capabilities") != NULL) {
8496 strcat(scan_array[index].ap_SupportedStandards, ",n");
8497 strcpy(scan_array[index].ap_OperatingStandards, "n");
8498 } else if (strstr(line, "VHT operation") != NULL) {
8499 ret = fgets(line, sizeof(line), f);
8500 sscanf(line," * channel width: %d", &vht_channel_width);
8501 if(vht_channel_width == 1) {
8502 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8503 } else {
8504 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8505 }
8506 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8507 continue;
8508 } else if (strstr(line, "HT operation") != NULL) {
8509 ret = fgets(line, sizeof(line), f);
8510 sscanf(line," * secondary channel offset: %s", &buf);
8511 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008512 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008513 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 +08008514 }
developer615510b2022-09-27 10:14:35 +08008515 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008516 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008517 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8518 } else {
8519 //20Mhz
8520 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 +08008521 }
developer615510b2022-09-27 10:14:35 +08008522 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008523 continue;
developer615510b2022-09-27 10:14:35 +08008524 } else if (strstr(line, "HE capabilities") != NULL) {
8525 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8526 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8527 ret = fgets(line, sizeof(line), f);
8528 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8529 if (strstr(line, "HE40/2.4GHz") != NULL)
8530 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8531 else
8532 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8533 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8534 if (strstr(line, "HE80/5GHz") != NULL) {
8535 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8536 ret = fgets(line, sizeof(line), f);
8537 } else
8538 continue;
8539 if (strstr(line, "HE160/5GHz") != NULL)
8540 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008541 }
developer615510b2022-09-27 10:14:35 +08008542 continue;
8543 } else if (strstr(line, "WPA") != NULL) {
8544 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8545 } else if (strstr(line, "RSN") != NULL) {
8546 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8547 } else if (strstr(line, "Group cipher") != NULL) {
8548 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8549 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8550 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008551 }
developer06a01d92022-09-07 16:32:39 +08008552 }
developer615510b2022-09-27 10:14:35 +08008553 ret = fgets(line, sizeof(line), f);
8554 }
8555
8556 if (!filter_BSS) {
8557 *output_array_size = index + 1;
8558 } else {
8559 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8560 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008561 }
developer06a01d92022-09-07 16:32:39 +08008562 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008563 pclose(f);
developer5550e242022-09-30 09:59:32 +08008564 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008566 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008567}
developer615510b2022-09-27 10:14:35 +08008568
developer06a01d92022-09-07 16:32:39 +08008569INT wifi_getApAssociatedDeviceStats(
8570 INT apIndex,
8571 mac_address_t *clientMacAddress,
8572 wifi_associated_dev_stats_t *associated_dev_stats,
8573 u64 *handle)
8574{
8575 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8576 char interface_name[50] = {0};
8577 char cmd[1024] = {0};
8578 char mac_str[18] = {0};
8579 char *key = NULL;
8580 char *val = NULL;
8581 FILE *f = NULL;
8582 char *line = NULL;
8583 size_t len = 0;
8584 ssize_t read = 0;
8585
8586 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8587 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8588 return RETURN_ERR;
8589 }
8590
8591 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8592 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8593 if((f = popen(cmd, "r")) == NULL) {
8594 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8595 return RETURN_ERR;
8596 }
8597
8598 while ((read = getline(&line, &len, f)) != -1) {
8599 key = strtok(line,":");
8600 val = strtok(NULL,":");
8601
8602 if(!strncmp(key,"rx bytes",8))
8603 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8604 if(!strncmp(key,"tx bytes",8))
8605 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8606 if(!strncmp(key,"rx packets",10))
8607 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8608 if(!strncmp(key,"tx packets",10))
8609 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8610 if(!strncmp(key,"tx retries",10))
8611 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8612 if(!strncmp(key,"tx failed",9))
8613 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8614 if(!strncmp(key,"rx drop misc",13))
8615 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8616 if(!strncmp(key,"rx bitrate",10)) {
8617 val = strtok(val, " ");
8618 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8619 }
8620 if(!strncmp(key,"tx bitrate",10)) {
8621 val = strtok(val, " ");
8622 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8623 }
8624 }
8625 free(line);
8626 pclose(f);
8627 return RETURN_OK;
8628}
8629
8630INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8631{
8632 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8633
8634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8635 if (NULL == output_string)
8636 return RETURN_ERR;
8637
8638 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8639 _syscmd(cmd, buf, sizeof(buf));
8640
8641 //size of SSID name restricted to value less than 32 bytes
8642 snprintf(output_string, 32, "%s", buf);
8643 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8644
8645 return RETURN_OK;
8646}
8647
8648INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8649{
8650 //char cmd[MAX_CMD_SIZE] = {0};
8651 char config_file[MAX_BUF_SIZE] = {0};
8652 char buf[32] = {0};
8653
8654 if (!output_filterMode)
8655 return RETURN_ERR;
8656
8657 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8658 //_syscmd(cmd, buf, sizeof(buf));
8659 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8660 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008661 if(strlen(buf) == 0) {
8662 *output_filterMode = 0;
8663 }
8664 else {
8665 int macaddr_acl_mode = strtol(buf, NULL, 10);
8666 if (macaddr_acl_mode == 1) {
8667 *output_filterMode = 1;
8668 } else if (macaddr_acl_mode == 0) {
8669 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8670 if (strlen(buf) == 0) {
8671 *output_filterMode = 0;
8672 } else {
8673 *output_filterMode = 2;
8674 }
8675 } else {
8676 return RETURN_ERR;
8677 }
8678 }
developer06a01d92022-09-07 16:32:39 +08008679
8680 return RETURN_OK;
8681}
8682
8683INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8684{
8685 FILE *fp = NULL;
8686 char str[MAX_BUF_SIZE] = {0};
8687 int wificlientindex = 0 ;
8688 int count = 0;
8689 int signalstrength = 0;
8690 int arr[MACADDRESS_SIZE] = {0};
8691 unsigned char mac[MACADDRESS_SIZE] = {0};
8692 UINT wifi_count = 0;
8693 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8694 char pipeCmd[MAX_CMD_SIZE] = {0};
8695
8696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8697 *output_array_size = 0;
8698 *associated_dev_array = NULL;
8699 char interface_name[50] = {0};
8700
8701 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8702 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8703 return RETURN_ERR;
8704 }
8705
8706 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8707 fp = popen(pipeCmd, "r");
8708 if (fp == NULL)
8709 {
8710 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8711 return RETURN_ERR;
8712 }
8713
8714 /* Read the output a line at a time - output it. */
8715 fgets(str, sizeof(str)-1, fp);
8716 wifi_count = (unsigned int) atoi ( str );
8717 *output_array_size = wifi_count;
8718 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8719 pclose(fp);
8720
8721 if(wifi_count == 0)
8722 {
8723 return RETURN_OK;
8724 }
8725 else
8726 {
8727 wifi_associated_dev2_t* temp = NULL;
8728 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8729 *associated_dev_array = temp;
8730 if(temp == NULL)
8731 {
8732 printf("Error Statement. Insufficient memory \n");
8733 return RETURN_ERR;
8734 }
8735
8736 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8737 system(pipeCmd);
8738
8739 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8740 if(fp == NULL)
8741 {
8742 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8743 return RETURN_ERR;
8744 }
8745 fclose(fp);
8746
8747 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8748 fp = popen(pipeCmd, "r");
8749 if(fp)
8750 {
8751 for(count =0 ; count < wifi_count; count++)
8752 {
8753 fgets(str, MAX_BUF_SIZE, fp);
8754 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8755 {
8756 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8757 {
8758 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8759
8760 }
8761 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8762 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]);
8763 }
8764 temp[count].cli_AuthenticationState = 1; //TODO
8765 temp[count].cli_Active = 1; //TODO
8766 }
8767 pclose(fp);
8768 }
8769
8770 //Updating RSSI per client
8771 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8772 fp = popen(pipeCmd, "r");
8773 if(fp)
8774 {
8775 pclose(fp);
8776 }
8777 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8778 if(fp)
8779 {
8780 for(count =0 ; count < wifi_count ;count++)
8781 {
8782 fgets(str, MAX_BUF_SIZE, fp);
8783 signalstrength = atoi(str);
8784 temp[count].cli_RSSI = signalstrength;
8785 }
8786 pclose(fp);
8787 }
8788
8789
8790 //LastDataDownlinkRate
8791 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8792 fp = popen(pipeCmd, "r");
8793 if (fp)
8794 {
8795 pclose(fp);
8796 }
8797 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8798 if (fp)
8799 {
8800 for (count = 0; count < wifi_count; count++)
8801 {
8802 fgets(str, MAX_BUF_SIZE, fp);
8803 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8804 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8805 }
8806 pclose(fp);
8807 }
8808
8809 //LastDataUplinkRate
8810 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8811 fp = popen(pipeCmd, "r");
8812 if (fp)
8813 {
8814 pclose(fp);
8815 }
8816 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8817 if (fp)
8818 {
8819 for (count = 0; count < wifi_count; count++)
8820 {
8821 fgets(str, MAX_BUF_SIZE, fp);
8822 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8823 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8824 }
8825 pclose(fp);
8826 }
8827 }
8828 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8829 return RETURN_OK;
8830
8831}
8832
8833INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8834{
8835#if 0
8836 /*char buf[1024] = {0};
8837 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8838 _syscmd(cmd, buf, sizeof(buf));*/
8839
8840 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8841 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8842 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8843 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8844
8845 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.
8846 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].
8847 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].
8848 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].
8849 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8850 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8851
8852 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8853 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8854 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8855 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.
8856 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.
8857 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.
8858 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.
8859 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.
8860 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.
8861 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.
8862 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8863#endif
8864
8865 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008866 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008867 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008868 char pipeCmd[128] = {0};
8869 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008870 wifi_ssidTrafficStats2_t *out = output_struct;
8871
developerce736392022-09-13 15:24:34 +08008872 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008873 if (!output_struct)
8874 return RETURN_ERR;
8875
developerce736392022-09-13 15:24:34 +08008876 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8877 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8878 GetInterfaceName(interface_name, HConf_file);
8879 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008880
developer06a01d92022-09-07 16:32:39 +08008881 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008882 if (fp == NULL) {
8883 fprintf(stderr, "%s: popen failed\n", __func__);
8884 return RETURN_ERR;
8885 }
8886 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008887
developerce736392022-09-13 15:24:34 +08008888 if (strlen(str) == 0) // interface not exist
8889 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008890
developerce736392022-09-13 15:24:34 +08008891 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8892 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008893 pclose(fp);
8894
developerce736392022-09-13 15:24:34 +08008895 memset(str, 0, sizeof(str));
8896 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008897 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008898 if (fp == NULL) {
8899 fprintf(stderr, "%s: popen failed\n", __func__);
8900 return RETURN_ERR;
8901 }
8902 fgets(str, sizeof(str), fp);
8903
8904 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8905 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008906 pclose(fp);
developerce736392022-09-13 15:24:34 +08008907
8908 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8909 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8910
8911 // Not supported
8912 output_struct->ssid_RetransCount = 0;
8913 output_struct->ssid_FailedRetransCount = 0;
8914 output_struct->ssid_RetryCount = 0;
8915 output_struct->ssid_MultipleRetryCount = 0;
8916 output_struct->ssid_ACKFailureCount = 0;
8917 output_struct->ssid_AggregatedPacketCount = 0;
8918
developer06a01d92022-09-07 16:32:39 +08008919 return RETURN_OK;
8920}
8921
8922//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).
8923INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8924{
8925 char output_val[16]={'\0'};
8926 char config_file[MAX_BUF_SIZE] = {0};
8927
8928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8929 if (!output)
8930 return RETURN_ERR;
8931 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8932 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8933
8934 if( strcmp(output_val,"1") == 0 )
8935 *output = TRUE;
8936 else
8937 *output = FALSE;
8938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8939
8940 return RETURN_OK;
8941}
8942
8943INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8944{
8945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8946 char str[MAX_BUF_SIZE]={'\0'};
8947 char string[MAX_BUF_SIZE]={'\0'};
8948 char cmd[MAX_CMD_SIZE]={'\0'};
8949 char *ch;
8950 char config_file[MAX_BUF_SIZE] = {0};
8951 struct params params;
8952
8953 if(enable == TRUE)
8954 strcpy(string,"1");
8955 else
8956 strcpy(string,"0");
8957
8958 params.name = "ap_isolate";
8959 params.value = string;
8960
8961 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8962 wifi_hostapdWrite(config_file,&params,1);
8963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8964
8965 return RETURN_OK;
8966}
8967
8968INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8969{
8970 if (NULL == output_dBm)
8971 return RETURN_ERR;
8972
8973 *output_dBm = 0;
8974 return RETURN_OK;
8975}
8976
8977INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8978{
8979 return RETURN_OK;
8980}
8981INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8982{
8983 return RETURN_OK;
8984}
8985INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8986{
8987 return RETURN_OK;
8988}
8989INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8990{
8991 return RETURN_OK;
8992}
8993INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8994{
8995 return RETURN_OK;
8996}
8997INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8998{
8999 char config_file[MAX_BUF_SIZE] = {0};
9000 struct params list;
9001
9002 list.name = "bss_transition";
9003 list.value = activate?"1":"0";
9004 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9005 wifi_hostapdWrite(config_file, &list, 1);
9006
9007 return RETURN_OK;
9008}
9009wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9010
9011void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9012{
9013 return;
9014}
9015
9016INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9017{
9018 // TODO Implement me!
9019 return RETURN_OK;
9020}
9021
9022INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9023{
developera3c68b92022-09-13 15:27:29 +08009024 char file_name[128] = {0};
9025 char buf[128] = {0};
9026 FILE *f = NULL;
9027
9028 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9029
9030 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9031 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
9032 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9033 f = fopen(file_name, "w");
9034 if (f == NULL)
9035 return RETURN_ERR;
9036 // For mode == 0 is to disable filter, just don't write to the file.
9037 if (mode)
9038 fprintf(f, "%s", essid);
9039
9040 fclose(f);
9041 }
9042 } else { // special case, need to set AP's SSID as filter for each radio.
9043 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9044 f = fopen(file_name, "w");
9045 if (f == NULL)
9046 return RETURN_ERR;
9047
9048 // For mode == 0 is to disable filter, just don't write to the file.
9049 if (mode)
9050 fprintf(f, "%s", essid);
9051
9052 fclose(f);
9053 }
9054
9055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009056 return RETURN_OK;
9057}
9058
9059INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9060{
9061 // TODO Implement me!
9062 //Apply wifi_pushRadioChannel() instantly
9063 return RETURN_ERR;
9064}
9065
9066INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9067{
9068 // TODO Implement me!
9069 return RETURN_OK;
9070}
9071
9072#ifdef HAL_NETLINK_IMPL
9073static int tidStats_callback(struct nl_msg *msg, void *arg) {
9074 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9075 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9076 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9077 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9078 int rem , tid_index = 0;
9079
9080 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9081 wifi_associated_dev_tid_entry_t *stats_entry;
9082
9083 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9084 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9085 };
9086 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9087 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9088 };
9089
9090 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9091 genlmsg_attrlen(gnlh, 0), NULL);
9092
9093
9094 if (!tb[NL80211_ATTR_STA_INFO]) {
9095 fprintf(stderr, "station stats missing!\n");
9096 return NL_SKIP;
9097 }
9098
9099 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9100 tb[NL80211_ATTR_STA_INFO],
9101 stats_policy)) {
9102 fprintf(stderr, "failed to parse nested attributes!\n");
9103 return NL_SKIP;
9104 }
9105
9106 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9107 {
9108 stats_entry = &out->tid_array[tid_index];
9109
9110 stats_entry->tid = tid_index;
9111 stats_entry->ac = _tid_ac_index_get[tid_index];
9112
9113 if(sinfo[NL80211_STA_INFO_TID_STATS])
9114 {
9115 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9116 printf("failed to parse nested stats attributes!");
9117 return NL_SKIP;
9118 }
9119 }
9120 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9121 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9122
9123 if(tid_index < (PS_MAX_TID - 1))
9124 tid_index++;
9125 }
9126 //ToDo: sum_time_ms, ewma_time_ms
9127 return NL_SKIP;
9128}
9129#endif
9130
9131INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9132{
9133#ifdef HAL_NETLINK_IMPL
9134 Netlink nl;
9135 char if_name[10];
9136
9137 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9138
9139 nl.id = initSock80211(&nl);
9140
9141 if (nl.id < 0) {
9142 fprintf(stderr, "Error initializing netlink \n");
9143 return -1;
9144 }
9145
9146 struct nl_msg* msg = nlmsg_alloc();
9147
9148 if (!msg) {
9149 fprintf(stderr, "Failed to allocate netlink message.\n");
9150 nlfree(&nl);
9151 return -2;
9152 }
9153
9154 genlmsg_put(msg,
9155 NL_AUTO_PORT,
9156 NL_AUTO_SEQ,
9157 nl.id,
9158 0,
9159 0,
9160 NL80211_CMD_GET_STATION,
9161 0);
9162
9163 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9164 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9165 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9166 nl_send_auto(nl.socket, msg);
9167 nl_recvmsgs(nl.socket, nl.cb);
9168 nlmsg_free(msg);
9169 nlfree(&nl);
9170 return RETURN_OK;
9171#else
9172//iw implementation
9173#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9174#define TOTAL_MAX_LINES 50
9175
9176 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9177 char if_name[10];
9178 FILE *fp=NULL;
9179 char pipeCmd[1024]= {'\0'};
9180 int lines,tid_index=0;
9181 char mac_addr[20] = {'\0'};
9182
9183 wifi_associated_dev_tid_entry_t *stats_entry;
9184
9185 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9186 strcpy(mac_addr,clientMacAddress);
9187
9188 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9189 fp= popen(pipeCmd,"r");
9190 if(fp == NULL)
9191 {
9192 perror("popen for station dump failed\n");
9193 return RETURN_ERR;
9194 }
9195 pclose(fp);
9196
9197 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9198 fp=popen(pipeCmd,"r");
9199 if(fp == NULL)
9200 {
9201 perror("popen for grep station failed\n");
9202 return RETURN_ERR;
9203 }
9204 else if(fgets(buf,sizeof(buf),fp) != NULL)
9205 lines=atoi(buf);
9206 else
9207 {
9208 pclose(fp);
9209 fprintf(stderr,"No devices are connected \n");
9210 return RETURN_ERR;
9211 }
9212 pclose(fp);
9213
9214 if(lines == 1)
9215 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9216
9217 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9218 {
9219 stats_entry = &tid_stats->tid_array[tid_index];
9220 stats_entry->tid = tid_index;
9221
9222 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);
9223
9224 fp=popen(pipeCmd,"r");
9225 if(fp ==NULL)
9226 {
9227 perror("Failed to read from tid file \n");
9228 return RETURN_ERR;
9229 }
9230 else if(fgets(buf,sizeof(buf),fp) != NULL)
9231 stats_entry->num_msdus = atol(buf);
9232
9233 pclose(fp);
9234 stats_entry->ac = _tid_ac_index_get[tid_index];
9235// TODO:
9236// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9237// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9238 }
9239 return RETURN_OK;
9240#endif
9241}
9242
9243
9244INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9245{
developer615510b2022-09-27 10:14:35 +08009246 char cmd[128]={0};
9247 char buf[128]={0};
9248 int freq = 0;
9249
9250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9251
9252 // full mode is used to scan all channels.
9253 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9254 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9255 ieee80211_channel_to_frequency(chan_list[0], &freq);
9256
9257 if (freq)
9258 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9259 else
9260 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9261
9262 _syscmd(cmd, buf, sizeof(buf));
9263 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9264
developer06a01d92022-09-07 16:32:39 +08009265 return RETURN_OK;
9266}
9267
9268
9269INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9270{
9271 // TODO Implement me!
9272 return RETURN_ERR;
9273}
9274
9275INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9276{
9277 // TODO Implement me!
9278 return RETURN_ERR;
9279}
9280
9281INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9282{
9283 // TODO Implement me!
9284 return RETURN_ERR;
9285}
9286
9287INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9288{
9289 // TODO Implement me!
9290 return RETURN_ERR;
9291}
9292
9293INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9294{
9295 // TODO Implement me!
9296 return RETURN_ERR;
9297}
9298
9299INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9300{
9301 // TODO Implement me!
9302 return RETURN_ERR;
9303}
9304
9305INT wifi_steering_eventUnregister(void)
9306{
9307 // TODO Implement me!
9308 return RETURN_ERR;
9309}
9310
9311INT wifi_delApAclDevices(INT apIndex)
9312{
9313#if 0
9314 char cmd[MAX_BUF_SIZE] = {0};
9315 char buf[MAX_BUF_SIZE] = {0};
9316
9317 /* Not reset proof solution */
9318 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9319 if(_syscmd(cmd,buf,sizeof(buf)))
9320 return RETURN_ERR;
9321#endif
developere6aafda2022-09-13 14:59:28 +08009322 char cmd[MAX_CMD_SIZE]={0};
9323 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009324
developere6aafda2022-09-13 14:59:28 +08009325 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9326 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9327 if(_syscmd(cmd, buf, sizeof(buf)))
9328 return RETURN_ERR;
9329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009330
9331 return RETURN_OK;
9332}
9333
9334#ifdef HAL_NETLINK_IMPL
9335static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9336 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9337 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9338 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9339 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9340 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9341 char mac_addr[20],dev[20];
9342
9343 nla_parse(tb,
9344 NL80211_ATTR_MAX,
9345 genlmsg_attrdata(gnlh, 0),
9346 genlmsg_attrlen(gnlh, 0),
9347 NULL);
9348
9349 if(!tb[NL80211_ATTR_STA_INFO]) {
9350 fprintf(stderr, "sta stats missing!\n");
9351 return NL_SKIP;
9352 }
9353
9354 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9355 fprintf(stderr, "failed to parse nested attributes!\n");
9356 return NL_SKIP;
9357 }
9358 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9359
9360 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9361
9362 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9363 fprintf(stderr, "failed to parse nested rate attributes!");
9364 return NL_SKIP;
9365 }
9366
9367 if(sinfo[NL80211_STA_INFO_TID_STATS])
9368 {
9369 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9370 printf("failed to parse nested stats attributes!");
9371 return NL_SKIP;
9372 }
9373 }
9374
9375 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9376 {
9377 printf("Type is VHT\n");
9378 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9379 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9380
9381 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9382 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9383 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9384 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9385 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9386 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9387 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9388 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9389 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9390 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9391 }
9392 else
9393 {
9394 printf(" OFDM or CCK \n");
9395 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9396 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9397 }
9398
9399 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9400 if(rinfo[NL80211_RATE_INFO_MCS])
9401 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9402 }
9403 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9404 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9405 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9406 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9407
9408 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9409 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9410
9411 if (sinfo[NL80211_STA_INFO_SIGNAL])
9412 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9413 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9414 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9415 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9416 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9417 //rssi_array need to be filled
9418 return NL_SKIP;
9419}
9420#endif
9421
9422INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9423{
9424#ifdef HAL_NETLINK_IMPL
9425 Netlink nl;
9426 char if_name[10];
9427
9428 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9429
9430 if (*output_array_size <= 0)
9431 return RETURN_OK;
9432
9433 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9434 nl.id = initSock80211(&nl);
9435
9436 if (nl.id < 0) {
9437 fprintf(stderr, "Error initializing netlink \n");
9438 return 0;
9439 }
9440
9441 struct nl_msg* msg = nlmsg_alloc();
9442
9443 if (!msg) {
9444 fprintf(stderr, "Failed to allocate netlink message.\n");
9445 nlfree(&nl);
9446 return 0;
9447 }
9448
9449 genlmsg_put(msg,
9450 NL_AUTO_PORT,
9451 NL_AUTO_SEQ,
9452 nl.id,
9453 0,
9454 0,
9455 NL80211_CMD_GET_STATION,
9456 0);
9457
9458 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9459 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9460 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9461 nl_send_auto(nl.socket, msg);
9462 nl_recvmsgs(nl.socket, nl.cb);
9463 nlmsg_free(msg);
9464 nlfree(&nl);
9465 return RETURN_OK;
9466#else
9467 //TODO Implement me
9468 return RETURN_OK;
9469#endif
9470}
9471
9472#ifdef HAL_NETLINK_IMPL
9473static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9474 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9475 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9476 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9477 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9478 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9479 char mac_addr[20],dev[20];
9480
9481 nla_parse(tb,
9482 NL80211_ATTR_MAX,
9483 genlmsg_attrdata(gnlh, 0),
9484 genlmsg_attrlen(gnlh, 0),
9485 NULL);
9486
9487 if(!tb[NL80211_ATTR_STA_INFO]) {
9488 fprintf(stderr, "sta stats missing!\n");
9489 return NL_SKIP;
9490 }
9491
9492 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9493 fprintf(stderr, "failed to parse nested attributes!\n");
9494 return NL_SKIP;
9495 }
9496
9497 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9498
9499 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9500
9501 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9502 fprintf(stderr, "failed to parse nested rate attributes!");
9503 return NL_SKIP;
9504 }
9505
9506 if(sinfo[NL80211_STA_INFO_TID_STATS])
9507 {
9508 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9509 printf("failed to parse nested stats attributes!");
9510 return NL_SKIP;
9511 }
9512 }
9513 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9514 {
9515 printf("Type is VHT\n");
9516 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9517 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9518
9519 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9520 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9521 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9522 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9523 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9524 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9525 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9526 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9527 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9528 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9529 }
9530 else
9531 {
9532 printf(" OFDM or CCK \n");
9533 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9534 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9535 }
9536
9537 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9538 if(rinfo[NL80211_RATE_INFO_MCS])
9539 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9540 }
9541
9542 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9543 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9544 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9545 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9546
9547 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9548 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9549 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9550
9551 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9552 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9553
9554 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9555 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9556
9557 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9558 ((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]);
9559
9560 return NL_SKIP;
9561}
9562#endif
9563
9564INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9565{
9566#ifdef HAL_NETLINK_IMPL
9567 Netlink nl;
9568 char if_name[10];
9569
9570 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9571
9572 if (*output_array_size <= 0)
9573 return RETURN_OK;
9574
9575 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9576
9577 nl.id = initSock80211(&nl);
9578
9579 if(nl.id < 0) {
9580 fprintf(stderr, "Error initializing netlink \n");
9581 return 0;
9582 }
9583
9584 struct nl_msg* msg = nlmsg_alloc();
9585
9586 if(!msg) {
9587 fprintf(stderr, "Failed to allocate netlink message.\n");
9588 nlfree(&nl);
9589 return 0;
9590 }
9591
9592 genlmsg_put(msg,
9593 NL_AUTO_PORT,
9594 NL_AUTO_SEQ,
9595 nl.id,
9596 0,
9597 0,
9598 NL80211_CMD_GET_STATION,
9599 0);
9600
9601 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9602 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9603 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9604 nl_send_auto(nl.socket, msg);
9605 nl_recvmsgs(nl.socket, nl.cb);
9606 nlmsg_free(msg);
9607 nlfree(&nl);
9608 return RETURN_OK;
9609#else
9610 //TODO Implement me
9611 return RETURN_OK;
9612#endif
9613}
9614
9615INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9616{
9617 // TODO Implement me!
9618 char buf[MAX_BUF_SIZE] = {0};
9619 char config_file[MAX_BUF_SIZE] = {0};
9620
9621 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9622 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9623 *activate = (strncmp("1",buf,1) == 0);
9624
9625 return RETURN_OK;
9626}
9627
9628INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9629{
9630 char config_file[MAX_BUF_SIZE] = {0};
9631 struct params list;
9632
9633 list.name = "rrm_neighbor_report";
9634 list.value = activate?"1":"0";
9635 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9636 wifi_hostapdWrite(config_file, &list, 1);
9637
9638 return RETURN_OK;
9639}
9640
9641INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9642{
9643 char buf[32] = {0};
9644 char config_file[MAX_BUF_SIZE] = {0};
9645
9646 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9647 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9648 *activate = (strncmp("1",buf,1) == 0);
9649
9650 return RETURN_OK;
9651}
9652#undef HAL_NETLINK_IMPL
9653#ifdef HAL_NETLINK_IMPL
9654static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9655 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9656 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9657 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9658 char dev[20];
9659 int freq =0 ;
9660 static int i=0;
9661
9662 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9663
9664 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9665 };
9666
9667 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9668
9669 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9670
9671 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9672 fprintf(stderr, "survey data missing!\n");
9673 return NL_SKIP;
9674 }
9675
9676 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9677 {
9678 fprintf(stderr, "failed to parse nested attributes!\n");
9679 return NL_SKIP;
9680 }
9681
9682
9683 if(out[0].array_size == 1 )
9684 {
9685 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9686 {
9687 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9688 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9689 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9690
9691 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9692 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9693 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9694 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9695 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9696 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9697 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9698 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9699 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9700 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9701 if (sinfo[NL80211_SURVEY_INFO_TIME])
9702 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9703 return NL_STOP;
9704 }
9705 }
9706 else
9707 {
9708 if ( i <= out[0].array_size )
9709 {
9710 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9711 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9712 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9713
9714 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9715 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9716 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9717 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9718 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9719 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9720 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9721 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9722 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9723 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9724 if (sinfo[NL80211_SURVEY_INFO_TIME])
9725 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9726 }
9727 }
9728
9729 i++;
9730 return NL_SKIP;
9731}
9732#endif
9733
9734static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9735{
9736 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9737 FILE *fp;
9738
9739 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9740 {
9741 printf("Creating Frequency-Channel Map\n");
9742 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9743 }
9744 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9745 if((fp = popen(command, "r")))
9746 {
9747 fgets(output, sizeof(output), fp);
9748 *freqMHz = atoi(output);
9749 fclose(fp);
9750 }
9751
9752 return 0;
9753}
9754
9755static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9756{
9757 int freqMHz = -1;
9758 char cmd[MAX_CMD_SIZE] = {'\0'};
9759
9760 ieee80211_channel_to_frequency(channel, &freqMHz);
9761 if (freqMHz == -1) {
9762 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9763 return -1;
9764 }
9765
9766 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9767 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9768 radioIndex, freqMHz);
9769 return -1;
9770 }
9771
9772 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9773 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9774 return -1;
9775 }
9776
9777 return 0;
9778}
9779
9780static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9781{
9782 const char *ptr = buf;
9783 char *key = NULL;
9784 char *val = NULL;
9785 char line[256] = { '\0' };
9786
9787 while (ptr = get_line_from_str_buf(ptr, line)) {
9788 if (strstr(line, "Frequency")) continue;
9789
9790 key = strtok(line, ":");
9791 val = strtok(NULL, " ");
9792 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9793
9794 if (!strcmp(key, "noise")) {
9795 sscanf(val, "%d", &stats->ch_noise);
9796 if (stats->ch_noise == 0) {
9797 // Workaround for missing noise information.
9798 // Assume -95 for 2.4G and -103 for 5G
9799 if (radioIndex == 0) stats->ch_noise = -95;
9800 if (radioIndex == 1) stats->ch_noise = -103;
9801 }
9802 }
9803 else if (!strcmp(key, "channel active time")) {
9804 sscanf(val, "%llu", &stats->ch_utilization_total);
9805 }
9806 else if (!strcmp(key, "channel busy time")) {
9807 sscanf(val, "%llu", &stats->ch_utilization_busy);
9808 }
9809 else if (!strcmp(key, "channel receive time")) {
9810 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9811 }
9812 else if (!strcmp(key, "channel transmit time")) {
9813 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9814 }
9815 };
9816
9817 return 0;
9818}
9819
9820INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9821{
9822 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9823#ifdef HAL_NETLINK_IMPL
9824 Netlink nl;
9825 wifi_channelStats_t_loc local[array_size];
9826 char if_name[10];
9827
9828 local[0].array_size = array_size;
9829
9830 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9831
9832 nl.id = initSock80211(&nl);
9833
9834 if (nl.id < 0) {
9835 fprintf(stderr, "Error initializing netlink \n");
9836 return -1;
9837 }
9838
9839 struct nl_msg* msg = nlmsg_alloc();
9840
9841 if (!msg) {
9842 fprintf(stderr, "Failed to allocate netlink message.\n");
9843 nlfree(&nl);
9844 return -2;
9845 }
9846
9847 genlmsg_put(msg,
9848 NL_AUTO_PORT,
9849 NL_AUTO_SEQ,
9850 nl.id,
9851 0,
9852 NLM_F_DUMP,
9853 NL80211_CMD_GET_SURVEY,
9854 0);
9855
9856 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9857 nl_send_auto(nl.socket, msg);
9858 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9859 nl_recvmsgs(nl.socket, nl.cb);
9860 nlmsg_free(msg);
9861 nlfree(&nl);
9862 //Copying the Values
9863 for(int i=0;i<array_size;i++)
9864 {
9865 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9866 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9867 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9868 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9869 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9870 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9871 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9872 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9873 }
9874#else
9875 ULONG channel = 0;
9876 int i;
9877 int number_of_channels = array_size;
9878 char buf[512];
9879 INT ret;
9880 wifi_channelStats_t tmp_stats;
9881
9882 if (number_of_channels == 0) {
9883 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9884 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9885 return RETURN_ERR;
9886 }
9887 number_of_channels = 1;
9888 input_output_channelStats_array[0].ch_number = channel;
9889 }
9890
9891 for (i = 0; i < number_of_channels; i++) {
9892
9893 input_output_channelStats_array[i].ch_noise = 0;
9894 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9895 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9896 input_output_channelStats_array[i].ch_utilization_busy = 0;
9897 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9898 input_output_channelStats_array[i].ch_utilization_total = 0;
9899
9900 memset(buf, 0, sizeof(buf));
9901 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9902 return RETURN_ERR;
9903 }
9904 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9905 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9906 return RETURN_ERR;
9907 }
9908
9909 // XXX: fake missing 'self' counter which is not available in iw survey output
9910 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9911 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9912
9913 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9914 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9915 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9916 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9917 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9918
9919 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",
9920 __func__,
9921 input_output_channelStats_array[i].ch_number,
9922 input_output_channelStats_array[i].ch_noise,
9923 input_output_channelStats_array[i].ch_utilization_total,
9924 input_output_channelStats_array[i].ch_utilization_busy,
9925 input_output_channelStats_array[i].ch_utilization_busy_rx,
9926 input_output_channelStats_array[i].ch_utilization_busy_tx,
9927 input_output_channelStats_array[i].ch_utilization_busy_self,
9928 input_output_channelStats_array[i].ch_utilization_busy_ext);
9929 }
9930#endif
9931 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9932 return RETURN_OK;
9933}
9934#define HAL_NETLINK_IMPL
9935
9936/* Hostapd events */
9937
9938#ifndef container_of
9939#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9940#define container_of(ptr, type, member) \
9941 ((type *)((char *)ptr - offset_of(type, member)))
9942#endif /* container_of */
9943
9944struct ctrl {
9945 char sockpath[128];
9946 char sockdir[128];
9947 char bss[IFNAMSIZ];
9948 char reply[4096];
9949 int ssid_index;
9950 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9951 void (*overrun)(struct ctrl *ctrl);
9952 struct wpa_ctrl *wpa;
9953 unsigned int ovfl;
9954 size_t reply_len;
9955 int initialized;
9956 ev_timer retry;
9957 ev_timer watchdog;
9958 ev_stat stat;
9959 ev_io io;
9960};
9961static wifi_newApAssociatedDevice_callback clients_connect_cb;
9962static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9963static struct ctrl wpa_ctrl[MAX_APS];
9964static int initialized;
9965
9966static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9967{
9968 char cbuf[256] = {};
9969 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9970 struct cmsghdr *cmsg;
9971 unsigned int ovfl = ctrl->ovfl;
9972 unsigned int drop;
9973
9974 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9975 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9976 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9977 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9978
9979 drop = ovfl - ctrl->ovfl;
9980 ctrl->ovfl = ovfl;
9981
9982 return drop;
9983}
9984
9985static void ctrl_close(struct ctrl *ctrl)
9986{
9987 if (ctrl->io.cb)
9988 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9989 if (ctrl->retry.cb)
9990 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9991 if (!ctrl->wpa)
9992 return;
9993
9994 wpa_ctrl_detach(ctrl->wpa);
9995 wpa_ctrl_close(ctrl->wpa);
9996 ctrl->wpa = NULL;
9997 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9998}
9999
10000static void ctrl_process(struct ctrl *ctrl)
10001{
10002 const char *str;
10003 int drops;
10004 int level;
10005 int err;
10006
10007 /* Example events:
10008 *
10009 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10010 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10011 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10012 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10013 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10014 */
10015 if (!(str = index(ctrl->reply, '>')))
10016 return;
10017 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10018 return;
10019
10020 str++;
10021
10022 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10023 if (!(str = index(ctrl->reply, ' ')))
10024 return;
10025 wifi_associated_dev_t sta;
10026 memset(&sta, 0, sizeof(sta));
10027
10028 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10029 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10030 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10031
10032 sta.cli_Active=true;
10033
10034 (clients_connect_cb)(ctrl->ssid_index, &sta);
10035 goto handled;
10036 }
10037
10038 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10039 if (!(str = index(ctrl->reply, ' ')))
10040 return;
10041
10042 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10043 goto handled;
10044 }
10045
10046 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10047 printf("CTRL_WPA: handle TERMINATING event\n");
10048 goto retry;
10049 }
10050
10051 if (strncmp("AP-DISABLED", str, 11) == 0) {
10052 printf("CTRL_WPA: handle AP-DISABLED\n");
10053 goto retry;
10054 }
10055
10056 printf("Event not supported!!\n");
10057
10058handled:
10059
10060 if ((drops = ctrl_get_drops(ctrl))) {
10061 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10062 if (ctrl->overrun)
10063 ctrl->overrun(ctrl);
10064 }
10065
10066 return;
10067
10068retry:
10069 printf("WPA_CTRL: closing\n");
10070 ctrl_close(ctrl);
10071 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10072 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10073}
10074
10075static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10076{
10077 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10078 int err;
10079
10080 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10081 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10082 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10083 ctrl->reply[ctrl->reply_len] = 0;
10084 if (err < 0) {
10085 if (errno == EAGAIN || errno == EWOULDBLOCK)
10086 return;
10087 ctrl_close(ctrl);
10088 ev_timer_again(EV_A_ &ctrl->retry);
10089 return;
10090 }
10091
10092 ctrl_process(ctrl);
10093}
10094
10095static int ctrl_open(struct ctrl *ctrl)
10096{
10097 int fd;
10098
10099 if (ctrl->wpa)
10100 return 0;
10101
10102 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10103 if (!ctrl->wpa)
10104 goto err;
10105
10106 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10107 goto err_close;
10108
10109 fd = wpa_ctrl_get_fd(ctrl->wpa);
10110 if (fd < 0)
10111 goto err_detach;
10112
10113 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10114 goto err_detach;
10115
10116 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10117 ev_io_start(EV_DEFAULT_ &ctrl->io);
10118
10119 return 0;
10120
10121err_detach:
10122 wpa_ctrl_detach(ctrl->wpa);
10123err_close:
10124 wpa_ctrl_close(ctrl->wpa);
10125err:
10126 ctrl->wpa = NULL;
10127 return -1;
10128}
10129
10130static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10131{
10132 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10133
10134 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10135 ctrl_open(ctrl);
10136}
10137
10138static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10139{
10140 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10141
10142 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10143 if (ctrl_open(ctrl) == 0) {
10144 printf("WPA_CTRL: retry successful\n");
10145 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10146 }
10147}
10148
10149int ctrl_enable(struct ctrl *ctrl)
10150{
10151 if (ctrl->wpa)
10152 return 0;
10153
10154 if (!ctrl->stat.cb) {
10155 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10156 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10157 }
10158
10159 if (!ctrl->retry.cb) {
10160 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10161 }
10162
10163 return ctrl_open(ctrl);
10164}
10165
10166static void
10167ctrl_msg_cb(char *buf, size_t len)
10168{
10169 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10170
10171 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10172 ctrl_process(ctrl);
10173}
10174
10175static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10176{
10177 int err;
10178
10179 if (!ctrl->wpa)
10180 return -1;
10181 if (*reply_len < 2)
10182 return -1;
10183
10184 (*reply_len)--;
10185 ctrl->reply_len = sizeof(ctrl->reply);
10186 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10187 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10188 if (err < 0)
10189 return err;
10190
10191 if (ctrl->reply_len > *reply_len)
10192 ctrl->reply_len = *reply_len;
10193
10194 *reply_len = ctrl->reply_len;
10195 memcpy(reply, ctrl->reply, *reply_len);
10196 reply[*reply_len - 1] = 0;
10197 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10198 return 0;
10199}
10200
10201static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10202{
10203 const char *pong = "PONG";
10204 const char *ping = "PING";
10205 char reply[1024];
10206 size_t len = sizeof(reply);
10207 int err;
10208 ULONG s, snum;
10209 INT ret;
10210 BOOL status;
10211
10212 printf("WPA_CTRL: watchdog cb\n");
10213
10214 ret = wifi_getSSIDNumberOfEntries(&snum);
10215 if (ret != RETURN_OK) {
10216 printf("%s: failed to get SSID count", __func__);
10217 return;
10218 }
10219
10220 if (snum > MAX_APS) {
10221 printf("more ssid than supported! %lu\n", snum);
10222 return;
10223 }
10224
10225 for (s = 0; s < snum; s++) {
10226 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10227 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10228 continue;
10229 }
10230 if (status == false) continue;
10231
10232 memset(reply, 0, sizeof(reply));
10233 len = sizeof(reply);
10234 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10235 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10236 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10237 continue;
10238
10239 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10240 ctrl_close(&wpa_ctrl[s]);
10241 printf("WPA_CTRL: ev_timer_again %d\n", s);
10242 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10243 }
10244}
10245
10246static int init_wpa()
10247{
10248 int ret = 0, i = 0;
10249 ULONG s, snum;
10250
10251 ret = wifi_getSSIDNumberOfEntries(&snum);
10252 if (ret != RETURN_OK) {
10253 printf("%s: failed to get SSID count", __func__);
10254 return RETURN_ERR;
10255 }
10256
10257 if (snum > MAX_APS) {
10258 printf("more ssid than supported! %lu\n", snum);
10259 return RETURN_ERR;
10260 }
10261
10262 for (s = 0; s < snum; s++) {
10263 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10264 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10265 wpa_ctrl[s].ssid_index = s;
10266 ctrl_enable(&wpa_ctrl[s]);
10267 }
10268
10269 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10270 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10271
10272 initialized = 1;
10273 printf("WPA_CTRL: initialized\n");
10274
10275 return RETURN_OK;
10276}
10277
10278void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10279{
10280 clients_connect_cb = callback_proc;
10281 if (!initialized)
10282 init_wpa();
10283}
10284
10285void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10286{
10287 clients_disconnect_cb = callback_proc;
10288 if (!initialized)
10289 init_wpa();
10290}
10291
10292INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10293{
10294 // TODO Implement me!
10295 return RETURN_ERR;
10296}
10297
10298INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10299{
10300 // TODO Implement me!
10301 return RETURN_ERR;
10302}
10303
10304INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10305{
10306 int i;
10307 char cmd[256];
10308 char channel_numbers_buf[256];
10309 char dfs_state_buf[256];
10310 char line[256];
10311 const char *ptr;
10312
10313 memset(cmd, 0, sizeof(cmd));
10314 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10315 memset(line, 0, sizeof(line));
10316 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10317 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10318
10319 if (radioIndex == 0) { // 2.4G - all allowed
10320 if (outputMapSize < 11) {
10321 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10322 return RETURN_ERR;
10323 }
10324
10325 for (i = 0; i < 11; i++) {
10326 outputMap[i].ch_number = i + 1;
10327 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10328 }
10329
10330 return RETURN_OK;
10331 }
10332
10333 if (radioIndex == 1) { // 5G
10334// Example output of iw list:
10335//
10336// Frequencies:
10337// * 5180 MHz [36] (17.0 dBm)
10338// * 5200 MHz [40] (17.0 dBm)
10339// * 5220 MHz [44] (17.0 dBm)
10340// * 5240 MHz [48] (17.0 dBm)
10341// * 5260 MHz [52] (23.0 dBm) (radar detection)
10342// DFS state: usable (for 78930 sec)
10343// DFS CAC time: 60000 ms
10344// * 5280 MHz [56] (23.0 dBm) (radar detection)
10345// DFS state: usable (for 78930 sec)
10346// DFS CAC time: 60000 ms
10347// * 5300 MHz [60] (23.0 dBm) (radar detection)
10348// DFS state: usable (for 78930 sec)
10349// DFS CAC time: 60000 ms
10350// * 5320 MHz [64] (23.0 dBm) (radar detection)
10351// DFS state: usable (for 78930 sec)
10352// DFS CAC time: 60000 ms
10353// * 5500 MHz [100] (disabled)
10354// * 5520 MHz [104] (disabled)
10355// * 5540 MHz [108] (disabled)
10356// * 5560 MHz [112] (disabled)
10357//
10358// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10359 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10360 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10361 return RETURN_ERR;
10362 }
10363
10364 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10365 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10366 return RETURN_ERR;
10367 }
10368
10369 ptr = channel_numbers_buf;
10370 i = 0;
10371 while (ptr = get_line_from_str_buf(ptr, line)) {
10372 if (i >= outputMapSize) {
10373 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10374 return RETURN_ERR;
10375 }
10376 sscanf(line, "%d", &outputMap[i].ch_number);
10377
10378 memset(cmd, 0, sizeof(cmd));
10379 // Below command should fetch string for DFS state (usable, available or unavailable)
10380 // Example line: "DFS state: usable (for 78930 sec)"
10381 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) {
10382 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10383 return RETURN_ERR;
10384 }
10385
10386 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10387 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10388 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10389 return RETURN_ERR;
10390 }
10391
10392 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10393
10394 if (!strcmp(dfs_state_buf, "usable")) {
10395 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10396 } else if (!strcmp(dfs_state_buf, "available")) {
10397 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10398 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10399 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10400 } else {
10401 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10402 }
10403 i++;
10404 }
10405
10406 return RETURN_OK;
10407 }
10408
10409 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10410 return RETURN_ERR;
10411}
10412
10413INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10414{
10415 // TODO Implement me!
10416 return RETURN_ERR;
10417}
10418
10419INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10420{
10421 return RETURN_OK;
10422}
10423
10424INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10425{
10426 // TODO Implement me!
10427 return RETURN_ERR;
10428}
10429
10430INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10431{
10432 // TODO API refrence Implementaion is present on RPI hal
10433 return RETURN_ERR;
10434}
10435
10436INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10437{
developera5005b62022-09-13 15:43:35 +080010438 char cmd[128]={'\0'};
10439 char buf[128]={'\0'};
10440 char *support;
10441 int maximum_tx = 0, current_tx = 0;
10442
10443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10444 if(txpwr_pcntg == NULL)
10445 return RETURN_ERR;
10446
10447 // Get the maximum tx power of the device
10448 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10449 _syscmd(cmd, buf, sizeof(buf));
10450 maximum_tx = strtol(buf, NULL, 10);
10451
10452 // Get the current tx power
10453 memset(cmd, 0, sizeof(cmd));
10454 memset(buf, 0, sizeof(buf));
10455 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10456 _syscmd(cmd, buf, sizeof(buf));
10457 current_tx = strtol(buf, NULL, 10);
10458
10459 // Get the power supported list and find the current power percentage in supported list
10460 memset(buf, 0, sizeof(buf));
10461 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10462 support = strtok(buf, ",");
10463 while(true)
10464 {
10465 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10466 *txpwr_pcntg = 0;
10467 wifi_dbg_printf("current power is not in supported list\n");
10468 return RETURN_ERR;
10469 }
10470 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10471 if (tmp == current_tx) {
10472 *txpwr_pcntg = strtol(support, NULL, 10);
10473 break;
10474 }
10475 support = strtok(NULL, ",");
10476 }
10477 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010478 return RETURN_OK;
10479}
10480
10481INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10482{
developer58599c22022-09-13 16:40:34 +080010483 // TODO precac feature.
10484 struct params params = {0};
10485 char config_file[128] = {0};
10486
10487 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10488
10489 params.name = "enable_background_radar";
10490 params.value = enable?"1":"0";
10491 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10492 wifi_hostapdWrite(config_file, &params, 1);
10493 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10494
10495 /* TODO precac feature */
10496
10497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10498 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010499}
10500
10501INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10502{
developer58599c22022-09-13 16:40:34 +080010503 char config_file[128] = {0};
10504 char buf[64] = {0};
10505
10506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10507 if (NULL == enable || NULL == precac)
10508 return RETURN_ERR;
10509
10510 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10511 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10512 if (strncmp(enable, "1", 1) == 0)
10513 *enable = true;
10514 else
10515 *enable = false;
10516
10517 /* TODO precac feature */
10518
10519 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10520 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010521}
10522
10523INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10524{
developer58599c22022-09-13 16:40:34 +080010525 *supported = TRUE;
10526 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010527}
10528
developer3e6b1692022-09-30 18:04:05 +080010529INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10530{
10531 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10532 struct params params = {0};
10533 char config_file[64] = {0};
10534 char buf[64] = {0};
10535 unsigned int set_mu_type = 0;
10536 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10537
10538 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10539 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10540
10541 if (strlen(buf) > 0)
10542 set_mu_type = strtol(buf, NULL, 10);
10543
10544 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10545 set_mu_type &= ~0x05; // unset bit 0, 2
10546 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10547 set_mu_type |= 0x01;
10548 set_mu_type &= ~0x04;
10549 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10550 set_mu_type &= ~0x01;
10551 set_mu_type |= 0x04;
10552 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10553 set_mu_type |= 0x05; // set bit 0, 2
10554 }
10555
10556 params.name = "hemu_onoff";
10557 sprintf(buf, "%u", set_mu_type);
10558 params.value = buf;
10559 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10560 wifi_hostapdWrite(config_file, &params, 1);
10561 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10562
10563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10564 return RETURN_OK;
10565}
10566
10567INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10568{
10569 struct params params={0};
10570 char config_file[64] = {0};
10571 char buf[64] = {0};
10572 unsigned int get_mu_type = 0;
10573
10574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10575
10576 if (mu_type == NULL)
10577 return RETURN_ERR;
10578
10579 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10580 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10581 get_mu_type = strtol(buf, NULL, 10);
10582
10583 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10584 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10585 else if (get_mu_type & 0x04)
10586 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10587 else if (get_mu_type & 0x01)
10588 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10589 else
10590 *mu_type = WIFI_DL_MU_TYPE_NONE;
10591
10592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10593 return RETURN_OK;
10594}
10595
10596INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10597{
10598 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10599 struct params params={0};
10600 char config_file[64] = {0};
10601 char buf[64] = {0};
10602 unsigned int set_mu_type = 0;
10603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10604
10605 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10606 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10607
10608 if (strlen(buf) > 0)
10609 set_mu_type = strtol(buf, NULL, 10);
10610
10611 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10612 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10613 set_mu_type &= ~0x0a;
10614 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10615 set_mu_type |= 0x02;
10616 set_mu_type &= ~0x08;
10617 }
10618
10619 params.name = "hemu_onoff";
10620 sprintf(buf, "%u", set_mu_type);
10621 params.value = buf;
10622 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10623 wifi_hostapdWrite(config_file, &params, 1);
10624 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10625
10626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10627 return RETURN_OK;
10628}
10629
10630INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10631{
10632 struct params params={0};
10633 char config_file[64] = {0};
10634 char buf[64] = {0};
10635 unsigned int get_mu_type = 0;
10636
10637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10638
10639 if (mu_type == NULL)
10640 return RETURN_ERR;
10641
10642 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10643 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10644
10645 get_mu_type = strtol(buf, NULL, 10);
10646 if (get_mu_type & 0x02)
10647 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10648 else
10649 *mu_type = WIFI_DL_MU_TYPE_NONE;
10650
10651 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10652 return RETURN_OK;
10653}
10654
10655
developer454b9462022-09-13 15:29:16 +080010656INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10657{
10658 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010659 char buf[256] = {0};
10660 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010661 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010662 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010663 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010664 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010665
10666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10667
developer254882b2022-09-30 17:12:31 +080010668 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010669 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10670 return RETURN_ERR;
10671 }
developer454b9462022-09-13 15:29:16 +080010672
developer254882b2022-09-30 17:12:31 +080010673 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010674 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010675
developer254882b2022-09-30 17:12:31 +080010676 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10677 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
10678 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
10679 _syscmd(cmd, buf, sizeof(buf));
10680 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10681 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10682 if (strstr(buf, "[SHORT-GI-") == NULL) {
10683 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
10684 _syscmd(cmd, buf, sizeof(buf));
10685 }
10686 if (band == band_5) {
10687 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10688 if (strstr(buf, "[SHORT-GI-") == NULL) {
10689 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
10690 _syscmd(cmd, buf, sizeof(buf));
10691 }
10692 }
10693 }
10694 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010695
developer254882b2022-09-30 17:12:31 +080010696 if (guard_interval == wifi_guard_interval_400)
10697 strcpy(GI, "0.4");
10698 else if (guard_interval == wifi_guard_interval_800)
10699 strcpy(GI, "0.8");
10700 else if (guard_interval == wifi_guard_interval_1600)
10701 strcpy(GI, "1.6");
10702 else if (guard_interval == wifi_guard_interval_3200)
10703 strcpy(GI, "3.2");
10704 else if (guard_interval == wifi_guard_interval_auto)
10705 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010706 // Record GI for get GI function
10707 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10708 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010709 if (f == NULL)
10710 return RETURN_ERR;
10711 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010712 fclose(f);
10713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10714 return RETURN_OK;
10715}
10716
10717INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10718{
10719 char buf[32] = {0};
10720 char cmd[64] = {0};
10721
10722 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10723
10724 if (guard_interval == NULL)
10725 return RETURN_ERR;
10726
10727 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10728 _syscmd(cmd, buf, sizeof(buf));
10729
10730 if (strncmp(buf, "0.4", 3) == 0)
10731 *guard_interval = wifi_guard_interval_400;
10732 else if (strncmp(buf, "0.8", 3) == 0)
10733 *guard_interval = wifi_guard_interval_800;
10734 else if (strncmp(buf, "1.6", 3) == 0)
10735 *guard_interval = wifi_guard_interval_1600;
10736 else if (strncmp(buf, "3.2", 3) == 0)
10737 *guard_interval = wifi_guard_interval_3200;
10738 else
10739 *guard_interval = wifi_guard_interval_auto;
10740
10741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10742 return RETURN_OK;
10743}
10744
developer3cc61d12022-09-13 16:36:05 +080010745INT wifi_setBSSColor(INT radio_index, UCHAR color)
10746{
10747 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10748 struct params params = {0};
10749 char config_file[128] = {0};
10750 char bss_color[4] ={0};
10751
10752 params.name = "he_bss_color";
10753 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10754 params.value = bss_color;
10755 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10756 wifi_hostapdWrite(config_file, &params, 1);
10757 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10758
10759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10760 return RETURN_OK;
10761}
10762
10763INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10764{
10765 char config_file[128] = {0};
10766 char buf[64] = {0};
10767 char temp_output[128] = {'\0'};
10768
10769 wifi_dbg_printf("\nFunc=%s\n", __func__);
10770 if (NULL == color)
10771 return RETURN_ERR;
10772
10773 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10774 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10775
10776 if(strlen(buf) > 0) {
10777 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10778 } else {
10779 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10780 }
10781
10782 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10783 wifi_dbg_printf("\noutput_string=%s\n", color);
10784
10785 return RETURN_OK;
10786}
10787
developer06a01d92022-09-07 16:32:39 +080010788/* multi-psk support */
10789INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10790{
10791 char cmd[256];
10792
10793 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10794 AP_PREFIX,
10795 apIndex,
10796 mac[0],
10797 mac[1],
10798 mac[2],
10799 mac[3],
10800 mac[4],
10801 mac[5]
10802 );
10803 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10804 _syscmd(cmd, key->wifi_keyId, 64);
10805
10806
10807 return RETURN_OK;
10808}
10809
10810INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10811{
10812 FILE *fd = NULL;
10813 char fname[100];
10814 char cmd[128] = {0};
10815 char out[64] = {0};
10816 wifi_key_multi_psk_t * key = NULL;
10817 if(keysNumber < 0)
10818 return RETURN_ERR;
10819
10820 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10821 fd = fopen(fname, "w");
10822 if (!fd) {
10823 return RETURN_ERR;
10824 }
10825 key= (wifi_key_multi_psk_t *) keys;
10826 for(int i=0; i<keysNumber; ++i, key++) {
10827 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10828 }
10829 fclose(fd);
10830
10831 //reload file
10832 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10833 _syscmd(cmd, out, 64);
10834 return RETURN_OK;
10835}
10836
10837INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10838{
10839 FILE *fd = NULL;
10840 char fname[100];
10841 char * line = NULL;
10842 char * pos = NULL;
10843 size_t len = 0;
10844 ssize_t read = 0;
10845 INT ret = RETURN_OK;
10846 wifi_key_multi_psk_t *keys_it = NULL;
10847
10848 if (keysNumber < 1) {
10849 return RETURN_ERR;
10850 }
10851
10852 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10853 fd = fopen(fname, "r");
10854 if (!fd) {
10855 return RETURN_ERR;
10856 }
10857
10858 if (keys == NULL) {
10859 ret = RETURN_ERR;
10860 goto close;
10861 }
10862
10863 keys_it = keys;
10864 while ((read = getline(&line, &len, fd)) != -1) {
10865 //Strip trailing new line if present
10866 if (read > 0 && line[read-1] == '\n') {
10867 line[read-1] = '\0';
10868 }
10869
10870 if(strcmp(line,"keyid=")) {
10871 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10872 if (!(pos = index(line, ' '))) {
10873 ret = RETURN_ERR;
10874 goto close;
10875 }
10876 pos++;
10877 //Here should be 00:00:00:00:00:00
10878 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10879 printf("Not supported MAC: %s\n", pos);
10880 }
10881 if (!(pos = index(pos, ' '))) {
10882 ret = RETURN_ERR;
10883 goto close;
10884 }
10885 pos++;
10886
10887 //The rest is PSK
10888 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10889 keys_it++;
10890
10891 if(--keysNumber <= 0)
10892 break;
10893 }
10894 }
10895
10896close:
10897 free(line);
10898 fclose(fd);
10899 return ret;
10900}
10901/* end of multi-psk support */
10902
10903INT wifi_setNeighborReports(UINT apIndex,
10904 UINT numNeighborReports,
10905 wifi_NeighborReport_t *neighborReports)
10906{
10907 char cmd[256] = { 0 };
10908 char hex_bssid[13] = { 0 };
10909 char bssid[18] = { 0 };
10910 char nr[256] = { 0 };
10911 char ssid[256];
10912 char hex_ssid[256];
10913 INT ret;
10914
10915 /*rmeove all neighbors*/
10916 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10917 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);
10918 system(cmd);
10919
10920 for(unsigned int i = 0; i < numNeighborReports; i++)
10921 {
10922 memset(ssid, 0, sizeof(ssid));
10923 ret = wifi_getSSIDName(apIndex, ssid);
10924 if (ret != RETURN_OK)
10925 return RETURN_ERR;
10926
10927 memset(hex_ssid, 0, sizeof(hex_ssid));
10928 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10929 sprintf(hex_ssid + k,"%02x", ssid[j]);
10930
10931 snprintf(hex_bssid, sizeof(hex_bssid),
10932 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10933 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10934 snprintf(bssid, sizeof(bssid),
10935 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10936 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10937
10938 snprintf(nr, sizeof(nr),
10939 "%s" // bssid
10940 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10941 "%02hhx" // operclass
10942 "%02hhx" // channel
10943 "%02hhx", // phy_mode
10944 hex_bssid,
10945 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10946 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10947 neighborReports[i].opClass,
10948 neighborReports[i].channel,
10949 neighborReports[i].phyTable);
10950
10951 snprintf(cmd, sizeof(cmd),
10952 "hostapd_cli set_neighbor "
10953 "%s " // bssid
10954 "ssid=%s " // ssid
10955 "nr=%s " // nr
10956 "-i %s%d",
10957 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10958
10959 if (WEXITSTATUS(system(cmd)) != 0)
10960 {
10961 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10962 }
10963 }
10964
10965 return RETURN_OK;
10966}
10967
10968INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10969{
10970 return RETURN_OK;
10971}
10972
10973#ifdef _WIFI_HAL_TEST_
10974int main(int argc,char **argv)
10975{
10976 int index;
10977 INT ret=0;
10978 char buf[1024]="";
10979
10980 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10981 if(argc<3)
10982 {
10983 if(argc==2)
10984 {
10985 if(!strcmp(argv[1], "init"))
10986 return wifi_init();
10987 if(!strcmp(argv[1], "reset"))
10988 return wifi_reset();
10989 if(!strcmp(argv[1], "wifi_getHalVersion"))
10990 {
10991 char buffer[64];
10992 if(wifi_getHalVersion(buffer)==RETURN_OK)
10993 printf("Version: %s\n", buffer);
10994 else
10995 printf("Error in wifi_getHalVersion\n");
10996 return RETURN_OK;
10997 }
10998 }
10999 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11000 exit(-1);
11001 }
11002
11003 index = atoi(argv[2]);
11004 if(strstr(argv[1], "wifi_getApName")!=NULL)
11005 {
11006 wifi_getApName(index,buf);
11007 printf("Ap name is %s \n",buf);
11008 return 0;
11009 }
11010 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11011 {
11012 BOOL b = FALSE;
11013 BOOL *output_bool = &b;
11014 wifi_getRadioAutoChannelEnable(index,output_bool);
11015 printf("Channel enabled = %d \n",b);
11016 return 0;
11017 }
11018 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11019 {
11020 wifi_getApWpaEncryptionMode(index,buf);
11021 printf("encryption enabled = %s\n",buf);
11022 return 0;
11023 }
11024 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11025 {
11026 BOOL b = FALSE;
11027 BOOL *output_bool = &b;
11028 wifi_getApSsidAdvertisementEnable(index,output_bool);
11029 printf("advertisment enabled = %d\n",b);
11030 return 0;
11031 }
11032 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11033 {
11034 if(argc <= 3 )
11035 {
11036 printf("Insufficient arguments \n");
11037 exit(-1);
11038 }
11039
11040 char sta[20] = {'\0'};
11041 ULLONG handle= 0;
11042 strcpy(sta,argv[3]);
11043 mac_address_t st;
11044 mac_addr_aton(st,sta);
11045
11046 wifi_associated_dev_tid_stats_t tid_stats;
11047 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11048 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11049 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);
11050 }
11051
11052 if(strstr(argv[1], "getApEnable")!=NULL) {
11053 BOOL enable;
11054 ret=wifi_getApEnable(index, &enable);
11055 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11056 }
11057 else if(strstr(argv[1], "setApEnable")!=NULL) {
11058 BOOL enable = atoi(argv[3]);
11059 ret=wifi_setApEnable(index, enable);
11060 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11061 }
11062 else if(strstr(argv[1], "getApStatus")!=NULL) {
11063 char status[64];
11064 ret=wifi_getApStatus(index, status);
11065 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11066 }
11067 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11068 {
11069 wifi_getSSIDNameStatus(index,buf);
11070 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11071 return 0;
11072 }
11073 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11074 wifi_ssidTrafficStats2_t stats={0};
11075 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11076 printf("%s %d: returns %d\n", argv[1], index, ret);
11077 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11078 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11079 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11080 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11081 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11082 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11083 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11084 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11085 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11086 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11087 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11088 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11089 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11090 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11091 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11092 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11093 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11094 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11095 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11096 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11097 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11098 }
11099 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11100 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11101 UINT array_size=0;
11102 UINT i=0;
11103 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11104 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11105 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11106 printf(" neighbor %d:\n", i);
11107 printf(" ap_SSID =%s\n", pt->ap_SSID);
11108 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11109 printf(" ap_Mode =%s\n", pt->ap_Mode);
11110 printf(" ap_Channel =%d\n", pt->ap_Channel);
11111 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11112 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11113 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11114 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11115 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11116 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11117 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11118 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11119 printf(" ap_Noise =%d\n", pt->ap_Noise);
11120 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11121 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11122 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11123 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11124 }
11125 if(neighbor_ap_array)
11126 free(neighbor_ap_array); //make sure to free the list
11127 }
11128 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11129 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11130 UINT array_size=0;
11131 UINT i=0;
11132 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11133 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11134 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11135 printf(" associated_dev %d:\n", i);
11136 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11137 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11138 printf(" cli_SNR =%d\n", pt->cli_SNR);
11139 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11140 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11141 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11142 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11143 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11144 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11145 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11146 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11147 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11148 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11149 }
11150 if(associated_dev_array)
11151 free(associated_dev_array); //make sure to free the list
11152 }
11153
11154 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11155 {
11156#define MAX_ARRAY_SIZE 64
11157 int i, array_size;
11158 char *p, *ch_str;
11159 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11160
11161 if(argc != 5)
11162 {
11163 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11164 exit(-1);
11165 }
11166 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11167
11168 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11169 {
11170 strtok_r(ch_str, ",", &p);
11171 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11172 }
11173 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11174 if(!array_size)
11175 array_size=1;//Need to print current channel statistics
11176 for(i=0; i<array_size; i++)
11177 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11178 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11179 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11180 input_output_channelStats_array[i].ch_number,\
11181 input_output_channelStats_array[i].ch_noise,\
11182 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11183 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11184 input_output_channelStats_array[i].ch_utilization_busy,\
11185 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11186 input_output_channelStats_array[i].ch_utilization_total);
11187 }
11188
11189 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11190 {
11191 if(argc <= 3 )
11192 {
11193 printf("Insufficient arguments \n");
11194 exit(-1);
11195 }
11196 char mac_addr[20] = {'\0'};
11197 wifi_device_t output_struct;
11198 int dev_index = atoi(argv[3]);
11199
11200 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11201 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11202 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);
11203 }
11204
11205 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11206 {
11207 if (argc <= 3)
11208 {
11209 printf("Insufficient arguments\n");
11210 exit(-1);
11211 }
11212 char args[256];
11213 wifi_NeighborReport_t *neighborReports;
11214
11215 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11216 if (!neighborReports)
11217 {
11218 printf("Failed to allocate memory");
11219 exit(-1);
11220 }
11221
11222 for (int i = 3; i < argc; ++i)
11223 {
11224 char *val;
11225 int j = 0;
11226 memset(args, 0, sizeof(args));
11227 strncpy(args, argv[i], sizeof(args));
11228 val = strtok(args, ";");
11229 while (val != NULL)
11230 {
11231 if (j == 0)
11232 {
11233 mac_addr_aton(neighborReports[i - 3].bssid, val);
11234 } else if (j == 1)
11235 {
11236 neighborReports[i - 3].info = strtol(val, NULL, 16);
11237 } else if (j == 2)
11238 {
11239 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11240 } else if (j == 3)
11241 {
11242 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11243 } else if (j == 4)
11244 {
11245 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11246 } else {
11247 printf("Insufficient arguments]n\n");
11248 exit(-1);
11249 }
11250 val = strtok(NULL, ";");
11251 j++;
11252 }
11253 }
11254
11255 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11256 if (ret != RETURN_OK)
11257 {
11258 printf("wifi_setNeighborReports ret = %d", ret);
11259 exit(-1);
11260 }
11261 }
11262 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11263 {
11264 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11265 printf("%s.\n", buf);
11266 else
11267 printf("Error returned\n");
11268 }
11269 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11270 {
11271 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11272 printf("%s.\n", buf);
11273 else
11274 printf("Error returned\n");
11275 }
11276 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11277 {
11278 if (argc <= 2)
11279 {
11280 printf("Insufficient arguments\n");
11281 exit(-1);
11282 }
11283 char buf[64]= {'\0'};
11284 wifi_getRadioOperatingChannelBandwidth(index,buf);
11285 printf("Current bandwidth is %s \n",buf);
11286 return 0;
11287 }
11288 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11289 {
11290 if (argc <= 5)
11291 {
11292 printf("Insufficient arguments\n");
11293 exit(-1);
11294 }
11295 UINT channel = atoi(argv[3]);
11296 UINT width = atoi(argv[4]);
11297 UINT beacon = atoi(argv[5]);
11298 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11299 printf("Result = %d", ret);
11300 }
11301
11302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11303 return 0;
11304}
11305
11306#endif
11307
11308#ifdef WIFI_HAL_VERSION_3
11309
developer1e5aa162022-09-13 16:06:24 +080011310INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11311{
11312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11313 if (bitMap & WIFI_BITRATE_1MBPS)
11314 strcat(BasicRate, "1,");
11315 if (bitMap & WIFI_BITRATE_2MBPS)
11316 strcat(BasicRate, "2,");
11317 if (bitMap & WIFI_BITRATE_5_5MBPS)
11318 strcat(BasicRate, "5.5,");
11319 if (bitMap & WIFI_BITRATE_6MBPS)
11320 strcat(BasicRate, "6,");
11321 if (bitMap & WIFI_BITRATE_9MBPS)
11322 strcat(BasicRate, "9,");
11323 if (bitMap & WIFI_BITRATE_11MBPS)
11324 strcat(BasicRate, "11,");
11325 if (bitMap & WIFI_BITRATE_12MBPS)
11326 strcat(BasicRate, "12,");
11327 if (bitMap & WIFI_BITRATE_18MBPS)
11328 strcat(BasicRate, "18,");
11329 if (bitMap & WIFI_BITRATE_24MBPS)
11330 strcat(BasicRate, "24,");
11331 if (bitMap & WIFI_BITRATE_36MBPS)
11332 strcat(BasicRate, "36,");
11333 if (bitMap & WIFI_BITRATE_48MBPS)
11334 strcat(BasicRate, "48,");
11335 if (bitMap & WIFI_BITRATE_54MBPS)
11336 strcat(BasicRate, "54,");
11337 if (strlen(BasicRate) != 0) // remove last comma
11338 BasicRate[strlen(BasicRate) - 1] = '\0';
11339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11340 return RETURN_OK;
11341}
11342
11343INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11344{
11345 UINT BitMap = 0;
11346 char *rate;
11347
11348 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11349 rate = strtok(BasicRatesList, ",");
11350 while(rate != NULL)
11351 {
11352 if (strcmp(rate, "1") == 0)
11353 BitMap |= WIFI_BITRATE_1MBPS;
11354 else if (strcmp(rate, "2") == 0)
11355 BitMap |= WIFI_BITRATE_2MBPS;
11356 else if (strcmp(rate, "5.5") == 0)
11357 BitMap |= WIFI_BITRATE_5_5MBPS;
11358 else if (strcmp(rate, "6") == 0)
11359 BitMap |= WIFI_BITRATE_6MBPS;
11360 else if (strcmp(rate, "9") == 0)
11361 BitMap |= WIFI_BITRATE_9MBPS;
11362 else if (strcmp(rate, "11") == 0)
11363 BitMap |= WIFI_BITRATE_11MBPS;
11364 else if (strcmp(rate, "12") == 0)
11365 BitMap |= WIFI_BITRATE_12MBPS;
11366 else if (strcmp(rate, "18") == 0)
11367 BitMap |= WIFI_BITRATE_18MBPS;
11368 else if (strcmp(rate, "24") == 0)
11369 BitMap |= WIFI_BITRATE_24MBPS;
11370 else if (strcmp(rate, "36") == 0)
11371 BitMap |= WIFI_BITRATE_36MBPS;
11372 else if (strcmp(rate, "48") == 0)
11373 BitMap |= WIFI_BITRATE_48MBPS;
11374 else if (strcmp(rate, "54") == 0)
11375 BitMap |= WIFI_BITRATE_54MBPS;
11376 rate = strtok(NULL, ",");
11377 }
11378 *basicRateBitMap = BitMap;
11379 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11380 return RETURN_OK;
11381}
11382
11383// 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 +080011384INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11385{
developer1e5aa162022-09-13 16:06:24 +080011386 char buf[128] = {0};
11387 char cmd[128] = {0};
11388 char config_file[64] = {0};
11389 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011390 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011391 wifi_radio_operationParam_t current_param;
11392
11393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11394
11395 multiple_set = TRUE;
11396 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11397 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11398 return RETURN_ERR;
11399 }
11400 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11401 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11402 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11403 return RETURN_ERR;
11404 }
11405 }
developer5884e982022-10-06 10:52:50 +080011406
11407 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11408 bandwidth = 20;
11409 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11410 bandwidth = 40;
11411 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11412 bandwidth = 80;
11413 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11414 bandwidth = 160;
11415 if (operationParam->autoChannelEnabled){
11416 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11417 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11418 return RETURN_ERR;
11419 }
11420 }else{
developer1e5aa162022-09-13 16:06:24 +080011421 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11422 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11423 return RETURN_ERR;
11424 }
11425 }
developer5884e982022-10-06 10:52:50 +080011426
developer1e5aa162022-09-13 16:06:24 +080011427 if (current_param.variant != operationParam->variant) {
11428 // Two different definition bit map, so need to check every bit.
11429 if (operationParam->variant & WIFI_80211_VARIANT_A)
11430 set_mode |= WIFI_MODE_A;
11431 if (operationParam->variant & WIFI_80211_VARIANT_B)
11432 set_mode |= WIFI_MODE_B;
11433 if (operationParam->variant & WIFI_80211_VARIANT_G)
11434 set_mode |= WIFI_MODE_G;
11435 if (operationParam->variant & WIFI_80211_VARIANT_N)
11436 set_mode |= WIFI_MODE_N;
11437 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11438 set_mode |= WIFI_MODE_AC;
11439 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11440 set_mode |= WIFI_MODE_AX;
11441 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11442 memset(buf, 0, sizeof(buf));
11443 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11444 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11445 return RETURN_ERR;
11446 }
11447 }
11448 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11449 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11450 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11451 return RETURN_ERR;
11452 }
11453 }
11454 if (current_param.beaconInterval != operationParam->beaconInterval) {
11455 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11456 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11457 return RETURN_ERR;
11458 }
11459 }
11460 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11461 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11462 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11463 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11464 return RETURN_ERR;
11465 }
11466 }
11467 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11468 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11469 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11470 return RETURN_ERR;
11471 }
11472 }
11473 if (current_param.guardInterval != operationParam->guardInterval) {
11474 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11475 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11476 return RETURN_ERR;
11477 }
11478 }
11479 if (current_param.transmitPower != operationParam->transmitPower) {
11480 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11481 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11482 return RETURN_ERR;
11483 }
11484 }
11485 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11486 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11487 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11488 return RETURN_ERR;
11489 }
11490 }
11491 if (current_param.obssCoex != operationParam->obssCoex) {
11492 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11493 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11494 return RETURN_ERR;
11495 }
11496 }
11497 if (current_param.stbcEnable != operationParam->stbcEnable) {
11498 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11499 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11500 return RETURN_ERR;
11501 }
11502 }
11503 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11504 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11505 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11506 return RETURN_ERR;
11507 }
11508 }
11509
11510 // if enable is true, then restart the radio
11511 wifi_setRadioEnable(index, FALSE);
11512 if (operationParam->enable == TRUE)
11513 wifi_setRadioEnable(index, TRUE);
11514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11515
developer06a01d92022-09-07 16:32:39 +080011516 return RETURN_OK;
11517}
11518
11519INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11520{
developer1e5aa162022-09-13 16:06:24 +080011521 char band[64] = {0};
11522 char buf[256] = {0};
11523 char config_file[64] = {0};
11524 char cmd[128] = {0};
11525 int ret = RETURN_ERR;
11526 int mode = 0;
11527 ULONG channel = 0;
11528 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011529
11530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11531 printf("Entering %s index = %d\n", __func__, (int)index);
11532
developer1e5aa162022-09-13 16:06:24 +080011533 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11534 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11535 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011536 {
developer1e5aa162022-09-13 16:06:24 +080011537 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011538 return RETURN_ERR;
11539 }
11540 operationParam->enable = enabled;
11541
11542 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011543 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011544 {
developer1e5aa162022-09-13 16:06:24 +080011545 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011546 return RETURN_ERR;
11547 }
11548
11549 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011550 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011551 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011552 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011553 else if (!strcmp(band, "6GHz"))
11554 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011555 else
11556 {
developer1e5aa162022-09-13 16:06:24 +080011557 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011558 band);
11559 }
11560
developer1e5aa162022-09-13 16:06:24 +080011561 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11562 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11563 operationParam->channel = 0;
11564 operationParam->autoChannelEnabled = TRUE;
11565 } else {
11566 operationParam->channel = strtol(buf, NULL, 10);
11567 operationParam->autoChannelEnabled = FALSE;
11568 }
11569
developer06a01d92022-09-07 16:32:39 +080011570 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011571 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11572 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11573 return RETURN_ERR;
11574 }
developer06a01d92022-09-07 16:32:39 +080011575 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11576 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11577 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011578 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11579 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011580 else
11581 {
developer1e5aa162022-09-13 16:06:24 +080011582 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11583 return false;
developer06a01d92022-09-07 16:32:39 +080011584 }
11585
developer1e5aa162022-09-13 16:06:24 +080011586 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11587 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11588 return RETURN_ERR;
11589 }
11590 // Two different definition bit map, so need to check every bit.
11591 if (mode & WIFI_MODE_A)
11592 operationParam->variant |= WIFI_80211_VARIANT_A;
11593 if (mode & WIFI_MODE_B)
11594 operationParam->variant |= WIFI_80211_VARIANT_B;
11595 if (mode & WIFI_MODE_G)
11596 operationParam->variant |= WIFI_80211_VARIANT_G;
11597 if (mode & WIFI_MODE_N)
11598 operationParam->variant |= WIFI_80211_VARIANT_N;
11599 if (mode & WIFI_MODE_AC)
11600 operationParam->variant |= WIFI_80211_VARIANT_AC;
11601 if (mode & WIFI_MODE_AX)
11602 operationParam->variant |= WIFI_80211_VARIANT_AX;
11603 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11604 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11605 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011606 }
developer1e5aa162022-09-13 16:06:24 +080011607 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11608 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11609 return RETURN_ERR;
11610 }
11611 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11612 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11613 return RETURN_ERR;
11614 }
developer06a01d92022-09-07 16:32:39 +080011615
developer1e5aa162022-09-13 16:06:24 +080011616 memset(buf, 0, sizeof(buf));
11617 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11618 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11619 return RETURN_ERR;
11620 }
11621 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11622
11623 memset(buf, 0, sizeof(buf));
11624 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11625 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11626 return RETURN_ERR;
11627 }
11628 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11629
11630 memset(buf, 0, sizeof(buf));
11631 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11632 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11633
11634 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11635 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11636 return RETURN_ERR;
11637 }
11638 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11639 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11640 return RETURN_ERR;
11641 }
11642
11643 memset(buf, 0, sizeof(buf));
11644 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11645 if (strcmp(buf, "-1") == 0) {
11646 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11647 operationParam->ctsProtection = FALSE;
11648 } else {
11649 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11650 operationParam->ctsProtection = TRUE;
11651 }
11652
11653 memset(buf, 0, sizeof(buf));
11654 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11655 if (strcmp(buf, "0") == 0)
11656 operationParam->obssCoex = FALSE;
11657 else
11658 operationParam->obssCoex = TRUE;
11659
11660 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11661 _syscmd(cmd, buf, sizeof(buf));
11662 if (strlen(buf) != 0)
11663 operationParam->stbcEnable = TRUE;
11664 else
11665 operationParam->stbcEnable = FALSE;
11666
11667 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11668 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11669 return RETURN_ERR;
11670 }
11671
11672 // Below value is hardcoded
11673
11674 operationParam->numSecondaryChannels = 0;
11675 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11676 operationParam->channelSecondary[i] = 0;
11677 }
11678 operationParam->csa_beacon_count = 15;
11679 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011680
11681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11682 return RETURN_OK;
11683}
11684
11685static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11686{
developerc086fb72022-10-04 10:18:22 +080011687 int max_radio_num = 0;
11688
11689 wifi_getMaxRadioNumber(&max_radio_num);
11690 if (radioIndex >= max_radio_num || radioIndex < 0) {
11691 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11692 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011693 }
11694
developerc086fb72022-10-04 10:18:22 +080011695 return (arrayIndex * max_radio_num) + radioIndex;
11696}
developer06a01d92022-09-07 16:32:39 +080011697
developerc086fb72022-10-04 10:18:22 +080011698wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11699 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11700 return WIFI_BITRATE_1MBPS;
11701 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11702 return WIFI_BITRATE_2MBPS;
11703 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11704 return WIFI_BITRATE_5_5MBPS;
11705 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11706 return WIFI_BITRATE_6MBPS;
11707 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11708 return WIFI_BITRATE_9MBPS;
11709 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11710 return WIFI_BITRATE_11MBPS;
11711 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11712 return WIFI_BITRATE_12MBPS;
11713 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11714 return WIFI_BITRATE_18MBPS;
11715 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11716 return WIFI_BITRATE_24MBPS;
11717 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11718 return WIFI_BITRATE_36MBPS;
11719 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11720 return WIFI_BITRATE_48MBPS;
11721 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11722 return WIFI_BITRATE_54MBPS;
11723 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011724}
11725
11726INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11727{
developerc086fb72022-10-04 10:18:22 +080011728 INT mode = 0;
11729 INT ret = -1;
11730 INT output = 0;
11731 int i = 0;
11732 int vap_index = 0;
11733 BOOL enabled = FALSE;
11734 char buf[256] = {0};
11735 wifi_vap_security_t security;
11736 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011737
11738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11739 printf("Entering %s index = %d\n", __func__, (int)index);
11740
developer06a01d92022-09-07 16:32:39 +080011741 for (i = 0; i < 5; i++)
11742 {
developerc086fb72022-10-04 10:18:22 +080011743 map->vap_array[i].radio_index = index;
11744
developer06a01d92022-09-07 16:32:39 +080011745 vap_index = array_index_to_vap_index(index, i);
11746 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011747 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011748
developerc086fb72022-10-04 10:18:22 +080011749 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011750
11751 map->vap_array[i].vap_index = vap_index;
11752
11753 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011754 ret = wifi_getApName(vap_index, buf);
11755 if (ret != RETURN_OK) {
11756 printf("%s: wifi_getApName return error\n", __func__);
11757 return RETURN_ERR;
11758 }
11759 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
11760
11761 memset(buf, 0, sizeof(buf));
11762 ret = wifi_getSSIDNameStatus(vap_index, buf);
11763 if (ret != RETURN_OK) {
11764 printf("%s: wifi_getSSIDNameStatus return error\n", __func__);
11765 return RETURN_ERR;
11766 }
11767 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 +080011768
11769 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080011770 if (ret != RETURN_OK) {
11771 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011772 return RETURN_ERR;
11773 }
11774 map->vap_array[i].u.bss_info.enabled = enabled;
11775
developerc086fb72022-10-04 10:18:22 +080011776 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
11777 if (ret != RETURN_OK) {
11778 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
11779 return RETURN_ERR;
11780 }
developer06a01d92022-09-07 16:32:39 +080011781 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080011782
11783 ret = wifi_getApIsolationEnable(vap_index, &enabled);
11784 if (ret != RETURN_OK) {
11785 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
11786 return RETURN_ERR;
11787 }
11788 map->vap_array[i].u.bss_info.isolation = enabled;
11789
11790 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
11791 if (ret != RETURN_OK) {
11792 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
11793 return RETURN_ERR;
11794 }
11795 map->vap_array[i].u.bss_info.bssMaxSta = output;
11796
11797 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
11798 if (ret != RETURN_OK) {
11799 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
11800 return RETURN_ERR;
11801 }
11802 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011803
developerc086fb72022-10-04 10:18:22 +080011804 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
11805 if (ret != RETURN_OK) {
11806 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
11807 return RETURN_ERR;
11808 }
11809 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011810
developerc086fb72022-10-04 10:18:22 +080011811 ret = wifi_getApSecurity(vap_index, &security);
11812 if (ret != RETURN_OK) {
11813 printf("%s: wifi_getApSecurity return error\n", __func__);
11814 return RETURN_ERR;
11815 }
11816 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080011817
developerc086fb72022-10-04 10:18:22 +080011818 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
11819 if (ret != RETURN_OK) {
11820 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
11821 return RETURN_ERR;
11822 }
11823 if (mode == 0)
11824 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
11825 else
11826 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
11827 if (mode == 1)
11828 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11829 else if (mode == 2)
11830 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080011831
developerc086fb72022-10-04 10:18:22 +080011832 ret = wifi_getApWmmEnable(vap_index, &enabled);
11833 if (ret != RETURN_OK) {
11834 printf("%s: wifi_getApWmmEnable return error\n", __func__);
11835 return RETURN_ERR;
11836 }
11837 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011838
developerc086fb72022-10-04 10:18:22 +080011839 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
11840 if (ret != RETURN_OK) {
11841 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011842 return RETURN_ERR;
11843 }
developerc086fb72022-10-04 10:18:22 +080011844 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011845
11846 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011847 ret = wifi_getApBeaconRate(vap_index, buf);
11848 if (ret != RETURN_OK) {
11849 printf("%s: wifi_getApBeaconRate return error\n", __func__);
11850 return RETURN_ERR;
11851 }
11852 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080011853
developerc086fb72022-10-04 10:18:22 +080011854 memset(buf, 0, sizeof(buf));
11855 ret = wifi_getBaseBSSID(vap_index, buf);
11856 if (ret != RETURN_OK) {
11857 printf("%s: wifi_getBaseBSSID return error\n", __func__);
11858 return RETURN_ERR;
11859 }
11860 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11861 &map->vap_array[i].u.bss_info.bssid[0],
11862 &map->vap_array[i].u.bss_info.bssid[1],
11863 &map->vap_array[i].u.bss_info.bssid[2],
11864 &map->vap_array[i].u.bss_info.bssid[3],
11865 &map->vap_array[i].u.bss_info.bssid[4],
11866 &map->vap_array[i].u.bss_info.bssid[5]);
developer06a01d92022-09-07 16:32:39 +080011867
developerc086fb72022-10-04 10:18:22 +080011868 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080011869 }
11870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11871 return RETURN_OK;
11872}
11873
11874INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11875{
11876 unsigned int i;
11877 wifi_vap_info_t *vap_info = NULL;
11878 int acl_mode;
11879 char *sec_str = NULL;
11880
11881 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11882 printf("Entering %s index = %d\n", __func__, (int)index);
11883 for (i = 0; i < map->num_vaps; i++)
11884 {
11885 vap_info = &map->vap_array[i];
11886 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11887
11888 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11889 else
11890 {
11891 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11892 else acl_mode = 1;
11893 }
11894 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11895 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11896 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11897
11898 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11899 if (sec_str)
11900 {
11901 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11902 }
11903 else
11904 {
11905 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11906 }
11907
11908 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11909 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11910
11911 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11912 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11913
11914 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11915
11916 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11917 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11918 }
11919 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11920 return RETURN_OK;
11921}
11922
11923int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11924{
11925 char *token, *next;
11926 const char s[2] = ",";
11927 int count =0;
11928
11929 /* get the first token */
11930 token = strtok_r(pchannels, s, &next);
11931
11932 /* walk through other tokens */
11933 while( token != NULL && count < MAX_CHANNELS) {
11934 chlistptr->channels_list[count++] = atoi(token);
11935 token = strtok_r(NULL, s, &next);
11936 }
11937
11938 return count;
11939}
11940
11941static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11942{
11943 INT status;
11944 wifi_channels_list_t *chlistp;
11945 CHAR output_string[64];
11946 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011947 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011948
11949 if(rcap == NULL)
11950 {
11951 return RETURN_ERR;
11952 }
11953
11954 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011955 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011956
developer1e5aa162022-09-13 16:06:24 +080011957 if (band == band_2_4)
11958 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11959 else if (band == band_5)
11960 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11961 else if (band == band_6)
11962 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011963
11964 chlistp = &(rcap->channel_list[0]);
11965 memset(pchannels, 0, sizeof(pchannels));
11966
11967 /* possible number of radio channels */
11968 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11969 {
11970 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11971 }
11972 /* Number of channels and list*/
11973 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11974
11975 /* autoChannelSupported */
11976 /* always ON with wifi_getRadioAutoChannelSupported */
11977 rcap->autoChannelSupported = TRUE;
11978
11979 /* DCSSupported */
11980 /* always ON with wifi_getRadioDCSSupported */
11981 rcap->DCSSupported = TRUE;
11982
11983 /* zeroDFSSupported - TBD */
11984 rcap->zeroDFSSupported = FALSE;
11985
11986 /* Supported Country List*/
11987 memset(output_string, 0, sizeof(output_string));
11988 status = wifi_getRadioCountryCode(radioIndex, output_string);
11989 if( status != 0 ) {
11990 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11991 return RETURN_ERR;
11992 } else {
11993 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11994 }
11995 if(!strcmp(output_string,"US")){
11996 rcap->countrySupported[0] = wifi_countrycode_US;
11997 rcap->countrySupported[1] = wifi_countrycode_CA;
11998 } else if (!strcmp(output_string,"CA")) {
11999 rcap->countrySupported[0] = wifi_countrycode_CA;
12000 rcap->countrySupported[1] = wifi_countrycode_US;
12001 } else {
12002 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12003 }
12004
12005 rcap->numcountrySupported = 2;
12006
12007 /* csi */
12008 rcap->csi.maxDevices = 8;
12009 rcap->csi.soudingFrameSupported = TRUE;
12010
12011 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
12012
12013 /* channelWidth - all supported bandwidths */
12014 int i=0;
12015 rcap->channelWidth[i] = 0;
12016 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12017 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12018 WIFI_CHANNELBANDWIDTH_40MHZ);
12019
12020 }
developer1e5aa162022-09-13 16:06:24 +080012021 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012022 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12023 WIFI_CHANNELBANDWIDTH_40MHZ |
12024 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12025 }
12026
12027
12028 /* mode - all supported variants */
12029 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12030 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012031 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 +080012032 }
12033 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012034 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12035 }
12036 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12037 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012038 }
12039 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12040 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12041
12042 /* supportedBitRate - all supported bitrates */
12043 rcap->supportedBitRate[i] = 0;
12044 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12045 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12046 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12047 }
developer1e5aa162022-09-13 16:06:24 +080012048 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012049 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12050 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12051 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12052 }
12053
12054
12055 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12056 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12057 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12058 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12059 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12060 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12061 rcap->cipherSupported = 0;
12062 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12063 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12064
12065 return RETURN_OK;
12066}
12067
12068INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12069{
12070 INT status, radioIndex;
12071 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12072 int iter = 0;
12073 unsigned int j;
12074 wifi_interface_name_idex_map_t *iface_info;
12075
12076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12077
12078 memset(cap, 0, sizeof(wifi_hal_capability_t));
12079
12080 /* version */
12081 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12082 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12083
12084 /* number of radios platform property */
12085 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12086 _syscmd(cmd, output, sizeof(output));
12087 cap->wifi_prop.numRadios = atoi(output);
12088
12089 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12090 {
12091 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12092 if (status != 0) {
12093 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12094 return RETURN_ERR;
12095 }
12096
12097 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12098 {
12099 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12100 {
12101 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12102 return RETURN_ERR;
12103 }
12104 iface_info = &cap->wifi_prop.interface_map[iter];
12105 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12106 iface_info->rdk_radio_index = radioIndex;
12107 memset(output, 0, sizeof(output));
12108 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12109 {
12110 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12111 }
12112 // TODO: bridge name
12113 // TODO: vlan id
12114 // TODO: primary
12115 iface_info->index = array_index_to_vap_index(radioIndex, j);
12116 memset(output, 0, sizeof(output));
12117 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12118 {
12119 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12120 }
12121 iter++;
12122 }
12123 }
12124
12125 cap->BandSteeringSupported = FALSE;
12126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12127 return RETURN_OK;
12128}
12129
developer9df4e652022-10-11 11:27:38 +080012130INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12131{
12132 struct params h_config={0};
12133 char config_file[64] = {0};
12134
12135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12136
12137 h_config.name = "okc";
12138 h_config.value = okc_enable?"1":"0";
12139
12140 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12141 wifi_hostapdWrite(config_file, &h_config, 1);
12142 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12143
12144 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12145 return RETURN_OK;
12146}
12147
12148INT wifi_setSAEMFP(int ap_index, BOOL enable)
12149{
12150 struct params h_config={0};
12151 char config_file[64] = {0};
12152 char buf[128] = {0};
12153
12154 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12155
12156 h_config.name = "sae_require_mfp";
12157 h_config.value = enable?"1":"0";
12158
12159 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12160 wifi_hostapdWrite(config_file, &h_config, 1);
12161 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12162
12163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12164 return RETURN_OK;
12165}
12166
12167INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12168{
12169 struct params h_config={0};
12170 char config_file[64] = {0};
12171 char buf[128] = {0};
12172
12173 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12174
12175 h_config.name = "sae_pwe";
12176 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12177 h_config.value = buf;
12178
12179 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12180 wifi_hostapdWrite(config_file, &h_config, 1);
12181 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12182
12183 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12184 return RETURN_OK;
12185}
12186
12187INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12188{
12189 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12190 struct params h_config={0};
12191 char config_file[64] = {0};
12192
12193 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12194
12195 h_config.name = "wpa_disable_eapol_key_retries";
12196 h_config.value = disable_EAPOL_retries?"1":"0";
12197
12198 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12199 wifi_hostapdWrite(config_file, &h_config, 1);
12200 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12201
12202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12203 return RETURN_OK;
12204}
12205
developer06a01d92022-09-07 16:32:39 +080012206INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12207{
developer587c1b62022-09-27 15:58:59 +080012208 char buf[128] = {0};
12209 char config_file[128] = {0};
12210 char password[64] = {0};
12211 char mfp[32] = {0};
12212 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012213 BOOL okc_enable = FALSE;
12214 BOOL sae_MFP = FALSE;
12215 BOOL disable_EAPOL_retries = TRUE;
12216 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012217 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012218 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012219
12220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12221
12222 multiple_set = TRUE;
12223 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12224 if (security->mode == wifi_security_mode_none) {
12225 strcpy(wpa_mode, "None");
12226 } else if (security->mode == wifi_security_mode_wpa_personal)
12227 strcpy(wpa_mode, "WPA-Personal");
12228 else if (security->mode == wifi_security_mode_wpa2_personal)
12229 strcpy(wpa_mode, "WPA2-Personal");
12230 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12231 strcpy(wpa_mode, "WPA-WPA2-Personal");
12232 else if (security->mode == wifi_security_mode_wpa_enterprise)
12233 strcpy(wpa_mode, "WPA-Enterprise");
12234 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12235 strcpy(wpa_mode, "WPA2-Enterprise");
12236 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12237 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012238 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012239 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012240 okc_enable = TRUE;
12241 sae_MFP = TRUE;
12242 sae_pwe = 2;
12243 disable_EAPOL_retries = FALSE;
12244 } else if (security->mode == wifi_security_mode_wpa3_transition) {
12245 strcpy(wpa_mode, "WPA3-Transition");
12246 okc_enable = TRUE;
12247 sae_MFP = TRUE;
12248 sae_pwe = 2;
12249 disable_EAPOL_retries = FALSE;
12250 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012251 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012252 sae_MFP = TRUE;
12253 sae_pwe = 2;
12254 disable_EAPOL_retries = FALSE;
12255 }
12256
12257 band = wifi_index_to_band(ap_index);
12258 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12259 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12260 return RETURN_ERR;
12261 }
developer587c1b62022-09-27 15:58:59 +080012262
12263 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012264 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012265 wifi_setSAEMFP(ap_index, sae_MFP);
12266 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012267 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012268
developer9df4e652022-10-11 11:27:38 +080012269 if (security->mode != wifi_security_mode_none) {
12270 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12271 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12272 password[63] = '\0';
12273 wifi_setApSecurityKeyPassphrase(ap_index, password);
12274 }
12275 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12276 params.name = "sae_password";
12277 params.value = security->u.key.key;
12278 wifi_hostapdWrite(config_file, &params, 1);
12279 }
12280 }
developer587c1b62022-09-27 15:58:59 +080012281
12282 if (security->mode != wifi_security_mode_none) {
12283 memset(&params, 0, sizeof(params));
12284 params.name = "wpa_pairwise";
12285 if (security->encr == wifi_encryption_tkip)
12286 params.value = "TKIP";
12287 else if (security->encr == wifi_encryption_aes)
12288 params.value = "CCMP";
12289 else if (security->encr == wifi_encryption_aes_tkip)
12290 params.value = "TKIP CCMP";
12291 wifi_hostapdWrite(config_file, &params, 1);
12292 }
12293
12294 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012295 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012296 else if (security->mfp == wifi_mfp_cfg_optional)
12297 strcpy(mfp, "Optional");
12298 else if (security->mfp == wifi_mfp_cfg_required)
12299 strcpy(mfp, "Required");
12300 wifi_setApSecurityMFPConfig(ap_index, mfp);
12301
12302 memset(&params, 0, sizeof(params));
12303 params.name = "transition_disable";
12304 if (security->wpa3_transition_disable == TRUE)
12305 params.value = "0x01";
12306 else
12307 params.value = "0x00";
12308 wifi_hostapdWrite(config_file, &params, 1);
12309
12310 memset(&params, 0, sizeof(params));
12311 params.name = "wpa_group_rekey";
12312 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12313 params.value = buf;
12314 wifi_hostapdWrite(config_file, &params, 1);
12315
12316 memset(&params, 0, sizeof(params));
12317 params.name = "wpa_strict_rekey";
12318 params.value = security->strict_rekey?"1":"0";
12319 wifi_hostapdWrite(config_file, &params, 1);
12320
12321 memset(&params, 0, sizeof(params));
12322 params.name = "wpa_pairwise_update_count";
12323 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12324 params.value = buf;
12325 wifi_hostapdWrite(config_file, &params, 1);
12326
12327 memset(&params, 0, sizeof(params));
12328 params.name = "disable_pmksa_caching";
12329 params.value = security->disable_pmksa_caching?"1":"0";
12330 wifi_hostapdWrite(config_file, &params, 1);
12331
12332 wifi_setApEnable(ap_index, FALSE);
12333 wifi_setApEnable(ap_index, TRUE);
12334
12335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12336
developer06a01d92022-09-07 16:32:39 +080012337 return RETURN_OK;
12338}
12339
12340INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12341{
developer9df4e652022-10-11 11:27:38 +080012342 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012343 char config_file[128] = {0};
12344 int disable = 0;
12345 // struct params params = {0};
12346
12347 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12348 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12349 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12350 security->mode = wifi_security_mode_none;
12351 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012352 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012353 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012354 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012355 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012356 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012357 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012358 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012359 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012360 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012361 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012362 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012363 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012364 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012365 security->mode = wifi_security_mode_wpa3_personal;
developer517a9792022-10-05 19:37:42 +080012366 else if (!strcmp(buf, "WPA3-Transition"))
developer587c1b62022-09-27 15:58:59 +080012367 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012368 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012369 security->mode = wifi_security_mode_wpa3_enterprise;
12370 }
12371
12372 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12373 if (security->mode == wifi_security_mode_none)
12374 security->encr = wifi_encryption_none;
12375 else {
12376 if (strcmp(buf, "TKIP") == 0)
12377 security->encr = wifi_encryption_tkip;
12378 else if (strcmp(buf, "CCMP") == 0)
12379 security->encr = wifi_encryption_aes;
12380 else
12381 security->encr = wifi_encryption_aes_tkip;
12382 }
12383
developer9df4e652022-10-11 11:27:38 +080012384 if (security->mode != wifi_encryption_none) {
12385 memset(buf, 0, sizeof(buf));
12386 // wpa3 can use one or both configs as password, so we check sae_password first.
12387 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12388 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12389 security->u.key.type = wifi_security_key_type_sae;
12390 } else {
12391 security->u.key.type = wifi_security_key_type_psk;
12392 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12393 }
12394 strncpy(security->u.key.key, buf, sizeof(buf));
12395 security->u.key.key[255] = '\0';
12396 }
12397
developer587c1b62022-09-27 15:58:59 +080012398 memset(buf, 0, sizeof(buf));
12399 wifi_getApSecurityMFPConfig(ap_index, buf);
12400 if (strcmp(buf, "Disabled") == 0)
12401 security->mfp = wifi_mfp_cfg_disabled;
12402 else if (strcmp(buf, "Optional") == 0)
12403 security->mfp = wifi_mfp_cfg_optional;
12404 else if (strcmp(buf, "Required") == 0)
12405 security->mfp = wifi_mfp_cfg_required;
12406
12407 memset(buf, 0, sizeof(buf));
12408 security->wpa3_transition_disable = FALSE;
12409 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12410 disable = strtol(buf, NULL, 16);
12411 if (disable != 0)
12412 security->wpa3_transition_disable = TRUE;
12413
12414 memset(buf, 0, sizeof(buf));
12415 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12416 if (strlen(buf) == 0)
12417 security->rekey_interval = 86400;
12418 else
12419 security->rekey_interval = strtol(buf, NULL, 10);
12420
12421 memset(buf, 0, sizeof(buf));
12422 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12423 if (strlen(buf) == 0)
12424 security->strict_rekey = 1;
12425 else
12426 security->strict_rekey = strtol(buf, NULL, 10);
12427
12428 memset(buf, 0, sizeof(buf));
12429 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12430 if (strlen(buf) == 0)
12431 security->eapol_key_retries = 4;
12432 else
12433 security->eapol_key_retries = strtol(buf, NULL, 10);
12434
12435 memset(buf, 0, sizeof(buf));
12436 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12437 if (strlen(buf) == 0)
12438 security->disable_pmksa_caching = FALSE;
12439 else
12440 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12441
12442 /* TODO
12443 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12444 */
12445 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12446 security->eap_identity_req_timeout = 0;
12447 security->eap_identity_req_retries = 0;
12448 security->eap_req_timeout = 0;
12449 security->eap_req_retries = 0;
12450 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012451 return RETURN_OK;
12452}
12453
12454#endif /* WIFI_HAL_VERSION_3 */
12455
12456#ifdef WIFI_HAL_VERSION_3_PHASE2
12457INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12458{
developer13df9332022-09-27 16:53:22 +080012459 char cmd[128] = {0};
12460 char buf[128] = {0};
12461 char *mac_addr = NULL;
12462 BOOL status = FALSE;
12463 size_t len = 0;
12464
12465 if(ap_index > MAX_APS)
12466 return RETURN_ERR;
12467
12468 *output_numDevices = 0;
12469 wifi_getApEnable(ap_index, &status);
12470 if (status == FALSE)
12471 return RETURN_OK;
12472
12473 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12474 _syscmd(cmd, buf, sizeof(buf));
12475
12476 mac_addr = strtok(buf, "\n");
12477 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12478 *output_numDevices = i + 1;
12479 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12480 addr_ptr = output_deviceMacAddressArray[i];
12481 mac_addr_aton(addr_ptr, mac_addr);
12482 mac_addr = strtok(NULL, "\n");
12483 }
12484
12485 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012486}
12487#else
12488INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12489{
12490 char cmd[128];
12491 BOOL status = false;
12492
12493 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12494 return RETURN_ERR;
12495
12496 output_buf[0] = '\0';
12497
12498 wifi_getApEnable(ap_index,&status);
12499 if (!status)
12500 return RETURN_OK;
12501
12502 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12503 _syscmd(cmd, output_buf, output_buf_size);
12504
12505 return RETURN_OK;
12506}
12507#endif
developer2f513ab2022-09-13 14:26:06 +080012508
12509INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12510{
12511 char output[16]={'\0'};
12512 char config_file[MAX_BUF_SIZE] = {0};
12513
12514 if (!enable)
12515 return RETURN_ERR;
12516
12517 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12518 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12519
12520 if (strlen(output) == 0)
12521 *enable = FALSE;
12522 else if (strncmp(output, "1", 1) == 0)
12523 *enable = TRUE;
12524 else
12525 *enable = FALSE;
12526
12527 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12528 return RETURN_OK;
12529}
developer2d9c30f2022-09-13 15:06:14 +080012530
12531INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12532{
12533 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12534 return RETURN_ERR;
12535 *output_enable=TRUE;
12536 return RETURN_OK;
12537}
developerfd7d2892022-09-13 16:44:53 +080012538
12539INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12540{
12541 char cmd[128] = {0};
12542 char buf[128] = {0};
12543 char line[128] = {0};
12544 size_t len = 0;
12545 ssize_t read = 0;
12546 FILE *f = NULL;
12547 int index = 0;
12548 int exp = 0;
12549 int mantissa = 0;
12550 int duration = 0;
12551 int radio_index = 0;
12552 int max_radio_num = 0;
12553 uint twt_wake_interval = 0;
12554
12555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12556
12557 wifi_getMaxRadioNumber(&max_radio_num);
12558 radio_index = ap_index % max_radio_num;
12559 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12560 _syscmd(cmd, buf, sizeof(buf));
12561 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12562 if (*numSessionReturned > maxNumberSessions)
12563 *numSessionReturned = maxNumberSessions;
12564 else if (*numSessionReturned < 1) {
12565 *numSessionReturned = 0;
12566 return RETURN_OK;
12567 }
12568
12569 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12570 if ((f = popen(cmd, "r")) == NULL) {
12571 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12572 return RETURN_ERR;
12573 }
12574
12575 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12576 while((read = fgets(line, sizeof(line), f)) != NULL) {
12577 char *tmp = NULL;
12578 strcpy(buf, line);
12579 tmp = strtok(buf, " ");
12580 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12581 tmp = strtok(NULL, " ");
12582 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12583 tmp = strtok(NULL, " ");
12584 if (strstr(tmp, "t")) {
12585 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12586 }
12587 if (strstr(tmp, "a")) {
12588 twtSessions[index].twtParameters.operation.announced = TRUE;
12589 }
12590 tmp = strtok(NULL, " ");
12591 exp = strtol(tmp, NULL, 10);
12592 tmp = strtok(NULL, " ");
12593 mantissa = strtol(tmp, NULL, 10);
12594 tmp = strtok(NULL, " ");
12595 duration = strtol(tmp, NULL, 10);
12596
12597 // only implicit supported
12598 twtSessions[index].twtParameters.operation.implicit = TRUE;
12599 // only individual agreement supported
12600 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12601
12602 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12603 twt_wake_interval = mantissa * (1 << exp);
12604 if (twt_wake_interval/mantissa != (1 << exp)) {
12605 // Overflow handling
12606 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12607 } else {
12608 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12609 }
12610 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12611 index++;
12612 }
12613
12614 pclose(f);
12615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12616 return RETURN_OK;
12617}