blob: cd9769eccb1e8f0be83b68d15f69159b2d33b093 [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
66#define MAX_BUF_SIZE 128
67#define MAX_CMD_SIZE 1024
68#define MAX_POSSIBLE_CHANNEL_STRING_BUF 512
69#define IF_NAME_SIZE 50
70#define CONFIG_PREFIX "/nvram/hostapd"
71#define ACL_PREFIX "/tmp/hostapd-acl"
developer10adcc12022-09-13 14:39:17 +080072#define DENY_PREFIX "/tmp/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080073//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
75#define VAP_STATUS_FILE "/tmp/vap-status"
developera3c68b92022-09-13 15:27:29 +080076#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080077#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
developer06a01d92022-09-07 16:32:39 +0800100
developer033b37b2022-10-18 11:27:46 +0800101#ifdef WIFI_HAL_VERSION_3
102#define MAX_RADIOS 3
103#else
104#define MAX_RADIOS 2
105#endif
106
107#define MAX_APS MAX_RADIOS*5
developer06a01d92022-09-07 16:32:39 +0800108#ifndef AP_PREFIX
109#define AP_PREFIX "wifi"
110#endif
111
112#ifndef RADIO_PREFIX
113#define RADIO_PREFIX "wlan"
114#endif
115
116#define MAX_BUF_SIZE 128
117#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800118#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800119
120//Uncomment to enable debug logs
121//#define WIFI_DEBUG
122
123#ifdef WIFI_DEBUG
124#define wifi_dbg_printf printf
125#define WIFI_ENTRY_EXIT_DEBUG printf
126#else
127#define wifi_dbg_printf(format, args...) printf("")
128#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
129#endif
130
131#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
132#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
133#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
134#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
135#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
136#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
137#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
138#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
139#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
140#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
141
developer4fb0b922022-09-30 14:29:09 +0800142#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800143
144#define BW_FNAME "/nvram/bw_file.txt"
145
146#define PS_MAX_TID 16
147
148static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
149 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
150 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
151 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
153 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
154 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
155 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
156 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
157 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
158 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
159 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
160 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
161 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
162 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
163 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
164 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
165};
166
167typedef unsigned long long u64;
168
169/* Enum to define WiFi Bands */
170typedef enum
171{
172 band_invalid = -1,
173 band_2_4 = 0,
174 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800175 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800176} wifi_band;
177
developerdb744382022-09-13 15:34:54 +0800178typedef enum {
179 WIFI_MODE_A = 0x01,
180 WIFI_MODE_B = 0x02,
181 WIFI_MODE_G = 0x04,
182 WIFI_MODE_N = 0x08,
183 WIFI_MODE_AC = 0x10,
184 WIFI_MODE_AX = 0x20,
185} wifi_ieee80211_Mode;
186
developer06a01d92022-09-07 16:32:39 +0800187#ifdef WIFI_HAL_VERSION_3
188
189// Return number of elements in array
190#ifndef ARRAY_SIZE
191#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
192#endif /* ARRAY_SIZE */
193
194#ifndef ARRAY_AND_SIZE
195#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
196#endif /* ARRAY_AND_SIZE */
197
198#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
199
200typedef struct {
201 int32_t value;
202 int32_t param;
203 intptr_t key;
204 intptr_t data;
205} wifi_secur_list;
206
207wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
208wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
209char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800210static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800211
212static wifi_secur_list map_security[] =
213{
214 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
215 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
216 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
219 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
220 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
221 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800222 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
223 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800224 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800225 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800226};
227
228wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
229{
230 wifi_secur_list *item;
231 int i;
232
233 for (item = list,i = 0;i < list_sz; item++, i++) {
234 if ((int)(item->key) == key) {
235 return item;
236 }
237 }
238
239 return NULL;
240}
241
242char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
243{
244 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
245
246 if (!item) {
247 return "";
248 }
249
250 return (char *)(item->data);
251}
252
253wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
254{
255 wifi_secur_list *item;
256 int i;
257
258 for (item = list,i = 0;i < list_sz; item++, i++) {
259 if (strcmp((char *)(item->data), str) == 0) {
260 return item;
261 }
262 }
263
264 return NULL;
265}
266#endif /* WIFI_HAL_VERSION_3 */
267
268#ifdef HAL_NETLINK_IMPL
269typedef struct {
270 int id;
271 struct nl_sock* socket;
272 struct nl_cb* cb;
273} Netlink;
274
275static int mac_addr_aton(unsigned char *mac_addr, char *arg)
276{
277 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800278 sscanf(arg, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
developer06a01d92022-09-07 16:32:39 +0800279 mac_addr[0] = mac_addr_int[0];
280 mac_addr[1] = mac_addr_int[1];
281 mac_addr[2] = mac_addr_int[2];
282 mac_addr[3] = mac_addr_int[3];
283 mac_addr[4] = mac_addr_int[4];
284 mac_addr[5] = mac_addr_int[5];
285 return 0;
286}
287
288static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
289{
290 unsigned int mac_addr_int[6]={};
291 mac_addr_int[0] = arg[0];
292 mac_addr_int[1] = arg[1];
293 mac_addr_int[2] = arg[2];
294 mac_addr_int[3] = arg[3];
295 mac_addr_int[4] = arg[4];
296 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800297 snprintf(mac_addr, 20, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
developer06a01d92022-09-07 16:32:39 +0800298 return;
299}
300
301static int ieee80211_frequency_to_channel(int freq)
302{
developerf5745ee2022-10-05 16:09:53 +0800303 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800304 if (freq == 2484)
305 return 14;
developerf5745ee2022-10-05 16:09:53 +0800306 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
307 else if (freq == 5935)
308 return 2;
developer06a01d92022-09-07 16:32:39 +0800309 else if (freq < 2484)
310 return (freq - 2407) / 5;
311 else if (freq >= 4910 && freq <= 4980)
312 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800313 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800314 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800315 else if (freq <= 45000) /* DMG band lower limit */
316 /* see 802.11ax D6.1 27.3.23.2 */
317 return (freq - 5950) / 5;
318 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800319 return (freq - 56160) / 2160;
320 else
321 return 0;
322}
323
324static int initSock80211(Netlink* nl) {
325 nl->socket = nl_socket_alloc();
326 if (!nl->socket) {
327 fprintf(stderr, "Failing to allocate the sock\n");
328 return -ENOMEM;
329 }
330
331 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
332
333 if (genl_connect(nl->socket)) {
334 fprintf(stderr, "Failed to connect\n");
335 nl_close(nl->socket);
336 nl_socket_free(nl->socket);
337 return -ENOLINK;
338 }
339
340 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
341 if (nl->id< 0) {
342 fprintf(stderr, "interface not found.\n");
343 nl_close(nl->socket);
344 nl_socket_free(nl->socket);
345 return -ENOENT;
346 }
347
348 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
349 if ((!nl->cb)) {
350 fprintf(stderr, "Failed to allocate netlink callback.\n");
351 nl_close(nl->socket);
352 nl_socket_free(nl->socket);
353 return ENOMEM;
354 }
355
356 return nl->id;
357}
358
359static int nlfree(Netlink *nl)
360{
361 nl_cb_put(nl->cb);
362 nl_close(nl->socket);
363 nl_socket_free(nl->socket);
364 return 0;
365}
366
367static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
368 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
369 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
370 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
371};
372
373static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
374};
375
376static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
377};
378
379typedef struct _wifi_channelStats_loc {
380 INT array_size;
381 INT ch_number;
382 BOOL ch_in_pool;
383 INT ch_noise;
384 BOOL ch_radar_noise;
385 INT ch_max_80211_rssi;
386 INT ch_non_80211_noise;
387 INT ch_utilization;
388 ULLONG ch_utilization_total;
389 ULLONG ch_utilization_busy;
390 ULLONG ch_utilization_busy_tx;
391 ULLONG ch_utilization_busy_rx;
392 ULLONG ch_utilization_busy_self;
393 ULLONG ch_utilization_busy_ext;
394} wifi_channelStats_t_loc;
395
396typedef struct wifi_device_info {
397 INT wifi_devIndex;
398 UCHAR wifi_devMacAddress[6];
399 CHAR wifi_devIPAddress[64];
400 BOOL wifi_devAssociatedDeviceAuthentiationState;
401 INT wifi_devSignalStrength;
402 INT wifi_devTxRate;
403 INT wifi_devRxRate;
404} wifi_device_info_t;
405
406#endif
407
408//For 5g Alias Interfaces
409static BOOL priv_flag = TRUE;
410static BOOL pub_flag = TRUE;
411static BOOL Radio_flag = TRUE;
412//wifi_setApBeaconRate(1, beaconRate);
413
developer1e5aa162022-09-13 16:06:24 +0800414BOOL multiple_set = FALSE;
415
developer06a01d92022-09-07 16:32:39 +0800416struct params
417{
418 char * name;
419 char * value;
420};
421
422static int _syscmd(char *cmd, char *retBuf, int retBufSize)
423{
424 FILE *f;
425 char *ptr = retBuf;
426 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
427
428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
429 if((f = popen(cmd, "r")) == NULL) {
430 fprintf(stderr,"\npopen %s error\n", cmd);
431 return RETURN_ERR;
432 }
433
434 while(!feof(f))
435 {
436 *ptr = 0;
437 if(bufSize>=128) {
438 bufbytes=128;
439 } else {
440 bufbytes=bufSize-1;
441 }
442
443 fgets(ptr,bufbytes,f);
444 readbytes=strlen(ptr);
445
446 if(!readbytes)
447 break;
448
449 bufSize-=readbytes;
450 ptr += readbytes;
451 }
452 cmd_ret = pclose(f);
453 retBuf[retBufSize-1]=0;
454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
455
456 return cmd_ret >> 8;
457}
458
developer033b37b2022-10-18 11:27:46 +0800459INT radio_index_to_phy(int radioIndex)
460{
461 char cmd[128] = {0};
462 char buf[64] = {0};
463 int phyIndex = 0;
464 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
465 _syscmd(cmd, buf, sizeof(buf));
466
467 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
468 fprintf(stderr, "%s: failed to get phy index\n", __func__);
469 return RETURN_ERR;
470 }
471 sscanf(buf, "phy%d", &phyIndex);
472
473 return phyIndex;
474}
developerc707e972022-09-13 15:38:02 +0800475wifi_band wifi_index_to_band(int apIndex)
476{
477 char cmd[128] = {0};
478 char buf[64] = {0};
479 int freq = 0;
developer5884e982022-10-06 10:52:50 +0800480 int i = 0;
developerc707e972022-09-13 15:38:02 +0800481 wifi_band band = band_invalid;
482
483 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5884e982022-10-06 10:52:50 +0800484 while(i < 10){
485 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
486 _syscmd(cmd, buf, sizeof(buf));
487 freq = strtol(buf, NULL, 10);
488 if (freq > 2401 && freq < 2495)
489 band = band_2_4;
490 else if (freq > 5160 && freq < 5915)
491 band = band_5;
492 else if (freq > 5955 && freq < 7125)
493 band = band_6;
494
495 if(band != band_invalid)
496 break;
497
498 i++;
499 sleep(1);
500 }
developerc707e972022-09-13 15:38:02 +0800501
502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
503 return band;
504}
505
developer06a01d92022-09-07 16:32:39 +0800506static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
507{
508 char cmd[MAX_CMD_SIZE]={'\0'};
509 char buf[MAX_BUF_SIZE]={'\0'};
510 int ret = 0;
511
512 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
513 ret = _syscmd(cmd, buf, sizeof(buf));
514 if ((ret != 0) && (strlen(buf) == 0))
515 return -1;
516 snprintf(output, output_size, "%s", buf);
517
518 return 0;
519}
520
521static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
522{
523 char cmd[MAX_CMD_SIZE]={'\0'};
524 char buf[MAX_BUF_SIZE]={'\0'};
525
526 for(int i=0;i<item_count;i++)
527 {
528 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
529 if (strlen(buf) == 0) //Insert
530 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
531 else //Update
532 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 +0800533
developer06a01d92022-09-07 16:32:39 +0800534 if(_syscmd(cmd, buf, sizeof(buf)))
535 return -1;
536 }
537
538 return 0;
539}
540
541static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
542{
developer1e5aa162022-09-13 16:06:24 +0800543 if (multiple_set == TRUE)
544 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800545 char cmd[MAX_CMD_SIZE]="", output[32]="";
546 FILE *fp;
547 int i;
548 //NOTE RELOAD should be done in ApplySSIDSettings
549
550 for(i=0; i<item_count; i++, list++)
551 {
552 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
553 if((fp = popen(cmd, "r"))==NULL)
554 {
555 perror("popen failed");
556 return -1;
557 }
558 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
559 {
560 pclose(fp);
561 perror("fgets failed");
562 return -1;
563 }
564 pclose(fp);
565 }
566 return 0;
567}
568
569static int wifi_reloadAp(int apIndex)
570{
developer1e5aa162022-09-13 16:06:24 +0800571 if (multiple_set == TRUE)
572 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800573 char cmd[MAX_CMD_SIZE]="";
574 char buf[MAX_BUF_SIZE]="";
575
576 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
577 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
578 return RETURN_ERR;
579
580 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
581 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
582 return RETURN_ERR;
583
584 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
585 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
586 return RETURN_ERR;
587
588 return RETURN_OK;
589}
590
591
592//For Getting Current Interface Name from corresponding hostapd configuration
593void GetInterfaceName(char *interface_name, char *conf_file)
594{
595 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
596 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
598}
599
600INT File_Reading(CHAR *file, char *Value)
601{
602 FILE *fp = NULL;
603 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
604 int count = 0;
605
606 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
607 fp = popen(file,"r");
608 if(fp == NULL)
609 return RETURN_ERR;
610
611 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
612 {
613 for(count=0;buf[count]!='\n';count++)
614 copy_buf[count]=buf[count];
615 copy_buf[count]='\0';
616 }
617 strcpy(Value,copy_buf);
618 pclose(fp);
619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
620
621 return RETURN_OK;
622}
623
624void wifi_RestartHostapd_2G()
625{
626 int Public2GApIndex = 4;
627
628 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
629 wifi_setApEnable(Public2GApIndex, FALSE);
630 wifi_setApEnable(Public2GApIndex, TRUE);
631 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
632}
633
634void wifi_RestartHostapd_5G()
635{
636 int Public5GApIndex = 5;
637
638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
639 wifi_setApEnable(Public5GApIndex, FALSE);
640 wifi_setApEnable(Public5GApIndex, TRUE);
641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
642}
643
644void wifi_RestartPrivateWifi_2G()
645{
646 int PrivateApIndex = 0;
647
648 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
649 wifi_setApEnable(PrivateApIndex, FALSE);
650 wifi_setApEnable(PrivateApIndex, TRUE);
651 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
652}
653
654void wifi_RestartPrivateWifi_5G()
655{
656 int Private5GApIndex = 1;
657
658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
659 wifi_setApEnable(Private5GApIndex, FALSE);
660 wifi_setApEnable(Private5GApIndex, TRUE);
661 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
662}
663
664static int writeBandWidth(int radioIndex,char *bw_value)
665{
666 char buf[MAX_BUF_SIZE];
667 char cmd[MAX_CMD_SIZE];
668
669 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
670 if(_syscmd(cmd, buf, sizeof(buf)))
671 {
672 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
673 _syscmd(cmd, buf, sizeof(buf));
674 return RETURN_OK;
675 }
676
677 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
678 _syscmd(cmd,buf,sizeof(buf));
679 return RETURN_OK;
680}
681
682static int readBandWidth(int radioIndex,char *bw_value)
683{
684 char buf[MAX_BUF_SIZE];
685 char cmd[MAX_CMD_SIZE];
686 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
687 _syscmd(cmd,buf,sizeof(buf));
688 if(NULL!=strstr(buf,"20MHz"))
689 {
690 strcpy(bw_value,"20MHz");
691 }
692 else if(NULL!=strstr(buf,"40MHz"))
693 {
694 strcpy(bw_value,"40MHz");
695 }
696 else if(NULL!=strstr(buf,"80MHz"))
697 {
698 strcpy(bw_value,"80MHz");
699 }
700 else
701 {
702 return RETURN_ERR;
703 }
704 return RETURN_OK;
705}
706
developer39a5efb2022-09-13 16:09:06 +0800707INT wifi_getMaxRadioNumber(INT *max_radio_num)
708{
709 char cmd[64] = {0};
710 char buf[4] = {0};
711
712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
713
714 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
715 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800716 *max_radio_num = strtoul(buf, NULL, 10) > MAX_RADIOS ? MAX_RADIOS:strtoul(buf, NULL, 10);
developer39a5efb2022-09-13 16:09:06 +0800717
718 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
719
720 return RETURN_OK;
721}
722
developer5f222492022-09-13 15:21:52 +0800723// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800724INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
725{
developer5f222492022-09-13 15:21:52 +0800726 struct params params={'\0'};
727 char config_file[MAX_BUF_SIZE] = {0};
728 char buf[MAX_BUF_SIZE] = {'\0'};
729
730 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
731 if (strlen (beaconRate) < 5)
732 return RETURN_ERR;
733 // Copy the numeric value
734 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
735 buf[strlen(beaconRate) - 4] = '\0';
736
737 params.name = "beacon_rate";
738 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
739 if (strncmp(buf, "5.5", 3) == 0) {
740 snprintf(buf, sizeof(buf), "55");
741 params.value = buf;
742 } else {
743 strcat(buf, "0");
744 params.value = buf;
745 }
746
747 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
748 wifi_hostapdWrite(config_file, &params, 1);
749 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
750 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
751
752 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800753}
754
755INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
756{
developer1d57d002022-10-12 18:03:15 +0800757 char config_file[128] = {'\0'};
758 char temp_output[128] = {'\0'};
759 char buf[128] = {'\0'};
760 char cmd[128] = {'\0'};
761 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800762 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800763
764 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
765 if (NULL == beaconRate)
766 return RETURN_ERR;
767
768 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
769 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800770 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800771 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
772 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800773 if (strncmp(buf, "55", 2) == 0)
774 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
775 else {
776 rate = strtol(buf, NULL, 10)/10;
777 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
778 }
developer5f222492022-09-13 15:21:52 +0800779 } else {
developer1d57d002022-10-12 18:03:15 +0800780 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800781 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
developer1d57d002022-10-12 18:03:15 +0800782 _syscmd(cmd, buf, sizeof(buf));
783 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800784 }
785 strncpy(beaconRate, temp_output, sizeof(temp_output));
786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
787
788 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800789}
790
791INT wifi_setLED(INT radioIndex, BOOL enable)
792{
793 return 0;
794}
795INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
796{
797 return RETURN_OK;
798}
799/**********************************************************************************
800 *
801 * Wifi Subsystem level function prototypes
802 *
803**********************************************************************************/
804//---------------------------------------------------------------------------------------------------
805//Wifi system api
806//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
807INT wifi_getHalVersion(CHAR *output_string) //RDKB
808{
809 if(!output_string)
810 return RETURN_ERR;
811 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
812
813 return RETURN_OK;
814}
815
816
817/* wifi_factoryReset() function */
818/**
819* @description Clears internal variables to implement a factory reset of the Wi-Fi
820* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
821*
822* @param None
823*
824* @return The status of the operation.
825* @retval RETURN_OK if successful.
826* @retval RETURN_ERR if any error is detected
827*
828* @execution Synchronous
829* @sideeffect None
830*
831* @note This function must not suspend and must not invoke any blocking system
832* calls. It should probably just send a message to a driver event handler task.
833*
834*/
835INT wifi_factoryReset()
836{
837 char cmd[128];
838
839 /*delete running hostapd conf files*/
840 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
841 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
842 system(cmd);
843 system("systemctl restart hostapd.service");
844
845 return RETURN_OK;
846}
847
848/* wifi_factoryResetRadios() function */
849/**
850* @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.
851*
852* @param None
853* @return The status of the operation
854* @retval RETURN_OK if successful
855* @retval RETURN_ERR if any error is detected
856*
857* @execution Synchronous
858*
859* @sideeffect None
860*
861* @note This function must not suspend and must not invoke any blocking system
862* calls. It should probably just send a message to a driver event handler task.
863*
864*/
865INT wifi_factoryResetRadios()
866{
867 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
868 return RETURN_OK;
869
870 return RETURN_ERR;
871}
872
873
874/* wifi_factoryResetRadio() function */
875/**
876* @description Restore selected radio parameters without touching access point parameters
877*
878* @param radioIndex - Index of Wi-Fi Radio channel
879*
880* @return The status of the operation.
881* @retval RETURN_OK if successful.
882* @retval RETURN_ERR if any error is detected
883*
884* @execution Synchronous.
885* @sideeffect None.
886*
887* @note This function must not suspend and must not invoke any blocking system
888* calls. It should probably just send a message to a driver event handler task.
889*
890*/
891INT wifi_factoryResetRadio(int radioIndex) //RDKB
892{
developer5ff7f5f2022-09-13 15:12:16 +0800893 system("systemctl stop hostapd.service");
894
developer06a01d92022-09-07 16:32:39 +0800895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
896 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800897 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800898 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800899 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800900 else
901 return RETURN_ERR;
902
developer5ff7f5f2022-09-13 15:12:16 +0800903 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800904 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
905 return RETURN_OK;
906}
907
908/* wifi_initRadio() function */
909/**
910* Description: This function call initializes the specified radio.
911* Implementation specifics may dictate the functionality since
912* different hardware implementations may have different initilization requirements.
913* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
914*
915* @return The status of the operation.
916* @retval RETURN_OK if successful.
917* @retval RETURN_ERR if any error is detected
918*
919* @execution Synchronous.
920* @sideeffect None.
921*
922* @note This function must not suspend and must not invoke any blocking system
923* calls. It should probably just send a message to a driver event handler task.
924*
925*/
926INT wifi_initRadio(INT radioIndex)
927{
928 //TODO: Initializes the wifi subsystem (for specified radio)
929 return RETURN_OK;
930}
931void macfilter_init()
932{
933 char count[4]={'\0'};
934 char buf[253]={'\0'};
935 char tmp[19]={'\0'};
936 int dev_count,block,mac_entry=0;
937 char res[4]={'\0'};
938 char acl_file_path[64] = {'\0'};
939 FILE *fp = NULL;
940 int index=0;
941 char iface[10]={'\0'};
942 char config_file[MAX_BUF_SIZE] = {0};
943
944
945 sprintf(acl_file_path,"/tmp/mac_filter.sh");
946
947 fp=fopen(acl_file_path,"w+");
948 sprintf(buf,"#!/bin/sh \n");
949 fprintf(fp,"%s\n",buf);
950
951 system("chmod 0777 /tmp/mac_filter.sh");
952
953 for(index=0;index<=1;index++)
954 {
955 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
956 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
957 sprintf(buf,"syscfg get %dcountfilter",index);
958 _syscmd(buf,count,sizeof(count));
959 mac_entry=atoi(count);
960
961 sprintf(buf,"syscfg get %dblockall",index);
962 _syscmd(buf,res,sizeof(res));
963 block = atoi(res);
964
965 //Allow only those macs mentioned in ACL
966 if(block==1)
967 {
968 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
969 fprintf(fp,"%s\n",buf);
970 for(dev_count=1;dev_count<=mac_entry;dev_count++)
971 {
972 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
973 _syscmd(buf,tmp,sizeof(tmp));
974 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
975 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
976 fprintf(fp,"%s\n",buf);
977 }
978 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
979 fprintf(fp,"%s\n",buf);
980 }
981
982 //Block all the macs mentioned in ACL
983 else if(block==2)
984 {
985 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
986 fprintf(fp,"%s\n",buf);
987
988 for(dev_count=1;dev_count<=mac_entry;dev_count++)
989 {
990 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
991 _syscmd(buf,tmp,sizeof(tmp));
992 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
993 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
994 fprintf(fp,"%s\n",buf);
995 }
996 }
997 }
998 fclose(fp);
999}
1000
1001// Initializes the wifi subsystem (all radios)
1002INT wifi_init() //RDKB
1003{
1004 char interface[MAX_BUF_SIZE]={'\0'};
1005 char bridge_name[MAX_BUF_SIZE]={'\0'};
1006 INT len=0;
1007
1008 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1009 //Not intitializing macfilter for Turris-Omnia Platform for now
1010 //macfilter_init();
1011
1012 system("/usr/sbin/iw reg set US");
1013 system("systemctl start hostapd.service");
1014 sleep(2);//sleep to wait for hostapd to start
1015
1016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1017
1018 return RETURN_OK;
1019}
1020
1021/* wifi_reset() function */
1022/**
1023* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1024* Implementation specifics may dictate what is actualy reset since
1025* different hardware implementations may have different requirements.
1026* Parameters : None
1027*
1028* @return The status of the operation.
1029* @retval RETURN_OK if successful.
1030* @retval RETURN_ERR if any error is detected
1031*
1032* @execution Synchronous.
1033* @sideeffect None.
1034*
1035* @note This function must not suspend and must not invoke any blocking system
1036* calls. It should probably just send a message to a driver event handler task.
1037*
1038*/
1039INT wifi_reset()
1040{
1041 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001042 system("systemctl stop hostapd.service");
1043 sleep(2);
1044 system("systemctl start hostapd.service");
1045 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001046 return RETURN_OK;
1047}
1048
1049/* wifi_down() function */
1050/**
1051* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1052* Implementation specifics may dictate some functionality since
1053* different hardware implementations may have different requirements.
1054*
1055* @param None
1056*
1057* @return The status of the operation
1058* @retval RETURN_OK if successful
1059* @retval RETURN_ERR if any error is detected
1060*
1061* @execution Synchronous
1062* @sideeffect None
1063*
1064* @note This function must not suspend and must not invoke any blocking system
1065* calls. It should probably just send a message to a driver event handler task.
1066*
1067*/
1068INT wifi_down()
1069{
1070 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001071 system("systemctl stop hostapd.service");
1072 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001073 return RETURN_OK;
1074}
1075
1076
1077/* wifi_createInitialConfigFiles() function */
1078/**
1079* @description This function creates wifi configuration files. The format
1080* and content of these files are implementation dependent. This function call is
1081* used to trigger this task if necessary. Some implementations may not need this
1082* function. If an implementation does not need to create config files the function call can
1083* do nothing and return RETURN_OK.
1084*
1085* @param None
1086*
1087* @return The status of the operation
1088* @retval RETURN_OK if successful
1089* @retval RETURN_ERR if any error is detected
1090*
1091* @execution Synchronous
1092* @sideeffect None
1093*
1094* @note This function must not suspend and must not invoke any blocking system
1095* calls. It should probably just send a message to a driver event handler task.
1096*
1097*/
1098INT wifi_createInitialConfigFiles()
1099{
1100 //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)
1101 return RETURN_OK;
1102}
1103
1104// outputs the country code to a max 64 character string
1105INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1106{
developer7543b3b2022-09-13 13:47:17 +08001107 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer033b37b2022-10-18 11:27:46 +08001108 if(!output_string || (radioIndex >= MAX_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001109 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001110
1111 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1112 _syscmd(cmd, buf, sizeof(buf));
1113 if(strlen(buf) > 0)
1114 snprintf(output_string, 64, "%s", buf);
1115 else
1116 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001117
1118 return RETURN_OK;
1119}
1120
1121INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1122{
1123 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001124 char str[MAX_BUF_SIZE]={'\0'};
1125 char cmd[MAX_CMD_SIZE]={'\0'};
1126 struct params params;
1127 char config_file[MAX_BUF_SIZE] = {0};
1128
1129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1130 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1131 return RETURN_ERR;
1132
developerb86c6f32022-10-07 14:34:58 +08001133 if (strlen(CountryCode) == 0)
1134 strcpy(CountryCode, "US");
1135
developer7543b3b2022-09-13 13:47:17 +08001136 params.name = "country_code";
1137 params.value = CountryCode;
1138 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1139 int ret = wifi_hostapdWrite(config_file, &params, 1);
1140 if (ret) {
1141 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1142 ,__func__, ret);
1143 }
1144
1145 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1146 if (ret) {
1147 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1148 ,__func__, ret);
1149 }
1150 wifi_reloadAp(radioIndex);
1151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1152
developer06a01d92022-09-07 16:32:39 +08001153 return RETURN_OK;
1154}
1155
developera748dcf2022-09-13 15:56:48 +08001156INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1157{
1158 char channel_util_file[64] = {0};
1159 char cmd[128] = {0};
1160 char buf[128] = {0};
1161 char line[128] = {0};
1162 char *param = NULL, *value = NULL;
1163 int read = 0;
1164 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1165 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1166 size_t len = 0;
1167 FILE *f = NULL;
1168
1169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1170
1171 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1172 _syscmd(cmd, buf, sizeof(buf));
1173 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1174
1175 memset(cmd, 0, sizeof(cmd));
1176 memset(buf, 0, sizeof(buf));
1177 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1178 if ((f = popen(cmd, "r")) == NULL) {
1179 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1180 return RETURN_ERR;
1181 }
1182
1183 read = getline(&line, &len, f);
1184 while (read != -1) {
1185 param = strtok(line, ":\t");
1186 value = strtok(NULL, " ");
1187 if(strstr(param, "frequency") != NULL) {
1188 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1189 }
1190 if(strstr(param, "noise") != NULL) {
1191 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1192 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1193 }
1194 if(strstr(param, "channel active time") != NULL) {
1195 ActiveTime = strtol(value, NULL, 10);
1196 }
1197 if(strstr(param, "channel busy time") != NULL) {
1198 BusyTime = strtol(value, NULL, 10);
1199 }
1200 if(strstr(param, "channel transmit time") != NULL) {
1201 TransmitTime = strtol(value, NULL, 10);
1202 }
1203 read = getline(&line, &len, f);
1204 }
1205 pclose(f);
1206
1207 // The file should store the last active, busy and transmit time
1208 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1209 f = fopen(channel_util_file, "r");
1210 if (f != NULL) {
1211 read = getline(&line, &len, f);
1212 preActiveTime = strtol(line, NULL, 10);
1213 read = getline(&line, &len, f);
1214 preBusyTime = strtol(line, NULL, 10);
1215 read = getline(&line, &len, f);
1216 preTransmitTime = strtol(line, NULL, 10);
1217 fclose(f);
1218 }
1219
1220 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1221 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1222
1223 f = fopen(channel_util_file, "w");
1224 if (f != NULL) {
1225 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1226 fclose(f);
1227 }
1228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1229 return RETURN_OK;
1230}
1231
developer06a01d92022-09-07 16:32:39 +08001232/**********************************************************************************
1233 *
1234 * Wifi radio level function prototypes
1235 *
1236**********************************************************************************/
1237
1238//Get the total number of radios in this wifi subsystem
1239INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1240{
1241 if (NULL == output)
1242 return RETURN_ERR;
1243 *output = 2;
1244
1245 return RETURN_OK;
1246}
1247
1248//Get the total number of SSID entries in this wifi subsystem
1249INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1250{
1251 if (NULL == output)
1252 return RETURN_ERR;
1253 *output = MAX_APS;
1254
1255 return RETURN_OK;
1256}
1257
1258//Get the Radio enable config parameter
1259INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1260{
1261 char interface_path[MAX_CMD_SIZE] = {0};
1262 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001263 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001264
1265 if (NULL == output_bool)
1266 return RETURN_ERR;
1267
1268 *output_bool = FALSE;
developer033b37b2022-10-18 11:27:46 +08001269 if (radioIndex >= MAX_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001270 return RETURN_ERR;
1271
developer033b37b2022-10-18 11:27:46 +08001272 phyId = radio_index_to_phy(radioIndex);
1273
1274 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001275 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001276 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001277 {
developercf48e482022-09-13 14:49:50 +08001278 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001279 }
1280 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001281 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1282 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1283 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001284
developercf48e482022-09-13 14:49:50 +08001285 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1286 *output_bool = TRUE;
1287 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001288 return RETURN_OK;
1289}
1290
1291INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1292{
1293 char cmd[MAX_CMD_SIZE] = {0};
1294 char buf[MAX_CMD_SIZE] = {0};
1295 int apIndex, ret;
1296 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001297 int max_radio_num = 0;
1298 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001299
1300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001301
1302 phyId = radio_index_to_phy(radioIndex);
1303
1304 wifi_getMaxRadioNumber(&max_radio_num);
1305
developer06a01d92022-09-07 16:32:39 +08001306 if(enable==FALSE)
1307 {
developer033b37b2022-10-18 11:27:46 +08001308 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001309 {
1310 //Detaching %s%d from hostapd daemon
1311 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1312 _syscmd(cmd, buf, sizeof(buf));
1313 if(strncmp(buf, "OK", 2))
1314 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1315 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1316 _syscmd(cmd, buf, sizeof(buf));
1317 }
developer033b37b2022-10-18 11:27:46 +08001318 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001319 _syscmd(cmd, buf, sizeof(buf));
1320 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001321 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001322 }
1323 else
1324 {
developer033b37b2022-10-18 11:27:46 +08001325 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001326 _syscmd(cmd, buf, sizeof(buf));
1327 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001328 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001329 sleep(1);
developer033b37b2022-10-18 11:27:46 +08001330
1331 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001332 {
developer033b37b2022-10-18 11:27:46 +08001333 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, phyId, AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08001334 ret = _syscmd(cmd, buf, sizeof(buf));
1335 if ( ret == RETURN_ERR)
1336 {
1337 fprintf(stderr, "VAP interface creation failed\n");
1338 continue;
1339 }
1340 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1341 _syscmd(cmd, buf, sizeof(buf));
1342 if(*buf == '1')
1343 {
1344 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001345 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001346 _syscmd(cmd, buf, sizeof(buf));
1347 if(strncmp(buf, "OK", 2))
1348 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1349 }
1350 }
1351 }
1352
1353 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1354 return RETURN_OK;
1355}
1356
1357//Get the Radio enable status
1358INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1359{
1360 if (NULL == output_bool)
1361 return RETURN_ERR;
1362
1363 return wifi_getRadioEnable(radioIndex, output_bool);
1364}
1365
1366//Get the Radio Interface name from platform, eg "wlan0"
1367INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1368{
developer033b37b2022-10-18 11:27:46 +08001369 int phyId = 0;
1370 if (NULL == output_string || radioIndex>=MAX_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001371 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08001372 phyId = radio_index_to_phy(radioIndex);
1373 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001374
1375 return RETURN_OK;
1376}
1377
1378//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1379//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.
1380INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1381{
developerbcc556a2022-09-22 20:02:45 +08001382 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1383 // For max bit rate, we should always choose the best MCS
1384 char mode[64] = {0};
1385 char channel_bandwidth_str[16] = {0};
1386 char *tmp = NULL;
1387 UINT mode_map = 0;
1388 UINT num_subcarrier = 0;
1389 UINT code_bits = 0;
1390 float code_rate = 0; // use max code rate
1391 int NSS = 0;
1392 UINT Symbol_duration = 0;
1393 UINT GI_duration = 0;
1394 wifi_band band = band_invalid;
1395 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1396 BOOL enable = FALSE;
1397 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001398
1399 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1400 if (NULL == output_string)
1401 return RETURN_ERR;
1402
developerbcc556a2022-09-22 20:02:45 +08001403 wifi_getRadioEnable(radioIndex, &enable);
1404 if (enable == FALSE) {
1405 snprintf(output_string, 64, "0 Mb/s");
1406 return RETURN_OK;
1407 }
1408
1409 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1410 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1411 return RETURN_ERR;
1412 }
1413
1414 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1415 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1416 return RETURN_ERR;
1417 }
1418
1419 if (gi == wifi_guard_interval_3200)
1420 GI_duration = 32;
1421 else if (gi == wifi_guard_interval_1600)
1422 GI_duration = 16;
1423 else if (gi == wifi_guard_interval_800)
1424 GI_duration = 8;
1425 else // auto, 400
1426 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001427
developerbcc556a2022-09-22 20:02:45 +08001428 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1429 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1430 return RETURN_ERR;
1431 }
1432
1433 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1434 strcpy(channel_bandwidth_str, "160");
1435
1436 if (mode_map & WIFI_MODE_AX) {
1437 if (strstr(channel_bandwidth_str, "160") != NULL)
1438 num_subcarrier = 1960;
1439 else if (strstr(channel_bandwidth_str, "80") != NULL)
1440 num_subcarrier = 980;
1441 else if (strstr(channel_bandwidth_str, "40") != NULL)
1442 num_subcarrier = 468;
1443 else if (strstr(channel_bandwidth_str, "20") != NULL)
1444 num_subcarrier = 234;
1445 code_bits = 10;
1446 code_rate = (float)5/6;
1447 Symbol_duration = 128;
1448 } else if (mode_map & WIFI_MODE_AC) {
1449 if (strstr(channel_bandwidth_str, "160") != NULL)
1450 num_subcarrier = 468;
1451 else if (strstr(channel_bandwidth_str, "80") != NULL)
1452 num_subcarrier = 234;
1453 else if (strstr(channel_bandwidth_str, "40") != NULL)
1454 num_subcarrier = 108;
1455 else if (strstr(channel_bandwidth_str, "20") != NULL)
1456 num_subcarrier = 52;
1457 code_bits = 8;
1458 code_rate = (float)5/6;
1459 Symbol_duration = 32;
1460 } else if (mode_map & WIFI_MODE_N) {
1461 if (strstr(channel_bandwidth_str, "160") != NULL)
1462 num_subcarrier = 468;
1463 else if (strstr(channel_bandwidth_str, "80") != NULL)
1464 num_subcarrier = 234;
1465 else if (strstr(channel_bandwidth_str, "40") != NULL)
1466 num_subcarrier = 108;
1467 else if (strstr(channel_bandwidth_str, "20") != NULL)
1468 num_subcarrier = 52;
1469 code_bits = 6;
1470 code_rate = (float)3/4;
1471 Symbol_duration = 32;
1472 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1473 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1474 snprintf(output_string, 64, "65 Mb/s");
1475 return RETURN_OK;
1476 } else {
1477 snprintf(output_string, 64, "0 Mb/s");
1478 return RETURN_OK;
1479 }
developer06a01d92022-09-07 16:32:39 +08001480
developerbcc556a2022-09-22 20:02:45 +08001481 // Spatial streams
1482 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1483 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1484 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001485 }
developerbcc556a2022-09-22 20:02:45 +08001486
1487 // multiple 10 is to align duration unit (0.1 us)
1488 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1489 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1490
developer06a01d92022-09-07 16:32:39 +08001491 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1492
1493 return RETURN_OK;
1494}
1495#if 0
1496INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1497{
1498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1499 char cmd[64];
1500 char buf[1024];
1501 int apIndex;
1502
1503 if (NULL == output_string)
1504 return RETURN_ERR;
1505
1506 apIndex=(radioIndex==0)?0:1;
1507
1508 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1509 _syscmd(cmd,buf, sizeof(buf));
1510
1511 snprintf(output_string, 64, "%s", buf);
1512 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1513 return RETURN_OK;
1514}
1515#endif
1516
1517
1518//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1519//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.
1520INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1521{
developer963da0c2022-09-13 15:58:27 +08001522 wifi_band band = band_invalid;
1523
developer06a01d92022-09-07 16:32:39 +08001524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1525 if (NULL == output_string)
1526 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001527
1528 band = wifi_index_to_band(radioIndex);
1529
1530 memset(output_string, 0, 10);
1531 if (band == band_2_4)
1532 strcpy(output_string, "2.4GHz");
1533 else if (band == band_5)
1534 strcpy(output_string, "5GHz");
1535 else if (band == band_6)
1536 strcpy(output_string, "6GHz");
1537 else
1538 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001539 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1540
1541 return RETURN_OK;
1542#if 0
1543 char buf[MAX_BUF_SIZE]={'\0'};
1544 char str[MAX_BUF_SIZE]={'\0'};
1545 char cmd[MAX_CMD_SIZE]={'\0'};
1546 char *ch=NULL;
1547 char *ch2=NULL;
1548
1549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1550 if (NULL == output_string)
1551 return RETURN_ERR;
1552
1553
1554 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1555
1556 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1557 {
1558 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1559 return RETURN_ERR;
1560 }
1561 ch=strchr(buf,'\n');
1562 *ch='\0';
1563 ch=strchr(buf,'=');
1564 if(ch==NULL)
1565 return RETURN_ERR;
1566
1567
1568 ch++;
1569
1570 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1571 strcpy(buf,"0");
1572 if(strlen(ch) == 1)
1573 ch=strcat(buf,ch);
1574
1575
1576 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1577
1578 if(_syscmd(cmd,str,64) == RETURN_ERR)
1579 {
1580 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1581 return RETURN_ERR;
1582 }
1583
1584
1585 ch2=strchr(str,'\n');
1586 //replace \n with \0
1587 *ch2='\0';
1588 ch2=strchr(str,'=');
1589 if(ch2==NULL)
1590 {
1591 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1592 return RETURN_ERR;
1593 }
1594 else
1595 wifi_dbg_printf("%s",ch2+1);
1596
1597
1598 ch2++;
1599
1600
1601 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1602
1603 memset(buf,'\0',sizeof(buf));
1604 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1605 {
1606 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1607 return RETURN_ERR;
1608 }
1609 if (strstr(buf,"2.4") != NULL )
1610 strcpy(output_string,"2.4GHz");
1611 else if(strstr(buf,"5.") != NULL )
1612 strcpy(output_string,"5GHz");
1613 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1614
1615 return RETURN_OK;
1616#endif
1617}
1618
1619//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1620//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.
1621INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1622{
developerb7593de2022-10-18 09:51:57 +08001623 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1625 if (NULL == output_string)
1626 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001627 band = wifi_index_to_band(radioIndex);
1628
1629 if (band == band_2_4)
1630 snprintf(output_string, 64, "2.4GHz");
1631 else if (band == band_5)
1632 snprintf(output_string, 64, "5GHz");
1633 else if (band == band_6)
1634 snprintf(output_string, 64, "6GHz");
1635
developer06a01d92022-09-07 16:32:39 +08001636 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1637
1638 return RETURN_OK;
1639#if 0
1640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1641 char buf[MAX_BUF_SIZE]={'\0'};
1642 char str[MAX_BUF_SIZE]={'\0'};
1643 char cmd[MAX_CMD_SIZE]={'\0'};
1644 char *ch=NULL;
1645 char *ch2=NULL;
1646 char ch1[5]="0";
1647
1648 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1649
1650 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1651 {
1652 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1653 return RETURN_ERR;
1654 }
1655
1656 ch=strchr(buf,'\n');
1657 *ch='\0';
1658 ch=strchr(buf,'=');
1659 if(ch==NULL)
1660 return RETURN_ERR;
1661 ch++;
1662
1663 if(strlen(ch)==1)
1664 {
1665 strcat(ch1,ch);
1666
1667 }
1668 else
1669 {
1670 strcpy(ch1,ch);
1671 }
1672
1673
1674
1675 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1676 if(_syscmd(cmd,str,64) == RETURN_ERR)
1677 {
1678 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1679 return RETURN_ERR;
1680 }
1681
1682
1683 ch2=strchr(str,'\n');
1684 //replace \n with \0
1685 *ch2='\0';
1686 ch2=strchr(str,'=');
1687 if(ch2==NULL)
1688 {
1689 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1690 return RETURN_ERR;
1691 }
1692 else
1693 wifi_dbg_printf("%s",ch2+1);
1694 ch2++;
1695
1696
1697 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1698 memset(buf,'\0',sizeof(buf));
1699 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1700 {
1701 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1702 return RETURN_ERR;
1703 }
1704
1705
1706 if(strstr(buf,"2.4")!=NULL)
1707 {
1708 strcpy(output_string,"2.4GHz");
1709 }
1710 if(strstr(buf,"5.")!=NULL)
1711 {
1712 strcpy(output_string,"5GHz");
1713 }
1714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1715 return RETURN_OK;
1716#endif
1717}
1718
1719//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1720//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.
1721INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1722{
developer963da0c2022-09-13 15:58:27 +08001723 char cmd[128]={0};
1724 char buf[128]={0};
1725 char temp_output[128] = {0};
1726 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001727 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001728
1729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001730 if (NULL == output_string)
1731 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001732
1733 band = wifi_index_to_band(radioIndex);
1734 if (band == band_2_4) {
1735 strcat(temp_output, "b,g,");
1736 } else if (band == band_5) {
1737 strcat(temp_output, "a,");
1738 }
developer033b37b2022-10-18 11:27:46 +08001739 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001740 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001741 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001742 _syscmd(cmd, buf, sizeof(buf));
1743 if (strncmp(buf, "0x00", 4) != 0) {
1744 strcat(temp_output, "n,");
1745 }
developer06a01d92022-09-07 16:32:39 +08001746
developer963da0c2022-09-13 15:58:27 +08001747 // vht capabilities
1748 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001749 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001750 _syscmd(cmd, buf, sizeof(buf));
1751 if (strncmp(buf, "0x00000000", 10) != 0) {
1752 strcat(temp_output, "ac,");
1753 }
1754 }
1755
1756 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001757 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001758 _syscmd(cmd, buf, sizeof(buf));
1759 if (strncmp (buf, "0x0000", 6) != 0) {
1760 strcat(temp_output, "ax,");
1761 }
1762
1763 // Remove the last comma
1764 if (strlen(temp_output) != 0)
1765 temp_output[strlen(temp_output)-1] = '\0';
1766 strncpy(output_string, temp_output, strlen(temp_output));
1767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001768 return RETURN_OK;
1769}
1770
1771//Get the radio operating mode, and pure mode flag. eg: "ac"
1772//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.
1773INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1774{
1775 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1776 if (NULL == output_string)
1777 return RETURN_ERR;
1778
1779 if (radioIndex == 0) {
1780 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1781 *gOnly = FALSE;
1782 *nOnly = TRUE;
1783 *acOnly = FALSE;
1784 } else {
1785 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1786 *gOnly = FALSE;
1787 *nOnly = FALSE;
1788 *acOnly = FALSE;
1789 }
1790 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1791
1792 return RETURN_OK;
1793#if 0
1794 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1795 char buf[64] = {0};
1796 char config_file[MAX_BUF_SIZE] = {0};
1797
1798 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1799 return RETURN_ERR;
1800
1801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1802 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1803
1804 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1805 if (strlen(buf) == 0)
1806 {
1807 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1808 return RETURN_ERR;
1809 }
1810 if(strcmp(buf,"g")==0)
1811 {
1812 wifi_dbg_printf("\nG\n");
1813 *gOnly=TRUE;
1814 *nOnly=FALSE;
1815 *acOnly=FALSE;
1816 }
1817 else if(strcmp(buf,"n")==0)
1818 {
1819 wifi_dbg_printf("\nN\n");
1820 *gOnly=FALSE;
1821 *nOnly=TRUE;
1822 *acOnly=FALSE;
1823 }
1824 else if(strcmp(buf,"ac")==0)
1825 {
1826 wifi_dbg_printf("\nac\n");
1827 *gOnly=FALSE;
1828 *nOnly=FALSE;
1829 *acOnly=TRUE;
1830 }
1831 /* hostapd-5G.conf has "a" as hw_mode */
1832 else if(strcmp(buf,"a")==0)
1833 {
1834 wifi_dbg_printf("\na\n");
1835 *gOnly=FALSE;
1836 *nOnly=FALSE;
1837 *acOnly=FALSE;
1838 }
1839 else
1840 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1841
1842 //for a,n mode
1843 if(radioIndex == 1)
1844 {
1845 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1846 if(strcmp(buf,"1")==0)
1847 {
1848 strncpy(output_string, "n", 1);
1849 *nOnly=FALSE;
1850 }
1851 }
1852
1853 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1854 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1855 return RETURN_OK;
1856#endif
1857}
1858
developerdb744382022-09-13 15:34:54 +08001859INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1860{
1861 char cmd[128] = {0};
1862 char buf[64] = {0};
1863 char config_file[64] = {0};
1864 wifi_band band;
1865
1866 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1867 if(NULL == output_string || NULL == pureMode)
1868 return RETURN_ERR;
1869
1870 // grep all of the ieee80211 protocol config set to 1
1871 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1872 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1873 _syscmd(cmd, buf, sizeof(buf));
1874
1875 band = wifi_index_to_band(radioIndex);
1876 // puremode is a bit map
1877 *pureMode = 0;
1878 if (band == band_2_4) {
1879 strcat(output_string, "b,g");
1880 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1881 if (strstr(buf, "n") != NULL) {
1882 strcat(output_string, ",n");
1883 *pureMode |= WIFI_MODE_N;
1884 }
1885 if (strstr(buf, "ax") != NULL) {
1886 strcat(output_string, ",ax");
1887 *pureMode |= WIFI_MODE_AX;
1888 }
1889 } else if (band == band_5) {
1890 strcat(output_string, "a");
1891 *pureMode |= WIFI_MODE_A;
1892 if (strstr(buf, "n") != NULL) {
1893 strcat(output_string, ",n");
1894 *pureMode |= WIFI_MODE_N;
1895 }
1896 if (strstr(buf, "ac") != NULL) {
1897 strcat(output_string, ",ac");
1898 *pureMode |= WIFI_MODE_AC;
1899 }
1900 if (strstr(buf, "ax") != NULL) {
1901 strcat(output_string, ",ax");
1902 *pureMode |= WIFI_MODE_AX;
1903 }
1904 } else if (band == band_6) {
1905 if (strstr(buf, "ax") != NULL) {
1906 strcat(output_string, "ax");
1907 *pureMode |= WIFI_MODE_AX;
1908 }
1909 }
1910
1911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1912 return RETURN_OK;
1913}
1914
1915// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001916INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1917{
1918 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1919 if (strcmp (channelMode,"11A") == 0)
1920 {
1921 writeBandWidth(radioIndex,"20MHz");
1922 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1923 printf("\nChannel Mode is 802.11a (5GHz)\n");
1924 }
1925 else if (strcmp (channelMode,"11NAHT20") == 0)
1926 {
1927 writeBandWidth(radioIndex,"20MHz");
1928 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1929 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1930 }
1931 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1932 {
1933 writeBandWidth(radioIndex,"40MHz");
1934 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1935 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1936 }
1937 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1938 {
1939 writeBandWidth(radioIndex,"40MHz");
1940 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1941 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1942 }
1943 else if (strcmp (channelMode,"11ACVHT20") == 0)
1944 {
1945 writeBandWidth(radioIndex,"20MHz");
1946 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1947 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1948 }
1949 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1950 {
1951 writeBandWidth(radioIndex,"40MHz");
1952 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1953 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1954 }
1955 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1956 {
1957 writeBandWidth(radioIndex,"40MHz");
1958 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1959 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1960 }
1961 else if (strcmp (channelMode,"11ACVHT80") == 0)
1962 {
1963 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1964 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1965 }
1966 else if (strcmp (channelMode,"11ACVHT160") == 0)
1967 {
1968 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1969 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1970 }
1971 else if (strcmp (channelMode,"11B") == 0)
1972 {
1973 writeBandWidth(radioIndex,"20MHz");
1974 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1975 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1976 }
1977 else if (strcmp (channelMode,"11G") == 0)
1978 {
1979 writeBandWidth(radioIndex,"20MHz");
1980 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1981 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1982 }
1983 else if (strcmp (channelMode,"11NGHT20") == 0)
1984 {
1985 writeBandWidth(radioIndex,"20MHz");
1986 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1987 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1988 }
1989 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1990 {
1991 writeBandWidth(radioIndex,"40MHz");
1992 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1993 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1994 }
1995 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1996 {
1997 writeBandWidth(radioIndex,"40MHz");
1998 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1999 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2000 }
2001 else
2002 {
2003 return RETURN_ERR;
2004 }
2005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2006
2007 return RETURN_OK;
2008}
2009
developerdb744382022-09-13 15:34:54 +08002010// Set the radio operating mode, and pure mode flag.
2011INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2012{
2013 int num_hostapd_support_mode = 3; // n, ac, ax
2014 struct params list[num_hostapd_support_mode];
2015 char config_file[64] = {0};
2016 char bandwidth[16] = {0};
2017 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002018
developerdb744382022-09-13 15:34:54 +08002019
2020 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2021 // Set radio mode
2022 list[0].name = "ieee80211n";
2023 list[1].name = "ieee80211ac";
2024 list[2].name = "ieee80211ax";
2025 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2026
2027 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002028 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002029 list[0].value = "1";
2030 else
2031 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002032 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002033 list[1].value = "1";
2034 else
2035 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002036 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002037 list[2].value = "1";
2038 else
2039 list[2].value = "0";
2040 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2041
2042 if (channelMode == NULL || strlen(channelMode) == 0)
2043 return RETURN_OK;
2044 // Set bandwidth
2045 if (strstr(channelMode, "40") != NULL)
2046 strcpy(bandwidth, "40MHz");
2047 else if (strstr(channelMode, "80") != NULL)
2048 strcpy(bandwidth, "80MHz");
2049 else if (strstr(channelMode, "160") != NULL)
2050 strcpy(bandwidth, "160MHz");
2051 else // 11A, 11B, 11G....
2052 strcpy(bandwidth, "20MHz");
2053
2054 writeBandWidth(radioIndex, bandwidth);
2055 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2056
2057 wifi_reloadAp(radioIndex);
2058 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2059
2060 return RETURN_OK;
2061}
2062
developer1d12ebf2022-10-04 15:13:38 +08002063INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2064
2065 char config_file[64] = {0};
2066 struct params params = {0};
2067 wifi_band band = band_invalid;
2068
2069 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2070
2071 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002072
2073 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002074 return RETURN_ERR;
2075 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2076 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002077 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2078 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002079
2080 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2081 params.name = "hw_mode";
2082 params.value = hw_mode;
2083 wifi_hostapdWrite(config_file, &params, 1);
2084 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2085
2086 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2087 return RETURN_OK;
2088}
2089
developer06a01d92022-09-07 16:32:39 +08002090//Get the list of supported channel. eg: "1-11"
2091//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.
2092INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2093{
developer6318ed52022-09-13 15:17:58 +08002094 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002095 if (NULL == output_string)
2096 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002097 char cmd[256] = {0};
2098 char buf[128] = {0};
2099 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002100 int phyId = 0;
2101
developer6318ed52022-09-13 15:17:58 +08002102 // Parse possible channel number and separate them with commas.
2103 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002104 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002105 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002106 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002107 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002108 else
developer033b37b2022-10-18 11:27:46 +08002109 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002110
2111 _syscmd(cmd,buf,sizeof(buf));
2112 strncpy(output_string, buf, sizeof(buf));
2113
2114 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2115 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002116}
2117
2118//Get the list for used channel. eg: "1,6,9,11"
2119//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.
2120INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2121{
developerf5745ee2022-10-05 16:09:53 +08002122 char cmd[128] = {0};
2123 char buf[128] = {0};
2124 char config_file[64] = {0};
2125 int channel = 0;
2126 int freq = 0;
2127 int bandwidth = 0;
2128 int center_freq = 0;
2129 int center_channel = 0;
2130 int channel_delta = 0;
2131 wifi_band band = band_invalid;
2132
2133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2134
developer06a01d92022-09-07 16:32:39 +08002135 if (NULL == output_string)
2136 return RETURN_ERR;
2137
developerf5745ee2022-10-05 16:09:53 +08002138 sprintf(cmd, "iw %s%d info | grep channel | sed -e 's/[^0-9 ]//g'", AP_PREFIX, radioIndex);
2139 _syscmd(cmd, buf, sizeof(buf));
2140 if (strlen(buf) == 0) {
2141 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2142 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002143 }
developerf5745ee2022-10-05 16:09:53 +08002144 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2145
2146 if (bandwidth == 20) {
2147 snprintf(output_string, 256, "%d", channel);
2148 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002149 }
developerf5745ee2022-10-05 16:09:53 +08002150
2151 center_channel = ieee80211_frequency_to_channel(center_freq);
2152
2153 band = wifi_index_to_band(radioIndex);
2154 if (band == band_2_4 && bandwidth == 40) {
2155 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2156 memset(buf, 0, sizeof(buf));
2157 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2158
2159 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2160 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2161 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2162 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2163 } else {
2164 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2165 return RETURN_ERR;
2166 }
2167 } else if (band == band_5 || band == band_6){
2168 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2169 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2170 channel_delta = (bandwidth-20)/10;
2171 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2172 } else
2173 return RETURN_ERR;
2174
2175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002176 return RETURN_OK;
2177}
2178
2179//Get the running channel number
2180INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2181{
developerda1ed692022-09-13 13:59:20 +08002182#ifdef MTK_IMPL
2183 if(!wifi_getApChannel(radioIndex, output_ulong))
2184 return RETURN_OK;
2185 else
2186 return RETURN_ERR;
2187#else
developer06a01d92022-09-07 16:32:39 +08002188 char cmd[1024] = {0}, buf[5] = {0};
2189
2190 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2191 if (NULL == output_ulong)
2192 return RETURN_ERR;
2193
2194 snprintf(cmd, sizeof(cmd),
2195 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2196 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2197 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2198 _syscmd(cmd, buf, sizeof(buf));
2199
2200 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2201 if (*output_ulong <= 0) {
2202 *output_ulong = 0;
2203 return RETURN_ERR;
2204 }
2205
2206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2207 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002208#endif
developer06a01d92022-09-07 16:32:39 +08002209}
2210
2211
2212INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2213{
2214 char cmd[1024] = {0}, buf[5] = {0};
2215 char interface_name[50] = {0};
2216
2217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2218 if (NULL == output_ulong)
2219 return RETURN_ERR;
2220
2221 wifi_getApName(apIndex,interface_name);
2222 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2223 _syscmd(cmd,buf,sizeof(buf));
2224 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2225 if (*output_ulong == 0) {
2226 return RETURN_ERR;
2227 }
2228
2229 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2230 return RETURN_OK;
2231}
2232
2233//Storing the previous channel value
2234INT wifi_storeprevchanval(INT radioIndex)
2235{
2236 char buf[256] = {0};
2237 char output[4]={'\0'};
2238 char config_file[MAX_BUF_SIZE] = {0};
2239 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2240 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2241 if(radioIndex == 0)
2242 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2243 else if(radioIndex == 1)
2244 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2245 system(buf);
2246 Radio_flag = FALSE;
2247 return RETURN_OK;
2248}
2249
2250//Set the running channel number
2251INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2252{
developer76989232022-10-04 14:13:19 +08002253 // We only write hostapd config here
2254 char str_channel[8]={0};
2255 char *list_channel;
2256 char config_file[128] = {0};
2257 char possible_channels[256] = {0};
2258 int max_radio_num = 0;
2259 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002260
developer76989232022-10-04 14:13:19 +08002261 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002262
developer76989232022-10-04 14:13:19 +08002263 // Check valid
2264 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002265
developer76989232022-10-04 14:13:19 +08002266 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2267 list_channel = strtok(possible_channels, ",");
2268 while(true)
developer06a01d92022-09-07 16:32:39 +08002269 {
developer76989232022-10-04 14:13:19 +08002270 if(list_channel == NULL) { // input not in the list
2271 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2272 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002273 }
developer76989232022-10-04 14:13:19 +08002274 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2275 break;
2276 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002277 }
2278
developer76989232022-10-04 14:13:19 +08002279 list.name = "channel";
2280 list.value = str_channel;
2281 wifi_getMaxRadioNumber(&max_radio_num);
2282 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002283 {
developer76989232022-10-04 14:13:19 +08002284 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2285 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002286 }
2287
developer76989232022-10-04 14:13:19 +08002288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002289 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002290}
developer06a01d92022-09-07 16:32:39 +08002291
2292INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2293{
developer76989232022-10-04 14:13:19 +08002294 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002295 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002296 char config_file[64];
2297 int max_num_radios = 0;
2298 wifi_band band = band_invalid;
2299
2300 band = wifi_index_to_band(radioIndex);
2301 if (band == band_2_4)
2302 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002303
developer06a01d92022-09-07 16:32:39 +08002304 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002305 list[0].name = "vht_oper_centr_freq_seg0_idx";
2306 list[0].value = str_idx;
2307 list[1].name = "he_oper_centr_freq_seg0_idx";
2308 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002309
developer76989232022-10-04 14:13:19 +08002310 wifi_getMaxRadioNumber(&max_num_radios);
2311 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002312 {
developer76989232022-10-04 14:13:19 +08002313 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2314 if (band == band_6)
2315 wifi_hostapdWrite(config_file, &list[1], 1);
2316 else
2317 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002318 }
2319
2320 return RETURN_OK;
2321}
2322
2323//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2324//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2325INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2326{
2327 //Set to wifi config only. Wait for wifi reset to apply.
2328 char buf[256] = {0};
2329 char str_channel[256] = {0};
2330 int count = 0;
2331 ULONG Value = 0;
2332 FILE *fp = NULL;
2333 if(enable == TRUE)
2334 {
developer06a01d92022-09-07 16:32:39 +08002335 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002336 }
developer5884e982022-10-06 10:52:50 +08002337 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002338}
2339
developer0b246d12022-09-30 15:24:20 +08002340INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2341{
2342 if (output_bool == NULL)
2343 return RETURN_ERR;
2344
2345 *output_bool = TRUE;
2346
2347 return RETURN_OK;
2348}
2349
developer06a01d92022-09-07 16:32:39 +08002350INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2351{
2352 if (NULL == output_bool)
2353 return RETURN_ERR;
2354 *output_bool=FALSE;
2355 return RETURN_OK;
2356}
2357
2358INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2359{
2360 if (NULL == output_bool)
2361 return RETURN_ERR;
2362 *output_bool=FALSE;
2363 return RETURN_OK;
2364}
2365
2366INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2367{
2368 //Set to wifi config only. Wait for wifi reset to apply.
2369 return RETURN_OK;
2370}
2371
2372INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2373{
2374 return RETURN_OK;
2375}
2376
2377INT wifi_factoryResetAP(int apIndex)
2378{
developer838cca92022-10-03 13:19:57 +08002379 char ap_config_file[64] = {0};
2380 char cmd[128] = {0};
2381
developer06a01d92022-09-07 16:32:39 +08002382 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002383
2384 wifi_setApEnable(apIndex, FALSE);
2385 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2386 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2387 wifi_setApEnable(apIndex, TRUE);
2388
developer06a01d92022-09-07 16:32:39 +08002389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002390
developer06a01d92022-09-07 16:32:39 +08002391 return RETURN_OK;
2392}
2393
2394//To set Band Steering AP group
2395//To-do
2396INT wifi_setBandSteeringApGroup(char *ApGroup)
2397{
2398 return RETURN_OK;
2399}
2400
developer1e5aa162022-09-13 16:06:24 +08002401INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2402{
2403 char config_file[128] = {'\0'};
2404 char buf[128] = {'\0'};
2405
2406 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2407 if (dtimInterval == NULL)
2408 return RETURN_ERR;
2409
2410 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2411 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2412
2413 if (strlen(buf) == 0) {
2414 *dtimInterval = 2;
2415 } else {
2416 *dtimInterval = strtoul(buf, NULL, 10);
2417 }
2418
2419 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2420 return RETURN_OK;
2421}
2422
developer06a01d92022-09-07 16:32:39 +08002423INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2424{
developer5f222492022-09-13 15:21:52 +08002425 struct params params={0};
2426 char config_file[MAX_BUF_SIZE] = {'\0'};
2427 char buf[MAX_BUF_SIZE] = {'\0'};
2428
2429 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2430 if (dtimInterval < 1 || dtimInterval > 255) {
2431 return RETURN_ERR;
2432 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2433 }
2434
2435 params.name = "dtim_period";
2436 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2437 params.value = buf;
2438
2439 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2440 wifi_hostapdWrite(config_file, &params, 1);
2441 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2442
2443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2444 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002445}
2446
2447//Check if the driver support the Dfs
2448INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2449{
2450 if (NULL == output_bool)
2451 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002452 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002453 return RETURN_OK;
2454}
2455
2456//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.
2457//The value of this parameter is a comma seperated list of channel number
2458INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2459{
2460 if (NULL == output_pool)
2461 return RETURN_ERR;
2462 if (radioIndex==1)
2463 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2464 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2465
2466 return RETURN_OK;
2467}
2468
2469INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2470{
2471 //Set to wifi config. And apply instantly.
2472 return RETURN_OK;
2473}
2474
2475INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2476{
2477 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2478 return RETURN_ERR;
2479 *output_interval_seconds=1800;
2480 *output_dwell_milliseconds=40;
2481
2482 return RETURN_OK;
2483}
2484
2485INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2486{
2487 //Set to wifi config. And apply instantly.
2488 return RETURN_OK;
2489}
2490
developerbfc18512022-10-05 17:54:28 +08002491INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2492{
2493 if (output_bool == NULL)
2494 return RETURN_ERR;
2495 *output_bool = true;
2496 return RETURN_OK;
2497}
2498
2499INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2500{
2501 return RETURN_OK;
2502}
2503
developer06a01d92022-09-07 16:32:39 +08002504//Get the Dfs enable status
2505INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2506{
developer9964b5b2022-09-13 15:59:34 +08002507 char buf[16] = {0};
2508 FILE *f = NULL;
2509 wifi_band band;
2510
2511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2512
2513 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002514 if (NULL == output_bool)
2515 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002516
2517 band = wifi_index_to_band(radioIndex);
2518 if (band != band_5)
2519 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002520
developer9964b5b2022-09-13 15:59:34 +08002521 f = fopen(DFS_ENABLE_FILE, "r");
2522 if (f != NULL) {
2523 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002524 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002525 *output_bool = FALSE;
2526 fclose(f);
2527 }
2528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002529 return RETURN_OK;
2530}
2531
2532//Set the Dfs enable status
2533INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2534{
developer9964b5b2022-09-13 15:59:34 +08002535 char config_file[128] = {0};
2536 FILE *f = NULL;
2537 struct params params={0};
2538 wifi_band band;
2539
2540 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2541
2542 band = wifi_index_to_band(radioIndex);
2543 if (band != band_5)
2544 return RETURN_OK;
2545
2546 f = fopen(DFS_ENABLE_FILE, "w");
2547 if (f == NULL)
2548 return RETURN_ERR;
2549 fprintf(f, "%d", enable);
2550 fclose(f);
2551
2552 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002553 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002554 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2555 wifi_hostapdWrite(config_file, &params, 1);
2556 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2557
2558 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2559
developer9964b5b2022-09-13 15:59:34 +08002560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002561 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002562}
2563
2564//Check if the driver support the AutoChannelRefreshPeriod
2565INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2566{
2567 if (NULL == output_bool)
2568 return RETURN_ERR;
2569 *output_bool=FALSE; //not support
2570
2571 return RETURN_OK;
2572}
2573
2574//Get the ACS refresh period in seconds
2575INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2576{
2577 if (NULL == output_ulong)
2578 return RETURN_ERR;
2579 *output_ulong=300;
2580
2581 return RETURN_OK;
2582}
2583
2584//Set the ACS refresh period in seconds
2585INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2586{
2587 return RETURN_ERR;
2588}
2589
2590//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2591//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.
2592INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2593{
developer70490032022-09-13 15:45:20 +08002594 char cmd[128] = {0}, buf[64] = {0};
2595 char interface_name[64] = {0};
2596 int ret = 0, len=0;
2597 BOOL radio_enable = FALSE;
2598
2599 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2600
developer06a01d92022-09-07 16:32:39 +08002601 if (NULL == output_string)
2602 return RETURN_ERR;
2603
developer70490032022-09-13 15:45:20 +08002604 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2605 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002606
developer70490032022-09-13 15:45:20 +08002607 if (radio_enable != TRUE)
2608 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002609
developer70490032022-09-13 15:45:20 +08002610 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002611 ret = _syscmd(cmd, buf, sizeof(buf));
2612 len = strlen(buf);
2613 if((ret != 0) || (len == 0))
2614 {
2615 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2616 return RETURN_ERR;
2617 }
2618
2619 buf[len-1] = '\0';
2620 snprintf(output_string, 64, "%sMHz", buf);
2621 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2622
2623#if 0
2624 //TODO: revisit below implementation
2625 char output_buf[8]={0};
2626 char bw_value[10];
2627 char config_file[MAX_BUF_SIZE] = {0};
2628
2629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2630 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2631 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2632 readBandWidth(radioIndex,bw_value);
2633
2634 if(strstr (output_buf,"0") != NULL )
2635 {
2636 strcpy(output_string,bw_value);
2637 }
2638 else if (strstr (output_buf,"1") != NULL)
2639 {
2640 strcpy(output_string,"80MHz");
2641 }
2642 else if (strstr (output_buf,"2") != NULL)
2643 {
2644 strcpy(output_string,"160MHz");
2645 }
2646 else if (strstr (output_buf,"3") != NULL)
2647 {
2648 strcpy(output_string,"80+80");
2649 }
2650 else
2651 {
2652 strcpy(output_string,"Auto");
2653 }
2654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2655#endif
2656
2657 return RETURN_OK;
2658}
2659
2660//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002661INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002662{
developerf7a466e2022-09-29 11:55:56 +08002663 char config_file[128];
2664 char set_value[16];
2665 struct params params[2];
2666 int max_radio_num = 0;
2667
developer06a01d92022-09-07 16:32:39 +08002668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002669
developerf7a466e2022-09-29 11:55:56 +08002670 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002671 return RETURN_ERR;
2672
developerf7a466e2022-09-29 11:55:56 +08002673 if(strstr(bandwidth,"80+80") != NULL)
2674 strcpy(set_value, "3");
2675 else if(strstr(bandwidth,"160") != NULL)
2676 strcpy(set_value, "2");
2677 else if(strstr(bandwidth,"80") != NULL)
2678 strcpy(set_value, "1");
2679 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2680 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002681 else
2682 {
developerf7a466e2022-09-29 11:55:56 +08002683 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002684 return RETURN_ERR;
2685 }
2686
developerf7a466e2022-09-29 11:55:56 +08002687 params[0].name = "vht_oper_chwidth";
2688 params[0].value = set_value;
2689 params[1].name = "he_oper_chwidth";
2690 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002691
developerf7a466e2022-09-29 11:55:56 +08002692 wifi_getMaxRadioNumber(&max_radio_num);
2693 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002694 {
developerf7a466e2022-09-29 11:55:56 +08002695 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2696 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002697 }
2698
2699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2700 return RETURN_OK;
2701}
2702
2703//Getting current radio extension channel
2704INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2705{
2706 CHAR buf[150] = {0};
2707 CHAR cmd[150] = {0};
2708 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2709 _syscmd(cmd, buf, sizeof(buf));
2710 if(NULL != strstr(buf,"HT40+"))
2711 strcpy(Value,"AboveControlChannel");
2712 else if(NULL != strstr(buf,"HT40-"))
2713 strcpy(Value,"BelowControlChannel");
2714 return RETURN_OK;
2715}
2716
2717//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2718//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.
2719INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2720{
2721 if (NULL == output_string)
2722 return RETURN_ERR;
2723
2724 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2725#if 0
2726 CHAR Value[100] = {0};
2727 if (NULL == output_string)
2728 return RETURN_ERR;
2729 if(radioIndex == 0)
2730 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2731 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2732 {
2733 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2734 if(strcmp(Value,"40MHz") == 0)
2735 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2736 else
2737 strcpy(Value,"Auto");
2738 }
2739 strcpy(output_string,Value);
2740#endif
2741
2742 return RETURN_OK;
2743}
2744
2745//Set the extension channel.
2746INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2747{
2748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2749 struct params params={'\0'};
2750 char config_file[MAX_BUF_SIZE] = {0};
2751 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002752 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002753 params.name = "ht_capab";
2754
developer033b37b2022-10-18 11:27:46 +08002755 if(NULL!= strstr(string,"Above"))
2756 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2757 else if(NULL!= strstr(string,"Below"))
2758 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2759 else
2760 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2761
developer06a01d92022-09-07 16:32:39 +08002762
2763 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002764
2765 wifi_getMaxRadioNumber(&max_radio_num);
2766 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002767 {
developer033b37b2022-10-18 11:27:46 +08002768 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002769 wifi_hostapdWrite(config_file, &params, 1);
2770 }
2771
2772 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2774 return RETURN_OK;
2775}
2776
2777//Get the guard interval value. eg "400nsec" or "800nsec"
2778//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.
2779INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2780{
developer454b9462022-09-13 15:29:16 +08002781 wifi_guard_interval_t GI;
2782
2783 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2784
2785 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002786 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002787
2788 if (GI == wifi_guard_interval_400)
2789 strcpy(output_string, "400nsec");
2790 else if (GI == wifi_guard_interval_800)
2791 strcpy(output_string, "800nsec");
2792 else if (GI == wifi_guard_interval_1600)
2793 strcpy(output_string, "1600nsec");
2794 else if (GI == wifi_guard_interval_3200)
2795 strcpy(output_string, "3200nsec");
2796 else
2797 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002798
developer454b9462022-09-13 15:29:16 +08002799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002800 return RETURN_OK;
2801}
2802
2803//Set the guard interval value.
2804INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2805{
developer454b9462022-09-13 15:29:16 +08002806 wifi_guard_interval_t GI;
2807 int ret = 0;
2808
2809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2810
2811 if (strcmp(string, "400nsec") == 0)
2812 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002813 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002814 GI = wifi_guard_interval_800;
2815 else if (strcmp(string , "1600nsec") == 0)
2816 GI = wifi_guard_interval_1600;
2817 else if (strcmp(string , "3200nsec") == 0)
2818 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002819 else
2820 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002821
2822 ret = wifi_setGuardInterval(radioIndex, GI);
2823
2824 if (ret == RETURN_ERR) {
2825 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2826 return RETURN_ERR;
2827 }
2828
2829 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2830 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002831}
2832
2833//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2834INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2835{
developerf49437e2022-09-29 19:58:21 +08002836 char buf[32]={0};
2837 char mcs_file[64] = {0};
2838 char cmd[64] = {0};
2839 int mode_bitmap = 0;
2840
2841 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2842 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002843 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002844 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2845
2846 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2847 _syscmd(cmd, buf, sizeof(buf));
2848 if (strlen(buf) > 0)
2849 *output_int = strtol(buf, NULL, 10);
2850 else {
2851 // output the max MCS for the current radio mode
2852 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2853 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2854 return RETURN_ERR;
2855 }
2856 if (mode_bitmap & WIFI_MODE_AX) {
2857 *output_int = 11;
2858 } else if (mode_bitmap & WIFI_MODE_AC) {
2859 *output_int = 9;
2860 } else if (mode_bitmap & WIFI_MODE_N) {
2861 *output_int = 7;
2862 }
2863 }
2864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002865
2866 return RETURN_OK;
2867}
2868
2869//Set the Modulation Coding Scheme index
2870INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2871{
developerf49437e2022-09-29 19:58:21 +08002872 // 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).
2873 char config_file[64] = {0};
2874 char set_value[16] = {0};
2875 char mcs_file[32] = {0};
2876 wifi_band band = band_invalid;
2877 struct params set_config = {0};
2878 FILE *f = NULL;
2879
2880 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2881
2882 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2883
2884 if (MCS > 11 || MCS < 0) {
2885 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2886 return RETURN_ERR;
2887 }
2888
2889 if (MCS <= 7)
2890 strcpy(set_value, "0");
2891 else if (MCS <= 9)
2892 strcpy(set_value, "1");
2893 else
2894 strcpy(set_value, "2");
2895
2896 set_config.name = "he_basic_mcs_nss_set";
2897 set_config.value = set_value;
2898
2899 wifi_hostapdWrite(config_file, &set_config, 1);
2900 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2901
2902 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2903 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2904 f = fopen(mcs_file, "w");
2905 if (f == NULL) {
2906 fprintf(stderr, "%s: fopen failed\n", __func__);
2907 return RETURN_ERR;
2908 }
2909 fprintf(f, "%d", MCS);
2910 fclose(f);
2911
2912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2913 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002914}
2915
2916//Get supported Transmit Power list, eg : "0,25,50,75,100"
2917//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.
2918INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2919{
2920 if (NULL == output_list)
2921 return RETURN_ERR;
2922 snprintf(output_list, 64,"0,25,50,75,100");
2923 return RETURN_OK;
2924}
2925
developera5005b62022-09-13 15:43:35 +08002926//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002927//The transmite power level is in units of full power for this radio.
2928INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2929{
2930 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002931 char buf[16]={0};
2932 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002933
developera5005b62022-09-13 15:43:35 +08002934 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002935 return RETURN_ERR;
2936
developera5005b62022-09-13 15:43:35 +08002937 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 +08002938 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002939
developera5005b62022-09-13 15:43:35 +08002940 *output_ulong = strtol(buf, NULL, 10);
2941
2942 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002943 return RETURN_OK;
2944}
2945
2946//Set Transmit Power
2947//The transmite power level is in units of full power for this radio.
2948INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2949{
developera5005b62022-09-13 15:43:35 +08002950 char *support;
developer06a01d92022-09-07 16:32:39 +08002951 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002952 char buf[128]={0};
2953 char txpower_str[64] = {0};
2954 int txpower = 0;
2955 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08002956 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08002957
2958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002959
developera5005b62022-09-13 15:43:35 +08002960 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 +08002961 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002962 maximum_tx = strtol(buf, NULL, 10);
2963
2964 // Get the Tx power supported list and check that is the input in the list
2965 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2966 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2967 support = strtok(buf, ",");
2968 while(true)
2969 {
2970 if(support == NULL) { // input not in the list
2971 wifi_dbg_printf("Input value is invalid.\n");
2972 return RETURN_ERR;
2973 }
2974 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2975 break;
2976 }
2977 support = strtok(NULL, ",");
2978 }
2979 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08002980 phyId = radio_index_to_phy(radioIndex);
2981 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08002982 _syscmd(cmd, buf, sizeof(buf));
2983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002984
2985 return RETURN_OK;
2986}
2987
2988//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2989INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2990{
2991 if (NULL == Supported)
2992 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002993 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002994
2995 return RETURN_OK;
2996}
2997
2998//Get 80211h feature enable
2999INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3000{
developer3885fec2022-09-13 15:13:47 +08003001 char buf[64]={'\0'};
3002 char config_file[64] = {'\0'};
3003
3004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3005 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003006 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003007
3008 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3009 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003010
developer3885fec2022-09-13 15:13:47 +08003011 if (strncmp(buf, "1", 1) == 0)
3012 *enable = TRUE;
3013 else
3014 *enable = FALSE;
3015
3016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003017 return RETURN_OK;
3018}
3019
3020//Set 80211h feature enable
3021INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3022{
developer3885fec2022-09-13 15:13:47 +08003023 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3024 struct params params={'\0'};
3025 char config_file[MAX_BUF_SIZE] = {0};
3026
3027 params.name = "ieee80211h";
3028
3029 if (enable) {
3030 params.value = "1";
3031 } else {
3032 params.value = "0";
3033 }
3034
3035 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3036 wifi_hostapdWrite(config_file, &params, 1);
3037
3038 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3039 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3040 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003041}
3042
3043//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.
3044INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3045{
3046 if (NULL == output)
3047 return RETURN_ERR;
3048 *output=100;
3049
3050 return RETURN_OK;
3051}
3052
3053//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.
3054INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3055{
3056 if (NULL == output)
3057 return RETURN_ERR;
3058 *output = -99;
3059
3060 return RETURN_OK;
3061}
3062
3063INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3064{
3065 return RETURN_ERR;
3066}
3067
3068
3069//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3070INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3071{
developer5f222492022-09-13 15:21:52 +08003072 char cmd[MAX_BUF_SIZE]={'\0'};
3073 char buf[MAX_CMD_SIZE]={'\0'};
3074
3075 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3076 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003077 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003078
3079 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3080 _syscmd(cmd, buf, sizeof(buf));
3081 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003082
developer5f222492022-09-13 15:21:52 +08003083 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003084 return RETURN_OK;
3085}
3086
3087INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3088{
developer5f222492022-09-13 15:21:52 +08003089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3090 struct params params={'\0'};
3091 char buf[MAX_BUF_SIZE] = {'\0'};
3092 char config_file[MAX_BUF_SIZE] = {'\0'};
3093
3094 params.name = "beacon_int";
3095 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3096 params.value = buf;
3097
3098 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3099 wifi_hostapdWrite(config_file, &params, 1);
3100
3101 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3102 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3103 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003104}
3105
3106//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.
3107INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3108{
developer06a01d92022-09-07 16:32:39 +08003109 //TODO: need to revisit below implementation
3110 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003111 char temp_output[128] = {0};
3112 char temp_TransmitRates[64] = {0};
3113 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003114
3115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3116 if (NULL == output)
3117 return RETURN_ERR;
3118 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003119 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3120
3121 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3122 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3123 } else {
3124 temp = strtok(temp_TransmitRates," ");
3125 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003126 {
developere9d0abd2022-09-13 15:40:57 +08003127 // Convert 100 kbps to Mbps
3128 temp[strlen(temp)-1]=0;
3129 if((temp[0]=='5') && (temp[1]=='\0'))
3130 {
3131 temp="5.5";
3132 }
3133 strcat(temp_output,temp);
3134 temp = strtok(NULL," ");
3135 if(temp!=NULL)
3136 {
3137 strcat(temp_output,",");
3138 }
developer06a01d92022-09-07 16:32:39 +08003139 }
developere9d0abd2022-09-13 15:40:57 +08003140 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003141 }
developer06a01d92022-09-07 16:32:39 +08003142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003143 return RETURN_OK;
3144}
3145
3146INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3147{
3148 char *temp;
3149 char temp1[128];
3150 char temp_output[128];
3151 char temp_TransmitRates[128];
3152 char set[128];
3153 char sub_set[128];
3154 int set_count=0,subset_count=0;
3155 int set_index=0,subset_index=0;
3156 char *token;
3157 int flag=0, i=0;
3158 struct params params={'\0'};
3159 char config_file[MAX_BUF_SIZE] = {0};
3160
3161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3162 if(NULL == TransmitRates)
3163 return RETURN_ERR;
3164 strcpy(sub_set,TransmitRates);
3165
3166 //Allow only supported Data transmit rate to be set
3167 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3168 token = strtok(sub_set,",");
3169 while( token != NULL ) /* split the basic rate to be set, by comma */
3170 {
3171 sub_set[subset_count]=atoi(token);
3172 subset_count++;
3173 token=strtok(NULL,",");
3174 }
3175 token=strtok(set,",");
3176 while(token!=NULL) /* split the supported rate by comma */
3177 {
3178 set[set_count]=atoi(token);
3179 set_count++;
3180 token=strtok(NULL,",");
3181 }
3182 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3183 {
3184 for(set_index=0;set_index < set_count;set_index++)
3185 {
3186 flag=0;
3187 if(sub_set[subset_index]==set[set_index])
3188 break;
3189 else
3190 flag=1; /* No match found */
3191 }
3192 if(flag==1)
3193 return RETURN_ERR; //If value not found return Error
3194 }
3195 strcpy(temp_TransmitRates,TransmitRates);
3196
3197 for(i=0;i<strlen(temp_TransmitRates);i++)
3198 {
3199 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3200 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3201 {
3202 continue;
3203 }
3204 else
3205 {
3206 return RETURN_ERR;
3207 }
3208 }
3209 strcpy(temp_output,"");
3210 temp = strtok(temp_TransmitRates,",");
3211 while(temp!=NULL)
3212 {
3213 strcpy(temp1,temp);
3214 if(radioIndex==1)
3215 {
3216 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3217 {
3218 return RETURN_ERR;
3219 }
3220 }
3221
3222 if(strcmp(temp,"5.5")==0)
3223 {
3224 strcpy(temp1,"55");
3225 }
3226 else
3227 {
3228 strcat(temp1,"0");
3229 }
3230 strcat(temp_output,temp1);
3231 temp = strtok(NULL,",");
3232 if(temp!=NULL)
3233 {
3234 strcat(temp_output," ");
3235 }
3236 }
3237 strcpy(TransmitRates,temp_output);
3238
3239 params.name= "basic_rates";
3240 params.value =TransmitRates;
3241
3242 wifi_dbg_printf("\n%s:",__func__);
3243 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3244 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3245 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3246 wifi_hostapdWrite(config_file,&params,1);
3247 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3248 return RETURN_OK;
3249}
3250
3251//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3252INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3253{
3254 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3255 FILE *fp = NULL;
3256 char path[256] = {0}, output_string[256] = {0};
3257 int count = 0;
3258 char *interface = NULL;
3259
3260 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3261 if (fp == NULL)
3262 {
3263 printf("Failed to run command in Function %s\n", __FUNCTION__);
3264 return RETURN_ERR;
3265 }
3266 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3267 {
3268 interface = strchr(path, '=');
3269
3270 if (interface != NULL)
3271 {
3272 strcpy(output_string, interface + 1);
3273 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3274 interface_name[count] = output_string[count];
3275
3276 interface_name[count] = '\0';
3277 }
3278 }
3279 pclose(fp);
3280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3281 return RETURN_OK;
3282}
3283
3284INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3285{
3286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3287 output_struct->radio_BytesSent = 0;
3288 output_struct->radio_BytesReceived = 0;
3289 output_struct->radio_PacketsSent = 0;
3290 output_struct->radio_PacketsReceived = 0;
3291 output_struct->radio_ErrorsSent = 0;
3292 output_struct->radio_ErrorsReceived = 0;
3293 output_struct->radio_DiscardPacketsSent = 0;
3294 output_struct->radio_DiscardPacketsReceived = 0;
3295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3296 return RETURN_OK;
3297}
3298
3299
3300INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3301{
3302 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3303 CHAR buf[MAX_CMD_SIZE] = {0};
3304 CHAR Value[MAX_BUF_SIZE] = {0};
3305 FILE *fp = NULL;
3306
3307 if (ifname == NULL || strlen(ifname) <= 1)
3308 return RETURN_OK;
3309
3310 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3311 system(buf);
3312
3313 fp = fopen("/tmp/Radio_Stats.txt", "r");
3314 if(fp == NULL)
3315 {
3316 printf("/tmp/Radio_Stats.txt not exists \n");
3317 return RETURN_ERR;
3318 }
3319 fclose(fp);
3320
3321 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3322 File_Reading(buf, Value);
3323 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3324
3325 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3326 File_Reading(buf, Value);
3327 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3328
3329 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3330 File_Reading(buf, Value);
3331 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3332
3333 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3334 File_Reading(buf, Value);
3335 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3336
3337 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3338 File_Reading(buf, Value);
3339 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3340
3341 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3342 File_Reading(buf, Value);
3343 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3344
3345 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3346 File_Reading(buf, Value);
3347 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3348
3349 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3350 File_Reading(buf, Value);
3351 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3352
3353 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3354 return RETURN_OK;
3355}
3356
3357INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3358{
3359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3360 CHAR buf[MAX_CMD_SIZE] = {0};
3361 FILE *fp = NULL;
3362 INT count = 0;
3363
3364 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3365 {
3366 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3367 File_Reading(buf, status);
3368 }
3369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3370 return RETURN_OK;
3371}
3372
3373//Get detail radio traffic static info
3374INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3375{
3376
3377#if 0
3378 //ifconfig radio_x
3379 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3380 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3381 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3382 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3383
3384 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3385 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3386 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.
3387 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.
3388
3389 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3390 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].
3391 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3392 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.
3393 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
3394 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
3395 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
3396 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
3397 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
3398
3399 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
3400 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
3401 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
3402 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.
3403
3404 return RETURN_OK;
3405#endif
3406
developera91d99f2022-09-29 15:59:10 +08003407 CHAR interface_name[64] = {0};
3408 CHAR config_path[64] = {0};
3409 BOOL iface_status = FALSE;
3410 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003411
3412 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3413 if (NULL == output_struct)
3414 return RETURN_ERR;
3415
developera91d99f2022-09-29 15:59:10 +08003416 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3417 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003418
developera91d99f2022-09-29 15:59:10 +08003419 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003420
developera91d99f2022-09-29 15:59:10 +08003421 if (iface_status == TRUE)
3422 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3423 else
3424 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003425
developera91d99f2022-09-29 15:59:10 +08003426 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3427 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3428 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3429 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3430 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3431 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3432 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3433 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003434
3435 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3436 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].
3437 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3438 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.
3439 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
3440 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
3441 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
3442 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
3443 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
3444
3445 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
3446 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
3447 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
3448 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.
3449
3450 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3451
3452 return RETURN_OK;
3453}
3454
3455//Set radio traffic static Measureing rules
3456INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3457{
3458 //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
3459 // Else, save the MeasuringRate and MeasuringInterval for future usage
3460
3461 return RETURN_OK;
3462}
3463
3464//To start or stop RadioTrafficStats
3465INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3466{
3467 //zqiu: If the RadioTrafficStats process running
3468 // if(enable)
3469 // return RETURN_OK.
3470 // else
3471 // Stop RadioTrafficStats process
3472 // Else
3473 // if(enable)
3474 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3475 // else
3476 // return RETURN_OK.
3477
3478 return RETURN_OK;
3479}
3480
3481//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
3482INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3483{
3484 //zqiu: Please ignor signalIndex.
3485 if (NULL == SignalLevel)
3486 return RETURN_ERR;
3487 *SignalLevel=(radioIndex==0)?-19:-19;
3488
3489 return RETURN_OK;
3490}
3491
3492//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3493INT wifi_applyRadioSettings(INT radioIndex)
3494{
3495 return RETURN_OK;
3496}
3497
3498//Get the radio index assocated with this SSID entry
3499INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3500{
3501 if (NULL == radioIndex)
3502 return RETURN_ERR;
3503 *radioIndex=ssidIndex%2;
3504
3505 return RETURN_OK;
3506}
3507
3508//Device.WiFi.SSID.{i}.Enable
3509//Get SSID enable configuration parameters (not the SSID enable status)
3510INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3511{
3512 if (NULL == output_bool)
3513 return RETURN_ERR;
3514
3515 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3516 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3517 return wifi_getApEnable(ssidIndex, output_bool);
3518}
3519
3520//Device.WiFi.SSID.{i}.Enable
3521//Set SSID enable configuration parameters
3522INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3523{
3524 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3525 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3526 return wifi_setApEnable(ssidIndex, enable);
3527}
3528
3529//Device.WiFi.SSID.{i}.Status
3530//Get the SSID enable status
3531INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3532{
3533 char cmd[MAX_CMD_SIZE]={0};
3534 char buf[MAX_BUF_SIZE]={0};
3535 BOOL output_bool;
3536
3537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3538 if (NULL == output_string)
3539 return RETURN_ERR;
3540 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3541 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3542
3543 wifi_getApEnable(ssidIndex,&output_bool);
3544 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3545
3546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3547 return RETURN_OK;
3548}
3549
3550// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3551INT wifi_getSSIDName(INT apIndex, CHAR *output)
3552{
3553 char config_file[MAX_BUF_SIZE] = {0};
3554
3555 if (NULL == output)
3556 return RETURN_ERR;
3557
3558 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3559 wifi_hostapdRead(config_file,"ssid",output,32);
3560
3561 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3562 return RETURN_OK;
3563}
3564
3565// Set a max 32 byte string and sets an internal variable to the SSID name
3566INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3567{
3568 char str[MAX_BUF_SIZE]={'\0'};
3569 char cmd[MAX_CMD_SIZE]={'\0'};
3570 struct params params;
3571 char config_file[MAX_BUF_SIZE] = {0};
3572
3573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3574 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3575 return RETURN_ERR;
3576
3577 params.name = "ssid";
3578 params.value = ssid_string;
3579 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3580 wifi_hostapdWrite(config_file, &params, 1);
3581 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3583
3584 return RETURN_OK;
3585}
3586
3587//Get the BSSID
3588INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3589{
3590 char cmd[MAX_CMD_SIZE]="";
3591
3592 if (NULL == output_string)
3593 return RETURN_ERR;
3594
3595 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3596 {
developer1d57d002022-10-12 18:03:15 +08003597 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
developer06a01d92022-09-07 16:32:39 +08003598 _syscmd(cmd, output_string, 64);
3599 return RETURN_OK;
3600 }
3601 strncpy(output_string, "\0", 1);
3602
3603 return RETURN_ERR;
3604}
3605
3606//Get the MAC address associated with this Wifi SSID
3607INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3608{
3609 wifi_getBaseBSSID(ssidIndex,output_string);
3610 return RETURN_OK;
3611}
3612
3613//Get the basic SSID traffic static info
3614//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3615//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3616INT wifi_applySSIDSettings(INT ssidIndex)
3617{
3618 BOOL status = false;
3619 char cmd[MAX_CMD_SIZE] = {0};
3620 char buf[MAX_CMD_SIZE] = {0};
3621 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003622 int max_radio_num = 0;
3623 int radioIndex = 0;
3624
3625 wifi_getMaxRadioNumber(&max_radio_num);
3626
3627 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003628
3629 wifi_getApEnable(ssidIndex,&status);
3630 // Do not apply when ssid index is disabled
3631 if (status == false)
3632 return RETURN_OK;
3633
3634 /* Doing full remove and add for ssid Index
3635 * Not all hostapd options are supported with reload
3636 * for example macaddr_acl
3637 */
3638 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3639 return RETURN_ERR;
3640
3641 ret = wifi_setApEnable(ssidIndex,true);
3642
3643 /* Workaround for hostapd issue with multiple bss definitions
3644 * when first created interface will be removed
3645 * then all vaps other vaps on same phy are removed
3646 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003647 for(int i=0; i < MAX_APS/max_radio_num; i++) {
3648 apIndex = max_radio_num*i+radioIndex;
developer06a01d92022-09-07 16:32:39 +08003649 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3650 _syscmd(cmd, buf, sizeof(buf));
3651 if(*buf == '1')
3652 wifi_setApEnable(apIndex, true);
3653 }
3654
3655 return ret;
3656}
3657
developera3c68b92022-09-13 15:27:29 +08003658struct channels_noise {
3659 int channel;
3660 int noise;
3661};
3662
3663// Return noise array for each channel
3664int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3665{
3666 FILE *f = NULL;
3667 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003668 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003669 size_t len = 0;
3670 ssize_t read = 0;
3671 int tmp = 0, arr_index = -1;
3672
3673 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3674
3675 if ((f = popen(cmd, "r")) == NULL) {
3676 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3677 return RETURN_ERR;
3678 }
developer5550e242022-09-30 09:59:32 +08003679
3680 while(fgets(line, sizeof(line), f) != NULL) {
3681 if(arr_index < channels_num){
3682 sscanf(line, "%d", &tmp);
3683 if (tmp > 0) { // channel frequency, the first line must be frequency
3684 arr_index++;
3685 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3686 } else { // noise
3687 channels_noise_arr[arr_index].noise = tmp;
3688 }
3689 }else{
3690 break;
developera3c68b92022-09-13 15:27:29 +08003691 }
3692 }
developera3c68b92022-09-13 15:27:29 +08003693 pclose(f);
3694 return RETURN_OK;
3695}
3696
developer06a01d92022-09-07 16:32:39 +08003697//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3698//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3699INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3700{
developera3c68b92022-09-13 15:27:29 +08003701 int index = -1;
3702 wifi_neighbor_ap2_t *scan_array = NULL;
3703 char cmd[256]={0};
3704 char buf[128]={0};
3705 char file_name[32] = {0};
3706 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003707 char line[256] = {0};
3708 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003709 int freq=0;
3710 FILE *f = NULL;
3711 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003712 int channels_num = 0;
3713 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003714 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003715 bool filter_enable = false;
3716 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003717 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003718
developer615510b2022-09-27 10:14:35 +08003719 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003720
3721 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3722 f = fopen(file_name, "r");
3723 if (f != NULL) {
3724 fgets(filter_SSID, sizeof(file_name), f);
3725 if (strlen(filter_SSID) != 0)
3726 filter_enable = true;
3727 fclose(f);
3728 }
3729
developer033b37b2022-10-18 11:27:46 +08003730 phyId = radio_index_to_phy(radioIndex);
3731 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003732 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003733 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003734
developer5550e242022-09-30 09:59:32 +08003735
developer06a01d92022-09-07 16:32:39 +08003736
developera3c68b92022-09-13 15:27:29 +08003737 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 +08003738 // 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 +08003739 fprintf(stderr, "cmd: %s\n", cmd);
3740 if ((f = popen(cmd, "r")) == NULL) {
3741 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3742 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003743 }
developer5550e242022-09-30 09:59:32 +08003744
3745 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3746 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3747
developer615510b2022-09-27 10:14:35 +08003748 ret = fgets(line, sizeof(line), f);
3749 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003750 if(strstr(line, "BSS") != NULL) { // new neighbor info
3751 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3752 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3753 // 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 +08003754
developera3c68b92022-09-13 15:27:29 +08003755 if (!filter_BSS) {
3756 index++;
3757 wifi_neighbor_ap2_t *tmp;
3758 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3759 if (tmp == NULL) { // no more memory to use
3760 index--;
3761 wifi_dbg_printf("%s: realloc failed\n", __func__);
3762 break;
3763 }
3764 scan_array = tmp;
3765 }
3766 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3767
3768 filter_BSS = false;
3769 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3770 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3771 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3772 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3773 } else if (strstr(line, "freq") != NULL) {
3774 sscanf(line," freq: %d", &freq);
3775 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3776
3777 if (freq >= 2412 && freq <= 2484) {
3778 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3779 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3780 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3781 }
3782 else if (freq >= 5160 && freq <= 5805) {
3783 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3784 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3785 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3786 }
3787
3788 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003789 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003790 for (int i = 0; i < channels_num; i++) {
3791 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3792 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3793 break;
3794 }
3795 }
3796 }
3797 } else if (strstr(line, "beacon interval") != NULL) {
3798 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3799 } else if (strstr(line, "signal") != NULL) {
3800 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3801 } else if (strstr(line,"SSID") != NULL) {
3802 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3803 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3804 filter_BSS = true;
3805 }
3806 } else if (strstr(line, "Supported rates") != NULL) {
3807 char SRate[80] = {0}, *tmp = NULL;
3808 memset(buf, 0, sizeof(buf));
3809 strcpy(SRate, line);
3810 tmp = strtok(SRate, ":");
3811 tmp = strtok(NULL, ":");
3812 strcpy(buf, tmp);
3813 memset(SRate, 0, sizeof(SRate));
3814
3815 tmp = strtok(buf, " \n");
3816 while (tmp != NULL) {
3817 strcat(SRate, tmp);
3818 if (SRate[strlen(SRate) - 1] == '*') {
3819 SRate[strlen(SRate) - 1] = '\0';
3820 }
3821 strcat(SRate, ",");
3822
3823 tmp = strtok(NULL, " \n");
3824 }
3825 SRate[strlen(SRate) - 1] = '\0';
3826 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3827 } else if (strstr(line, "DTIM") != NULL) {
3828 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3829 } else if (strstr(line, "VHT capabilities") != NULL) {
3830 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3831 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3832 } else if (strstr(line, "HT capabilities") != NULL) {
3833 strcat(scan_array[index].ap_SupportedStandards, ",n");
3834 strcpy(scan_array[index].ap_OperatingStandards, "n");
3835 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003836 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003837 sscanf(line," * channel width: %d", &vht_channel_width);
3838 if(vht_channel_width == 1) {
3839 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3840 } else {
3841 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3842 }
3843 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3844 continue;
3845 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003846 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003847 sscanf(line," * secondary channel offset: %s", &buf);
3848 if (!strcmp(buf, "above")) {
3849 //40Mhz +
3850 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3851 }
3852 else if (!strcmp(buf, "below")) {
3853 //40Mhz -
3854 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3855 } else {
3856 //20Mhz
3857 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3858 }
3859 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3860 continue;
3861 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003862 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3863 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3864 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003865 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3866 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003867 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003868 else
developer615510b2022-09-27 10:14:35 +08003869 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003870 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003871 if (strstr(line, "HE80/5GHz") != NULL) {
3872 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3873 ret = fgets(line, sizeof(line), f);
3874 } else
3875 continue;
developera3c68b92022-09-13 15:27:29 +08003876 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003877 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003878 }
developer615510b2022-09-27 10:14:35 +08003879 continue;
developera3c68b92022-09-13 15:27:29 +08003880 } else if (strstr(line, "WPA") != NULL) {
3881 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3882 } else if (strstr(line, "RSN") != NULL) {
3883 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3884 } else if (strstr(line, "Group cipher") != NULL) {
3885 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3886 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3887 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3888 }
3889 }
developer615510b2022-09-27 10:14:35 +08003890 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003891 }
3892
3893 if (!filter_BSS) {
3894 *output_array_size = index + 1;
3895 } else {
3896 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3897 *output_array_size = index;
3898 }
3899 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003900 pclose(f);
developer5550e242022-09-30 09:59:32 +08003901 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003903 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003904}
3905
3906//>> Deprecated: used for old RDKB code.
3907INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3908{
3909 INT status = RETURN_ERR;
3910
3911 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3912 output_struct->wifi_PLCPErrorCount = 0;
3913 output_struct->wifi_FCSErrorCount = 0;
3914 output_struct->wifi_InvalidMACCount = 0;
3915 output_struct->wifi_PacketsOtherReceived = 0;
3916 output_struct->wifi_Noise = 0;
3917 status = RETURN_OK;
3918 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3919 return status;
3920}
3921
3922INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3923{
3924 char cmd[128];
3925 char buf[1280];
3926 char *pos = NULL;
3927
3928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3929 if (NULL == output_struct)
3930 return RETURN_ERR;
3931
3932 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3933
3934 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3935 _syscmd(cmd, buf, sizeof(buf));
3936
3937 pos = buf;
3938 if ((pos = strstr(pos, "RX packets:")) == NULL)
3939 return RETURN_ERR;
3940 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3941
3942 if ((pos = strstr(pos, "TX packets:")) == NULL)
3943 return RETURN_ERR;
3944 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3945
3946 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3947 return RETURN_ERR;
3948 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3949
3950 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3951 return RETURN_ERR;
3952 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3953
3954 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3955 _syscmd(cmd, buf, sizeof(buf));
3956 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3957
3958#if 0
3959 //TODO: need to revisit below implementation
3960 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3961 char interface_name[MAX_BUF_SIZE] = {0};
3962 char interface_status[MAX_BUF_SIZE] = {0};
3963 char Value[MAX_BUF_SIZE] = {0};
3964 char buf[MAX_CMD_SIZE] = {0};
3965 char cmd[MAX_CMD_SIZE] = {0};
3966 FILE *fp = NULL;
3967
3968 if (NULL == output_struct) {
3969 return RETURN_ERR;
3970 }
3971
3972 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3973
3974 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3975 {
3976 if(apIndex == 0) //private_wifi for 2.4G
3977 {
3978 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3979 }
3980 else if(apIndex == 1) //private_wifi for 5G
3981 {
3982 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3983 }
3984 else if(apIndex == 4) //public_wifi for 2.4G
3985 {
3986 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3987 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3988 {
3989 return RETURN_ERR;
3990 }
3991 if(buf[0] == '#')//tp-link
3992 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3993 else//tenda
3994 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3995 }
3996 else if(apIndex == 5) //public_wifi for 5G
3997 {
3998 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3999 }
4000
4001 GetIfacestatus(interface_name, interface_status);
4002
4003 if(0 != strcmp(interface_status, "1"))
4004 return RETURN_ERR;
4005
4006 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4007 system(cmd);
4008
4009 fp = fopen("/tmp/SSID_Stats.txt", "r");
4010 if(fp == NULL)
4011 {
4012 printf("/tmp/SSID_Stats.txt not exists \n");
4013 return RETURN_ERR;
4014 }
4015 fclose(fp);
4016
4017 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4018 File_Reading(buf, Value);
4019 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4020
4021 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4022 File_Reading(buf, Value);
4023 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4024
4025 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4026 File_Reading(buf, Value);
4027 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4028
4029 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4030 File_Reading(buf, Value);
4031 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4032
4033 /* There is no specific parameter from caller to associate the value wifi_Associations */
4034 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4035 //_syscmd(cmd, buf, sizeof(buf));
4036 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4037 }
4038#endif
4039 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4040 return RETURN_OK;
4041}
4042
4043INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4044{
4045 char interface_name[MAX_BUF_SIZE] = {0};
4046 char interface_status[MAX_BUF_SIZE] = {0};
4047 char Value[MAX_BUF_SIZE] = {0};
4048 char buf[MAX_CMD_SIZE] = {0};
4049 char cmd[MAX_CMD_SIZE] = {0};
4050 FILE *fp = NULL;
4051
4052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4053 if (NULL == output_struct)
4054 return RETURN_ERR;
4055
4056 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4057
4058 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4059 {
4060 if(apIndex == 0) //private_wifi for 2.4G
4061 {
4062 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4063 }
4064 else if(apIndex == 1) //private_wifi for 5G
4065 {
4066 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4067 }
4068 else if(apIndex == 4) //public_wifi for 2.4G
4069 {
4070 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4071 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4072 {
4073 return RETURN_ERR;
4074 }
4075 if(buf[0] == '#')
4076 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4077 else
4078 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4079 }
4080 else if(apIndex == 5) //public_wifi for 5G
4081 {
4082 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4083 }
4084
4085 GetIfacestatus(interface_name, interface_status);
4086
4087 if(0 != strcmp(interface_status, "1"))
4088 return RETURN_ERR;
4089
4090 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4091 system(cmd);
4092
4093 fp = fopen("/tmp/SSID_Stats.txt", "r");
4094 if(fp == NULL)
4095 {
4096 printf("/tmp/SSID_Stats.txt not exists \n");
4097 return RETURN_ERR;
4098 }
4099 fclose(fp);
4100
4101 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4102 File_Reading(buf, Value);
4103 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4104
4105 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4106 File_Reading(buf, Value);
4107 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4108
4109 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4110 File_Reading(buf, Value);
4111 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4112
4113 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4114 File_Reading(buf, Value);
4115 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4116 }
4117
4118 output_struct->wifi_UnicastPacketsSent = 0;
4119 output_struct->wifi_UnicastPacketsReceived = 0;
4120 output_struct->wifi_MulticastPacketsSent = 0;
4121 output_struct->wifi_MulticastPacketsReceived = 0;
4122 output_struct->wifi_BroadcastPacketsSent = 0;
4123 output_struct->wifi_BroadcastPacketsRecevied = 0;
4124 output_struct->wifi_UnknownPacketsReceived = 0;
4125
4126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4127 return RETURN_OK;
4128}
4129
4130INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4131{
4132 INT status = RETURN_ERR;
4133
4134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4135 //Below values should get updated from hal
4136 output_struct->wifi_RetransCount=0;
4137 output_struct->wifi_FailedRetransCount=0;
4138 output_struct->wifi_RetryCount=0;
4139 output_struct->wifi_MultipleRetryCount=0;
4140 output_struct->wifi_ACKFailureCount=0;
4141 output_struct->wifi_AggregatedPacketCount=0;
4142
4143 status = RETURN_OK;
4144 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4145
4146 return status;
4147}
4148
4149INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4150{
4151 INT status = RETURN_ERR;
4152 UINT index;
4153 wifi_neighbor_ap_t *pt=NULL;
4154
4155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4156 *output_array_size=2;
4157 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4158 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4159 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4160 strcpy(pt->ap_Radio,"");
4161 strcpy(pt->ap_SSID,"");
4162 strcpy(pt->ap_BSSID,"");
4163 strcpy(pt->ap_Mode,"");
4164 pt->ap_Channel=1;
4165 pt->ap_SignalStrength=0;
4166 strcpy(pt->ap_SecurityModeEnabled,"");
4167 strcpy(pt->ap_EncryptionMode,"");
4168 strcpy(pt->ap_OperatingFrequencyBand,"");
4169 strcpy(pt->ap_SupportedStandards,"");
4170 strcpy(pt->ap_OperatingStandards,"");
4171 strcpy(pt->ap_OperatingChannelBandwidth,"");
4172 pt->ap_BeaconPeriod=1;
4173 pt->ap_Noise=0;
4174 strcpy(pt->ap_BasicDataTransferRates,"");
4175 strcpy(pt->ap_SupportedDataTransferRates,"");
4176 pt->ap_DTIMPeriod=1;
4177 pt->ap_ChannelUtilization = 1;
4178 }
4179
4180 status = RETURN_OK;
4181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4182
4183 return status;
4184}
4185
4186//----------------- AP HAL -------------------------------
4187
4188//>> Deprecated: used for old RDKB code.
4189INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4190{
4191 if (NULL == output_ulong || NULL == output_struct)
4192 return RETURN_ERR;
4193 *output_ulong = 0;
4194 *output_struct = NULL;
4195 return RETURN_OK;
4196}
4197
4198#ifdef HAL_NETLINK_IMPL
4199static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4200 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4201 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4202 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4203 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4204 char mac_addr[20];
4205 static int count=0;
4206 int rate=0;
4207
4208 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4209
4210 nla_parse(tb,
4211 NL80211_ATTR_MAX,
4212 genlmsg_attrdata(gnlh, 0),
4213 genlmsg_attrlen(gnlh, 0),
4214 NULL);
4215
4216 if(!tb[NL80211_ATTR_STA_INFO]) {
4217 fprintf(stderr, "sta stats missing!\n");
4218 return NL_SKIP;
4219 }
4220
4221
4222 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4223 fprintf(stderr, "failed to parse nested attributes!\n");
4224 return NL_SKIP;
4225 }
4226
4227 //devIndex starts from 1
4228 if( ++count == out->wifi_devIndex )
4229 {
4230 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4231 //Getting the mac addrress
4232 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4233
4234 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4235 fprintf(stderr, "failed to parse nested rate attributes!");
4236 return NL_SKIP;
4237 }
4238
4239 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4240 if(rinfo[NL80211_RATE_INFO_BITRATE])
4241 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4242 out->wifi_devTxRate = rate/10;
4243 }
4244
4245 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4246 fprintf(stderr, "failed to parse nested rate attributes!");
4247 return NL_SKIP;
4248 }
4249
4250 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4251 if(rinfo[NL80211_RATE_INFO_BITRATE])
4252 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4253 out->wifi_devRxRate = rate/10;
4254 }
4255 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4256 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4257
4258 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4259 count = 0; //starts the count for next cycle
4260 return NL_STOP;
4261 }
4262
4263 return NL_SKIP;
4264
4265}
4266#endif
4267
4268INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4269{
4270#ifdef HAL_NETLINK_IMPL
4271 Netlink nl;
4272 char if_name[10];
4273
4274 wifi_device_info_t info;
4275 info.wifi_devIndex = devIndex;
4276
4277 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4278
4279 nl.id = initSock80211(&nl);
4280
4281 if (nl.id < 0) {
4282 fprintf(stderr, "Error initializing netlink \n");
4283 return -1;
4284 }
4285
4286 struct nl_msg* msg = nlmsg_alloc();
4287
4288 if (!msg) {
4289 fprintf(stderr, "Failed to allocate netlink message.\n");
4290 nlfree(&nl);
4291 return -2;
4292 }
4293
4294 genlmsg_put(msg,
4295 NL_AUTO_PORT,
4296 NL_AUTO_SEQ,
4297 nl.id,
4298 0,
4299 NLM_F_DUMP,
4300 NL80211_CMD_GET_STATION,
4301 0);
4302
4303 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4304 nl_send_auto(nl.socket, msg);
4305 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4306 nl_recvmsgs(nl.socket, nl.cb);
4307 nlmsg_free(msg);
4308 nlfree(&nl);
4309
4310 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4311 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4312 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4313 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4314 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4315 return RETURN_OK;
4316#else
4317 //iw utility to retrieve station information
4318#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4319#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4320#define MACFILE "/tmp/wifi_AssoMac.txt"
4321#define TXRATEFILE "/tmp/wifi_txrate.txt"
4322#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4323 FILE *file = NULL;
4324 char if_name[10] = {'\0'};
4325 char pipeCmd[256] = {'\0'};
4326 char line[256];
4327 int count,device = 0;
4328
4329 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4330
4331 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4332 file = popen(pipeCmd, "r");
4333
4334 if(file == NULL)
4335 return RETURN_ERR; //popen failed
4336
4337 fgets(line, sizeof line, file);
4338 device = atoi(line);
4339 pclose(file);
4340
4341 if(device == 0)
4342 return RETURN_ERR; //No devices are connected
4343
4344 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4345 system(pipeCmd);
4346
4347 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4348
4349 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4350
4351 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4352
4353 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4354
4355 //devIndex starts from 1, ++count
4356 if((file = fopen(SIGNALFILE, "r")) != NULL )
4357 {
4358 for(count =0;fgets(line, sizeof line, file) != NULL;)
4359 {
4360 if (++count == devIndex)
4361 {
4362 output_struct->wifi_devSignalStrength = atoi(line);
4363 break;
4364 }
4365 }
4366 fclose(file);
4367 }
4368 else
4369 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4370
4371 if((file = fopen(MACFILE, "r")) != NULL )
4372 {
4373 for(count =0;fgets(line, sizeof line, file) != NULL;)
4374 {
4375 if (++count == devIndex)
4376 {
4377 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]);
4378 break;
4379 }
4380 }
4381 fclose(file);
4382 }
4383 else
4384 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4385
4386 if((file = fopen(TXRATEFILE, "r")) != NULL )
4387 {
4388 for(count =0;fgets(line, sizeof line, file) != NULL;)
4389 {
4390 if (++count == devIndex)
4391 {
4392 output_struct->wifi_devTxRate = atoi(line);
4393 break;
4394 }
4395 }
4396 fclose(file);
4397 }
4398 else
4399 fprintf(stderr,"fopen wifi_txrate.txt failed");
4400
4401 if((file = fopen(RXRATEFILE, "r")) != NULL)
4402 {
4403 for(count =0;fgets(line, sizeof line, file) != NULL;)
4404 {
4405 if (++count == devIndex)
4406 {
4407 output_struct->wifi_devRxRate = atoi(line);
4408 break;
4409 }
4410 }
4411 fclose(file);
4412 }
4413 else
4414 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4415
4416 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4417
4418 return RETURN_OK;
4419#endif
4420}
4421
4422INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4423{
4424 if (NULL == device)
4425 return RETURN_ERR;
4426 return RETURN_OK;
4427}
4428//<<
4429
4430
4431//--------------wifi_ap_hal-----------------------------
4432//enables CTS protection for the radio used by this AP
4433INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4434{
4435 //save config and Apply instantly
4436 return RETURN_ERR;
4437}
4438
4439// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4440INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4441{
developer463d39a2022-09-13 15:32:51 +08004442 char config_file[64] = {'\0'};
4443 char buf[64] = {'\0'};
4444 struct params list;
4445
4446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4447 list.name = "ht_coex";
4448 snprintf(buf, sizeof(buf), "%d", enable);
4449 list.value = buf;
4450
4451 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4452 wifi_hostapdWrite(config_file, &list, 1);
4453 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4454
4455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4456
4457 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004458}
4459
4460//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4461INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4462{
developerea4bcce2022-09-13 15:26:13 +08004463 char config_file[MAX_BUF_SIZE] = {'\0'};
4464 char buf[MAX_BUF_SIZE] = {'\0'};
4465 struct params list;
4466
4467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4468 if (threshold < 256 || threshold > 2346 )
4469 return RETURN_ERR;
4470 list.name = "fragm_threshold";
4471 snprintf(buf, sizeof(buf), "%d", threshold);
4472 list.value = buf;
4473
4474 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4475 wifi_hostapdWrite(config_file, &list, 1);
4476 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004477
developerea4bcce2022-09-13 15:26:13 +08004478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004479
4480 return RETURN_OK;
4481}
4482
4483// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4484INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4485{
developer51a927d2022-09-13 15:42:22 +08004486 char config_file[64] = {'\0'};
4487 char cmd[128] = {'\0'};
4488 char buf[64] = {'\0'};
4489 char stbc_config[16] = {'\0'};
4490 wifi_band band;
4491 int iterator = 0;
4492 BOOL current_stbc = FALSE;
4493
4494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4495
4496 band = wifi_index_to_band(radioIndex);
4497 if (band == band_invalid)
4498 return RETURN_ERR;
4499
4500 if (band == band_2_4)
4501 iterator = 1;
4502 else if (band == band_5)
4503 iterator = 2;
4504 else
4505 return RETURN_OK;
4506
4507 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4508
4509 // set ht and vht config
4510 for (int i = 0; i < iterator; i++) {
4511 memset(stbc_config, 0, sizeof(stbc_config));
4512 memset(cmd, 0, sizeof(cmd));
4513 memset(buf, 0, sizeof(buf));
4514 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4515 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4516 _syscmd(cmd, buf, sizeof(buf));
4517 if (strlen(buf) != 0)
4518 current_stbc = TRUE;
4519 if (current_stbc == STBC_Enable)
4520 continue;
4521
4522 if (STBC_Enable == TRUE) {
4523 // Append the STBC flags in capab config
4524 memset(cmd, 0, sizeof(cmd));
4525 if (i == 0)
4526 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4527 else
4528 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4529 _syscmd(cmd, buf, sizeof(buf));
4530 } else if (STBC_Enable == FALSE) {
4531 // Remove the STBC flags and remain other flags in capab
4532 memset(cmd, 0, sizeof(cmd));
4533 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4534 _syscmd(cmd, buf, sizeof(buf));
4535 memset(cmd, 0, sizeof(cmd));
4536 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4537 _syscmd(cmd, buf, sizeof(buf));
4538 }
4539 }
4540
4541 wifi_reloadAp(radioIndex);
4542
4543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4544 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004545}
4546
4547// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4548INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4549{
developer54e6b9f2022-09-28 14:41:20 +08004550 char AMSDU_file_path[64] = {0};
4551
4552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4553
4554 if(output_bool == NULL)
4555 return RETURN_ERR;
4556
4557 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4558
4559 if (access(AMSDU_file_path, F_OK) == 0)
4560 *output_bool = TRUE;
4561 else
4562 *output_bool = FALSE;
4563
4564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4565 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004566}
4567
4568// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4569INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4570{
developer54e6b9f2022-09-28 14:41:20 +08004571 char cmd[64]={0};
4572 char buf[64]={0};
4573 char AMSDU_file_path[64] = {0};
4574
4575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4576
4577 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4578 _syscmd(cmd, buf, sizeof(buf));
4579
4580 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4581 memset(cmd, 0, sizeof(cmd));
4582 if (amsduEnable == TRUE)
4583 sprintf(cmd, "touch %s", AMSDU_file_path);
4584 else
4585 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4586 _syscmd(cmd, buf, sizeof(buf));
4587
4588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4589 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004590}
4591
4592//P2 // outputs the number of Tx streams
4593INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4594{
developer2de97692022-09-26 14:00:03 +08004595 char buf[8] = {0};
4596 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004597 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004598
4599 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4600
4601 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4602 _syscmd(cmd, buf, sizeof(buf));
4603
developer033b37b2022-10-18 11:27:46 +08004604 phyId = radio_index_to_phy(radioIndex);
developer2de97692022-09-26 14:00:03 +08004605 // if there is no record, output the max number of spatial streams
4606 if (strlen(buf) == 0) {
developer033b37b2022-10-18 11:27:46 +08004607 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", phyId);
developer2de97692022-09-26 14:00:03 +08004608 _syscmd(cmd, buf, sizeof(buf));
4609 }
4610
4611 *output_int = (INT)strtol(buf, NULL, 10);
4612
4613 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4614
4615 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004616}
4617
4618//P2 // sets the number of Tx streams to an enviornment variable
4619INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4620{
developer2de97692022-09-26 14:00:03 +08004621 char cmd[128] = {0};
4622 char buf[128] = {0};
4623 char chain_mask_file[128] = {0};
4624 FILE *f = NULL;
developer033b37b2022-10-18 11:27:46 +08004625 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004626
4627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4628
4629 if (numStreams == 0) {
4630 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4631 return RETURN_ERR;
4632 }
4633 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004634
4635 phyId = radio_index_to_phy(radioIndex);
4636 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004637 _syscmd(cmd, buf, sizeof(buf));
4638
4639 if (strlen(buf) > 0) {
4640 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4641 return RETURN_ERR;
4642 }
4643 wifi_setRadioEnable(radioIndex, TRUE);
4644
4645 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4646 f = fopen(chain_mask_file, "w");
4647 if (f == NULL) {
4648 fprintf(stderr, "%s: fopen failed.\n", __func__);
4649 return RETURN_ERR;
4650 }
4651 fprintf(f, "%d", numStreams);
4652 fclose(f);
4653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4654 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004655}
4656
4657//P2 // outputs the number of Rx streams
4658INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4659{
developer2de97692022-09-26 14:00:03 +08004660 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4661 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4662 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004663 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004664 }
4665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004666 return RETURN_OK;
4667}
4668
4669//P2 // sets the number of Rx streams to an enviornment variable
4670INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4671{
developer2de97692022-09-26 14:00:03 +08004672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4673 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4674 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4675 return RETURN_ERR;
4676 }
4677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004678 return RETURN_ERR;
4679}
4680
4681//Get radio RDG enable setting
4682INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4683{
4684 if (NULL == output_bool)
4685 return RETURN_ERR;
4686 *output_bool = TRUE;
4687 return RETURN_OK;
4688}
4689
4690//Get radio RDG enable setting
4691INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4692{
4693 if (NULL == output_bool)
4694 return RETURN_ERR;
4695 *output_bool = TRUE;
4696 return RETURN_OK;
4697}
4698
4699//Set radio RDG enable setting
4700INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4701{
4702 return RETURN_ERR;
4703}
4704
4705//Get radio ADDBA enable setting
4706INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4707{
4708 if (NULL == output_bool)
4709 return RETURN_ERR;
4710 *output_bool = TRUE;
4711 return RETURN_OK;
4712}
4713
4714//Set radio ADDBA enable setting
4715INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4716{
4717 return RETURN_ERR;
4718}
4719
4720//Get radio auto block ack enable setting
4721INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4722{
4723 if (NULL == output_bool)
4724 return RETURN_ERR;
4725 *output_bool = TRUE;
4726 return RETURN_OK;
4727}
4728
4729//Set radio auto block ack enable setting
4730INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4731{
4732 return RETURN_ERR;
4733}
4734
4735//Get radio 11n pure mode enable support
4736INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4737{
4738 if (NULL == output_bool)
4739 return RETURN_ERR;
4740 *output_bool = TRUE;
4741 return RETURN_OK;
4742}
4743
4744//Get radio 11n pure mode enable setting
4745INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4746{
4747 if (NULL == output_bool)
4748 return RETURN_ERR;
4749 *output_bool = TRUE;
4750 return RETURN_OK;
4751}
4752
4753//Set radio 11n pure mode enable setting
4754INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4755{
4756 return RETURN_ERR;
4757}
4758
4759//Get radio IGMP snooping enable setting
4760INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4761{
developer81bf2ed2022-09-13 15:31:14 +08004762 char cmd[128]={0};
4763 char buf[4]={0};
4764 bool bridge = FALSE, mac80211 = FALSE;
4765 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4766
4767 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004768 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004769
4770 *output_bool = FALSE;
4771
4772 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4773 _syscmd(cmd, buf, sizeof(buf));
4774 if (strncmp(buf, "1", 1) == 0)
4775 bridge = TRUE;
4776
4777 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4778 _syscmd(cmd, buf, sizeof(buf));
4779 if (strncmp(buf, "1", 1) == 0)
4780 mac80211 = TRUE;
4781
4782 if (bridge && mac80211)
4783 *output_bool = TRUE;
4784
4785 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004786 return RETURN_OK;
4787}
4788
4789//Set radio IGMP snooping enable setting
4790INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4791{
developer81bf2ed2022-09-13 15:31:14 +08004792 char cmd[128]={0};
4793 char buf[4]={0};
4794
4795 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4796
4797 // bridge
4798 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4799 _syscmd(cmd, buf, sizeof(buf));
4800
4801 // mac80211
developer033b37b2022-10-18 11:27:46 +08004802 for (int i = 0; i < MAX_RADIOS; i++) {
developer81bf2ed2022-09-13 15:31:14 +08004803 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4804 _syscmd(cmd, buf, sizeof(buf));
4805 }
4806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4807 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004808}
4809
4810//Get the Reset count of radio
4811INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4812{
4813 if (NULL == output_int)
4814 return RETURN_ERR;
4815 *output_int = (radioIndex==0)? 1: 3;
4816
4817 return RETURN_OK;
4818}
4819
4820
4821//---------------------------------------------------------------------------------------------------
4822//
4823// Additional Wifi AP level APIs used for Access Point devices
4824//
4825//---------------------------------------------------------------------------------------------------
4826
4827// creates a new ap and pushes these parameters to the hardware
4828INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4829{
4830 char buf[1024];
4831 char cmd[128];
developer033b37b2022-10-18 11:27:46 +08004832 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004833
4834 if (NULL == essid)
4835 return RETURN_ERR;
4836
developer033b37b2022-10-18 11:27:46 +08004837 phyId = radio_index_to_phy(radioIndex);
4838 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08004839 _syscmd(cmd, buf, sizeof(buf));
4840
4841 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4842 _syscmd(cmd, buf, sizeof(buf));
4843
4844 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4845
4846 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4847 _syscmd(cmd, buf, sizeof(buf));
4848
4849 return RETURN_OK;
4850}
4851
4852// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4853INT wifi_deleteAp(INT apIndex)
4854{
4855 char buf[1024];
4856 char cmd[128];
4857
4858 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4859 _syscmd(cmd, buf, sizeof(buf));
4860
4861 wifi_removeApSecVaribles(apIndex);
4862
4863 return RETURN_OK;
4864}
4865
4866// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4867INT wifi_getApName(INT apIndex, CHAR *output_string)
4868{
4869 if(NULL == output_string)
4870 return RETURN_ERR;
4871
4872 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4873 return RETURN_OK;
4874}
4875
4876// Outputs the index number in that corresponds to the SSID string
4877INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4878{
4879 CHAR *pos = NULL;
4880
4881 *output_int = -1;
4882 pos = strstr(inputSsidString, AP_PREFIX);
4883 if(pos)
4884 {
4885 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4886 return RETURN_OK;
4887 }
4888 return RETURN_ERR;
4889}
4890
4891INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4892{
4893 return wifi_getIndexFromName(inputSsidString, output_int);
4894}
4895
4896// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4897INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4898{
4899 char buf[MAX_BUF_SIZE] = {0};
4900 char cmd[MAX_CMD_SIZE] = {0};
4901 char config_file[MAX_BUF_SIZE] = {0};
4902
4903 if(NULL == output_string)
4904 return RETURN_ERR;
4905
4906 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4907 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4908 if((strcmp(buf,"3")==0))
4909 snprintf(output_string, 32, "WPAand11i");
4910 else if((strcmp(buf,"2")==0))
4911 snprintf(output_string, 32, "11i");
4912 else if((strcmp(buf,"1")==0))
4913 snprintf(output_string, 32, "WPA");
4914 else
4915 snprintf(output_string, 32, "None");
4916
4917 return RETURN_OK;
4918}
4919
4920// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4921INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4922{
4923 char config_file[MAX_BUF_SIZE] = {0};
4924 struct params list;
4925
4926 if (NULL == beaconTypeString)
4927 return RETURN_ERR;
4928 list.name = "wpa";
4929 list.value = "0";
4930
4931 if((strcmp(beaconTypeString,"WPAand11i")==0))
4932 list.value="3";
4933 else if((strcmp(beaconTypeString,"11i")==0))
4934 list.value="2";
4935 else if((strcmp(beaconTypeString,"WPA")==0))
4936 list.value="1";
4937
4938 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4939 wifi_hostapdWrite(config_file, &list, 1);
4940 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4941 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4942 return RETURN_OK;
4943}
4944
4945// sets the beacon interval on the hardware for this AP
4946INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4947{
developer5f222492022-09-13 15:21:52 +08004948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4949 struct params params={'\0'};
4950 char buf[MAX_BUF_SIZE] = {'\0'};
4951 char config_file[MAX_BUF_SIZE] = {'\0'};
4952
4953 params.name = "beacon_int";
4954 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4955 params.value = buf;
4956
4957 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4958 wifi_hostapdWrite(config_file, &params, 1);
4959
4960 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4961 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4962 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004963}
4964
4965INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4966{
4967 //save config and apply instantly
4968 return RETURN_ERR;
4969}
4970
4971// Get the packet size threshold supported.
4972INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4973{
4974 //save config and apply instantly
4975 if (NULL == output_bool)
4976 return RETURN_ERR;
4977 *output_bool = FALSE;
4978 return RETURN_OK;
4979}
4980
4981// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4982INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4983{
4984 char cmd[128];
4985 char buf[512];
4986
4987 if (threshold > 0)
4988 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4989 else
4990 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4991 _syscmd(cmd, buf, sizeof(buf));
4992
4993 return RETURN_OK;
4994}
4995
4996// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4997INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4998{
4999 if (NULL == output_string)
5000 return RETURN_ERR;
5001 snprintf(output_string, 32, "TKIPandAESEncryption");
5002 return RETURN_OK;
5003
5004}
5005
5006// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5007INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5008{
5009 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5010 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
5011
5012 if(NULL == output_string)
5013 return RETURN_ERR;
5014
5015 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5016 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5017
5018 if(strcmp(buf,"0")==0)
5019 {
5020 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5021 snprintf(output_string, 32, "None");
5022 return RETURN_OK;
5023 }
5024 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5025 param_name = "rsn_pairwise";
5026 else if((strcmp(buf,"1")==0))
5027 param_name = "wpa_pairwise";
5028 else
5029 return RETURN_ERR;
5030 memset(output_string,'\0',32);
5031 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5032 wifi_hostapdRead(config_file,param_name,output_string,32);
5033 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5034
5035 if(strcmp(output_string,"TKIP") == 0)
5036 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5037 else if(strcmp(output_string,"CCMP") == 0)
5038 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5039 else if(strcmp(output_string,"TKIP CCMP") == 0)
5040 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5041
5042 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5043 return RETURN_OK;
5044}
5045
5046// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5047INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5048{
5049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5050 struct params params={'\0'};
5051 char output_string[32];
5052 char config_file[MAX_BUF_SIZE] = {0};
5053
5054 memset(output_string,'\0',32);
5055 wifi_getApWpaEncryptionMode(apIndex,output_string);
5056
5057 if(strcmp(encMode, "TKIPEncryption") == 0)
5058 params.value = "TKIP";
5059 else if(strcmp(encMode,"AESEncryption") == 0)
5060 params.value = "CCMP";
5061 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5062 params.value = "TKIP CCMP";
5063
5064 if((strcmp(output_string,"WPAand11i")==0))
5065 {
5066 params.name = "wpa_pairwise";
5067 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5068 wifi_hostapdWrite(config_file, &params, 1);
5069 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5070
5071 params.name,"rsn_pairwise";
5072 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5073 wifi_hostapdWrite(config_file, &params, 1);
5074 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5075
5076 return RETURN_OK;
5077 }
5078 else if((strcmp(output_string,"11i")==0))
5079 {
5080 params.name = "rsn_pairwise";
5081 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5082 wifi_hostapdWrite(config_file, &params, 1);
5083 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5084 return RETURN_OK;
5085 }
5086 else if((strcmp(output_string,"WPA")==0))
5087 {
5088 params.name = "wpa_pairwise";
5089 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5090 wifi_hostapdWrite(config_file, &params, 1);
5091 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5092 return RETURN_OK;
5093 }
5094
5095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5096 return RETURN_OK;
5097}
5098
5099// deletes internal security varable settings for this ap
5100INT wifi_removeApSecVaribles(INT apIndex)
5101{
5102 //TODO: remove the entry in hostapd config file
5103 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5104 //_syscmd(cmd, buf, sizeof(buf));
5105
5106 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5107 //_syscmd(cmd, buf, sizeof(buf));
5108 return RETURN_ERR;
5109}
5110
5111// changes the hardware settings to disable encryption on this ap
5112INT wifi_disableApEncryption(INT apIndex)
5113{
5114 //Apply instantly
5115 return RETURN_ERR;
5116}
5117
5118// set the authorization mode on this ap
5119// mode mapping as: 1: open, 2: shared, 4:auto
5120INT wifi_setApAuthMode(INT apIndex, INT mode)
5121{
developeraf95c502022-09-13 16:18:22 +08005122 struct params params={0};
5123 char config_file[64] = {0};
5124 int ret;
5125
5126 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5127
5128 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5129 params.name = "auth_algs";
5130
5131 if (mode & 1 && mode & 2)
5132 params.value = "3";
5133 else if (mode & 2)
5134 params.value = "2";
5135 else if (mode & 1)
5136 params.value = "1";
5137 else
5138 params.value = "0";
5139
5140 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5141 wifi_hostapdWrite(config_file, &params, 1);
5142 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5144
5145 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005146}
5147
5148// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5149INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5150{
5151 //save to wifi config, and wait for wifi restart to apply
5152 struct params params={'\0'};
5153 char config_file[MAX_BUF_SIZE] = {0};
5154 int ret;
5155
5156 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5157 if(authMode == NULL)
5158 return RETURN_ERR;
5159
5160 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5161 params.name = "wpa_key_mgmt";
5162
5163 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5164 params.value = "WPA-PSK";
5165 else if(strcmp(authMode,"EAPAuthentication") == 0)
5166 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005167 else if (strcmp(authMode, "SAEAuthentication") == 0)
5168 params.value = "SAE";
5169 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5170 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005171 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5172 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005173 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5174 return RETURN_OK; //This is taken careof in beaconType
5175
5176 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5177 ret=wifi_hostapdWrite(config_file,&params,1);
5178 if(!ret)
5179 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5181
5182 return ret;
5183}
5184
5185// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5186INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5187{
5188 //save to wifi config, and wait for wifi restart to apply
5189 char BeaconType[50] = {0};
5190 char config_file[MAX_BUF_SIZE] = {0};
5191
5192 *authMode = 0;
5193 wifi_getApBeaconType(apIndex,BeaconType);
5194 printf("%s____%s \n",__FUNCTION__,BeaconType);
5195
5196 if(strcmp(BeaconType,"None") == 0)
5197 strcpy(authMode,"None");
5198 else
5199 {
5200 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5201 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5202 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5203 if(strcmp(authMode,"WPA-PSK") == 0)
5204 strcpy(authMode,"SharedAuthentication");
5205 else if(strcmp(authMode,"WPA-EAP") == 0)
5206 strcpy(authMode,"EAPAuthentication");
5207 }
5208
5209 return RETURN_OK;
5210}
5211
5212// Outputs the number of stations associated per AP
5213INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5214{
5215 char cmd[128]={0};
5216 char buf[128]={0};
5217 BOOL status = false;
5218
5219 if(apIndex > MAX_APS)
5220 return RETURN_ERR;
5221
5222 wifi_getApEnable(apIndex,&status);
5223 if (!status)
5224 return RETURN_OK;
5225
5226 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5227 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5228 _syscmd(cmd, buf, sizeof(buf));
5229 sscanf(buf,"%lu", output_ulong);
5230
5231 return RETURN_OK;
5232}
5233
5234// manually removes any active wi-fi association with the device specified on this ap
5235INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5236{
5237 char buf[126]={'\0'};
5238
5239 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5240 system(buf);
5241
5242 return RETURN_OK;
5243}
5244
5245// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5246INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5247{
5248 if(NULL == output_int)
5249 return RETURN_ERR;
5250 *output_int = apIndex%2;
5251 return RETURN_OK;
5252}
5253
5254// sets the radio index for the specific ap
5255INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5256{
5257 //set to config only and wait for wifi reset to apply settings
5258 return RETURN_ERR;
5259}
5260
5261// Get the ACL MAC list per AP
5262INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5263{
5264 char cmd[MAX_CMD_SIZE]={'\0'};
5265 int ret = 0;
5266
5267 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5268 ret = _syscmd(cmd,macArray,buf_size);
5269 if (ret != 0)
5270 return RETURN_ERR;
5271
5272 return RETURN_OK;
5273}
5274
developere6aafda2022-09-13 14:59:28 +08005275INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5276{
5277 char cmd[MAX_CMD_SIZE]={'\0'};
5278 int ret = 0;
5279
5280 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5281 ret = _syscmd(cmd,macArray,buf_size);
5282 if (ret != 0)
5283 return RETURN_ERR;
5284
5285 return RETURN_OK;
5286}
5287
5288
developer06a01d92022-09-07 16:32:39 +08005289// Get the list of stations associated per AP
5290INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5291{
5292 char cmd[128];
5293
5294 if(apIndex > 3) //Currently supporting apIndex upto 3
5295 return RETURN_ERR;
5296 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5297 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5298 _syscmd(cmd, macArray, buf_size);
5299
5300 return RETURN_OK;
5301}
5302
5303// adds the mac address to the filter list
5304//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5305INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5306{
5307 char cmd[MAX_CMD_SIZE]={'\0'};
5308 char buf[MAX_BUF_SIZE]={'\0'};
5309
5310#if 0
5311 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5312 if(_syscmd(cmd,buf,sizeof(buf)))
5313 return RETURN_ERR;
5314#endif
5315 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5316 if(_syscmd(cmd,buf,sizeof(buf)))
5317 return RETURN_ERR;
5318
5319 return RETURN_OK;
5320}
5321
5322// deletes the mac address from the filter list
5323//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5324INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5325{
5326 char cmd[MAX_CMD_SIZE]={'\0'};
5327 char buf[MAX_BUF_SIZE]={'\0'};
5328
5329#if 0
5330 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5331 if(_syscmd(cmd,buf,sizeof(buf)))
5332 return RETURN_ERR;
5333
5334#endif
5335 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5336 if(_syscmd(cmd,buf,sizeof(buf)))
5337 return RETURN_ERR;
5338
5339 return RETURN_OK;
5340}
5341
5342// outputs the number of devices in the filter list
5343INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5344{
developere6aafda2022-09-13 14:59:28 +08005345 char cmd[MAX_BUF_SIZE]={0};
5346 char buf[MAX_CMD_SIZE]={0};
5347
5348 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5349 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005350 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005351
5352 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5353 _syscmd(cmd, buf, sizeof(buf));
5354
5355 *output_uint = atoi(buf);
5356
5357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5358 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005359}
5360
5361INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5362{
5363 char cmd[128]={'\0'};
5364 char buf[128]={'\0'};
5365
5366 if(strcmp(action,"DENY")==0)
5367 {
5368 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5369 system(buf);
5370 return RETURN_OK;
5371 }
5372
5373 if(strcmp(action,"ALLOW")==0)
5374 {
5375 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5376 system(buf);
5377 return RETURN_OK;
5378 }
5379
5380 return RETURN_ERR;
5381
5382}
5383
5384// enable kick for devices on acl black list
5385INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5386{
5387 char aclArray[512] = {0}, *acl = NULL;
5388 char assocArray[512] = {0}, *asso = NULL;
5389
developere6aafda2022-09-13 14:59:28 +08005390 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005391 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5392
5393 // if there are no devices connected there is nothing to do
5394 if (strlen(assocArray) < 17)
5395 return RETURN_OK;
5396
5397 if (enable == TRUE)
5398 {
5399 //kick off the MAC which is in ACL array (deny list)
5400 acl = strtok(aclArray, "\r\n");
5401 while (acl != NULL) {
5402 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5403 wifi_kickApAssociatedDevice(apIndex, acl);
5404
5405 acl = strtok(NULL, "\r\n");
5406 }
developere6aafda2022-09-13 14:59:28 +08005407 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005408 }
5409 else
5410 {
developere6aafda2022-09-13 14:59:28 +08005411 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005412 }
5413
5414#if 0
5415 //TODO: need to revisit below implementation
5416 char aclArray[512]={0}, *acl=NULL;
5417 char assocArray[512]={0}, *asso=NULL;
5418 char buf[256]={'\0'};
5419 char action[10]={'\0'};
5420 FILE *fr=NULL;
5421 char interface[10]={'\0'};
5422 char config_file[MAX_BUF_SIZE] = {0};
5423
5424 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5425 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5426 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5427 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5428
5429 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5430 system(buf);
5431 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5432 system(buf);
5433 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5434 system(buf);
5435 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5436 system(buf);
5437 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5438 system(buf);
5439
5440 if ( enable == TRUE )
5441 {
5442 int device_count=0;
5443 strcpy(action,"DENY");
5444 //kick off the MAC which is in ACL array (deny list)
5445 acl = strtok (aclArray,",");
5446 while (acl != NULL) {
5447 if(strlen(acl)>=17)
5448 {
5449 apply_rules(apIndex, acl,action,interface);
5450 device_count++;
5451 //Register mac to be blocked ,in syscfg.db persistent storage
5452 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5453 system(buf);
5454 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5455 system(buf);
5456 system("syscfg commit");
5457
5458 wifi_kickApAssociatedDevice(apIndex, acl);
5459 }
5460 acl = strtok (NULL, ",");
5461 }
5462 }
5463 else
5464 {
5465 int device_count=0;
5466 char cmdmac[20]={'\0'};
5467 strcpy(action,"ALLOW");
5468 //kick off the MAC which is not in ACL array (allow list)
5469 acl = strtok (aclArray,",");
5470 while (acl != NULL) {
5471 if(strlen(acl)>=17)
5472 {
5473 apply_rules(apIndex, acl,action,interface);
5474 device_count++;
5475 //Register mac to be Allowed ,in syscfg.db persistent storage
5476 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5477 system(buf);
5478 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5479 system(buf);
5480 sprintf(cmdmac,"%s",acl);
5481 }
5482 acl = strtok (NULL, ",");
5483 }
5484 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5485 system(buf);
5486
5487 //Disconnect the mac which is not in ACL
5488 asso = strtok (assocArray,",");
5489 while (asso != NULL) {
5490 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5491 wifi_kickApAssociatedDevice(apIndex, asso);
5492 asso = strtok (NULL, ",");
5493 }
5494 }
5495#endif
5496 return RETURN_OK;
5497}
5498
5499INT wifi_setPreferPrivateConnection(BOOL enable)
5500{
5501 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5502 char buf[1024] = {0};
5503
5504 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5505 if(enable == TRUE)
5506 {
5507 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5508 sprintf(buf,"ifconfig %s down" ,interface_name);
5509 system(buf);
5510 memset(buf,0,sizeof(buf));
5511 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5512 sprintf(buf,"ifconfig %s down" ,interface_name);
5513 system(buf);
5514 }
5515 else
5516 {
5517 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5518 if(strcmp(ssid_cur_value,"1") == 0)
5519 wifi_RestartPrivateWifi_5G();
5520 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5521 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5522 if(strcmp(ssid_cur_value,"1") == 0)
5523 wifi_RestartHostapd_2G();
5524 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5525 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5526 if(strcmp(ssid_cur_value,"1") == 0)
5527 wifi_RestartHostapd_5G();
5528 }
5529 return RETURN_OK;
5530}
5531
5532// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5533INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5534{
5535 int items = 1;
5536 struct params list[2];
5537 char buf[MAX_BUF_SIZE] = {0};
5538 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005539 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005540
5541 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005542
developer10adcc12022-09-13 14:39:17 +08005543 if (filterMode == 0) {
5544 sprintf(buf, "%d", 0);
5545 list[0].value = buf;
5546
5547 char cmd[128], rtn[128];
5548 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5549 _syscmd(cmd, rtn, sizeof(rtn));
5550 memset(cmd,0,sizeof(cmd));
5551 // Delete deny_mac_file in hostapd configuration
5552 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5553 _syscmd(cmd, rtn, sizeof(rtn));
5554 }
5555 else if (filterMode == 1) {
5556 sprintf(buf, "%d", filterMode);
5557 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005558 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5559 list[1].name = "accept_mac_file";
5560 list[1].value = acl_file;
5561 items = 2;
developer10adcc12022-09-13 14:39:17 +08005562 } else if (filterMode == 2) {
5563 //TODO: deny_mac_file
5564 sprintf(buf, "%d", 0);
5565 list[0].value = buf;
5566 list[1].name = "deny_mac_file";
5567 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5568 list[1].value = deny_file;
5569 items = 2;
5570 } else {
5571 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005572 }
developer10adcc12022-09-13 14:39:17 +08005573
developer06a01d92022-09-07 16:32:39 +08005574 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5575 wifi_hostapdWrite(config_file, list, items);
5576
5577 return RETURN_OK;
5578
5579#if 0
5580 if(apIndex==0 || apIndex==1)
5581 {
5582 //set the filtermode
5583 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5584 system(buf);
5585 system("syscfg commit");
5586
5587 if(filterMode==0)
5588 {
5589 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5590 system(buf);
5591 return RETURN_OK;
5592 }
5593 }
5594 return RETURN_OK;
5595#endif
5596}
5597
5598// 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.
5599INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5600{
5601 return RETURN_ERR;
5602}
5603
5604// gets the vlan ID for this ap from an internal enviornment variable
5605INT wifi_getApVlanID(INT apIndex, INT *output_int)
5606{
5607 if(apIndex=0)
5608 {
5609 *output_int=100;
5610 return RETURN_OK;
5611 }
5612
5613 return RETURN_ERR;
5614}
5615
5616// sets the vlan ID for this ap to an internal enviornment variable
5617INT wifi_setApVlanID(INT apIndex, INT vlanId)
5618{
5619 //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)
5620 return RETURN_ERR;
5621}
5622
5623// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5624INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5625{
5626 snprintf(bridgeName, 32, "brlan0");
5627 snprintf(IP, 32, "10.0.0.1");
5628 snprintf(subnet, 32, "255.255.255.0");
5629
5630 return RETURN_OK;
5631}
5632
5633//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5634INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5635{
5636 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5637 return RETURN_ERR;
5638}
5639
5640// reset the vlan configuration for this ap
5641INT wifi_resetApVlanCfg(INT apIndex)
5642{
developerf5fef612022-09-20 19:38:26 +08005643 char original_config_file[64] = {0};
5644 char current_config_file[64] = {0};
5645 char buf[64] = {0};
5646 char cmd[64] = {0};
5647 char vlan_file[64] = {0};
5648 char vlan_tagged_interface[16] = {0};
5649 char vlan_bridge[16] = {0};
5650 char vlan_naming[16] = {0};
5651 struct params list[4] = {0};
5652 wifi_band band;
5653
5654 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5655
5656 band = wifi_index_to_band(apIndex);
5657 if (band == band_2_4)
5658 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5659 else if (band = band_5)
5660 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5661 else if (band = band_6)
5662 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5663
5664 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5665
5666 if (strlen(vlan_file) == 0)
5667 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005668
developerf5fef612022-09-20 19:38:26 +08005669 // The file should exist or this vap would not work.
5670 if (access(vlan_file, F_OK) != 0) {
5671 sprintf(cmd, "touch %s", vlan_file);
5672 _syscmd(cmd, buf, sizeof(buf));
5673 }
5674 list[0].name = "vlan_file";
5675 list[0].value = vlan_file;
5676
5677 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5678 list[1].name = "vlan_tagged_interface";
5679 list[1].value = vlan_tagged_interface;
5680
5681 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5682 list[2].name = "vlan_bridge";
5683 list[2].value = vlan_bridge;
5684
5685 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5686 list[3].name = "vlan_naming";
5687 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005688
developerf5fef612022-09-20 19:38:26 +08005689 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5690 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005691 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005692 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005693
developerf5fef612022-09-20 19:38:26 +08005694 // restart this ap
5695 wifi_setApEnable(apIndex, FALSE);
5696 wifi_setApEnable(apIndex, TRUE);
5697
5698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5699
5700 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005701}
5702
5703// 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.
5704INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5705{
5706 return RETURN_ERR;
5707}
5708
5709// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5710INT wifi_startHostApd()
5711{
5712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5713 system("systemctl start hostapd.service");
5714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5715 return RETURN_OK;
5716 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5717}
5718
5719// stops hostapd
5720INT wifi_stopHostApd()
5721{
5722 char cmd[128] = {0};
5723 char buf[128] = {0};
5724
5725 sprintf(cmd,"systemctl stop hostapd");
5726 _syscmd(cmd, buf, sizeof(buf));
5727
5728 return RETURN_OK;
5729}
5730
5731// restart hostapd dummy function
5732INT wifi_restartHostApd()
5733{
5734 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5735 system("systemctl restart hostapd-global");
5736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5737
5738 return RETURN_OK;
5739}
5740
5741static int align_hostapd_config(int index)
5742{
5743 ULONG lval;
5744 wifi_getRadioChannel(index%2, &lval);
5745 wifi_setRadioChannel(index%2, lval);
5746}
5747
5748// sets the AP enable status variable for the specified ap.
5749INT wifi_setApEnable(INT apIndex, BOOL enable)
5750{
5751 char config_file[MAX_BUF_SIZE] = {0};
5752 char cmd[MAX_CMD_SIZE] = {0};
5753 char buf[MAX_BUF_SIZE] = {0};
5754 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005755 int max_radio_num = 0;
5756 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005757
5758 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005759
5760 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005761 if (enable == status)
5762 return RETURN_OK;
5763
5764 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005765 int radioIndex = apIndex % max_radio_num;
5766 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005767 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5768 //Hostapd will bring up this interface
5769 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5770 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005771 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005772 _syscmd(cmd, buf, sizeof(buf));
5773 }
5774 else {
5775 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5776 _syscmd(cmd, buf, sizeof(buf));
5777 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5778 _syscmd(cmd, buf, sizeof(buf));
5779 }
5780 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5781 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5782 _syscmd(cmd, buf, sizeof(buf));
5783 //Wait for wifi up/down to apply
5784 return RETURN_OK;
5785}
5786
5787// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5788INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5789{
5790 char cmd[MAX_CMD_SIZE] = {'\0'};
5791 char buf[MAX_BUF_SIZE] = {'\0'};
5792
5793 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5794 return RETURN_ERR;
5795
5796 *output_bool = 0;
5797
5798 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5799 {
developer70490032022-09-13 15:45:20 +08005800 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005801 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5802 }
5803
5804 return RETURN_OK;
5805}
5806
5807// Outputs the AP "Enabled" "Disabled" status from driver
5808INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5809{
5810 char cmd[128] = {0};
5811 char buf[128] = {0};
5812 BOOL output_bool;
5813
5814 if ( NULL == output_string)
5815 return RETURN_ERR;
5816 wifi_getApEnable(apIndex,&output_bool);
5817
5818 if(output_bool == 1)
5819 snprintf(output_string, 32, "Up");
5820 else
5821 snprintf(output_string, 32, "Disable");
5822
5823 return RETURN_OK;
5824}
5825
5826//Indicates whether or not beacons include the SSID name.
5827// outputs a 1 if SSID on the AP is enabled, else outputs 0
5828INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5829{
5830 //get the running status
5831 char config_file[MAX_BUF_SIZE] = {0};
5832 char buf[16] = {0};
5833
5834 if (!output)
5835 return RETURN_ERR;
5836
5837 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5838 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005839 // default is enable
5840 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5841 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005842
5843 return RETURN_OK;
5844}
5845
5846// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5847INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5848{
5849 //store the config, apply instantly
5850 char config_file[MAX_BUF_SIZE] = {0};
5851 struct params list;
5852
5853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5854 list.name = "ignore_broadcast_ssid";
5855 list.value = enable?"0":"1";
5856
5857 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5858 wifi_hostapdWrite(config_file, &list, 1);
5859 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5860 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005861 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005862 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5863
5864 return RETURN_OK;
5865}
5866
5867//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5868INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5869{
5870 //get the running status
5871 if(!output_uint)
5872 return RETURN_ERR;
5873 *output_uint=16;
5874 return RETURN_OK;
5875}
5876
5877INT wifi_setApRetryLimit(INT apIndex, UINT number)
5878{
5879 //apply instantly
5880 return RETURN_ERR;
5881}
5882
5883//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5884INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5885{
5886 if(!output)
5887 return RETURN_ERR;
5888 *output=TRUE;
5889 return RETURN_OK;
5890}
5891
5892//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5893INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5894{
5895 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005896 char cmd[128] = {0};
5897 char buf[128] = {0};
5898 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08005899 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08005900
developer0b246d12022-09-30 15:24:20 +08005901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005902
developer0b246d12022-09-30 15:24:20 +08005903 wifi_getMaxRadioNumber(&max_radio_num);
5904 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08005905 phyId = radio_index_to_phy(radioIndex);
5906 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08005907 _syscmd(cmd,buf, sizeof(buf));
5908
5909 if (strlen(buf) > 0)
5910 *output = true;
5911
5912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005913
developer06a01d92022-09-07 16:32:39 +08005914 return RETURN_OK;
5915}
5916
5917//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5918INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5919{
5920 //get the running status from driver
5921 if(!output)
5922 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005923
5924 char config_file[MAX_BUF_SIZE] = {0};
5925 char buf[16] = {0};
5926
5927 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5928 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005929 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08005930 *output = TRUE;
5931 else
5932 *output = FALSE;
5933
developer06a01d92022-09-07 16:32:39 +08005934 return RETURN_OK;
5935}
5936
5937// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5938INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5939{
5940 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005941 char config_file[MAX_BUF_SIZE] = {0};
5942 struct params list;
5943
5944 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5945 list.name = "wmm_enabled";
5946 list.value = enable?"1":"0";
5947
5948 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5949 wifi_hostapdWrite(config_file, &list, 1);
5950 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5951 wifi_reloadAp(apIndex);
5952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5953
5954 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005955}
5956
5957//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.
5958INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5959{
5960 //get the running status from driver
5961 if(!output)
5962 return RETURN_ERR;
5963 *output=TRUE;
5964 return RETURN_OK;
5965}
5966
5967// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5968INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5969{
5970 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005971 char config_file[MAX_BUF_SIZE] = {0};
5972 struct params list;
5973
5974 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5975 list.name = "uapsd_advertisement_enabled";
5976 list.value = enable?"1":"0";
5977
5978 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5979 wifi_hostapdWrite(config_file, &list, 1);
5980 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5981 wifi_reloadAp(apIndex);
5982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5983
5984 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005985}
5986
developer6daeb3f2022-09-30 13:36:39 +08005987// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005988INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5989{
developer6daeb3f2022-09-30 13:36:39 +08005990 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5991 char cmd[128] = {0};
5992 char buf[128] = {0};
5993 char ack_filepath[128] = {0};
5994 uint16_t bitmap = 0;
5995 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5996 FILE *f = NULL;
5997
5998 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5999
6000 // Get current setting
6001 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6002 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6003 _syscmd(cmd, buf, sizeof(buf));
6004 if (strlen(buf) > 0)
6005 bitmap = strtoul(buf, NULL, 10);
6006
6007 bitmap = strtoul(buf, NULL, 10);
6008
6009 if (ackPolicy == TRUE) { // True, unset this class
6010 bitmap &= ~class_map[class];
6011 } else { // False, set this class
6012 bitmap |= class_map[class];
6013 }
6014
6015 f = fopen(ack_filepath, "w");
6016 if (f == NULL) {
6017 fprintf(stderr, "%s: fopen failed\n", __func__);
6018 return RETURN_ERR;
6019 }
6020 fprintf(f, "%hu", bitmap);
6021 fclose(f);
6022
6023 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
6024 _syscmd(cmd, buf, sizeof(buf));
6025
6026 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6027 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006028}
6029
6030//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.
6031INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6032{
6033 //get the running status from driver
6034 if(!output_uint)
6035 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006036
6037 char output[16]={'\0'};
6038 char config_file[MAX_BUF_SIZE] = {0};
6039
6040 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6041 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6042 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6043 else {
6044 int device_num = atoi(output);
6045 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6046 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6047 return RETURN_ERR;
6048 }
6049 else {
6050 *output_uint = device_num;
6051 }
6052 }
6053
developer06a01d92022-09-07 16:32:39 +08006054 return RETURN_OK;
6055}
6056
6057INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6058{
6059 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006060 char str[MAX_BUF_SIZE]={'\0'};
6061 char cmd[MAX_CMD_SIZE]={'\0'};
6062 struct params params;
6063 char config_file[MAX_BUF_SIZE] = {0};
6064
6065 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6066 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
6067 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6068 return RETURN_ERR;
6069 }
6070 sprintf(str, "%d", number);
6071 params.name = "max_num_sta";
6072 params.value = str;
6073
6074 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6075 int ret = wifi_hostapdWrite(config_file, &params, 1);
6076 if (ret) {
6077 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6078 ,__func__, ret);
6079 }
6080
6081 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6082 if (ret) {
6083 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6084 ,__func__, ret);
6085 }
6086 wifi_reloadAp(apIndex);
6087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6088
6089 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006090}
6091
6092//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.
6093INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6094{
6095 //get the current threshold
6096 if(!output_uint)
6097 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006098 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6099 if (*output_uint == 0)
6100 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006101 return RETURN_OK;
6102}
6103
6104INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6105{
6106 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006107 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6108 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006109 return RETURN_ERR;
6110}
6111
6112//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.
6113INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6114{
6115 if(!output_uint)
6116 return RETURN_ERR;
6117 *output_uint = 3;
6118 return RETURN_OK;
6119}
6120
6121//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6122INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6123{
6124 if(!output_uint)
6125 return RETURN_ERR;
6126 *output_uint = 3;
6127 return RETURN_OK;
6128}
6129
6130//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.
6131INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6132{
6133 if(!output_in_seconds)
6134 return RETURN_ERR;
6135 *output_in_seconds = 0;
6136 return RETURN_OK;
6137}
6138
6139//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
6140INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6141{
6142 if(!output || apIndex>=MAX_APS)
6143 return RETURN_ERR;
6144 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006145 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006146 return RETURN_OK;
6147}
6148
6149//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6150INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6151{
developer587c1b62022-09-27 15:58:59 +08006152 char config_file[128] = {0};
6153 char wpa[16] = {0};
6154 char key_mgmt[64] = {0};
6155 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006156 if (!output)
6157 return RETURN_ERR;
6158
6159 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006160 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006161
developer587c1b62022-09-27 15:58:59 +08006162 strcpy(output, "None");//Copying "None" to output string for default case
6163 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006164 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006165 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006166 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006167 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006168 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006169 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006170 snprintf(output, 32, "WPA-WPA2-Personal");
6171
6172 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006173 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006174 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006175 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006176 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006177 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006178 snprintf(output, 32, "WPA-WPA2-Enterprise");
6179 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006180 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006181 snprintf(output, 32, "WPA3-Personal");
6182 else
developer4a359672022-10-13 15:30:46 +08006183 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006184 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6185 snprintf(output, 32, "WPA3-Enterprise");
6186 }
developer06a01d92022-09-07 16:32:39 +08006187
6188 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6189 return RETURN_OK;
6190#if 0
6191 //TODO: need to revisit below implementation
6192 char securityType[32], authMode[32];
6193 int enterpriseMode=0;
6194
6195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6196 if(!output)
6197 return RETURN_ERR;
6198
6199 wifi_getApBeaconType(apIndex, securityType);
6200 strcpy(output,"None");//By default, copying "None" to output string
6201 if (strncmp(securityType,"None", strlen("None")) == 0)
6202 return RETURN_OK;
6203
6204 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6205 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6206
6207 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6208 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6209 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6210 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6211 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6212 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6214
6215 return RETURN_OK;
6216#endif
6217}
6218
6219INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6220{
6221 char securityType[32];
6222 char authMode[32];
6223
6224 //store settings and wait for wifi up to apply
6225 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6226 if(!encMode)
6227 return RETURN_ERR;
6228
developer06a01d92022-09-07 16:32:39 +08006229 if (strcmp(encMode, "None")==0)
6230 {
6231 strcpy(securityType,"None");
6232 strcpy(authMode,"None");
6233 }
6234 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6235 {
6236 strcpy(securityType,"WPAand11i");
6237 strcpy(authMode,"PSKAuthentication");
6238 }
6239 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6240 {
6241 strcpy(securityType,"WPAand11i");
6242 strcpy(authMode,"EAPAuthentication");
6243 }
6244 else if (strcmp(encMode, "WPA-Personal")==0)
6245 {
6246 strcpy(securityType,"WPA");
6247 strcpy(authMode,"PSKAuthentication");
6248 }
6249 else if (strcmp(encMode, "WPA-Enterprise")==0)
6250 {
6251 strcpy(securityType,"WPA");
6252 strcpy(authMode,"EAPAuthentication");
6253 }
6254 else if (strcmp(encMode, "WPA2-Personal")==0)
6255 {
6256 strcpy(securityType,"11i");
6257 strcpy(authMode,"PSKAuthentication");
6258 }
6259 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6260 {
6261 strcpy(securityType,"11i");
6262 strcpy(authMode,"EAPAuthentication");
6263 }
developer587c1b62022-09-27 15:58:59 +08006264 else if (strcmp(encMode, "WPA3-Personal") == 0)
6265 {
6266 strcpy(securityType,"11i");
6267 strcpy(authMode,"SAEAuthentication");
6268 }
developer4a359672022-10-13 15:30:46 +08006269 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006270 {
6271 strcpy(securityType, "11i");
6272 strcpy(authMode, "PSK-SAEAuthentication");
6273 }
developer587c1b62022-09-27 15:58:59 +08006274 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6275 {
6276 strcpy(securityType,"11i");
6277 strcpy(authMode,"EAP_192-bit_Authentication");
6278 }
developer06a01d92022-09-07 16:32:39 +08006279 else
6280 {
6281 strcpy(securityType,"None");
6282 strcpy(authMode,"None");
6283 }
6284 wifi_setApBeaconType(apIndex, securityType);
6285 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6286 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6287
6288 return RETURN_OK;
6289}
6290
6291
6292//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6293// output_string must be pre-allocated as 64 character string by caller
6294// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6295INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6296{
6297 char buf[16];
6298 char config_file[MAX_BUF_SIZE] = {0};
6299
6300 if(output_string==NULL)
6301 return RETURN_ERR;
6302
6303 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6304 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6305
6306 if(strcmp(buf,"0")==0)
6307 {
6308 printf("wpa_mode is %s ......... \n",buf);
6309 return RETURN_ERR;
6310 }
6311
6312 wifi_dbg_printf("\nFunc=%s\n",__func__);
6313 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6314 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6315 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6316
6317 return RETURN_OK;
6318}
6319
6320// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6321// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6322INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6323{
6324 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6325 struct params params={'\0'};
6326 int ret;
6327 char config_file[MAX_BUF_SIZE] = {0};
6328
6329 if(NULL == preSharedKey)
6330 return RETURN_ERR;
6331
6332 params.name = "wpa_passphrase";
6333
6334 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6335 {
6336 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6337 return RETURN_ERR;
6338 }
6339 params.value = preSharedKey;
6340 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6341 ret = wifi_hostapdWrite(config_file, &params, 1);
6342 if(!ret)
6343 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6344 return ret;
6345 //TODO: call hostapd_cli for dynamic_config_control
6346}
6347
6348//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6349// outputs the passphrase, maximum 63 characters
6350INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6351{
6352 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6353
6354 wifi_dbg_printf("\nFunc=%s\n",__func__);
6355 if (NULL == output_string)
6356 return RETURN_ERR;
6357
6358 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6359 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6360 if(strcmp(buf,"0")==0)
6361 {
6362 printf("wpa_mode is %s ......... \n",buf);
6363 return RETURN_ERR;
6364 }
6365
6366 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6367 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6368
6369 return RETURN_OK;
6370}
6371
6372// sets the passphrase enviornment variable, max 63 characters
6373INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6374{
6375 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6376 struct params params={'\0'};
6377 char config_file[MAX_BUF_SIZE] = {0};
6378 int ret;
6379
6380 if(NULL == passPhrase)
6381 return RETURN_ERR;
6382
6383 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6384 {
6385 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6386 return RETURN_ERR;
6387 }
6388 params.name = "wpa_passphrase";
6389 params.value = passPhrase;
6390 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6391 ret=wifi_hostapdWrite(config_file,&params,1);
6392 if(!ret)
6393 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6394
6395 return ret;
6396}
6397
6398//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.
6399INT wifi_setApSecurityReset(INT apIndex)
6400{
developer8d583982022-09-20 11:28:22 +08006401 char original_config_file[64] = {0};
6402 char current_config_file[64] = {0};
6403 char buf[64] = {0};
6404 char cmd[64] = {0};
6405 char wpa[4] = {0};
6406 char wpa_psk[64] = {0};
6407 char wpa_passphrase[64] = {0};
6408 char wpa_psk_file[128] = {0};
6409 char wpa_key_mgmt[64] = {0};
6410 char wpa_pairwise[32] = {0};
6411 wifi_band band;
6412 struct params list[6];
6413
6414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6415
6416 band = wifi_index_to_band(apIndex);
6417 if (band == band_2_4)
6418 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6419 else if (band = band_5)
6420 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6421 else if (band = band_6)
6422 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6423 else
6424 return RETURN_ERR;
6425
6426 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6427 list[0].name = "wpa";
6428 list[0].value = wpa;
6429
6430 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6431 list[1].name = "wpa_psk";
6432 list[1].value = wpa_psk;
6433
6434 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6435 list[2].name = "wpa_passphrase";
6436 list[2].value = wpa_passphrase;
6437
6438 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6439
6440 if (strlen(wpa_psk_file) == 0)
6441 strcpy(wpa_psk_file, PSK_FILE);
6442
6443 if (access(wpa_psk_file, F_OK) != 0) {
6444 sprintf(cmd, "touch %s", wpa_psk_file);
6445 _syscmd(cmd, buf, sizeof(buf));
6446 }
6447 list[3].name = "wpa_psk_file";
6448 list[3].value = wpa_psk_file;
6449
6450 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6451 list[4].name = "wpa_key_mgmt";
6452 list[4].value = wpa_key_mgmt;
6453
6454 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6455 list[5].name = "wpa_pairwise";
6456 list[5].value = wpa_pairwise;
6457
6458 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6459 wifi_hostapdWrite(current_config_file, list, 6);
6460
6461 wifi_setApEnable(apIndex, FALSE);
6462 wifi_setApEnable(apIndex, TRUE);
6463
6464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6465 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006466}
6467
6468//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).
6469INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6470{
developer8f2ddd52022-09-13 15:39:24 +08006471 char config_file[64] = {0};
6472 char buf[64] = {0};
6473 char cmd[256] = {0};
6474
6475 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6476
developer06a01d92022-09-07 16:32:39 +08006477 if(!IP_output || !Port_output || !RadiusSecret_output)
6478 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006479
developer8f2ddd52022-09-13 15:39:24 +08006480 // Read the first matched config
6481 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6482 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6483 _syscmd(cmd, buf, sizeof(buf));
6484 strncpy(IP_output, buf, 64);
6485
6486 memset(buf, 0, sizeof(buf));
6487 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6488 _syscmd(cmd, buf, sizeof(buf));
6489 *Port_output = atoi(buf);
6490
6491 memset(buf, 0, sizeof(buf));
6492 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6493 _syscmd(cmd, buf, sizeof(buf));
6494 strncpy(RadiusSecret_output, buf, 64);
6495
6496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006497 return RETURN_OK;
6498}
6499
6500INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6501{
developer8f2ddd52022-09-13 15:39:24 +08006502 char config_file[64] = {0};
6503 char port_str[8] = {0};
6504 char cmd[256] = {0};
6505 char buf[128] = {0};
6506
6507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6508
6509 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6510
6511 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6512 _syscmd(cmd, buf, sizeof(buf));
6513 memset(cmd, 0, sizeof(cmd));
6514
6515 snprintf(port_str, sizeof(port_str), "%d", port);
6516 if (strlen(buf) == 0)
6517 // Append
6518 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6519 "auth_server_addr=%s\\n"
6520 "auth_server_port=%s\\n"
6521 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6522 else {
6523 // Delete the three lines setting after the "# radius 1" comment
6524 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6525 _syscmd(cmd, buf, sizeof(buf));
6526 memset(cmd, 0, sizeof(cmd));
6527 // Use "# radius 1" comment to find the location to insert the radius setting
6528 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6529 "# radius 1\\n"
6530 "auth_server_addr=%s\\n"
6531 "auth_server_port=%s\\n"
6532 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6533 }
6534 if(_syscmd(cmd, buf, sizeof(buf))) {
6535 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6536 return RETURN_ERR;
6537 }
6538
6539 wifi_reloadAp(apIndex);
6540 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6541 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006542}
6543
6544INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6545{
developer8f2ddd52022-09-13 15:39:24 +08006546 char config_file[64] = {0};
6547 char buf[64] = {0};
6548 char cmd[256] = {0};
6549
6550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6551
developer06a01d92022-09-07 16:32:39 +08006552 if(!IP_output || !Port_output || !RadiusSecret_output)
6553 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006554
6555 // Read the second matched config
6556 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6557 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6558 _syscmd(cmd, buf, sizeof(buf));
6559 strncpy(IP_output, buf, 64);
6560
6561 memset(buf, 0, sizeof(buf));
6562 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6563 _syscmd(cmd, buf, sizeof(buf));
6564 *Port_output = atoi(buf);
6565
6566 memset(buf, 0, sizeof(buf));
6567 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6568 _syscmd(cmd, buf, sizeof(buf));
6569 strncpy(RadiusSecret_output, buf, 64);
6570
6571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006572 return RETURN_OK;
6573}
6574
6575INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6576{
developer8f2ddd52022-09-13 15:39:24 +08006577 char config_file[64] = {0};
6578 char port_str[8] = {0};
6579 char cmd[256] = {0};
6580 char buf[128] = {0};
6581
6582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6583
6584 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6585
6586 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6587 _syscmd(cmd, buf, sizeof(buf));
6588 memset(cmd, 0, sizeof(cmd));
6589
6590 snprintf(port_str, sizeof(port_str), "%d", port);
6591 if (strlen(buf) == 0)
6592 // Append
6593 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6594 "auth_server_addr=%s\\n"
6595 "auth_server_port=%s\\n"
6596 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6597 else {
6598 // Delete the three lines setting after the "# radius 2" comment
6599 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6600 _syscmd(cmd, buf, sizeof(buf));
6601 memset(cmd, 0, sizeof(cmd));
6602 // Use "# radius 2" comment to find the location to insert the radius setting
6603 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6604 "# radius 2\\n"
6605 "auth_server_addr=%s\\n"
6606 "auth_server_port=%s\\n"
6607 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6608 }
6609 if(_syscmd(cmd, buf, sizeof(buf))) {
6610 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6611 return RETURN_ERR;
6612 }
6613
6614 wifi_reloadAp(apIndex);
6615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6616 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006617}
6618
6619//RadiusSettings
6620INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6621{
6622 if(!output)
6623 return RETURN_ERR;
6624
6625 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6626 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6627 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6628 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6629 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6630 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.
6631 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6632 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6633 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6634 //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.
6635
6636 return RETURN_OK;
6637}
6638
6639INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6640{
6641 //store the paramters, and apply instantly
6642 return RETURN_ERR;
6643}
6644
6645//Device.WiFi.AccessPoint.{i}.WPS.Enable
6646//Enables or disables WPS functionality for this access point.
6647// outputs the WPS enable state of this ap in output_bool
6648INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6649{
6650 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6651 if(!output_bool || !(apIndex==0 || apIndex==1))
6652 return RETURN_ERR;
6653 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6654 _syscmd(cmd, buf, sizeof(buf));
6655 if(strstr(buf, "configured"))
6656 *output_bool=TRUE;
6657 else
6658 *output_bool=FALSE;
6659
6660 return RETURN_OK;
6661}
6662
6663//Device.WiFi.AccessPoint.{i}.WPS.Enable
6664// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6665INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6666{
6667 char config_file[MAX_BUF_SIZE] = {0};
6668 struct params params;
6669
6670 if(!(apIndex==0 || apIndex==1))
6671 return RETURN_ERR;
6672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6673 //store the paramters, and wait for wifi up to apply
6674 params.name = "wps_state";
6675 params.value = enable ? "2":"0";
6676
6677 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6678 wifi_hostapdWrite(config_file, &params, 1);
6679 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6680 wifi_reloadAp(apIndex);
6681
6682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6683 return RETURN_OK;
6684}
6685
6686//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
6687INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6688{
6689 if(!output)
6690 return RETURN_ERR;
6691 snprintf(output, 128, "PushButton,PIN");
6692 return RETURN_OK;
6693}
6694
6695//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6696//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.
6697// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6698INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6699{
6700 if(!output)
6701 return RETURN_ERR;
6702 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6703
6704 return RETURN_OK;
6705}
6706
6707//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6708// 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
6709INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6710{
6711 //apply instantly. No setting need to be stored.
6712 char methods[MAX_BUF_SIZE], *token, *next_token;
6713 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6714 struct params params;
6715
6716 if(!methodString || !(apIndex==0 || apIndex==1))
6717 return RETURN_ERR;
6718 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6719 //store the paramters, and wait for wifi up to apply
6720
6721 snprintf(methods, sizeof(methods), "%s", methodString);
6722 for(token=methods; *token; token=next_token)
6723 {
6724 strtok_r(token, ",", &next_token);
6725 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6726 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6727 else if(*token=='E')
6728 {
6729 if(!strcmp(methods, "Ethernet"))
6730 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6731 else if(!strcmp(methods, "ExternalNFCToken"))
6732 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6733 else
6734 printf("%s: Unknown WpsConfigMethod\n", __func__);
6735 }
6736 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6737 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6738 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6739 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6740 else if(*token=='P' )
6741 {
6742 if(!strcmp(token, "PushButton"))
6743 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6744 else if(!strcmp(token, "PIN"))
6745 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6746 else
6747 printf("%s: Unknown WpsConfigMethod\n", __func__);
6748 }
6749 else
6750 printf("%s: Unknown WpsConfigMethod\n", __func__);
6751 }
6752 params.name = "config_methods";
6753 params.value = config_methods;
6754 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6755 wifi_hostapdWrite(config_file, &params, 1);
6756 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6758
6759 return RETURN_OK;
6760}
6761
6762// outputs the pin value, ulong_pin must be allocated by the caller
6763INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6764{
6765 char buf[MAX_BUF_SIZE] = {0};
6766 char cmd[MAX_CMD_SIZE] = {0};
6767
6768 if(!output_ulong || !(apIndex==0 || apIndex==1))
6769 return RETURN_ERR;
6770 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6771 _syscmd(cmd, buf, sizeof(buf));
6772 if(strlen(buf) > 0)
6773 *output_ulong=strtoul(buf, NULL, 10);
6774
6775 return RETURN_OK;
6776}
6777
6778// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6779INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6780{
6781 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6782 char ap_pin[16] = {0};
6783 char buf[MAX_BUF_SIZE] = {0};
6784 char config_file[MAX_BUF_SIZE] = {0};
6785 ULONG prev_pin = 0;
6786 struct params params;
6787
6788 if(!(apIndex==0 || apIndex==1))
6789 return RETURN_ERR;
6790 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6791 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6792 params.name = "ap_pin";
6793 params.value = ap_pin;
6794 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6795 wifi_hostapdWrite(config_file, &params, 1);
6796 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6797 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6798
6799 return RETURN_OK;
6800}
6801
6802// Output string is either Not configured or Configured, max 32 characters
6803INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6804{
6805 char cmd[MAX_CMD_SIZE];
6806 char buf[MAX_BUF_SIZE]={0};
6807
6808 if(!output_string || !(apIndex==0 || apIndex==1))
6809 return RETURN_ERR;
6810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6811 snprintf(output_string, 32, "Not configured");
6812 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6813 _syscmd(cmd, buf, sizeof(buf));
6814
developer348e3d92022-09-13 14:48:41 +08006815 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006816 snprintf(output_string, 32, "Configured");
6817 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6818
6819 return RETURN_OK;
6820}
6821
6822// sets the WPS pin for this AP
6823INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6824{
6825 char cmd[MAX_CMD_SIZE];
6826 char buf[MAX_BUF_SIZE]={0};
6827 BOOL enable;
6828
6829 if(!(apIndex==0 || apIndex==1))
6830 return RETURN_ERR;
6831 wifi_getApEnable(apIndex, &enable);
6832 if (!enable)
6833 return RETURN_ERR;
6834 wifi_getApWpsEnable(apIndex, &enable);
6835 if (!enable)
6836 return RETURN_ERR;
6837
6838 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6839 _syscmd(cmd, buf, sizeof(buf));
6840 if((strstr(buf, "OK"))!=NULL)
6841 return RETURN_OK;
6842
6843 return RETURN_ERR;
6844}
6845
6846// This function is called when the WPS push button has been pressed for this AP
6847INT wifi_setApWpsButtonPush(INT apIndex)
6848{
6849 char cmd[MAX_CMD_SIZE];
6850 char buf[MAX_BUF_SIZE]={0};
6851 BOOL enable=FALSE;
6852
6853 if(!(apIndex==0 || apIndex==1))
6854 return RETURN_ERR;
6855 wifi_getApEnable(apIndex, &enable);
6856 if (!enable)
6857 return RETURN_ERR;
6858
6859 wifi_getApWpsEnable(apIndex, &enable);
6860 if (!enable)
6861 return RETURN_ERR;
6862
6863 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6864 _syscmd(cmd, buf, sizeof(buf));
6865
6866 if((strstr(buf, "OK"))!=NULL)
6867 return RETURN_OK;
6868 return RETURN_ERR;
6869}
6870
6871// cancels WPS mode for this AP
6872INT wifi_cancelApWPS(INT apIndex)
6873{
6874 char cmd[MAX_CMD_SIZE];
6875 char buf[MAX_BUF_SIZE]={0};
6876
6877 if(!(apIndex==0 || apIndex==1))
6878 return RETURN_ERR;
6879 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6880 _syscmd(cmd,buf, sizeof(buf));
6881
6882 if((strstr(buf, "OK"))!=NULL)
6883 return RETURN_OK;
6884 return RETURN_ERR;
6885}
6886
6887//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6888//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6889INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6890{
6891 FILE *f;
6892 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6893 char cmd[256], buf[2048];
6894 char *param , *value, *line=NULL;
6895 size_t len = 0;
6896 ssize_t nread;
6897 wifi_associated_dev_t *dev=NULL;
6898
6899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6900 *associated_dev_array = NULL;
6901 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6902 _syscmd(cmd,buf,sizeof(buf));
6903 *output_array_size = atoi(buf);
6904
6905 if (*output_array_size <= 0)
6906 return RETURN_OK;
6907
6908 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6909 *associated_dev_array = dev;
6910 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6911 _syscmd(cmd,buf,sizeof(buf));
6912 f = fopen("/tmp/connected_devices.txt", "r");
6913 if (f==NULL)
6914 {
6915 *output_array_size=0;
6916 return RETURN_ERR;
6917 }
6918 while ((nread = getline(&line, &len, f)) != -1)
6919 {
6920 param = strtok(line,"=");
6921 value = strtok(NULL,"=");
6922
6923 if( strcmp("flags",param) == 0 )
6924 {
6925 value[strlen(value)-1]='\0';
6926 if(strstr (value,"AUTHORIZED") != NULL )
6927 {
6928 dev[auth_temp].cli_AuthenticationState = 1;
6929 dev[auth_temp].cli_Active = 1;
6930 auth_temp++;
6931 read_flag=1;
6932 }
6933 }
6934 if(read_flag==1)
6935 {
6936 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6937 {
6938 value[strlen(value)-1]='\0';
6939 sscanf(value, "%x:%x:%x:%x:%x:%x",
6940 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6941 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6942 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6943 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6944 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6945 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6946 mac_temp++;
6947 read_flag=0;
6948 }
6949 }
6950 }
6951 *output_array_size = auth_temp;
6952 auth_temp=0;
6953 mac_temp=0;
6954 free(line);
6955 fclose(f);
6956 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6957 return RETURN_OK;
6958}
6959
6960#define MACADDRESS_SIZE 6
6961
6962INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6963{
6964 FILE *fp = NULL;
6965 char str[MAX_BUF_SIZE] = {0};
6966 int wificlientindex = 0 ;
6967 int count = 0;
6968 int signalstrength = 0;
6969 int arr[MACADDRESS_SIZE] = {0};
6970 unsigned char mac[MACADDRESS_SIZE] = {0};
6971 UINT wifi_count = 0;
6972 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6973 char pipeCmd[MAX_CMD_SIZE] = {0};
6974
6975 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6976 *output_array_size = 0;
6977 *associated_dev_array = NULL;
6978
6979 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6980 fp = popen(pipeCmd, "r");
6981 if (fp == NULL)
6982 {
6983 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6984 return RETURN_ERR;
6985 }
6986
6987 /* Read the output a line at a time - output it. */
6988 fgets(str, sizeof(str)-1, fp);
6989 wifi_count = (unsigned int) atoi ( str );
6990 *output_array_size = wifi_count;
6991 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6992 pclose(fp);
6993
6994 if(wifi_count == 0)
6995 {
6996 return RETURN_OK;
6997 }
6998 else
6999 {
7000 wifi_associated_dev3_t* temp = NULL;
7001 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7002 if(temp == NULL)
7003 {
7004 printf("Error Statement. Insufficient memory \n");
7005 return RETURN_ERR;
7006 }
7007
7008 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7009 system(pipeCmd);
7010 memset(pipeCmd,0,sizeof(pipeCmd));
7011 if(apIndex == 0)
7012 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7013 else if(apIndex == 1)
7014 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7015 system(pipeCmd);
7016
7017 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7018 if(fp == NULL)
7019 {
7020 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7021 return RETURN_ERR;
7022 }
7023 fclose(fp);
7024
7025 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7026 fp = popen(pipeCmd, "r");
7027 if(fp)
7028 {
7029 for(count =0 ; count < wifi_count; count++)
7030 {
7031 fgets(str, MAX_BUF_SIZE, fp);
7032 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7033 {
7034 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7035 {
7036 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7037
7038 }
7039 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7040 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]);
7041 }
7042 temp[count].cli_AuthenticationState = 1; //TODO
7043 temp[count].cli_Active = 1; //TODO
7044 }
7045 pclose(fp);
7046 }
7047
7048 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7049 fp = popen(pipeCmd, "r");
7050 if(fp)
7051 {
7052 pclose(fp);
7053 }
7054 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7055 if(fp)
7056 {
7057 for(count =0 ; count < wifi_count ;count++)
7058 {
7059 fgets(str, MAX_BUF_SIZE, fp);
7060 signalstrength = atoi(str);
7061 temp[count].cli_SignalStrength = signalstrength;
7062 temp[count].cli_RSSI = signalstrength;
7063 temp[count].cli_SNR = signalstrength + 95;
7064 }
7065 pclose(fp);
7066 }
7067
7068
7069 if((apIndex == 0) || (apIndex == 4))
7070 {
7071 for(count =0 ; count < wifi_count ;count++)
7072 {
7073 strcpy(temp[count].cli_OperatingStandard,"g");
7074 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7075 }
7076
7077 //BytesSent
7078 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
7079 fp = popen(pipeCmd, "r");
7080 if(fp)
7081 {
7082 pclose(fp);
7083 }
7084 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7085 if(fp)
7086 {
7087 for (count = 0; count < wifi_count; count++)
7088 {
7089 fgets(str, MAX_BUF_SIZE, fp);
7090 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7091 }
7092 pclose(fp);
7093 }
7094
7095 //BytesReceived
7096 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7097 fp = popen(pipeCmd, "r");
7098 if (fp)
7099 {
7100 pclose(fp);
7101 }
7102 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7103 if (fp)
7104 {
7105 for (count = 0; count < wifi_count; count++)
7106 {
7107 fgets(str, MAX_BUF_SIZE, fp);
7108 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7109 }
7110 pclose(fp);
7111 }
7112
7113 //PacketsSent
7114 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7115 fp = popen(pipeCmd, "r");
7116 if (fp)
7117 {
7118 pclose(fp);
7119 }
7120
7121 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7122 if (fp)
7123 {
7124 for (count = 0; count < wifi_count; count++)
7125 {
7126 fgets(str, MAX_BUF_SIZE, fp);
7127 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7128 }
7129 pclose(fp);
7130 }
7131
7132 //PacketsReceived
7133 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7134 fp = popen(pipeCmd, "r");
7135 if (fp)
7136 {
7137 pclose(fp);
7138 }
7139 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7140 if (fp)
7141 {
7142 for (count = 0; count < wifi_count; count++)
7143 {
7144 fgets(str, MAX_BUF_SIZE, fp);
7145 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7146 }
7147 pclose(fp);
7148 }
7149
7150 //ErrorsSent
7151 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7152 fp = popen(pipeCmd, "r");
7153 if (fp)
7154 {
7155 pclose(fp);
7156 }
7157 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7158 if (fp)
7159 {
7160 for (count = 0; count < wifi_count; count++)
7161 {
7162 fgets(str, MAX_BUF_SIZE, fp);
7163 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7164 }
7165 pclose(fp);
7166 }
7167
7168 //ErrorsSent
7169 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7170 fp = popen(pipeCmd, "r");
7171 if (fp)
7172 {
7173 pclose(fp);
7174 }
7175 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7176 if (fp)
7177 {
7178 for (count = 0; count < wifi_count; count++)
7179 {
7180 fgets(str, MAX_BUF_SIZE, fp);
7181 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7182 }
7183 pclose(fp);
7184 }
7185
7186 //LastDataDownlinkRate
7187 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7188 fp = popen(pipeCmd, "r");
7189 if (fp)
7190 {
7191 pclose(fp);
7192 }
7193 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7194 if (fp)
7195 {
7196 for (count = 0; count < wifi_count; count++)
7197 {
7198 fgets(str, MAX_BUF_SIZE, fp);
7199 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7200 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7201 }
7202 pclose(fp);
7203 }
7204
7205 //LastDataUplinkRate
7206 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7207 fp = popen(pipeCmd, "r");
7208 if (fp)
7209 {
7210 pclose(fp);
7211 }
7212 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7213 if (fp)
7214 {
7215 for (count = 0; count < wifi_count; count++)
7216 {
7217 fgets(str, MAX_BUF_SIZE, fp);
7218 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7219 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7220 }
7221 pclose(fp);
7222 }
7223
7224 }
7225 else if ((apIndex == 1) || (apIndex == 5))
7226 {
7227 for (count = 0; count < wifi_count; count++)
7228 {
7229 strcpy(temp[count].cli_OperatingStandard, "a");
7230 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7231 temp[count].cli_BytesSent = 0;
7232 temp[count].cli_BytesReceived = 0;
7233 temp[count].cli_LastDataUplinkRate = 0;
7234 temp[count].cli_LastDataDownlinkRate = 0;
7235 temp[count].cli_PacketsSent = 0;
7236 temp[count].cli_PacketsReceived = 0;
7237 temp[count].cli_ErrorsSent = 0;
7238 }
7239 }
7240
7241 for (count = 0; count < wifi_count; count++)
7242 {
7243 temp[count].cli_Retransmissions = 0;
7244 temp[count].cli_DataFramesSentAck = 0;
7245 temp[count].cli_DataFramesSentNoAck = 0;
7246 temp[count].cli_MinRSSI = 0;
7247 temp[count].cli_MaxRSSI = 0;
7248 strncpy(temp[count].cli_InterferenceSources, "", 64);
7249 memset(temp[count].cli_IPAddress, 0, 64);
7250 temp[count].cli_RetransCount = 0;
7251 temp[count].cli_FailedRetransCount = 0;
7252 temp[count].cli_RetryCount = 0;
7253 temp[count].cli_MultipleRetryCount = 0;
7254 }
7255 *associated_dev_array = temp;
7256 }
7257 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7258 return RETURN_OK;
7259}
7260
7261int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7262{
7263 FILE *fp = NULL;
7264 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7265 char cmd[MAX_CMD_SIZE];
7266 int count = 0;
7267
7268 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7269 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7270 fp = popen(cmd,"r");
7271 if(fp == NULL)
7272 {
7273 printf("Failed to run command in Function %s\n",__FUNCTION__);
7274 return 0;
7275 }
7276 if(fgets(path, sizeof(path)-1, fp) != NULL)
7277 {
7278 for(count=0;path[count]!='\n';count++)
7279 status[count]=path[count];
7280 status[count]='\0';
7281 }
7282 strcpy(wifi_status,status);
7283 pclose(fp);
7284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7285 return RETURN_OK;
7286}
7287
7288/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7289struct hostapd_sta_param {
7290 char key[50];
7291 char value[100];
7292}
7293
7294static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7295 int i = 0;
7296
7297 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7298 if (strncmp(params[i].key,key,50) == 0){
7299 return &params[i].value;
7300 }
7301 i++;
7302 }
7303 return NULL;
7304
7305} */
7306
7307static unsigned int count_occurences(const char *buf, const char *word)
7308{
7309 unsigned int n = 0;
7310 char *ptr = strstr(buf, word);
7311
7312 while (ptr++) {
7313 n++;
7314 ptr = strstr(ptr, word);
7315 }
7316
7317 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7318 return n;
7319}
7320
7321static const char *get_line_from_str_buf(const char *buf, char *line)
7322{
7323 int i;
7324 int n = strlen(buf);
7325
7326 for (i = 0; i < n; i++) {
7327 line[i] = buf[i];
7328 if (buf[i] == '\n') {
7329 line[i] = '\0';
7330 return &buf[i + 1];
7331 }
7332 }
7333
7334 return NULL;
7335}
7336
7337INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7338{
7339 unsigned int assoc_cnt = 0;
7340 char interface_name[50] = {0};
7341 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7342 char cmd[MAX_CMD_SIZE] = {'\0'};
7343 char line[256] = {'\0'};
7344 int i = 0;
7345 int ret = 0;
7346 const char *ptr = NULL;
7347 char *key = NULL;
7348 char *val = NULL;
7349 wifi_associated_dev3_t *temp = NULL;
7350 int rssi;
7351
7352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7353
7354 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7355 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7356 return RETURN_ERR;
7357 }
7358
7359 // Example filtered output of 'iw dev' command:
7360 // Station 0a:69:72:10:d2:fa (on wifi0)
7361 // signal avg:-67 [-71, -71] dBm
7362 // Station 28:c2:1f:25:5f:99 (on wifi0)
7363 // signal avg:-67 [-71, -70] dBm
7364 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7365 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7366 return RETURN_ERR;
7367 }
7368
7369 ret = _syscmd(cmd, buf, sizeof(buf));
7370 if (ret == RETURN_ERR) {
7371 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7372 return RETURN_ERR;
7373 }
7374
7375 *output_array_size = count_occurences(buf, "Station");
7376 if (*output_array_size == 0) return RETURN_OK;
7377
7378 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7379 if (temp == NULL) {
7380 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7381 return RETURN_ERR;
7382 }
7383 *associated_dev_array = temp;
7384
7385 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7386 ptr = get_line_from_str_buf(buf, line);
7387 i = -1;
7388 while (ptr) {
7389 if (strstr(line, "Station")) {
7390 i++;
7391 key = strtok(line, " ");
7392 val = strtok(NULL, " ");
7393 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7394 &temp[i].cli_MACAddress[0],
7395 &temp[i].cli_MACAddress[1],
7396 &temp[i].cli_MACAddress[2],
7397 &temp[i].cli_MACAddress[3],
7398 &temp[i].cli_MACAddress[4],
7399 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7400 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7401 free(*associated_dev_array);
7402 return RETURN_ERR;
7403 }
7404 }
7405 else if (i < 0) {
7406 ptr = get_line_from_str_buf(ptr, line);
7407 continue; // We didn't detect 'station' entry yet
7408 }
7409 else if (strstr(line, "signal avg")) {
7410 key = strtok(line, ":");
7411 val = strtok(NULL, " ");
7412 if (sscanf(val, "%d", &rssi) <= 0 ) {
7413 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7414 free(*associated_dev_array);
7415 return RETURN_ERR;
7416 }
7417 temp[i].cli_RSSI = rssi;
7418 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7419 }
7420 // Here other fields can be parsed if added to filter of 'iw dev' command
7421
7422 ptr = get_line_from_str_buf(ptr, line);
7423 };
7424
7425 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7426
7427 return RETURN_OK;
7428}
7429
7430#if 0
7431//To-do
7432INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7433{
7434 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7435
7436 //Using different approach to get required WiFi Parameters from system available commands
7437#if 0
7438 FILE *f;
7439 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7440 char cmd[256], buf[2048];
7441 char *param , *value, *line=NULL;
7442 size_t len = 0;
7443 ssize_t nread;
7444 wifi_associated_dev3_t *dev=NULL;
7445 *associated_dev_array = NULL;
7446 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7447 _syscmd(cmd,buf,sizeof(buf));
7448 *output_array_size = atoi(buf);
7449
7450 if (*output_array_size <= 0)
7451 return RETURN_OK;
7452
7453 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7454 *associated_dev_array = dev;
7455 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7456 _syscmd(cmd,buf,sizeof(buf));
7457 f = fopen("/tmp/connected_devices.txt", "r");
7458 if (f==NULL)
7459 {
7460 *output_array_size=0;
7461 return RETURN_ERR;
7462 }
7463 while ((nread = getline(&line, &len, f)) != -1)
7464 {
7465 param = strtok(line,"=");
7466 value = strtok(NULL,"=");
7467
7468 if( strcmp("flags",param) == 0 )
7469 {
7470 value[strlen(value)-1]='\0';
7471 if(strstr (value,"AUTHORIZED") != NULL )
7472 {
7473 dev[auth_temp].cli_AuthenticationState = 1;
7474 dev[auth_temp].cli_Active = 1;
7475 auth_temp++;
7476 read_flag=1;
7477 }
7478 }
7479 if(read_flag==1)
7480 {
7481 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7482 {
7483 value[strlen(value)-1]='\0';
7484 sscanf(value, "%x:%x:%x:%x:%x:%x",
7485 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7486 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7487 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7488 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7489 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7490 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7491
7492 }
7493 else if( strcmp("rx_packets",param) == 0 )
7494 {
7495 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7496 }
7497
7498 else if( strcmp("tx_packets",param) == 0 )
7499 {
7500 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7501 }
7502
7503 else if( strcmp("rx_bytes",param) == 0 )
7504 {
7505 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7506 }
7507
7508 else if( strcmp("tx_bytes",param) == 0 )
7509 {
7510 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7511 mac_temp++;
7512 read_flag=0;
7513 }
7514 }
7515 }
7516
7517 *output_array_size = auth_temp;
7518 auth_temp=0;
7519 mac_temp=0;
7520 free(line);
7521 fclose(f);
7522#endif
7523 char interface_name[MAX_BUF_SIZE] = {0};
7524 char wifi_status[MAX_BUF_SIZE] = {0};
7525 char hostapdconf[MAX_BUF_SIZE] = {0};
7526
7527 wifi_associated_dev3_t *dev_array = NULL;
7528 ULONG wifi_count = 0;
7529
7530 *associated_dev_array = NULL;
7531 *output_array_size = 0;
7532
7533 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7534 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7535 {
7536 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7537
7538 GetInterfaceName(interface_name, hostapdconf);
7539
7540 if(strlen(interface_name) > 1)
7541 {
7542 wifihal_interfacestatus(wifi_status,interface_name);
7543 if(strcmp(wifi_status,"RUNNING") == 0)
7544 {
7545 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7546
7547 *associated_dev_array = dev_array;
7548 *output_array_size = wifi_count;
7549 }
7550 else
7551 {
7552 *associated_dev_array = NULL;
7553 }
7554 }
7555 }
7556
7557 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7558 return RETURN_OK;
7559}
7560#endif
7561
7562/* getIPAddress function */
7563/**
7564* @description Returning IpAddress of the Matched String
7565*
7566* @param
7567* @str Having MacAddress
7568* @ipaddr Having ipaddr
7569* @return The status of the operation
7570* @retval RETURN_OK if successful
7571* @retval RETURN_ERR if any error is detected
7572*
7573*/
7574
7575INT getIPAddress(char *str,char *ipaddr)
7576{
7577 FILE *fp = NULL;
7578 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7579 int LeaseTime = 0,ret = 0;
7580 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7581 {
7582 return RETURN_ERR;
7583 }
7584
7585 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7586 {
7587 /*
7588 Sample:sss
7589 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7590 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7591 */
7592 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7593 &(LeaseTime),
7594 phyAddr,
7595 ipAddr,
7596 hostName
7597 );
7598 if(ret != 4)
7599 continue;
7600 if(strcmp(str,phyAddr) == 0)
7601 strcpy(ipaddr,ipAddr);
7602 }
7603 return RETURN_OK;
7604}
7605
7606/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7607/**
7608* @description Returning Inactive wireless connected clients informations
7609*
7610* @param
7611* @filename Holding private_wifi 2g/5g content files
7612* @associated_dev_array Having inactiv wireless clients informations
7613* @output_array_size Returning Inactive wireless counts
7614* @return The status of the operation
7615* @retval RETURN_OK if successful
7616* @retval RETURN_ERR if any error is detected
7617*
7618*/
7619
7620INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7621{
7622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7623 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7624 FILE *fp = NULL;
7625 int arr[MACADDRESS_SIZE] = {0};
7626 unsigned char mac[MACADDRESS_SIZE] = {0};
7627 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7628 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7629 fp = popen(buf,"r");
7630 if(fp == NULL)
7631 return RETURN_ERR;
7632 else
7633 {
7634 fgets(path,sizeof(path),fp);
7635 maccount = atoi(path);
7636 }
7637 pclose(fp);
7638 *output_array_size = maccount;
7639 wifi_associated_dev3_t* temp = NULL;
7640 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7641 *associated_dev_array = temp;
7642 if(temp == NULL)
7643 {
7644 printf("Error Statement. Insufficient memory \n");
7645 return RETURN_ERR;
7646 }
7647 memset(buf,0,sizeof(buf));
7648 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7649 fp = popen(buf,"r");
7650 for(count = 0; count < maccount ; count++)
7651 {
7652 fgets(path,sizeof(path),fp);
7653 for(i = 0; path[i]!='\n';i++)
7654 str[i]=path[i];
7655 str[i]='\0';
7656 getIPAddress(str,ipaddr);
7657 memset(buf,0,sizeof(buf));
7658 if(strlen(ipaddr) > 0)
7659 {
7660 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7661 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7662 {
7663 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7664 {
7665 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7666 {
7667 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7668
7669 }
7670 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7671 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]);
7672 }
7673 temp[count].cli_AuthenticationState = 0; //TODO
7674 temp[count].cli_Active = 0; //TODO
7675 temp[count].cli_SignalStrength = 0;
7676 }
7677 else //Active wireless clients info
7678 {
7679 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7680 {
7681 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7682 {
7683 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7684
7685 }
7686 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7687 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]);
7688 }
7689 temp[count].cli_Active = 1;
7690 }
7691 }
7692 memset(ipaddr,0,sizeof(ipaddr));
7693 }
7694 pclose(fp);
7695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7696 return RETURN_OK;
7697}
7698//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7699//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7700//To get Band Steering Capability
7701INT wifi_getBandSteeringCapability(BOOL *support)
7702{
7703 *support = FALSE;
7704 return RETURN_OK;
7705}
7706
7707
7708//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7709//To get Band Steering enable status
7710INT wifi_getBandSteeringEnable(BOOL *enable)
7711{
7712 *enable = FALSE;
7713 return RETURN_OK;
7714}
7715
7716//To turn on/off Band steering
7717INT wifi_setBandSteeringEnable(BOOL enable)
7718{
7719 return RETURN_OK;
7720}
7721
7722//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7723//To get Band Steering AP group
7724INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7725{
7726 if (NULL == output_ApGroup)
7727 return RETURN_ERR;
7728
7729 strcpy(output_ApGroup, "1,2");
7730 return RETURN_OK;
7731}
7732
7733//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7734//to set and read the band steering BandUtilizationThreshold parameters
7735INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7736{
7737 return RETURN_ERR;
7738}
7739
7740INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7741{
7742 return RETURN_ERR;
7743}
7744
7745//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7746//to set and read the band steering RSSIThreshold parameters
7747INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7748{
7749 return RETURN_ERR;
7750}
7751
7752INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7753{
7754 return RETURN_ERR;
7755}
7756
7757
7758//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7759//to set and read the band steering physical modulation rate threshold parameters
7760INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7761{
7762 //If chip is not support, return -1
7763 return RETURN_ERR;
7764}
7765
7766INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7767{
7768 //If chip is not support, return -1
7769 return RETURN_ERR;
7770}
7771
7772//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7773//to set and read the inactivity time (in seconds) for steering under overload condition
7774INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7775{
7776 return RETURN_ERR;
7777}
7778
7779INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7780{
7781 return RETURN_ERR;
7782}
7783
7784//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7785//to set and read the inactivity time (in seconds) for steering under Idle condition
7786INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7787{
7788 return RETURN_ERR;
7789}
7790
7791INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7792{
7793 return RETURN_ERR;
7794}
7795
7796//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7797//pClientMAC[64]
7798//pSourceSSIDIndex[64]
7799//pDestSSIDIndex[64]
7800//pSteeringReason[256]
7801INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7802{
7803 //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
7804 *pSteeringTime=time(NULL);
7805 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7806 return RETURN_OK;
7807}
7808
7809INT wifi_ifConfigDown(INT apIndex)
7810{
7811 INT status = RETURN_OK;
7812 char cmd[64];
7813
7814 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7815 printf("%s: %s\n", __func__, cmd);
7816 system(cmd);
7817
7818 return status;
7819}
7820
7821INT wifi_ifConfigUp(INT apIndex)
7822{
7823 char cmd[128];
7824 char buf[1024];
7825
7826 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7827 _syscmd(cmd, buf, sizeof(buf));
7828 return 0;
7829}
7830
7831//>> Deprecated. Replace with wifi_applyRadioSettings
7832INT wifi_pushBridgeInfo(INT apIndex)
7833{
7834 char ip[32];
7835 char subnet[32];
7836 char bridge[32];
7837 int vlanId;
7838 char cmd[128];
7839 char buf[1024];
7840
7841 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7842 wifi_getApVlanID(apIndex,&vlanId);
7843
7844 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7845 _syscmd(cmd,buf, sizeof(buf));
7846
7847 return 0;
7848}
7849
7850INT wifi_pushChannel(INT radioIndex, UINT channel)
7851{
7852 char cmd[128];
7853 char buf[1024];
7854 int apIndex;
7855
7856 apIndex=(radioIndex==0)?0:1;
7857 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7858 _syscmd(cmd,buf, sizeof(buf));
7859
7860 return 0;
7861}
7862
7863INT wifi_pushChannelMode(INT radioIndex)
7864{
7865 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7866 return RETURN_ERR;
7867}
7868
7869INT wifi_pushDefaultValues(INT radioIndex)
7870{
7871 //Apply Comcast specified default radio settings instantly
7872 //AMPDU=1
7873 //AMPDUFrames=32
7874 //AMPDULim=50000
7875 //txqueuelen=1000
7876
7877 return RETURN_ERR;
7878}
7879
7880INT wifi_pushTxChainMask(INT radioIndex)
7881{
7882 //Apply default TxChainMask instantly
7883 return RETURN_ERR;
7884}
7885
7886INT wifi_pushRxChainMask(INT radioIndex)
7887{
7888 //Apply default RxChainMask instantly
7889 return RETURN_ERR;
7890}
7891
7892INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7893{
7894 INT status;
7895
7896 status = wifi_setSSIDName(apIndex,ssid);
7897 wifi_setApEnable(apIndex,FALSE);
7898 wifi_setApEnable(apIndex,TRUE);
7899
7900 return status;
7901}
7902
7903INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7904{
7905 //Apply default Ssid Advertisement instantly
7906 return RETURN_ERR;
7907}
7908
7909INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7910{
7911 INT status = RETURN_ERR;
7912 *output = 0;
7913 return RETURN_ERR;
7914}
7915
7916INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7917{
7918 return RETURN_OK;
7919}
7920
7921INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7922{
7923 return RETURN_OK;
7924}
7925
7926//To-do
7927INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7928{
developereb199ae2022-09-13 14:04:27 +08007929 char output[16]={'\0'};
7930 char config_file[MAX_BUF_SIZE] = {0};
7931
7932 if (!output_string)
7933 return RETURN_ERR;
7934
7935 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7936 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7937
7938 if (strlen(output) == 0)
7939 snprintf(output_string, 64, "Disabled");
7940 else if (strncmp(output, "0", 1) == 0)
7941 snprintf(output_string, 64, "Disabled");
7942 else if (strncmp(output, "1", 1) == 0)
7943 snprintf(output_string, 64, "Optional");
7944 else if (strncmp(output, "2", 1) == 0)
7945 snprintf(output_string, 64, "Required");
7946 else {
7947 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7948 return RETURN_ERR;
7949 }
7950
7951 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007952 return RETURN_OK;
7953}
7954INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7955{
developereb199ae2022-09-13 14:04:27 +08007956 char str[MAX_BUF_SIZE]={'\0'};
7957 char cmd[MAX_CMD_SIZE]={'\0'};
7958 struct params params;
7959 char config_file[MAX_BUF_SIZE] = {0};
7960
7961 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7962 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7963 return RETURN_ERR;
7964
7965 params.name = "ieee80211w";
7966 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7967 params.value = "0";
7968 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7969 params.value = "1";
7970 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7971 params.value = "2";
7972 else{
7973 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7974 return RETURN_ERR;
7975 }
7976 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7977 wifi_hostapdWrite(config_file, &params, 1);
7978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007979 return RETURN_OK;
7980}
7981INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7982{
7983 char output[16]={'\0'};
7984 char config_file[MAX_BUF_SIZE] = {0};
7985
7986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7987 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7988 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7989
7990 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7991 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7992
7993 return RETURN_OK;
7994}
7995
7996INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7997{
7998 return RETURN_OK;
7999}
8000
8001INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8002{
8003 return RETURN_OK;
8004}
8005
8006INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8007{
8008 return RETURN_OK;
8009}
8010
8011INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8012{
8013 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8014 char config_file[MAX_BUF_SIZE] = {0};
8015
8016 if (NULL == output)
8017 return RETURN_ERR;
8018 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8019 wifi_hostapdRead(config_file,"hw_mode",output,64);
8020
8021 if(strcmp(output,"b")==0)
8022 sprintf(output, "%s", "1,2,5.5,11");
8023 else if (strcmp(output,"a")==0)
8024 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8025 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8026 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8027
8028 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8029 return RETURN_OK;
8030}
8031
8032INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8033{
8034 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8035 char *temp;
8036 char temp_output[128];
8037 char temp_TransmitRates[128];
8038 char config_file[MAX_BUF_SIZE] = {0};
8039
8040 if (NULL == output)
8041 return RETURN_ERR;
8042
8043 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8044 wifi_hostapdRead(config_file,"supported_rates",output,64);
8045
8046 strcpy(temp_TransmitRates,output);
8047 strcpy(temp_output,"");
8048 temp = strtok(temp_TransmitRates," ");
8049 while(temp!=NULL)
8050 {
8051 temp[strlen(temp)-1]=0;
8052 if((temp[0]=='5') && (temp[1]=='\0'))
8053 {
8054 temp="5.5";
8055 }
8056 strcat(temp_output,temp);
8057 temp = strtok(NULL," ");
8058 if(temp!=NULL)
8059 {
8060 strcat(temp_output,",");
8061 }
8062 }
8063 strcpy(output,temp_output);
8064 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8065
8066 return RETURN_OK;
8067}
8068
8069INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8070{
8071 return RETURN_OK;
8072}
8073
8074
8075INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8076{
8077 int i=0;
8078 char *temp;
8079 char temp1[128];
8080 char temp_output[128];
8081 char temp_TransmitRates[128];
8082 struct params params={'\0'};
8083 char config_file[MAX_BUF_SIZE] = {0};
8084
8085 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8086 if(NULL == output)
8087 return RETURN_ERR;
8088
8089 strcpy(temp_TransmitRates,output);
8090
8091 for(i=0;i<strlen(temp_TransmitRates);i++)
8092 {
8093 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
8094 {
8095 continue;
8096 }
8097 else
8098 {
8099 return RETURN_ERR;
8100 }
8101 }
8102 strcpy(temp_output,"");
8103 temp = strtok(temp_TransmitRates," ");
8104 while(temp!=NULL)
8105 {
8106 strcpy(temp1,temp);
8107 if(wlanIndex==1)
8108 {
8109 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8110 {
8111 return RETURN_ERR;
8112 }
8113 }
8114
8115 if(strcmp(temp,"5.5")==0)
8116 {
8117 strcpy(temp1,"55");
8118 }
8119 else
8120 {
8121 strcat(temp1,"0");
8122 }
8123 strcat(temp_output,temp1);
8124 temp = strtok(NULL," ");
8125 if(temp!=NULL)
8126 {
8127 strcat(temp_output," ");
8128 }
8129 }
8130 strcpy(output,temp_output);
8131
8132
8133 params.name = "supported_rates";
8134 params.value = output;
8135
8136 wifi_dbg_printf("\n%s:",__func__);
8137 wifi_dbg_printf("params.value=%s\n",params.value);
8138 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8139 wifi_hostapdWrite(config_file,&params,1);
8140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8141
8142 return RETURN_OK;
8143}
8144
8145
8146static char *sncopy(char *dst, int dst_sz, const char *src)
8147{
8148 if (src && dst && dst_sz > 0) {
8149 strncpy(dst, src, dst_sz);
8150 dst[dst_sz - 1] = '\0';
8151 }
8152 return dst;
8153}
8154
8155static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8156{
8157 if (0 == strcmp(ht_mode, "HT40") ||
8158 0 == strcmp(ht_mode, "HT80") ||
8159 0 == strcmp(ht_mode, "HT160")) {
8160 switch (channel) {
8161 case 1 ... 7:
8162 case 36:
8163 case 44:
8164 case 52:
8165 case 60:
8166 case 100:
8167 case 108:
8168 case 116:
8169 case 124:
8170 case 132:
8171 case 140:
8172 case 149:
8173 case 157:
8174 return 1;
8175 case 8 ... 13:
8176 case 40:
8177 case 48:
8178 case 56:
8179 case 64:
8180 case 104:
8181 case 112:
8182 case 120:
8183 case 128:
8184 case 136:
8185 case 144:
8186 case 153:
8187 case 161:
8188 return -1;
8189 default:
8190 return -EINVAL;
8191 }
8192 }
8193
8194 return -EINVAL;
8195}
8196
developerb7593de2022-10-18 09:51:57 +08008197static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8198{
8199 int idx = channel%8;
8200 if (0 == strcmp(ht_mode, "HT40") ||
8201 0 == strcmp(ht_mode, "HT80") ||
8202 0 == strcmp(ht_mode, "HT160")) {
8203 switch (idx) {
8204 case 1:
8205 return 1;
8206 case 5:
8207 return -1;
8208 default:
8209 return -EINVAL;
8210 }
8211 }
8212
8213 return -EINVAL;
8214}
developer06a01d92022-09-07 16:32:39 +08008215static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8216{
8217 if (NULL == hw_mode) return;
8218
8219 if (0 == strcmp(hw_mode, "ac"))
8220 sncopy(bw_mode, bw_mode_len, "ht vht");
8221
8222 if (0 == strcmp(hw_mode, "n"))
8223 sncopy(bw_mode, bw_mode_len, "ht");
8224
8225 return;
8226}
8227
8228static int util_chan_to_freq(int chan)
8229{
8230 if (chan == 14)
8231 return 2484;
8232 else if (chan < 14)
8233 return 2407 + chan * 5;
8234 else if (chan >= 182 && chan <= 196)
8235 return 4000 + chan * 5;
8236 else
8237 return 5000 + chan * 5;
8238 return 0;
8239}
8240
developerb7593de2022-10-18 09:51:57 +08008241static int util_6G_chan_to_freq(int chan)
8242{
8243 if (chan)
8244 return 5950 + chan * 5;
8245 else
8246 return 0;
8247
8248}
developer06a01d92022-09-07 16:32:39 +08008249const int *util_unii_5g_chan2list(int chan, int width)
8250{
8251 static const int lists[] = {
8252 // <width>, <chan1>, <chan2>..., 0,
8253 20, 36, 0,
8254 20, 40, 0,
8255 20, 44, 0,
8256 20, 48, 0,
8257 20, 52, 0,
8258 20, 56, 0,
8259 20, 60, 0,
8260 20, 64, 0,
8261 20, 100, 0,
8262 20, 104, 0,
8263 20, 108, 0,
8264 20, 112, 0,
8265 20, 116, 0,
8266 20, 120, 0,
8267 20, 124, 0,
8268 20, 128, 0,
8269 20, 132, 0,
8270 20, 136, 0,
8271 20, 140, 0,
8272 20, 144, 0,
8273 20, 149, 0,
8274 20, 153, 0,
8275 20, 157, 0,
8276 20, 161, 0,
8277 20, 165, 0,
8278 40, 36, 40, 0,
8279 40, 44, 48, 0,
8280 40, 52, 56, 0,
8281 40, 60, 64, 0,
8282 40, 100, 104, 0,
8283 40, 108, 112, 0,
8284 40, 116, 120, 0,
8285 40, 124, 128, 0,
8286 40, 132, 136, 0,
8287 40, 140, 144, 0,
8288 40, 149, 153, 0,
8289 40, 157, 161, 0,
8290 80, 36, 40, 44, 48, 0,
8291 80, 52, 56, 60, 64, 0,
8292 80, 100, 104, 108, 112, 0,
8293 80, 116, 120, 124, 128, 0,
8294 80, 132, 136, 140, 144, 0,
8295 80, 149, 153, 157, 161, 0,
8296 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8297 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8298 -1 // final delimiter
8299 };
8300 const int *start;
8301 const int *p;
8302
8303 for (p = lists; *p != -1; p++) {
8304 if (*p == width) {
8305 for (start = ++p; *p != 0; p++) {
8306 if (*p == chan)
8307 return start;
8308 }
8309 }
8310 // move to the end of channel list of given width
8311 while (*p != 0) {
8312 p++;
8313 }
8314 }
8315
8316 return NULL;
8317}
8318
8319static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8320{
8321 if (NULL == ht_mode)
8322 return 0;
8323
8324 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8325 const int *chans = util_unii_5g_chan2list(channel, width);
8326 int sum = 0;
8327 int cnt = 0;
8328
8329 if (NULL == chans)
8330 return 0;
8331
8332 while (*chans) {
8333 sum += *chans;
8334 cnt++;
8335 chans++;
8336 }
8337 return sum / cnt;
8338}
8339
developerb7593de2022-10-18 09:51:57 +08008340static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8341{
8342 if (NULL == ht_mode)
8343 return 0;
8344
8345 int width = strtol((ht_mode + 2), NULL, 10);
8346
8347 int idx = 0 ;
8348 int centerchan = 0;
8349 int chan_ofs = 1;
8350
8351 if (width == 40){
8352 idx = ((channel/4) + chan_ofs)%2;
8353 switch (idx) {
8354 case 0:
8355 centerchan = (channel - 2);
8356 break;
8357 case 1:
8358 centerchan = (channel + 2);
8359 break;
8360 default:
8361 return -EINVAL;
8362 }
8363 }else if (width == 80){
8364 idx = ((channel/4) + chan_ofs)%4;
8365 switch (idx) {
8366 case 0:
8367 centerchan = (channel - 6);
8368 break;
8369 case 1:
8370 centerchan = (channel + 6);
8371 break;
8372 case 2:
8373 centerchan = (channel + 2);
8374 break;
8375 case 3:
8376 centerchan = (channel - 2);
8377 break;
8378 default:
8379 return -EINVAL;
8380 }
8381 }else if (width == 160){
8382 switch (channel) {
8383 case 1 ... 29:
8384 centerchan = 15;
8385 break;
8386 case 33 ... 61:
8387 centerchan = 47;
8388 break;
8389 case 65 ... 93:
8390 centerchan = 79;
8391 break;
8392 case 97 ... 125:
8393 centerchan = 111;
8394 break;
8395 case 129 ... 157:
8396 centerchan = 143;
8397 break;
8398 case 161 ... 189:
8399 centerchan = 175;
8400 break;
8401 case 193 ... 221:
8402 centerchan = 207;
8403 break;
8404 default:
8405 return -EINVAL;
8406 }
8407 }
8408 return centerchan;
8409}
developer06a01d92022-09-07 16:32:39 +08008410static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8411{
8412 BOOL onlyG, onlyN, onlyA;
8413 CHAR tmp[64];
8414 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8415 if (ret == RETURN_OK) {
8416 sncopy(hw_mode, hw_mode_size, tmp);
8417 }
8418 return ret;
8419}
8420
8421INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8422{
8423 // Sample commands:
8424 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8425 // hostapd_cli -i wifi0 chan_switch 30 2437
8426 char cmd[MAX_CMD_SIZE] = {0};
8427 char buf[MAX_BUF_SIZE] = {0};
8428 int freq = 0, ret = 0;
8429 char center_freq1_str[32] = ""; // center_freq1=%d
8430 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8431 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8432 char hw_mode[16] = ""; // n|ac
8433 char bw_mode[16] = ""; // ht|ht vht
8434 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8435 int sec_chan_offset;
8436 int width;
developer4fb0b922022-09-30 14:29:09 +08008437 char config_file[64] = {0};
8438 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008439 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008440 wifi_band band = band_invalid;
8441 int center_chan = 0;
8442 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008443
developer4fb0b922022-09-30 14:29:09 +08008444 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008445
8446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8447
developerb7593de2022-10-18 09:51:57 +08008448 band = wifi_index_to_band(radioIndex);
8449
developer5884e982022-10-06 10:52:50 +08008450 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008451
8452 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008453 if (channel){
developerb7593de2022-10-18 09:51:57 +08008454 if (band == band_6){
8455 freq = util_6G_chan_to_freq(channel);
8456 }else{
8457 freq = util_chan_to_freq(channel);
8458 }
developer5884e982022-10-06 10:52:50 +08008459 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008460
developer5884e982022-10-06 10:52:50 +08008461 // Provide bandwith if specified
8462 if (channel_width_MHz > 20) {
8463 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8464 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8465 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008466
developer5884e982022-10-06 10:52:50 +08008467 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8468 }else if (channel_width_MHz == 20){
8469 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8470 }
developer06a01d92022-09-07 16:32:39 +08008471
developerb7593de2022-10-18 09:51:57 +08008472
developer5884e982022-10-06 10:52:50 +08008473 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008474 if (band == band_6){
8475 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8476 if(center_chan){
8477 center_freq1 = util_6G_chan_to_freq(center_chan);
8478 }
8479 }else{
8480 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8481 if(center_chan){
8482 center_freq1 = util_chan_to_freq(center_chan);
8483 }
developer5884e982022-10-06 10:52:50 +08008484 }
developerb7593de2022-10-18 09:51:57 +08008485
8486 if (center_freq1)
8487 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8488
8489 }
8490
8491 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8492 if (band == band_6){
8493 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8494 }else{
8495 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008496 }
developerb7593de2022-10-18 09:51:57 +08008497 if (sec_chan_offset != -EINVAL)
8498 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008499
developer5884e982022-10-06 10:52:50 +08008500 // Only the first AP, other are hanging on the same radio
8501 int apIndex = radioIndex;
8502 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8503 AP_PREFIX, apIndex, csa_beacon_count, freq,
8504 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8505 wifi_dbg_printf("execute: '%s'\n", cmd);
8506 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008507
developer5884e982022-10-06 10:52:50 +08008508 ret = wifi_setRadioChannel(radioIndex, channel);
8509 if (ret != RETURN_OK) {
8510 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8511 return RETURN_ERR;
8512 }
8513
8514 if (sec_chan_offset == 1) ext_str = "Above";
8515 else if (sec_chan_offset == -1) ext_str = "Below";
8516
8517 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008518
developer5884e982022-10-06 10:52:50 +08008519 } else {
8520 if (channel_width_MHz > 20)
8521 ext_str = "Above";
8522 }
developer4fb0b922022-09-30 14:29:09 +08008523 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8524 _syscmd(cmd, buf, sizeof(buf));
8525 if (strlen(buf) != 0)
8526 stbcEnable = TRUE;
8527
developer06a01d92022-09-07 16:32:39 +08008528 wifi_setRadioExtChannel(radioIndex, ext_str);
8529
developer4fb0b922022-09-30 14:29:09 +08008530 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8531
developer06a01d92022-09-07 16:32:39 +08008532 char mhz_str[16];
8533 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8534 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8535
8536 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8537
8538 return RETURN_OK;
8539}
8540
8541INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8542{
developer615510b2022-09-27 10:14:35 +08008543 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008544 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008545 char cmd[256]={0};
8546 char buf[128]={0};
8547 char file_name[32] = {0};
8548 char filter_SSID[32] = {0};
8549 char line[256] = {0};
8550 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008551 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008552 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008553 size_t len=0;
8554 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008555 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008556 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008557 bool filter_enable = false;
8558 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008559 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008560
developer615510b2022-09-27 10:14:35 +08008561 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008562
developer615510b2022-09-27 10:14:35 +08008563 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8564 f = fopen(file_name, "r");
8565 if (f != NULL) {
8566 fgets(filter_SSID, sizeof(file_name), f);
8567 if (strlen(filter_SSID) != 0)
8568 filter_enable = true;
8569 fclose(f);
8570 }
8571
developer033b37b2022-10-18 11:27:46 +08008572 phyId = radio_index_to_phy(radio_index);
8573
8574 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008575 _syscmd(cmd, buf, sizeof(buf));
8576 channels_num = strtol(buf, NULL, 10);
8577
developer615510b2022-09-27 10:14:35 +08008578 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8579 // 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);
8580 fprintf(stderr, "cmd: %s\n", cmd);
8581 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008582 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8583 return RETURN_ERR;
8584 }
developer5550e242022-09-30 09:59:32 +08008585
8586 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8587 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8588
developer615510b2022-09-27 10:14:35 +08008589 ret = fgets(line, sizeof(line), f);
8590 while (ret != NULL) {
8591 if(strstr(line, "BSS") != NULL) { // new neighbor info
8592 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8593 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8594 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8595
8596 if (!filter_BSS) {
8597 index++;
8598 wifi_neighbor_ap2_t *tmp;
8599 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8600 if (tmp == NULL) { // no more memory to use
8601 index--;
8602 wifi_dbg_printf("%s: realloc failed\n", __func__);
8603 break;
8604 }
8605 scan_array = tmp;
8606 }
8607 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008608
developer615510b2022-09-27 10:14:35 +08008609 filter_BSS = false;
8610 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8611 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8612 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8613 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8614 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008615 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008616 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008617
developer615510b2022-09-27 10:14:35 +08008618 if (freq >= 2412 && freq <= 2484) {
8619 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8620 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8621 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8622 }
8623 else if (freq >= 5160 && freq <= 5805) {
8624 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8625 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8626 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8627 }
developer06a01d92022-09-07 16:32:39 +08008628
developer615510b2022-09-27 10:14:35 +08008629 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008630 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008631 for (int i = 0; i < channels_num; i++) {
8632 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8633 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8634 break;
8635 }
8636 }
developer06a01d92022-09-07 16:32:39 +08008637 }
developer615510b2022-09-27 10:14:35 +08008638 } else if (strstr(line, "beacon interval") != NULL) {
8639 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8640 } else if (strstr(line, "signal") != NULL) {
8641 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8642 } else if (strstr(line,"SSID") != NULL) {
8643 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8644 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8645 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008646 }
developer615510b2022-09-27 10:14:35 +08008647 } else if (strstr(line, "Supported rates") != NULL) {
8648 char SRate[80] = {0}, *tmp = NULL;
8649 memset(buf, 0, sizeof(buf));
8650 strcpy(SRate, line);
8651 tmp = strtok(SRate, ":");
8652 tmp = strtok(NULL, ":");
8653 strcpy(buf, tmp);
8654 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008655
developer615510b2022-09-27 10:14:35 +08008656 tmp = strtok(buf, " \n");
8657 while (tmp != NULL) {
8658 strcat(SRate, tmp);
8659 if (SRate[strlen(SRate) - 1] == '*') {
8660 SRate[strlen(SRate) - 1] = '\0';
8661 }
8662 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008663
developer615510b2022-09-27 10:14:35 +08008664 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008665 }
developer615510b2022-09-27 10:14:35 +08008666 SRate[strlen(SRate) - 1] = '\0';
8667 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8668 } else if (strstr(line, "DTIM") != NULL) {
8669 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8670 } else if (strstr(line, "VHT capabilities") != NULL) {
8671 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8672 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8673 } else if (strstr(line, "HT capabilities") != NULL) {
8674 strcat(scan_array[index].ap_SupportedStandards, ",n");
8675 strcpy(scan_array[index].ap_OperatingStandards, "n");
8676 } else if (strstr(line, "VHT operation") != NULL) {
8677 ret = fgets(line, sizeof(line), f);
8678 sscanf(line," * channel width: %d", &vht_channel_width);
8679 if(vht_channel_width == 1) {
8680 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8681 } else {
8682 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8683 }
8684 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8685 continue;
8686 } else if (strstr(line, "HT operation") != NULL) {
8687 ret = fgets(line, sizeof(line), f);
8688 sscanf(line," * secondary channel offset: %s", &buf);
8689 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008690 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008691 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 +08008692 }
developer615510b2022-09-27 10:14:35 +08008693 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008694 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008695 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8696 } else {
8697 //20Mhz
8698 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 +08008699 }
developer615510b2022-09-27 10:14:35 +08008700 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008701 continue;
developer615510b2022-09-27 10:14:35 +08008702 } else if (strstr(line, "HE capabilities") != NULL) {
8703 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8704 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8705 ret = fgets(line, sizeof(line), f);
8706 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8707 if (strstr(line, "HE40/2.4GHz") != NULL)
8708 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8709 else
8710 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8711 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8712 if (strstr(line, "HE80/5GHz") != NULL) {
8713 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8714 ret = fgets(line, sizeof(line), f);
8715 } else
8716 continue;
8717 if (strstr(line, "HE160/5GHz") != NULL)
8718 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008719 }
developer615510b2022-09-27 10:14:35 +08008720 continue;
8721 } else if (strstr(line, "WPA") != NULL) {
8722 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8723 } else if (strstr(line, "RSN") != NULL) {
8724 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8725 } else if (strstr(line, "Group cipher") != NULL) {
8726 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8727 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8728 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008729 }
developer06a01d92022-09-07 16:32:39 +08008730 }
developer615510b2022-09-27 10:14:35 +08008731 ret = fgets(line, sizeof(line), f);
8732 }
8733
8734 if (!filter_BSS) {
8735 *output_array_size = index + 1;
8736 } else {
8737 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8738 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008739 }
developer06a01d92022-09-07 16:32:39 +08008740 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008741 pclose(f);
developer5550e242022-09-30 09:59:32 +08008742 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008744 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008745}
developer615510b2022-09-27 10:14:35 +08008746
developer06a01d92022-09-07 16:32:39 +08008747INT wifi_getApAssociatedDeviceStats(
8748 INT apIndex,
8749 mac_address_t *clientMacAddress,
8750 wifi_associated_dev_stats_t *associated_dev_stats,
8751 u64 *handle)
8752{
8753 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8754 char interface_name[50] = {0};
8755 char cmd[1024] = {0};
8756 char mac_str[18] = {0};
8757 char *key = NULL;
8758 char *val = NULL;
8759 FILE *f = NULL;
8760 char *line = NULL;
8761 size_t len = 0;
8762 ssize_t read = 0;
8763
8764 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8765 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8766 return RETURN_ERR;
8767 }
8768
8769 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8770 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8771 if((f = popen(cmd, "r")) == NULL) {
8772 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8773 return RETURN_ERR;
8774 }
8775
8776 while ((read = getline(&line, &len, f)) != -1) {
8777 key = strtok(line,":");
8778 val = strtok(NULL,":");
8779
8780 if(!strncmp(key,"rx bytes",8))
8781 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8782 if(!strncmp(key,"tx bytes",8))
8783 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8784 if(!strncmp(key,"rx packets",10))
8785 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8786 if(!strncmp(key,"tx packets",10))
8787 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8788 if(!strncmp(key,"tx retries",10))
8789 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8790 if(!strncmp(key,"tx failed",9))
8791 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8792 if(!strncmp(key,"rx drop misc",13))
8793 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8794 if(!strncmp(key,"rx bitrate",10)) {
8795 val = strtok(val, " ");
8796 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8797 }
8798 if(!strncmp(key,"tx bitrate",10)) {
8799 val = strtok(val, " ");
8800 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8801 }
8802 }
8803 free(line);
8804 pclose(f);
8805 return RETURN_OK;
8806}
8807
8808INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8809{
8810 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8811
8812 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8813 if (NULL == output_string)
8814 return RETURN_ERR;
8815
8816 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8817 _syscmd(cmd, buf, sizeof(buf));
8818
8819 //size of SSID name restricted to value less than 32 bytes
8820 snprintf(output_string, 32, "%s", buf);
8821 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8822
8823 return RETURN_OK;
8824}
8825
8826INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8827{
8828 //char cmd[MAX_CMD_SIZE] = {0};
8829 char config_file[MAX_BUF_SIZE] = {0};
8830 char buf[32] = {0};
8831
8832 if (!output_filterMode)
8833 return RETURN_ERR;
8834
8835 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8836 //_syscmd(cmd, buf, sizeof(buf));
8837 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8838 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008839 if(strlen(buf) == 0) {
8840 *output_filterMode = 0;
8841 }
8842 else {
8843 int macaddr_acl_mode = strtol(buf, NULL, 10);
8844 if (macaddr_acl_mode == 1) {
8845 *output_filterMode = 1;
8846 } else if (macaddr_acl_mode == 0) {
8847 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8848 if (strlen(buf) == 0) {
8849 *output_filterMode = 0;
8850 } else {
8851 *output_filterMode = 2;
8852 }
8853 } else {
8854 return RETURN_ERR;
8855 }
8856 }
developer06a01d92022-09-07 16:32:39 +08008857
8858 return RETURN_OK;
8859}
8860
8861INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8862{
8863 FILE *fp = NULL;
8864 char str[MAX_BUF_SIZE] = {0};
8865 int wificlientindex = 0 ;
8866 int count = 0;
8867 int signalstrength = 0;
8868 int arr[MACADDRESS_SIZE] = {0};
8869 unsigned char mac[MACADDRESS_SIZE] = {0};
8870 UINT wifi_count = 0;
8871 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8872 char pipeCmd[MAX_CMD_SIZE] = {0};
8873
8874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8875 *output_array_size = 0;
8876 *associated_dev_array = NULL;
8877 char interface_name[50] = {0};
8878
8879 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8880 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8881 return RETURN_ERR;
8882 }
8883
8884 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8885 fp = popen(pipeCmd, "r");
8886 if (fp == NULL)
8887 {
8888 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8889 return RETURN_ERR;
8890 }
8891
8892 /* Read the output a line at a time - output it. */
8893 fgets(str, sizeof(str)-1, fp);
8894 wifi_count = (unsigned int) atoi ( str );
8895 *output_array_size = wifi_count;
8896 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8897 pclose(fp);
8898
8899 if(wifi_count == 0)
8900 {
8901 return RETURN_OK;
8902 }
8903 else
8904 {
8905 wifi_associated_dev2_t* temp = NULL;
8906 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8907 *associated_dev_array = temp;
8908 if(temp == NULL)
8909 {
8910 printf("Error Statement. Insufficient memory \n");
8911 return RETURN_ERR;
8912 }
8913
8914 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8915 system(pipeCmd);
8916
8917 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8918 if(fp == NULL)
8919 {
8920 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8921 return RETURN_ERR;
8922 }
8923 fclose(fp);
8924
8925 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8926 fp = popen(pipeCmd, "r");
8927 if(fp)
8928 {
8929 for(count =0 ; count < wifi_count; count++)
8930 {
8931 fgets(str, MAX_BUF_SIZE, fp);
8932 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8933 {
8934 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8935 {
8936 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8937
8938 }
8939 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8940 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]);
8941 }
8942 temp[count].cli_AuthenticationState = 1; //TODO
8943 temp[count].cli_Active = 1; //TODO
8944 }
8945 pclose(fp);
8946 }
8947
8948 //Updating RSSI per client
8949 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8950 fp = popen(pipeCmd, "r");
8951 if(fp)
8952 {
8953 pclose(fp);
8954 }
8955 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8956 if(fp)
8957 {
8958 for(count =0 ; count < wifi_count ;count++)
8959 {
8960 fgets(str, MAX_BUF_SIZE, fp);
8961 signalstrength = atoi(str);
8962 temp[count].cli_RSSI = signalstrength;
8963 }
8964 pclose(fp);
8965 }
8966
8967
8968 //LastDataDownlinkRate
8969 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8970 fp = popen(pipeCmd, "r");
8971 if (fp)
8972 {
8973 pclose(fp);
8974 }
8975 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8976 if (fp)
8977 {
8978 for (count = 0; count < wifi_count; count++)
8979 {
8980 fgets(str, MAX_BUF_SIZE, fp);
8981 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8982 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8983 }
8984 pclose(fp);
8985 }
8986
8987 //LastDataUplinkRate
8988 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8989 fp = popen(pipeCmd, "r");
8990 if (fp)
8991 {
8992 pclose(fp);
8993 }
8994 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8995 if (fp)
8996 {
8997 for (count = 0; count < wifi_count; count++)
8998 {
8999 fgets(str, MAX_BUF_SIZE, fp);
9000 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9001 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9002 }
9003 pclose(fp);
9004 }
9005 }
9006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9007 return RETURN_OK;
9008
9009}
9010
9011INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9012{
9013#if 0
9014 /*char buf[1024] = {0};
9015 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
9016 _syscmd(cmd, buf, sizeof(buf));*/
9017
9018 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9019 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9020 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9021 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9022
9023 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.
9024 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].
9025 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].
9026 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].
9027 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9028 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9029
9030 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9031 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9032 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9033 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.
9034 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.
9035 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.
9036 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.
9037 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.
9038 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.
9039 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.
9040 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9041#endif
9042
9043 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08009044 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08009045 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009046 char pipeCmd[128] = {0};
9047 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009048 wifi_ssidTrafficStats2_t *out = output_struct;
9049
developerce736392022-09-13 15:24:34 +08009050 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009051 if (!output_struct)
9052 return RETURN_ERR;
9053
developerce736392022-09-13 15:24:34 +08009054 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9055 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
9056 GetInterfaceName(interface_name, HConf_file);
9057 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009058
developer06a01d92022-09-07 16:32:39 +08009059 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009060 if (fp == NULL) {
9061 fprintf(stderr, "%s: popen failed\n", __func__);
9062 return RETURN_ERR;
9063 }
9064 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08009065
developerce736392022-09-13 15:24:34 +08009066 if (strlen(str) == 0) // interface not exist
9067 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009068
developerce736392022-09-13 15:24:34 +08009069 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9070 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009071 pclose(fp);
9072
developerce736392022-09-13 15:24:34 +08009073 memset(str, 0, sizeof(str));
9074 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009075 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009076 if (fp == NULL) {
9077 fprintf(stderr, "%s: popen failed\n", __func__);
9078 return RETURN_ERR;
9079 }
9080 fgets(str, sizeof(str), fp);
9081
9082 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9083 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009084 pclose(fp);
developerce736392022-09-13 15:24:34 +08009085
9086 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9087 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9088
9089 // Not supported
9090 output_struct->ssid_RetransCount = 0;
9091 output_struct->ssid_FailedRetransCount = 0;
9092 output_struct->ssid_RetryCount = 0;
9093 output_struct->ssid_MultipleRetryCount = 0;
9094 output_struct->ssid_ACKFailureCount = 0;
9095 output_struct->ssid_AggregatedPacketCount = 0;
9096
developer06a01d92022-09-07 16:32:39 +08009097 return RETURN_OK;
9098}
9099
9100//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).
9101INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9102{
9103 char output_val[16]={'\0'};
9104 char config_file[MAX_BUF_SIZE] = {0};
9105
9106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9107 if (!output)
9108 return RETURN_ERR;
9109 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9110 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9111
9112 if( strcmp(output_val,"1") == 0 )
9113 *output = TRUE;
9114 else
9115 *output = FALSE;
9116 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9117
9118 return RETURN_OK;
9119}
9120
9121INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9122{
9123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9124 char str[MAX_BUF_SIZE]={'\0'};
9125 char string[MAX_BUF_SIZE]={'\0'};
9126 char cmd[MAX_CMD_SIZE]={'\0'};
9127 char *ch;
9128 char config_file[MAX_BUF_SIZE] = {0};
9129 struct params params;
9130
9131 if(enable == TRUE)
9132 strcpy(string,"1");
9133 else
9134 strcpy(string,"0");
9135
9136 params.name = "ap_isolate";
9137 params.value = string;
9138
9139 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9140 wifi_hostapdWrite(config_file,&params,1);
9141 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9142
9143 return RETURN_OK;
9144}
9145
9146INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9147{
9148 if (NULL == output_dBm)
9149 return RETURN_ERR;
9150
9151 *output_dBm = 0;
9152 return RETURN_OK;
9153}
9154
9155INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9156{
9157 return RETURN_OK;
9158}
9159INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9160{
9161 return RETURN_OK;
9162}
9163INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9164{
9165 return RETURN_OK;
9166}
9167INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9168{
9169 return RETURN_OK;
9170}
9171INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9172{
9173 return RETURN_OK;
9174}
9175INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9176{
9177 char config_file[MAX_BUF_SIZE] = {0};
9178 struct params list;
9179
9180 list.name = "bss_transition";
9181 list.value = activate?"1":"0";
9182 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9183 wifi_hostapdWrite(config_file, &list, 1);
9184
9185 return RETURN_OK;
9186}
9187wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9188
9189void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9190{
9191 return;
9192}
9193
9194INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9195{
9196 // TODO Implement me!
9197 return RETURN_OK;
9198}
9199
9200INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9201{
developera3c68b92022-09-13 15:27:29 +08009202 char file_name[128] = {0};
9203 char buf[128] = {0};
9204 FILE *f = NULL;
9205
9206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9207
9208 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer033b37b2022-10-18 11:27:46 +08009209 for (int index = 0; index < MAX_RADIOS; index++) {
developera3c68b92022-09-13 15:27:29 +08009210 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9211 f = fopen(file_name, "w");
9212 if (f == NULL)
9213 return RETURN_ERR;
9214 // For mode == 0 is to disable filter, just don't write to the file.
9215 if (mode)
9216 fprintf(f, "%s", essid);
9217
9218 fclose(f);
9219 }
9220 } else { // special case, need to set AP's SSID as filter for each radio.
9221 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9222 f = fopen(file_name, "w");
9223 if (f == NULL)
9224 return RETURN_ERR;
9225
9226 // For mode == 0 is to disable filter, just don't write to the file.
9227 if (mode)
9228 fprintf(f, "%s", essid);
9229
9230 fclose(f);
9231 }
9232
9233 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009234 return RETURN_OK;
9235}
9236
9237INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9238{
9239 // TODO Implement me!
9240 //Apply wifi_pushRadioChannel() instantly
9241 return RETURN_ERR;
9242}
9243
9244INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9245{
9246 // TODO Implement me!
9247 return RETURN_OK;
9248}
9249
9250#ifdef HAL_NETLINK_IMPL
9251static int tidStats_callback(struct nl_msg *msg, void *arg) {
9252 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9253 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9254 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9255 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9256 int rem , tid_index = 0;
9257
9258 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9259 wifi_associated_dev_tid_entry_t *stats_entry;
9260
9261 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9262 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9263 };
9264 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9265 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9266 };
9267
9268 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9269 genlmsg_attrlen(gnlh, 0), NULL);
9270
9271
9272 if (!tb[NL80211_ATTR_STA_INFO]) {
9273 fprintf(stderr, "station stats missing!\n");
9274 return NL_SKIP;
9275 }
9276
9277 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9278 tb[NL80211_ATTR_STA_INFO],
9279 stats_policy)) {
9280 fprintf(stderr, "failed to parse nested attributes!\n");
9281 return NL_SKIP;
9282 }
9283
9284 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9285 {
9286 stats_entry = &out->tid_array[tid_index];
9287
9288 stats_entry->tid = tid_index;
9289 stats_entry->ac = _tid_ac_index_get[tid_index];
9290
9291 if(sinfo[NL80211_STA_INFO_TID_STATS])
9292 {
9293 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9294 printf("failed to parse nested stats attributes!");
9295 return NL_SKIP;
9296 }
9297 }
9298 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9299 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9300
9301 if(tid_index < (PS_MAX_TID - 1))
9302 tid_index++;
9303 }
9304 //ToDo: sum_time_ms, ewma_time_ms
9305 return NL_SKIP;
9306}
9307#endif
9308
9309INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9310{
9311#ifdef HAL_NETLINK_IMPL
9312 Netlink nl;
9313 char if_name[10];
9314
9315 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9316
9317 nl.id = initSock80211(&nl);
9318
9319 if (nl.id < 0) {
9320 fprintf(stderr, "Error initializing netlink \n");
9321 return -1;
9322 }
9323
9324 struct nl_msg* msg = nlmsg_alloc();
9325
9326 if (!msg) {
9327 fprintf(stderr, "Failed to allocate netlink message.\n");
9328 nlfree(&nl);
9329 return -2;
9330 }
9331
9332 genlmsg_put(msg,
9333 NL_AUTO_PORT,
9334 NL_AUTO_SEQ,
9335 nl.id,
9336 0,
9337 0,
9338 NL80211_CMD_GET_STATION,
9339 0);
9340
9341 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9342 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9343 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9344 nl_send_auto(nl.socket, msg);
9345 nl_recvmsgs(nl.socket, nl.cb);
9346 nlmsg_free(msg);
9347 nlfree(&nl);
9348 return RETURN_OK;
9349#else
9350//iw implementation
9351#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9352#define TOTAL_MAX_LINES 50
9353
9354 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9355 char if_name[10];
9356 FILE *fp=NULL;
9357 char pipeCmd[1024]= {'\0'};
9358 int lines,tid_index=0;
9359 char mac_addr[20] = {'\0'};
9360
9361 wifi_associated_dev_tid_entry_t *stats_entry;
9362
9363 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9364 strcpy(mac_addr,clientMacAddress);
9365
9366 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9367 fp= popen(pipeCmd,"r");
9368 if(fp == NULL)
9369 {
9370 perror("popen for station dump failed\n");
9371 return RETURN_ERR;
9372 }
9373 pclose(fp);
9374
9375 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9376 fp=popen(pipeCmd,"r");
9377 if(fp == NULL)
9378 {
9379 perror("popen for grep station failed\n");
9380 return RETURN_ERR;
9381 }
9382 else if(fgets(buf,sizeof(buf),fp) != NULL)
9383 lines=atoi(buf);
9384 else
9385 {
9386 pclose(fp);
9387 fprintf(stderr,"No devices are connected \n");
9388 return RETURN_ERR;
9389 }
9390 pclose(fp);
9391
9392 if(lines == 1)
9393 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9394
9395 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9396 {
9397 stats_entry = &tid_stats->tid_array[tid_index];
9398 stats_entry->tid = tid_index;
9399
9400 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);
9401
9402 fp=popen(pipeCmd,"r");
9403 if(fp ==NULL)
9404 {
9405 perror("Failed to read from tid file \n");
9406 return RETURN_ERR;
9407 }
9408 else if(fgets(buf,sizeof(buf),fp) != NULL)
9409 stats_entry->num_msdus = atol(buf);
9410
9411 pclose(fp);
9412 stats_entry->ac = _tid_ac_index_get[tid_index];
9413// TODO:
9414// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9415// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9416 }
9417 return RETURN_OK;
9418#endif
9419}
9420
9421
9422INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9423{
developer615510b2022-09-27 10:14:35 +08009424 char cmd[128]={0};
9425 char buf[128]={0};
9426 int freq = 0;
9427
9428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9429
9430 // full mode is used to scan all channels.
9431 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9432 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9433 ieee80211_channel_to_frequency(chan_list[0], &freq);
9434
9435 if (freq)
9436 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9437 else
9438 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9439
9440 _syscmd(cmd, buf, sizeof(buf));
9441 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9442
developer06a01d92022-09-07 16:32:39 +08009443 return RETURN_OK;
9444}
9445
9446
9447INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9448{
9449 // TODO Implement me!
9450 return RETURN_ERR;
9451}
9452
9453INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9454{
9455 // TODO Implement me!
9456 return RETURN_ERR;
9457}
9458
9459INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9460{
9461 // TODO Implement me!
9462 return RETURN_ERR;
9463}
9464
9465INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9466{
9467 // TODO Implement me!
9468 return RETURN_ERR;
9469}
9470
9471INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9472{
9473 // TODO Implement me!
9474 return RETURN_ERR;
9475}
9476
9477INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9478{
9479 // TODO Implement me!
9480 return RETURN_ERR;
9481}
9482
9483INT wifi_steering_eventUnregister(void)
9484{
9485 // TODO Implement me!
9486 return RETURN_ERR;
9487}
9488
9489INT wifi_delApAclDevices(INT apIndex)
9490{
9491#if 0
9492 char cmd[MAX_BUF_SIZE] = {0};
9493 char buf[MAX_BUF_SIZE] = {0};
9494
9495 /* Not reset proof solution */
9496 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9497 if(_syscmd(cmd,buf,sizeof(buf)))
9498 return RETURN_ERR;
9499#endif
developere6aafda2022-09-13 14:59:28 +08009500 char cmd[MAX_CMD_SIZE]={0};
9501 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009502
developere6aafda2022-09-13 14:59:28 +08009503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9504 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9505 if(_syscmd(cmd, buf, sizeof(buf)))
9506 return RETURN_ERR;
9507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009508
9509 return RETURN_OK;
9510}
9511
9512#ifdef HAL_NETLINK_IMPL
9513static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9514 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9515 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9516 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9517 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9518 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9519 char mac_addr[20],dev[20];
9520
9521 nla_parse(tb,
9522 NL80211_ATTR_MAX,
9523 genlmsg_attrdata(gnlh, 0),
9524 genlmsg_attrlen(gnlh, 0),
9525 NULL);
9526
9527 if(!tb[NL80211_ATTR_STA_INFO]) {
9528 fprintf(stderr, "sta stats missing!\n");
9529 return NL_SKIP;
9530 }
9531
9532 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9533 fprintf(stderr, "failed to parse nested attributes!\n");
9534 return NL_SKIP;
9535 }
9536 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9537
9538 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9539
9540 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9541 fprintf(stderr, "failed to parse nested rate attributes!");
9542 return NL_SKIP;
9543 }
9544
9545 if(sinfo[NL80211_STA_INFO_TID_STATS])
9546 {
9547 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9548 printf("failed to parse nested stats attributes!");
9549 return NL_SKIP;
9550 }
9551 }
9552
9553 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9554 {
9555 printf("Type is VHT\n");
9556 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9557 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9558
9559 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9560 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9561 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9562 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9563 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9564 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9565 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9566 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9567 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9568 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9569 }
9570 else
9571 {
9572 printf(" OFDM or CCK \n");
9573 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9574 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9575 }
9576
9577 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9578 if(rinfo[NL80211_RATE_INFO_MCS])
9579 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9580 }
9581 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9582 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9583 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9584 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9585
9586 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9587 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9588
9589 if (sinfo[NL80211_STA_INFO_SIGNAL])
9590 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9591 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9592 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9593 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9594 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9595 //rssi_array need to be filled
9596 return NL_SKIP;
9597}
9598#endif
9599
9600INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9601{
9602#ifdef HAL_NETLINK_IMPL
9603 Netlink nl;
9604 char if_name[10];
9605
9606 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9607
9608 if (*output_array_size <= 0)
9609 return RETURN_OK;
9610
9611 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9612 nl.id = initSock80211(&nl);
9613
9614 if (nl.id < 0) {
9615 fprintf(stderr, "Error initializing netlink \n");
9616 return 0;
9617 }
9618
9619 struct nl_msg* msg = nlmsg_alloc();
9620
9621 if (!msg) {
9622 fprintf(stderr, "Failed to allocate netlink message.\n");
9623 nlfree(&nl);
9624 return 0;
9625 }
9626
9627 genlmsg_put(msg,
9628 NL_AUTO_PORT,
9629 NL_AUTO_SEQ,
9630 nl.id,
9631 0,
9632 0,
9633 NL80211_CMD_GET_STATION,
9634 0);
9635
9636 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9637 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9638 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9639 nl_send_auto(nl.socket, msg);
9640 nl_recvmsgs(nl.socket, nl.cb);
9641 nlmsg_free(msg);
9642 nlfree(&nl);
9643 return RETURN_OK;
9644#else
9645 //TODO Implement me
9646 return RETURN_OK;
9647#endif
9648}
9649
9650#ifdef HAL_NETLINK_IMPL
9651static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9652 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9653 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9654 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9655 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9656 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9657 char mac_addr[20],dev[20];
9658
9659 nla_parse(tb,
9660 NL80211_ATTR_MAX,
9661 genlmsg_attrdata(gnlh, 0),
9662 genlmsg_attrlen(gnlh, 0),
9663 NULL);
9664
9665 if(!tb[NL80211_ATTR_STA_INFO]) {
9666 fprintf(stderr, "sta stats missing!\n");
9667 return NL_SKIP;
9668 }
9669
9670 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9671 fprintf(stderr, "failed to parse nested attributes!\n");
9672 return NL_SKIP;
9673 }
9674
9675 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9676
9677 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9678
9679 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9680 fprintf(stderr, "failed to parse nested rate attributes!");
9681 return NL_SKIP;
9682 }
9683
9684 if(sinfo[NL80211_STA_INFO_TID_STATS])
9685 {
9686 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9687 printf("failed to parse nested stats attributes!");
9688 return NL_SKIP;
9689 }
9690 }
9691 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9692 {
9693 printf("Type is VHT\n");
9694 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9695 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9696
9697 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9698 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9699 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9700 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9701 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9702 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9703 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9704 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9705 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9706 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9707 }
9708 else
9709 {
9710 printf(" OFDM or CCK \n");
9711 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9712 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9713 }
9714
9715 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9716 if(rinfo[NL80211_RATE_INFO_MCS])
9717 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9718 }
9719
9720 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9721 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9722 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9723 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9724
9725 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9726 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9727 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9728
9729 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9730 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9731
9732 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9733 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9734
9735 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9736 ((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]);
9737
9738 return NL_SKIP;
9739}
9740#endif
9741
9742INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9743{
9744#ifdef HAL_NETLINK_IMPL
9745 Netlink nl;
9746 char if_name[10];
9747
9748 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9749
9750 if (*output_array_size <= 0)
9751 return RETURN_OK;
9752
9753 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9754
9755 nl.id = initSock80211(&nl);
9756
9757 if(nl.id < 0) {
9758 fprintf(stderr, "Error initializing netlink \n");
9759 return 0;
9760 }
9761
9762 struct nl_msg* msg = nlmsg_alloc();
9763
9764 if(!msg) {
9765 fprintf(stderr, "Failed to allocate netlink message.\n");
9766 nlfree(&nl);
9767 return 0;
9768 }
9769
9770 genlmsg_put(msg,
9771 NL_AUTO_PORT,
9772 NL_AUTO_SEQ,
9773 nl.id,
9774 0,
9775 0,
9776 NL80211_CMD_GET_STATION,
9777 0);
9778
9779 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9780 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9781 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9782 nl_send_auto(nl.socket, msg);
9783 nl_recvmsgs(nl.socket, nl.cb);
9784 nlmsg_free(msg);
9785 nlfree(&nl);
9786 return RETURN_OK;
9787#else
9788 //TODO Implement me
9789 return RETURN_OK;
9790#endif
9791}
9792
9793INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9794{
9795 // TODO Implement me!
9796 char buf[MAX_BUF_SIZE] = {0};
9797 char config_file[MAX_BUF_SIZE] = {0};
9798
9799 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9800 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9801 *activate = (strncmp("1",buf,1) == 0);
9802
9803 return RETURN_OK;
9804}
9805
9806INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9807{
9808 char config_file[MAX_BUF_SIZE] = {0};
9809 struct params list;
9810
9811 list.name = "rrm_neighbor_report";
9812 list.value = activate?"1":"0";
9813 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9814 wifi_hostapdWrite(config_file, &list, 1);
9815
9816 return RETURN_OK;
9817}
9818
9819INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9820{
9821 char buf[32] = {0};
9822 char config_file[MAX_BUF_SIZE] = {0};
9823
9824 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9825 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9826 *activate = (strncmp("1",buf,1) == 0);
9827
9828 return RETURN_OK;
9829}
9830#undef HAL_NETLINK_IMPL
9831#ifdef HAL_NETLINK_IMPL
9832static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9833 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9834 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9835 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9836 char dev[20];
9837 int freq =0 ;
9838 static int i=0;
9839
9840 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9841
9842 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9843 };
9844
9845 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9846
9847 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9848
9849 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9850 fprintf(stderr, "survey data missing!\n");
9851 return NL_SKIP;
9852 }
9853
9854 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9855 {
9856 fprintf(stderr, "failed to parse nested attributes!\n");
9857 return NL_SKIP;
9858 }
9859
9860
9861 if(out[0].array_size == 1 )
9862 {
9863 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9864 {
9865 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9866 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9867 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9868
9869 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9870 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9871 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9872 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9873 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9874 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9875 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9876 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9877 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9878 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9879 if (sinfo[NL80211_SURVEY_INFO_TIME])
9880 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9881 return NL_STOP;
9882 }
9883 }
9884 else
9885 {
9886 if ( i <= out[0].array_size )
9887 {
9888 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9889 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9890 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9891
9892 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9893 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9894 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9895 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9896 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9897 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9898 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9899 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9900 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9901 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9902 if (sinfo[NL80211_SURVEY_INFO_TIME])
9903 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9904 }
9905 }
9906
9907 i++;
9908 return NL_SKIP;
9909}
9910#endif
9911
9912static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9913{
9914 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9915 FILE *fp;
9916
9917 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9918 {
9919 printf("Creating Frequency-Channel Map\n");
9920 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9921 }
9922 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9923 if((fp = popen(command, "r")))
9924 {
9925 fgets(output, sizeof(output), fp);
9926 *freqMHz = atoi(output);
9927 fclose(fp);
9928 }
9929
9930 return 0;
9931}
9932
9933static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9934{
9935 int freqMHz = -1;
9936 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +08009937 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009938
9939 ieee80211_channel_to_frequency(channel, &freqMHz);
9940 if (freqMHz == -1) {
9941 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9942 return -1;
9943 }
9944
developer033b37b2022-10-18 11:27:46 +08009945 phyId = radio_index_to_phy(radioIndex);
9946 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, phyId, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +08009947 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9948 radioIndex, freqMHz);
9949 return -1;
9950 }
9951
9952 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9953 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9954 return -1;
9955 }
9956
9957 return 0;
9958}
9959
9960static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9961{
9962 const char *ptr = buf;
9963 char *key = NULL;
9964 char *val = NULL;
9965 char line[256] = { '\0' };
9966
9967 while (ptr = get_line_from_str_buf(ptr, line)) {
9968 if (strstr(line, "Frequency")) continue;
9969
9970 key = strtok(line, ":");
9971 val = strtok(NULL, " ");
9972 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9973
9974 if (!strcmp(key, "noise")) {
9975 sscanf(val, "%d", &stats->ch_noise);
9976 if (stats->ch_noise == 0) {
9977 // Workaround for missing noise information.
9978 // Assume -95 for 2.4G and -103 for 5G
9979 if (radioIndex == 0) stats->ch_noise = -95;
9980 if (radioIndex == 1) stats->ch_noise = -103;
9981 }
9982 }
9983 else if (!strcmp(key, "channel active time")) {
9984 sscanf(val, "%llu", &stats->ch_utilization_total);
9985 }
9986 else if (!strcmp(key, "channel busy time")) {
9987 sscanf(val, "%llu", &stats->ch_utilization_busy);
9988 }
9989 else if (!strcmp(key, "channel receive time")) {
9990 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9991 }
9992 else if (!strcmp(key, "channel transmit time")) {
9993 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9994 }
9995 };
9996
9997 return 0;
9998}
9999
10000INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10001{
10002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10003#ifdef HAL_NETLINK_IMPL
10004 Netlink nl;
10005 wifi_channelStats_t_loc local[array_size];
10006 char if_name[10];
10007
10008 local[0].array_size = array_size;
10009
10010 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
10011
10012 nl.id = initSock80211(&nl);
10013
10014 if (nl.id < 0) {
10015 fprintf(stderr, "Error initializing netlink \n");
10016 return -1;
10017 }
10018
10019 struct nl_msg* msg = nlmsg_alloc();
10020
10021 if (!msg) {
10022 fprintf(stderr, "Failed to allocate netlink message.\n");
10023 nlfree(&nl);
10024 return -2;
10025 }
10026
10027 genlmsg_put(msg,
10028 NL_AUTO_PORT,
10029 NL_AUTO_SEQ,
10030 nl.id,
10031 0,
10032 NLM_F_DUMP,
10033 NL80211_CMD_GET_SURVEY,
10034 0);
10035
10036 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10037 nl_send_auto(nl.socket, msg);
10038 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10039 nl_recvmsgs(nl.socket, nl.cb);
10040 nlmsg_free(msg);
10041 nlfree(&nl);
10042 //Copying the Values
10043 for(int i=0;i<array_size;i++)
10044 {
10045 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10046 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10047 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10048 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10049 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10050 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10051 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10052 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10053 }
10054#else
10055 ULONG channel = 0;
10056 int i;
10057 int number_of_channels = array_size;
10058 char buf[512];
10059 INT ret;
10060 wifi_channelStats_t tmp_stats;
10061
10062 if (number_of_channels == 0) {
10063 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10064 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10065 return RETURN_ERR;
10066 }
10067 number_of_channels = 1;
10068 input_output_channelStats_array[0].ch_number = channel;
10069 }
10070
10071 for (i = 0; i < number_of_channels; i++) {
10072
10073 input_output_channelStats_array[i].ch_noise = 0;
10074 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10075 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10076 input_output_channelStats_array[i].ch_utilization_busy = 0;
10077 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10078 input_output_channelStats_array[i].ch_utilization_total = 0;
10079
10080 memset(buf, 0, sizeof(buf));
10081 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10082 return RETURN_ERR;
10083 }
10084 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10085 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10086 return RETURN_ERR;
10087 }
10088
10089 // XXX: fake missing 'self' counter which is not available in iw survey output
10090 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10091 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10092
10093 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10094 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10095 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10096 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10097 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10098
10099 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",
10100 __func__,
10101 input_output_channelStats_array[i].ch_number,
10102 input_output_channelStats_array[i].ch_noise,
10103 input_output_channelStats_array[i].ch_utilization_total,
10104 input_output_channelStats_array[i].ch_utilization_busy,
10105 input_output_channelStats_array[i].ch_utilization_busy_rx,
10106 input_output_channelStats_array[i].ch_utilization_busy_tx,
10107 input_output_channelStats_array[i].ch_utilization_busy_self,
10108 input_output_channelStats_array[i].ch_utilization_busy_ext);
10109 }
10110#endif
10111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10112 return RETURN_OK;
10113}
10114#define HAL_NETLINK_IMPL
10115
10116/* Hostapd events */
10117
10118#ifndef container_of
10119#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10120#define container_of(ptr, type, member) \
10121 ((type *)((char *)ptr - offset_of(type, member)))
10122#endif /* container_of */
10123
10124struct ctrl {
10125 char sockpath[128];
10126 char sockdir[128];
10127 char bss[IFNAMSIZ];
10128 char reply[4096];
10129 int ssid_index;
10130 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10131 void (*overrun)(struct ctrl *ctrl);
10132 struct wpa_ctrl *wpa;
10133 unsigned int ovfl;
10134 size_t reply_len;
10135 int initialized;
10136 ev_timer retry;
10137 ev_timer watchdog;
10138 ev_stat stat;
10139 ev_io io;
10140};
10141static wifi_newApAssociatedDevice_callback clients_connect_cb;
10142static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10143static struct ctrl wpa_ctrl[MAX_APS];
10144static int initialized;
10145
10146static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10147{
10148 char cbuf[256] = {};
10149 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10150 struct cmsghdr *cmsg;
10151 unsigned int ovfl = ctrl->ovfl;
10152 unsigned int drop;
10153
10154 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10155 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10156 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10157 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10158
10159 drop = ovfl - ctrl->ovfl;
10160 ctrl->ovfl = ovfl;
10161
10162 return drop;
10163}
10164
10165static void ctrl_close(struct ctrl *ctrl)
10166{
10167 if (ctrl->io.cb)
10168 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10169 if (ctrl->retry.cb)
10170 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10171 if (!ctrl->wpa)
10172 return;
10173
10174 wpa_ctrl_detach(ctrl->wpa);
10175 wpa_ctrl_close(ctrl->wpa);
10176 ctrl->wpa = NULL;
10177 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10178}
10179
10180static void ctrl_process(struct ctrl *ctrl)
10181{
10182 const char *str;
10183 int drops;
10184 int level;
10185 int err;
10186
10187 /* Example events:
10188 *
10189 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10190 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10191 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10192 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10193 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10194 */
10195 if (!(str = index(ctrl->reply, '>')))
10196 return;
10197 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10198 return;
10199
10200 str++;
10201
10202 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10203 if (!(str = index(ctrl->reply, ' ')))
10204 return;
10205 wifi_associated_dev_t sta;
10206 memset(&sta, 0, sizeof(sta));
10207
10208 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10209 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10210 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10211
10212 sta.cli_Active=true;
10213
10214 (clients_connect_cb)(ctrl->ssid_index, &sta);
10215 goto handled;
10216 }
10217
10218 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10219 if (!(str = index(ctrl->reply, ' ')))
10220 return;
10221
10222 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10223 goto handled;
10224 }
10225
10226 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10227 printf("CTRL_WPA: handle TERMINATING event\n");
10228 goto retry;
10229 }
10230
10231 if (strncmp("AP-DISABLED", str, 11) == 0) {
10232 printf("CTRL_WPA: handle AP-DISABLED\n");
10233 goto retry;
10234 }
10235
10236 printf("Event not supported!!\n");
10237
10238handled:
10239
10240 if ((drops = ctrl_get_drops(ctrl))) {
10241 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10242 if (ctrl->overrun)
10243 ctrl->overrun(ctrl);
10244 }
10245
10246 return;
10247
10248retry:
10249 printf("WPA_CTRL: closing\n");
10250 ctrl_close(ctrl);
10251 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10252 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10253}
10254
10255static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10256{
10257 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10258 int err;
10259
10260 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10261 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10262 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10263 ctrl->reply[ctrl->reply_len] = 0;
10264 if (err < 0) {
10265 if (errno == EAGAIN || errno == EWOULDBLOCK)
10266 return;
10267 ctrl_close(ctrl);
10268 ev_timer_again(EV_A_ &ctrl->retry);
10269 return;
10270 }
10271
10272 ctrl_process(ctrl);
10273}
10274
10275static int ctrl_open(struct ctrl *ctrl)
10276{
10277 int fd;
10278
10279 if (ctrl->wpa)
10280 return 0;
10281
10282 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10283 if (!ctrl->wpa)
10284 goto err;
10285
10286 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10287 goto err_close;
10288
10289 fd = wpa_ctrl_get_fd(ctrl->wpa);
10290 if (fd < 0)
10291 goto err_detach;
10292
10293 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10294 goto err_detach;
10295
10296 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10297 ev_io_start(EV_DEFAULT_ &ctrl->io);
10298
10299 return 0;
10300
10301err_detach:
10302 wpa_ctrl_detach(ctrl->wpa);
10303err_close:
10304 wpa_ctrl_close(ctrl->wpa);
10305err:
10306 ctrl->wpa = NULL;
10307 return -1;
10308}
10309
10310static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10311{
10312 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10313
10314 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10315 ctrl_open(ctrl);
10316}
10317
10318static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10319{
10320 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10321
10322 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10323 if (ctrl_open(ctrl) == 0) {
10324 printf("WPA_CTRL: retry successful\n");
10325 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10326 }
10327}
10328
10329int ctrl_enable(struct ctrl *ctrl)
10330{
10331 if (ctrl->wpa)
10332 return 0;
10333
10334 if (!ctrl->stat.cb) {
10335 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10336 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10337 }
10338
10339 if (!ctrl->retry.cb) {
10340 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10341 }
10342
10343 return ctrl_open(ctrl);
10344}
10345
10346static void
10347ctrl_msg_cb(char *buf, size_t len)
10348{
10349 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10350
10351 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10352 ctrl_process(ctrl);
10353}
10354
10355static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10356{
10357 int err;
10358
10359 if (!ctrl->wpa)
10360 return -1;
10361 if (*reply_len < 2)
10362 return -1;
10363
10364 (*reply_len)--;
10365 ctrl->reply_len = sizeof(ctrl->reply);
10366 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10367 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10368 if (err < 0)
10369 return err;
10370
10371 if (ctrl->reply_len > *reply_len)
10372 ctrl->reply_len = *reply_len;
10373
10374 *reply_len = ctrl->reply_len;
10375 memcpy(reply, ctrl->reply, *reply_len);
10376 reply[*reply_len - 1] = 0;
10377 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10378 return 0;
10379}
10380
10381static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10382{
10383 const char *pong = "PONG";
10384 const char *ping = "PING";
10385 char reply[1024];
10386 size_t len = sizeof(reply);
10387 int err;
10388 ULONG s, snum;
10389 INT ret;
10390 BOOL status;
10391
10392 printf("WPA_CTRL: watchdog cb\n");
10393
10394 ret = wifi_getSSIDNumberOfEntries(&snum);
10395 if (ret != RETURN_OK) {
10396 printf("%s: failed to get SSID count", __func__);
10397 return;
10398 }
10399
10400 if (snum > MAX_APS) {
10401 printf("more ssid than supported! %lu\n", snum);
10402 return;
10403 }
10404
10405 for (s = 0; s < snum; s++) {
10406 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10407 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10408 continue;
10409 }
10410 if (status == false) continue;
10411
10412 memset(reply, 0, sizeof(reply));
10413 len = sizeof(reply);
10414 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10415 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10416 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10417 continue;
10418
10419 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10420 ctrl_close(&wpa_ctrl[s]);
10421 printf("WPA_CTRL: ev_timer_again %d\n", s);
10422 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10423 }
10424}
10425
10426static int init_wpa()
10427{
10428 int ret = 0, i = 0;
10429 ULONG s, snum;
10430
10431 ret = wifi_getSSIDNumberOfEntries(&snum);
10432 if (ret != RETURN_OK) {
10433 printf("%s: failed to get SSID count", __func__);
10434 return RETURN_ERR;
10435 }
10436
10437 if (snum > MAX_APS) {
10438 printf("more ssid than supported! %lu\n", snum);
10439 return RETURN_ERR;
10440 }
10441
10442 for (s = 0; s < snum; s++) {
10443 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10444 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10445 wpa_ctrl[s].ssid_index = s;
10446 ctrl_enable(&wpa_ctrl[s]);
10447 }
10448
10449 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10450 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10451
10452 initialized = 1;
10453 printf("WPA_CTRL: initialized\n");
10454
10455 return RETURN_OK;
10456}
10457
10458void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10459{
10460 clients_connect_cb = callback_proc;
10461 if (!initialized)
10462 init_wpa();
10463}
10464
10465void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10466{
10467 clients_disconnect_cb = callback_proc;
10468 if (!initialized)
10469 init_wpa();
10470}
10471
10472INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10473{
10474 // TODO Implement me!
10475 return RETURN_ERR;
10476}
10477
10478INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10479{
10480 // TODO Implement me!
10481 return RETURN_ERR;
10482}
10483
10484INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10485{
10486 int i;
10487 char cmd[256];
10488 char channel_numbers_buf[256];
10489 char dfs_state_buf[256];
10490 char line[256];
10491 const char *ptr;
10492
10493 memset(cmd, 0, sizeof(cmd));
10494 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10495 memset(line, 0, sizeof(line));
10496 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10497 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10498
10499 if (radioIndex == 0) { // 2.4G - all allowed
10500 if (outputMapSize < 11) {
10501 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10502 return RETURN_ERR;
10503 }
10504
10505 for (i = 0; i < 11; i++) {
10506 outputMap[i].ch_number = i + 1;
10507 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10508 }
10509
10510 return RETURN_OK;
10511 }
10512
10513 if (radioIndex == 1) { // 5G
10514// Example output of iw list:
10515//
10516// Frequencies:
10517// * 5180 MHz [36] (17.0 dBm)
10518// * 5200 MHz [40] (17.0 dBm)
10519// * 5220 MHz [44] (17.0 dBm)
10520// * 5240 MHz [48] (17.0 dBm)
10521// * 5260 MHz [52] (23.0 dBm) (radar detection)
10522// DFS state: usable (for 78930 sec)
10523// DFS CAC time: 60000 ms
10524// * 5280 MHz [56] (23.0 dBm) (radar detection)
10525// DFS state: usable (for 78930 sec)
10526// DFS CAC time: 60000 ms
10527// * 5300 MHz [60] (23.0 dBm) (radar detection)
10528// DFS state: usable (for 78930 sec)
10529// DFS CAC time: 60000 ms
10530// * 5320 MHz [64] (23.0 dBm) (radar detection)
10531// DFS state: usable (for 78930 sec)
10532// DFS CAC time: 60000 ms
10533// * 5500 MHz [100] (disabled)
10534// * 5520 MHz [104] (disabled)
10535// * 5540 MHz [108] (disabled)
10536// * 5560 MHz [112] (disabled)
10537//
10538// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10539 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10540 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10541 return RETURN_ERR;
10542 }
10543
10544 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10545 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10546 return RETURN_ERR;
10547 }
10548
10549 ptr = channel_numbers_buf;
10550 i = 0;
10551 while (ptr = get_line_from_str_buf(ptr, line)) {
10552 if (i >= outputMapSize) {
10553 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10554 return RETURN_ERR;
10555 }
10556 sscanf(line, "%d", &outputMap[i].ch_number);
10557
10558 memset(cmd, 0, sizeof(cmd));
10559 // Below command should fetch string for DFS state (usable, available or unavailable)
10560 // Example line: "DFS state: usable (for 78930 sec)"
10561 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) {
10562 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10563 return RETURN_ERR;
10564 }
10565
10566 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10567 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10568 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10569 return RETURN_ERR;
10570 }
10571
10572 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10573
10574 if (!strcmp(dfs_state_buf, "usable")) {
10575 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10576 } else if (!strcmp(dfs_state_buf, "available")) {
10577 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10578 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10579 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10580 } else {
10581 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10582 }
10583 i++;
10584 }
10585
10586 return RETURN_OK;
10587 }
10588
10589 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10590 return RETURN_ERR;
10591}
10592
10593INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10594{
10595 // TODO Implement me!
10596 return RETURN_ERR;
10597}
10598
10599INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10600{
10601 return RETURN_OK;
10602}
10603
10604INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10605{
10606 // TODO Implement me!
10607 return RETURN_ERR;
10608}
10609
10610INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10611{
10612 // TODO API refrence Implementaion is present on RPI hal
10613 return RETURN_ERR;
10614}
10615
10616INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10617{
developera5005b62022-09-13 15:43:35 +080010618 char cmd[128]={'\0'};
10619 char buf[128]={'\0'};
10620 char *support;
10621 int maximum_tx = 0, current_tx = 0;
10622
10623 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10624 if(txpwr_pcntg == NULL)
10625 return RETURN_ERR;
10626
10627 // Get the maximum tx power of the device
10628 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10629 _syscmd(cmd, buf, sizeof(buf));
10630 maximum_tx = strtol(buf, NULL, 10);
10631
10632 // Get the current tx power
10633 memset(cmd, 0, sizeof(cmd));
10634 memset(buf, 0, sizeof(buf));
10635 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10636 _syscmd(cmd, buf, sizeof(buf));
10637 current_tx = strtol(buf, NULL, 10);
10638
10639 // Get the power supported list and find the current power percentage in supported list
10640 memset(buf, 0, sizeof(buf));
10641 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10642 support = strtok(buf, ",");
10643 while(true)
10644 {
10645 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
developer033b37b2022-10-18 11:27:46 +080010646 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010647 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010648 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010649 }
10650 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10651 if (tmp == current_tx) {
10652 *txpwr_pcntg = strtol(support, NULL, 10);
10653 break;
10654 }
10655 support = strtok(NULL, ",");
10656 }
10657 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010658 return RETURN_OK;
10659}
10660
10661INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10662{
developer58599c22022-09-13 16:40:34 +080010663 // TODO precac feature.
10664 struct params params = {0};
10665 char config_file[128] = {0};
10666
10667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10668
10669 params.name = "enable_background_radar";
10670 params.value = enable?"1":"0";
10671 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10672 wifi_hostapdWrite(config_file, &params, 1);
10673 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10674
10675 /* TODO precac feature */
10676
10677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10678 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010679}
10680
10681INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10682{
developer58599c22022-09-13 16:40:34 +080010683 char config_file[128] = {0};
10684 char buf[64] = {0};
10685
10686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10687 if (NULL == enable || NULL == precac)
10688 return RETURN_ERR;
10689
10690 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10691 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10692 if (strncmp(enable, "1", 1) == 0)
10693 *enable = true;
10694 else
10695 *enable = false;
10696
10697 /* TODO precac feature */
10698
10699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10700 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010701}
10702
10703INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10704{
developer58599c22022-09-13 16:40:34 +080010705 *supported = TRUE;
10706 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010707}
10708
developer3e6b1692022-09-30 18:04:05 +080010709INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10710{
10711 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10712 struct params params = {0};
10713 char config_file[64] = {0};
10714 char buf[64] = {0};
10715 unsigned int set_mu_type = 0;
10716 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10717
10718 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10719 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10720
10721 if (strlen(buf) > 0)
10722 set_mu_type = strtol(buf, NULL, 10);
10723
10724 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10725 set_mu_type &= ~0x05; // unset bit 0, 2
10726 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10727 set_mu_type |= 0x01;
10728 set_mu_type &= ~0x04;
10729 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10730 set_mu_type &= ~0x01;
10731 set_mu_type |= 0x04;
10732 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10733 set_mu_type |= 0x05; // set bit 0, 2
10734 }
10735
10736 params.name = "hemu_onoff";
10737 sprintf(buf, "%u", set_mu_type);
10738 params.value = buf;
10739 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10740 wifi_hostapdWrite(config_file, &params, 1);
10741 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10742
10743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10744 return RETURN_OK;
10745}
10746
10747INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10748{
10749 struct params params={0};
10750 char config_file[64] = {0};
10751 char buf[64] = {0};
10752 unsigned int get_mu_type = 0;
10753
10754 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10755
10756 if (mu_type == NULL)
10757 return RETURN_ERR;
10758
10759 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10760 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10761 get_mu_type = strtol(buf, NULL, 10);
10762
10763 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10764 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10765 else if (get_mu_type & 0x04)
10766 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10767 else if (get_mu_type & 0x01)
10768 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10769 else
10770 *mu_type = WIFI_DL_MU_TYPE_NONE;
10771
10772 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10773 return RETURN_OK;
10774}
10775
10776INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10777{
10778 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10779 struct params params={0};
10780 char config_file[64] = {0};
10781 char buf[64] = {0};
10782 unsigned int set_mu_type = 0;
10783 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10784
10785 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10786 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10787
10788 if (strlen(buf) > 0)
10789 set_mu_type = strtol(buf, NULL, 10);
10790
10791 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10792 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10793 set_mu_type &= ~0x0a;
10794 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10795 set_mu_type |= 0x02;
10796 set_mu_type &= ~0x08;
10797 }
10798
10799 params.name = "hemu_onoff";
10800 sprintf(buf, "%u", set_mu_type);
10801 params.value = buf;
10802 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10803 wifi_hostapdWrite(config_file, &params, 1);
10804 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10805
10806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10807 return RETURN_OK;
10808}
10809
10810INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10811{
10812 struct params params={0};
10813 char config_file[64] = {0};
10814 char buf[64] = {0};
10815 unsigned int get_mu_type = 0;
10816
10817 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10818
10819 if (mu_type == NULL)
10820 return RETURN_ERR;
10821
10822 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10823 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10824
10825 get_mu_type = strtol(buf, NULL, 10);
10826 if (get_mu_type & 0x02)
10827 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10828 else
10829 *mu_type = WIFI_DL_MU_TYPE_NONE;
10830
10831 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10832 return RETURN_OK;
10833}
10834
10835
developer454b9462022-09-13 15:29:16 +080010836INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10837{
10838 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010839 char buf[256] = {0};
10840 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010841 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010842 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010843 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010844 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010845
10846 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10847
developer254882b2022-09-30 17:12:31 +080010848 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010849 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10850 return RETURN_ERR;
10851 }
developer454b9462022-09-13 15:29:16 +080010852
developer254882b2022-09-30 17:12:31 +080010853 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010854 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010855
developer254882b2022-09-30 17:12:31 +080010856 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10857 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
10858 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
10859 _syscmd(cmd, buf, sizeof(buf));
10860 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10861 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10862 if (strstr(buf, "[SHORT-GI-") == NULL) {
10863 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
10864 _syscmd(cmd, buf, sizeof(buf));
10865 }
10866 if (band == band_5) {
10867 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10868 if (strstr(buf, "[SHORT-GI-") == NULL) {
10869 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
10870 _syscmd(cmd, buf, sizeof(buf));
10871 }
10872 }
10873 }
10874 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010875
developer254882b2022-09-30 17:12:31 +080010876 if (guard_interval == wifi_guard_interval_400)
10877 strcpy(GI, "0.4");
10878 else if (guard_interval == wifi_guard_interval_800)
10879 strcpy(GI, "0.8");
10880 else if (guard_interval == wifi_guard_interval_1600)
10881 strcpy(GI, "1.6");
10882 else if (guard_interval == wifi_guard_interval_3200)
10883 strcpy(GI, "3.2");
10884 else if (guard_interval == wifi_guard_interval_auto)
10885 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010886 // Record GI for get GI function
10887 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10888 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010889 if (f == NULL)
10890 return RETURN_ERR;
10891 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010892 fclose(f);
10893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10894 return RETURN_OK;
10895}
10896
10897INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10898{
10899 char buf[32] = {0};
10900 char cmd[64] = {0};
10901
10902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10903
10904 if (guard_interval == NULL)
10905 return RETURN_ERR;
10906
10907 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10908 _syscmd(cmd, buf, sizeof(buf));
10909
10910 if (strncmp(buf, "0.4", 3) == 0)
10911 *guard_interval = wifi_guard_interval_400;
10912 else if (strncmp(buf, "0.8", 3) == 0)
10913 *guard_interval = wifi_guard_interval_800;
10914 else if (strncmp(buf, "1.6", 3) == 0)
10915 *guard_interval = wifi_guard_interval_1600;
10916 else if (strncmp(buf, "3.2", 3) == 0)
10917 *guard_interval = wifi_guard_interval_3200;
10918 else
10919 *guard_interval = wifi_guard_interval_auto;
10920
10921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10922 return RETURN_OK;
10923}
10924
developer3cc61d12022-09-13 16:36:05 +080010925INT wifi_setBSSColor(INT radio_index, UCHAR color)
10926{
10927 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10928 struct params params = {0};
10929 char config_file[128] = {0};
10930 char bss_color[4] ={0};
10931
10932 params.name = "he_bss_color";
10933 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10934 params.value = bss_color;
10935 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10936 wifi_hostapdWrite(config_file, &params, 1);
10937 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10938
10939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10940 return RETURN_OK;
10941}
10942
10943INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10944{
10945 char config_file[128] = {0};
10946 char buf[64] = {0};
10947 char temp_output[128] = {'\0'};
10948
10949 wifi_dbg_printf("\nFunc=%s\n", __func__);
10950 if (NULL == color)
10951 return RETURN_ERR;
10952
10953 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10954 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10955
10956 if(strlen(buf) > 0) {
10957 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10958 } else {
10959 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10960 }
10961
10962 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10963 wifi_dbg_printf("\noutput_string=%s\n", color);
10964
10965 return RETURN_OK;
10966}
10967
developer06a01d92022-09-07 16:32:39 +080010968/* multi-psk support */
10969INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10970{
10971 char cmd[256];
10972
10973 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10974 AP_PREFIX,
10975 apIndex,
10976 mac[0],
10977 mac[1],
10978 mac[2],
10979 mac[3],
10980 mac[4],
10981 mac[5]
10982 );
10983 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10984 _syscmd(cmd, key->wifi_keyId, 64);
10985
10986
10987 return RETURN_OK;
10988}
10989
10990INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10991{
10992 FILE *fd = NULL;
10993 char fname[100];
10994 char cmd[128] = {0};
10995 char out[64] = {0};
10996 wifi_key_multi_psk_t * key = NULL;
10997 if(keysNumber < 0)
10998 return RETURN_ERR;
10999
11000 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11001 fd = fopen(fname, "w");
11002 if (!fd) {
11003 return RETURN_ERR;
11004 }
11005 key= (wifi_key_multi_psk_t *) keys;
11006 for(int i=0; i<keysNumber; ++i, key++) {
11007 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11008 }
11009 fclose(fd);
11010
11011 //reload file
11012 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
11013 _syscmd(cmd, out, 64);
11014 return RETURN_OK;
11015}
11016
11017INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11018{
11019 FILE *fd = NULL;
11020 char fname[100];
11021 char * line = NULL;
11022 char * pos = NULL;
11023 size_t len = 0;
11024 ssize_t read = 0;
11025 INT ret = RETURN_OK;
11026 wifi_key_multi_psk_t *keys_it = NULL;
11027
11028 if (keysNumber < 1) {
11029 return RETURN_ERR;
11030 }
11031
11032 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11033 fd = fopen(fname, "r");
11034 if (!fd) {
11035 return RETURN_ERR;
11036 }
11037
11038 if (keys == NULL) {
11039 ret = RETURN_ERR;
11040 goto close;
11041 }
11042
11043 keys_it = keys;
11044 while ((read = getline(&line, &len, fd)) != -1) {
11045 //Strip trailing new line if present
11046 if (read > 0 && line[read-1] == '\n') {
11047 line[read-1] = '\0';
11048 }
11049
11050 if(strcmp(line,"keyid=")) {
11051 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11052 if (!(pos = index(line, ' '))) {
11053 ret = RETURN_ERR;
11054 goto close;
11055 }
11056 pos++;
11057 //Here should be 00:00:00:00:00:00
11058 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11059 printf("Not supported MAC: %s\n", pos);
11060 }
11061 if (!(pos = index(pos, ' '))) {
11062 ret = RETURN_ERR;
11063 goto close;
11064 }
11065 pos++;
11066
11067 //The rest is PSK
11068 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11069 keys_it++;
11070
11071 if(--keysNumber <= 0)
11072 break;
11073 }
11074 }
11075
11076close:
11077 free(line);
11078 fclose(fd);
11079 return ret;
11080}
11081/* end of multi-psk support */
11082
11083INT wifi_setNeighborReports(UINT apIndex,
11084 UINT numNeighborReports,
11085 wifi_NeighborReport_t *neighborReports)
11086{
11087 char cmd[256] = { 0 };
11088 char hex_bssid[13] = { 0 };
11089 char bssid[18] = { 0 };
11090 char nr[256] = { 0 };
11091 char ssid[256];
11092 char hex_ssid[256];
11093 INT ret;
11094
11095 /*rmeove all neighbors*/
11096 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
11097 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);
11098 system(cmd);
11099
11100 for(unsigned int i = 0; i < numNeighborReports; i++)
11101 {
11102 memset(ssid, 0, sizeof(ssid));
11103 ret = wifi_getSSIDName(apIndex, ssid);
11104 if (ret != RETURN_OK)
11105 return RETURN_ERR;
11106
11107 memset(hex_ssid, 0, sizeof(hex_ssid));
11108 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11109 sprintf(hex_ssid + k,"%02x", ssid[j]);
11110
11111 snprintf(hex_bssid, sizeof(hex_bssid),
11112 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11113 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11114 snprintf(bssid, sizeof(bssid),
11115 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11116 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11117
11118 snprintf(nr, sizeof(nr),
11119 "%s" // bssid
11120 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11121 "%02hhx" // operclass
11122 "%02hhx" // channel
11123 "%02hhx", // phy_mode
11124 hex_bssid,
11125 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11126 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11127 neighborReports[i].opClass,
11128 neighborReports[i].channel,
11129 neighborReports[i].phyTable);
11130
11131 snprintf(cmd, sizeof(cmd),
11132 "hostapd_cli set_neighbor "
11133 "%s " // bssid
11134 "ssid=%s " // ssid
11135 "nr=%s " // nr
11136 "-i %s%d",
11137 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
11138
11139 if (WEXITSTATUS(system(cmd)) != 0)
11140 {
11141 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11142 }
11143 }
11144
11145 return RETURN_OK;
11146}
11147
11148INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11149{
11150 return RETURN_OK;
11151}
11152
11153#ifdef _WIFI_HAL_TEST_
11154int main(int argc,char **argv)
11155{
11156 int index;
11157 INT ret=0;
11158 char buf[1024]="";
11159
11160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11161 if(argc<3)
11162 {
11163 if(argc==2)
11164 {
11165 if(!strcmp(argv[1], "init"))
11166 return wifi_init();
11167 if(!strcmp(argv[1], "reset"))
11168 return wifi_reset();
11169 if(!strcmp(argv[1], "wifi_getHalVersion"))
11170 {
11171 char buffer[64];
11172 if(wifi_getHalVersion(buffer)==RETURN_OK)
11173 printf("Version: %s\n", buffer);
11174 else
11175 printf("Error in wifi_getHalVersion\n");
11176 return RETURN_OK;
11177 }
11178 }
11179 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11180 exit(-1);
11181 }
11182
11183 index = atoi(argv[2]);
11184 if(strstr(argv[1], "wifi_getApName")!=NULL)
11185 {
11186 wifi_getApName(index,buf);
11187 printf("Ap name is %s \n",buf);
11188 return 0;
11189 }
11190 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11191 {
11192 BOOL b = FALSE;
11193 BOOL *output_bool = &b;
11194 wifi_getRadioAutoChannelEnable(index,output_bool);
11195 printf("Channel enabled = %d \n",b);
11196 return 0;
11197 }
11198 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11199 {
11200 wifi_getApWpaEncryptionMode(index,buf);
11201 printf("encryption enabled = %s\n",buf);
11202 return 0;
11203 }
11204 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11205 {
11206 BOOL b = FALSE;
11207 BOOL *output_bool = &b;
11208 wifi_getApSsidAdvertisementEnable(index,output_bool);
11209 printf("advertisment enabled = %d\n",b);
11210 return 0;
11211 }
11212 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11213 {
11214 if(argc <= 3 )
11215 {
11216 printf("Insufficient arguments \n");
11217 exit(-1);
11218 }
11219
11220 char sta[20] = {'\0'};
11221 ULLONG handle= 0;
11222 strcpy(sta,argv[3]);
11223 mac_address_t st;
11224 mac_addr_aton(st,sta);
11225
11226 wifi_associated_dev_tid_stats_t tid_stats;
11227 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11228 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11229 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);
11230 }
11231
11232 if(strstr(argv[1], "getApEnable")!=NULL) {
11233 BOOL enable;
11234 ret=wifi_getApEnable(index, &enable);
11235 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11236 }
11237 else if(strstr(argv[1], "setApEnable")!=NULL) {
11238 BOOL enable = atoi(argv[3]);
11239 ret=wifi_setApEnable(index, enable);
11240 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11241 }
11242 else if(strstr(argv[1], "getApStatus")!=NULL) {
11243 char status[64];
11244 ret=wifi_getApStatus(index, status);
11245 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11246 }
11247 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11248 {
11249 wifi_getSSIDNameStatus(index,buf);
11250 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11251 return 0;
11252 }
11253 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11254 wifi_ssidTrafficStats2_t stats={0};
11255 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11256 printf("%s %d: returns %d\n", argv[1], index, ret);
11257 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11258 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11259 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11260 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11261 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11262 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11263 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11264 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11265 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11266 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11267 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11268 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11269 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11270 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11271 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11272 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11273 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11274 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11275 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11276 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11277 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11278 }
11279 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11280 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11281 UINT array_size=0;
11282 UINT i=0;
11283 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11284 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11285 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11286 printf(" neighbor %d:\n", i);
11287 printf(" ap_SSID =%s\n", pt->ap_SSID);
11288 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11289 printf(" ap_Mode =%s\n", pt->ap_Mode);
11290 printf(" ap_Channel =%d\n", pt->ap_Channel);
11291 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11292 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11293 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11294 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11295 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11296 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11297 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11298 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11299 printf(" ap_Noise =%d\n", pt->ap_Noise);
11300 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11301 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11302 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11303 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11304 }
11305 if(neighbor_ap_array)
11306 free(neighbor_ap_array); //make sure to free the list
11307 }
11308 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11309 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11310 UINT array_size=0;
11311 UINT i=0;
11312 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11313 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11314 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11315 printf(" associated_dev %d:\n", i);
11316 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11317 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11318 printf(" cli_SNR =%d\n", pt->cli_SNR);
11319 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11320 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11321 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11322 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11323 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11324 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11325 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11326 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11327 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11328 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11329 }
11330 if(associated_dev_array)
11331 free(associated_dev_array); //make sure to free the list
11332 }
11333
11334 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11335 {
11336#define MAX_ARRAY_SIZE 64
11337 int i, array_size;
11338 char *p, *ch_str;
11339 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11340
11341 if(argc != 5)
11342 {
11343 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11344 exit(-1);
11345 }
11346 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11347
11348 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11349 {
11350 strtok_r(ch_str, ",", &p);
11351 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11352 }
11353 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11354 if(!array_size)
11355 array_size=1;//Need to print current channel statistics
11356 for(i=0; i<array_size; i++)
11357 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11358 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11359 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11360 input_output_channelStats_array[i].ch_number,\
11361 input_output_channelStats_array[i].ch_noise,\
11362 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11363 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11364 input_output_channelStats_array[i].ch_utilization_busy,\
11365 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11366 input_output_channelStats_array[i].ch_utilization_total);
11367 }
11368
11369 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11370 {
11371 if(argc <= 3 )
11372 {
11373 printf("Insufficient arguments \n");
11374 exit(-1);
11375 }
11376 char mac_addr[20] = {'\0'};
11377 wifi_device_t output_struct;
11378 int dev_index = atoi(argv[3]);
11379
11380 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11381 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11382 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);
11383 }
11384
11385 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11386 {
11387 if (argc <= 3)
11388 {
11389 printf("Insufficient arguments\n");
11390 exit(-1);
11391 }
11392 char args[256];
11393 wifi_NeighborReport_t *neighborReports;
11394
11395 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11396 if (!neighborReports)
11397 {
11398 printf("Failed to allocate memory");
11399 exit(-1);
11400 }
11401
11402 for (int i = 3; i < argc; ++i)
11403 {
11404 char *val;
11405 int j = 0;
11406 memset(args, 0, sizeof(args));
11407 strncpy(args, argv[i], sizeof(args));
11408 val = strtok(args, ";");
11409 while (val != NULL)
11410 {
11411 if (j == 0)
11412 {
11413 mac_addr_aton(neighborReports[i - 3].bssid, val);
11414 } else if (j == 1)
11415 {
11416 neighborReports[i - 3].info = strtol(val, NULL, 16);
11417 } else if (j == 2)
11418 {
11419 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11420 } else if (j == 3)
11421 {
11422 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11423 } else if (j == 4)
11424 {
11425 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11426 } else {
11427 printf("Insufficient arguments]n\n");
11428 exit(-1);
11429 }
11430 val = strtok(NULL, ";");
11431 j++;
11432 }
11433 }
11434
11435 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11436 if (ret != RETURN_OK)
11437 {
11438 printf("wifi_setNeighborReports ret = %d", ret);
11439 exit(-1);
11440 }
11441 }
11442 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11443 {
11444 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11445 printf("%s.\n", buf);
11446 else
11447 printf("Error returned\n");
11448 }
11449 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11450 {
11451 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11452 printf("%s.\n", buf);
11453 else
11454 printf("Error returned\n");
11455 }
11456 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11457 {
11458 if (argc <= 2)
11459 {
11460 printf("Insufficient arguments\n");
11461 exit(-1);
11462 }
11463 char buf[64]= {'\0'};
11464 wifi_getRadioOperatingChannelBandwidth(index,buf);
11465 printf("Current bandwidth is %s \n",buf);
11466 return 0;
11467 }
11468 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11469 {
11470 if (argc <= 5)
11471 {
11472 printf("Insufficient arguments\n");
11473 exit(-1);
11474 }
11475 UINT channel = atoi(argv[3]);
11476 UINT width = atoi(argv[4]);
11477 UINT beacon = atoi(argv[5]);
11478 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11479 printf("Result = %d", ret);
11480 }
11481
11482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11483 return 0;
11484}
11485
11486#endif
11487
11488#ifdef WIFI_HAL_VERSION_3
11489
developer1e5aa162022-09-13 16:06:24 +080011490INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11491{
11492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11493 if (bitMap & WIFI_BITRATE_1MBPS)
11494 strcat(BasicRate, "1,");
11495 if (bitMap & WIFI_BITRATE_2MBPS)
11496 strcat(BasicRate, "2,");
11497 if (bitMap & WIFI_BITRATE_5_5MBPS)
11498 strcat(BasicRate, "5.5,");
11499 if (bitMap & WIFI_BITRATE_6MBPS)
11500 strcat(BasicRate, "6,");
11501 if (bitMap & WIFI_BITRATE_9MBPS)
11502 strcat(BasicRate, "9,");
11503 if (bitMap & WIFI_BITRATE_11MBPS)
11504 strcat(BasicRate, "11,");
11505 if (bitMap & WIFI_BITRATE_12MBPS)
11506 strcat(BasicRate, "12,");
11507 if (bitMap & WIFI_BITRATE_18MBPS)
11508 strcat(BasicRate, "18,");
11509 if (bitMap & WIFI_BITRATE_24MBPS)
11510 strcat(BasicRate, "24,");
11511 if (bitMap & WIFI_BITRATE_36MBPS)
11512 strcat(BasicRate, "36,");
11513 if (bitMap & WIFI_BITRATE_48MBPS)
11514 strcat(BasicRate, "48,");
11515 if (bitMap & WIFI_BITRATE_54MBPS)
11516 strcat(BasicRate, "54,");
11517 if (strlen(BasicRate) != 0) // remove last comma
11518 BasicRate[strlen(BasicRate) - 1] = '\0';
11519 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11520 return RETURN_OK;
11521}
11522
11523INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11524{
11525 UINT BitMap = 0;
11526 char *rate;
11527
11528 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11529 rate = strtok(BasicRatesList, ",");
11530 while(rate != NULL)
11531 {
11532 if (strcmp(rate, "1") == 0)
11533 BitMap |= WIFI_BITRATE_1MBPS;
11534 else if (strcmp(rate, "2") == 0)
11535 BitMap |= WIFI_BITRATE_2MBPS;
11536 else if (strcmp(rate, "5.5") == 0)
11537 BitMap |= WIFI_BITRATE_5_5MBPS;
11538 else if (strcmp(rate, "6") == 0)
11539 BitMap |= WIFI_BITRATE_6MBPS;
11540 else if (strcmp(rate, "9") == 0)
11541 BitMap |= WIFI_BITRATE_9MBPS;
11542 else if (strcmp(rate, "11") == 0)
11543 BitMap |= WIFI_BITRATE_11MBPS;
11544 else if (strcmp(rate, "12") == 0)
11545 BitMap |= WIFI_BITRATE_12MBPS;
11546 else if (strcmp(rate, "18") == 0)
11547 BitMap |= WIFI_BITRATE_18MBPS;
11548 else if (strcmp(rate, "24") == 0)
11549 BitMap |= WIFI_BITRATE_24MBPS;
11550 else if (strcmp(rate, "36") == 0)
11551 BitMap |= WIFI_BITRATE_36MBPS;
11552 else if (strcmp(rate, "48") == 0)
11553 BitMap |= WIFI_BITRATE_48MBPS;
11554 else if (strcmp(rate, "54") == 0)
11555 BitMap |= WIFI_BITRATE_54MBPS;
11556 rate = strtok(NULL, ",");
11557 }
11558 *basicRateBitMap = BitMap;
11559 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11560 return RETURN_OK;
11561}
11562
11563// 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 +080011564INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11565{
developer1e5aa162022-09-13 16:06:24 +080011566 char buf[128] = {0};
11567 char cmd[128] = {0};
11568 char config_file[64] = {0};
11569 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011570 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011571 wifi_radio_operationParam_t current_param;
11572
11573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11574
11575 multiple_set = TRUE;
11576 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11577 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11578 return RETURN_ERR;
11579 }
11580 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11581 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11582 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11583 return RETURN_ERR;
11584 }
11585 }
developer5884e982022-10-06 10:52:50 +080011586
11587 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11588 bandwidth = 20;
11589 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11590 bandwidth = 40;
11591 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11592 bandwidth = 80;
11593 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11594 bandwidth = 160;
11595 if (operationParam->autoChannelEnabled){
11596 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11597 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11598 return RETURN_ERR;
11599 }
11600 }else{
developer1e5aa162022-09-13 16:06:24 +080011601 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11602 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11603 return RETURN_ERR;
11604 }
11605 }
developer5884e982022-10-06 10:52:50 +080011606
developer1e5aa162022-09-13 16:06:24 +080011607 if (current_param.variant != operationParam->variant) {
11608 // Two different definition bit map, so need to check every bit.
11609 if (operationParam->variant & WIFI_80211_VARIANT_A)
11610 set_mode |= WIFI_MODE_A;
11611 if (operationParam->variant & WIFI_80211_VARIANT_B)
11612 set_mode |= WIFI_MODE_B;
11613 if (operationParam->variant & WIFI_80211_VARIANT_G)
11614 set_mode |= WIFI_MODE_G;
11615 if (operationParam->variant & WIFI_80211_VARIANT_N)
11616 set_mode |= WIFI_MODE_N;
11617 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11618 set_mode |= WIFI_MODE_AC;
11619 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11620 set_mode |= WIFI_MODE_AX;
11621 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11622 memset(buf, 0, sizeof(buf));
11623 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11624 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11625 return RETURN_ERR;
11626 }
11627 }
11628 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11629 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11630 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11631 return RETURN_ERR;
11632 }
11633 }
11634 if (current_param.beaconInterval != operationParam->beaconInterval) {
11635 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11636 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11637 return RETURN_ERR;
11638 }
11639 }
11640 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11641 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11642 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11643 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11644 return RETURN_ERR;
11645 }
11646 }
11647 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11648 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11649 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11650 return RETURN_ERR;
11651 }
11652 }
11653 if (current_param.guardInterval != operationParam->guardInterval) {
11654 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11655 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11656 return RETURN_ERR;
11657 }
11658 }
11659 if (current_param.transmitPower != operationParam->transmitPower) {
11660 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11661 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11662 return RETURN_ERR;
11663 }
11664 }
11665 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11666 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11667 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11668 return RETURN_ERR;
11669 }
11670 }
11671 if (current_param.obssCoex != operationParam->obssCoex) {
11672 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11673 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11674 return RETURN_ERR;
11675 }
11676 }
11677 if (current_param.stbcEnable != operationParam->stbcEnable) {
11678 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11679 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11680 return RETURN_ERR;
11681 }
11682 }
11683 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11684 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11685 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11686 return RETURN_ERR;
11687 }
11688 }
11689
11690 // if enable is true, then restart the radio
11691 wifi_setRadioEnable(index, FALSE);
11692 if (operationParam->enable == TRUE)
11693 wifi_setRadioEnable(index, TRUE);
11694 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11695
developer06a01d92022-09-07 16:32:39 +080011696 return RETURN_OK;
11697}
11698
11699INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11700{
developer1e5aa162022-09-13 16:06:24 +080011701 char band[64] = {0};
11702 char buf[256] = {0};
11703 char config_file[64] = {0};
11704 char cmd[128] = {0};
11705 int ret = RETURN_ERR;
11706 int mode = 0;
11707 ULONG channel = 0;
11708 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011709
11710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11711 printf("Entering %s index = %d\n", __func__, (int)index);
11712
developer1e5aa162022-09-13 16:06:24 +080011713 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11714 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11715 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011716 {
developer1e5aa162022-09-13 16:06:24 +080011717 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011718 return RETURN_ERR;
11719 }
11720 operationParam->enable = enabled;
11721
11722 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011723 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011724 {
developer1e5aa162022-09-13 16:06:24 +080011725 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011726 return RETURN_ERR;
11727 }
11728
11729 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011730 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011731 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011732 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011733 else if (!strcmp(band, "6GHz"))
11734 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011735 else
11736 {
developer1e5aa162022-09-13 16:06:24 +080011737 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011738 band);
11739 }
11740
developer1e5aa162022-09-13 16:06:24 +080011741 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11742 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11743 operationParam->channel = 0;
11744 operationParam->autoChannelEnabled = TRUE;
11745 } else {
11746 operationParam->channel = strtol(buf, NULL, 10);
11747 operationParam->autoChannelEnabled = FALSE;
11748 }
11749
developer06a01d92022-09-07 16:32:39 +080011750 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011751 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11752 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11753 return RETURN_ERR;
11754 }
developer06a01d92022-09-07 16:32:39 +080011755 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11756 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11757 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011758 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11759 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011760 else
11761 {
developer1e5aa162022-09-13 16:06:24 +080011762 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11763 return false;
developer06a01d92022-09-07 16:32:39 +080011764 }
11765
developer1e5aa162022-09-13 16:06:24 +080011766 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11767 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11768 return RETURN_ERR;
11769 }
11770 // Two different definition bit map, so need to check every bit.
11771 if (mode & WIFI_MODE_A)
11772 operationParam->variant |= WIFI_80211_VARIANT_A;
11773 if (mode & WIFI_MODE_B)
11774 operationParam->variant |= WIFI_80211_VARIANT_B;
11775 if (mode & WIFI_MODE_G)
11776 operationParam->variant |= WIFI_80211_VARIANT_G;
11777 if (mode & WIFI_MODE_N)
11778 operationParam->variant |= WIFI_80211_VARIANT_N;
11779 if (mode & WIFI_MODE_AC)
11780 operationParam->variant |= WIFI_80211_VARIANT_AC;
11781 if (mode & WIFI_MODE_AX)
11782 operationParam->variant |= WIFI_80211_VARIANT_AX;
11783 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11784 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11785 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011786 }
developer1e5aa162022-09-13 16:06:24 +080011787 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11788 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11789 return RETURN_ERR;
11790 }
11791 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11792 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11793 return RETURN_ERR;
11794 }
developer06a01d92022-09-07 16:32:39 +080011795
developer1e5aa162022-09-13 16:06:24 +080011796 memset(buf, 0, sizeof(buf));
11797 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11798 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11799 return RETURN_ERR;
11800 }
11801 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11802
11803 memset(buf, 0, sizeof(buf));
11804 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11805 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11806 return RETURN_ERR;
11807 }
11808 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11809
11810 memset(buf, 0, sizeof(buf));
11811 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11812 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11813
11814 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11815 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11816 return RETURN_ERR;
11817 }
11818 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11819 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11820 return RETURN_ERR;
11821 }
11822
11823 memset(buf, 0, sizeof(buf));
11824 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11825 if (strcmp(buf, "-1") == 0) {
11826 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11827 operationParam->ctsProtection = FALSE;
11828 } else {
11829 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11830 operationParam->ctsProtection = TRUE;
11831 }
11832
11833 memset(buf, 0, sizeof(buf));
11834 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11835 if (strcmp(buf, "0") == 0)
11836 operationParam->obssCoex = FALSE;
11837 else
11838 operationParam->obssCoex = TRUE;
11839
11840 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11841 _syscmd(cmd, buf, sizeof(buf));
11842 if (strlen(buf) != 0)
11843 operationParam->stbcEnable = TRUE;
11844 else
11845 operationParam->stbcEnable = FALSE;
11846
11847 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11848 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11849 return RETURN_ERR;
11850 }
11851
11852 // Below value is hardcoded
11853
11854 operationParam->numSecondaryChannels = 0;
11855 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11856 operationParam->channelSecondary[i] = 0;
11857 }
11858 operationParam->csa_beacon_count = 15;
11859 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011860
11861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11862 return RETURN_OK;
11863}
11864
11865static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11866{
developerc086fb72022-10-04 10:18:22 +080011867 int max_radio_num = 0;
11868
11869 wifi_getMaxRadioNumber(&max_radio_num);
11870 if (radioIndex >= max_radio_num || radioIndex < 0) {
11871 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11872 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011873 }
11874
developerc086fb72022-10-04 10:18:22 +080011875 return (arrayIndex * max_radio_num) + radioIndex;
11876}
developer06a01d92022-09-07 16:32:39 +080011877
developerc086fb72022-10-04 10:18:22 +080011878wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11879 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11880 return WIFI_BITRATE_1MBPS;
11881 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11882 return WIFI_BITRATE_2MBPS;
11883 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11884 return WIFI_BITRATE_5_5MBPS;
11885 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11886 return WIFI_BITRATE_6MBPS;
11887 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11888 return WIFI_BITRATE_9MBPS;
11889 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11890 return WIFI_BITRATE_11MBPS;
11891 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11892 return WIFI_BITRATE_12MBPS;
11893 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11894 return WIFI_BITRATE_18MBPS;
11895 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11896 return WIFI_BITRATE_24MBPS;
11897 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11898 return WIFI_BITRATE_36MBPS;
11899 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11900 return WIFI_BITRATE_48MBPS;
11901 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11902 return WIFI_BITRATE_54MBPS;
11903 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011904}
11905
developer1d57d002022-10-12 18:03:15 +080011906INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
11907{
11908 if (beacon == WIFI_BITRATE_1MBPS)
11909 strcpy(beacon_str, "1Mbps");
11910 else if (beacon == WIFI_BITRATE_2MBPS)
11911 strcpy(beacon_str, "2Mbps");
11912 else if (beacon == WIFI_BITRATE_5_5MBPS)
11913 strcpy(beacon_str, "5.5Mbps");
11914 else if (beacon == WIFI_BITRATE_6MBPS)
11915 strcpy(beacon_str, "6Mbps");
11916 else if (beacon == WIFI_BITRATE_9MBPS)
11917 strcpy(beacon_str, "9Mbps");
11918 else if (beacon == WIFI_BITRATE_11MBPS)
11919 strcpy(beacon_str, "11Mbps");
11920 else if (beacon == WIFI_BITRATE_12MBPS)
11921 strcpy(beacon_str, "12Mbps");
11922 else if (beacon == WIFI_BITRATE_18MBPS)
11923 strcpy(beacon_str, "18Mbps");
11924 else if (beacon == WIFI_BITRATE_24MBPS)
11925 strcpy(beacon_str, "24Mbps");
11926 else if (beacon == WIFI_BITRATE_36MBPS)
11927 strcpy(beacon_str, "36Mbps");
11928 else if (beacon == WIFI_BITRATE_48MBPS)
11929 strcpy(beacon_str, "48Mbps");
11930 else if (beacon == WIFI_BITRATE_54MBPS)
11931 strcpy(beacon_str, "54Mbps");
11932 return RETURN_OK;
11933}
11934
developer06a01d92022-09-07 16:32:39 +080011935INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11936{
developerc086fb72022-10-04 10:18:22 +080011937 INT mode = 0;
11938 INT ret = -1;
11939 INT output = 0;
11940 int i = 0;
11941 int vap_index = 0;
11942 BOOL enabled = FALSE;
11943 char buf[256] = {0};
11944 wifi_vap_security_t security;
11945 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011946
11947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11948 printf("Entering %s index = %d\n", __func__, (int)index);
11949
developer06a01d92022-09-07 16:32:39 +080011950 for (i = 0; i < 5; i++)
11951 {
developerc086fb72022-10-04 10:18:22 +080011952 map->vap_array[i].radio_index = index;
11953
developer06a01d92022-09-07 16:32:39 +080011954 vap_index = array_index_to_vap_index(index, i);
11955 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011956 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011957
developerc086fb72022-10-04 10:18:22 +080011958 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011959
11960 map->vap_array[i].vap_index = vap_index;
11961
11962 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011963 ret = wifi_getApName(vap_index, buf);
11964 if (ret != RETURN_OK) {
11965 printf("%s: wifi_getApName return error\n", __func__);
11966 return RETURN_ERR;
11967 }
11968 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
11969
11970 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080011971 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080011972 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080011973 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080011974 return RETURN_ERR;
11975 }
11976 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 +080011977
11978 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080011979 if (ret != RETURN_OK) {
11980 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011981 return RETURN_ERR;
11982 }
11983 map->vap_array[i].u.bss_info.enabled = enabled;
11984
developerc086fb72022-10-04 10:18:22 +080011985 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
11986 if (ret != RETURN_OK) {
11987 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
11988 return RETURN_ERR;
11989 }
developer06a01d92022-09-07 16:32:39 +080011990 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080011991
11992 ret = wifi_getApIsolationEnable(vap_index, &enabled);
11993 if (ret != RETURN_OK) {
11994 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
11995 return RETURN_ERR;
11996 }
11997 map->vap_array[i].u.bss_info.isolation = enabled;
11998
11999 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12000 if (ret != RETURN_OK) {
12001 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12002 return RETURN_ERR;
12003 }
12004 map->vap_array[i].u.bss_info.bssMaxSta = output;
12005
12006 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12007 if (ret != RETURN_OK) {
12008 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12009 return RETURN_ERR;
12010 }
12011 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012012
developerc086fb72022-10-04 10:18:22 +080012013 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12014 if (ret != RETURN_OK) {
12015 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12016 return RETURN_ERR;
12017 }
12018 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012019
developerc086fb72022-10-04 10:18:22 +080012020 ret = wifi_getApSecurity(vap_index, &security);
12021 if (ret != RETURN_OK) {
12022 printf("%s: wifi_getApSecurity return error\n", __func__);
12023 return RETURN_ERR;
12024 }
12025 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012026
developerc086fb72022-10-04 10:18:22 +080012027 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12028 if (ret != RETURN_OK) {
12029 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12030 return RETURN_ERR;
12031 }
12032 if (mode == 0)
12033 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12034 else
12035 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12036 if (mode == 1)
12037 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12038 else if (mode == 2)
12039 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012040
developerc086fb72022-10-04 10:18:22 +080012041 ret = wifi_getApWmmEnable(vap_index, &enabled);
12042 if (ret != RETURN_OK) {
12043 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12044 return RETURN_ERR;
12045 }
12046 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012047
developerc086fb72022-10-04 10:18:22 +080012048 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12049 if (ret != RETURN_OK) {
12050 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012051 return RETURN_ERR;
12052 }
developerc086fb72022-10-04 10:18:22 +080012053 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012054
12055 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012056 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012057 if (ret != RETURN_OK) {
12058 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12059 return RETURN_ERR;
12060 }
12061 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012062
developerc086fb72022-10-04 10:18:22 +080012063 memset(buf, 0, sizeof(buf));
12064 ret = wifi_getBaseBSSID(vap_index, buf);
12065 if (ret != RETURN_OK) {
12066 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12067 return RETURN_ERR;
12068 }
12069 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12070 &map->vap_array[i].u.bss_info.bssid[0],
12071 &map->vap_array[i].u.bss_info.bssid[1],
12072 &map->vap_array[i].u.bss_info.bssid[2],
12073 &map->vap_array[i].u.bss_info.bssid[3],
12074 &map->vap_array[i].u.bss_info.bssid[4],
12075 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012076 // fprintf(stderr, "%s index %d: mac: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", __func__, vap_index, map->vap_array[i].u.bss_info.bssid[0], map->vap_array[i].u.bss_info.bssid[1], map->vap_array[i].u.bss_info.bssid[2], map->vap_array[i].u.bss_info.bssid[3], map->vap_array[i].u.bss_info.bssid[4], map->vap_array[i].u.bss_info.bssid[5]);
12077
12078 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12079 if (ret != RETURN_OK) {
12080 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12081 return RETURN_ERR;
12082 }
12083 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012084
developerc086fb72022-10-04 10:18:22 +080012085 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012086 }
12087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12088 return RETURN_OK;
12089}
12090
12091INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12092{
12093 unsigned int i;
12094 wifi_vap_info_t *vap_info = NULL;
12095 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012096 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012097 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012098 char buf[256] = {0};
12099 char cmd[128] = {0};
12100 char config_file[64] = {0};
12101 char bssid[32] = {0};
12102 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012103
12104 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12105 printf("Entering %s index = %d\n", __func__, (int)index);
12106 for (i = 0; i < map->num_vaps; i++)
12107 {
developer1d57d002022-10-12 18:03:15 +080012108 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012109 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012110 if (vap_info->u.bss_info.enabled == FALSE)
12111 continue;
developer06a01d92022-09-07 16:32:39 +080012112
developer1d57d002022-10-12 18:03:15 +080012113 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12114
12115 // multi-ap need to copy current radio config
12116 if (vap_info->radio_index != vap_info->vap_index) {
12117 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12118 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012119 }
developer06a01d92022-09-07 16:32:39 +080012120
developer1d57d002022-10-12 18:03:15 +080012121 struct params params[3];
12122 snprintf(vap_info->vap_name, 64, "%s%d", AP_PREFIX, vap_info->vap_index);
12123 params[0].name = "interface";
12124 params[0].value = vap_info->vap_name;
12125 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12126 params[1].name = "bssid";
12127 params[1].value = bssid;
12128 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12129 params[2].name = "wpa_psk_file";
12130 params[2].value = psk_file;
12131
12132 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12133 wifi_hostapdWrite(config_file, params, 3);
12134
12135 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12136 _syscmd(cmd, buf, sizeof(buf));
12137
12138 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12139 if (ret != RETURN_OK) {
12140 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12141 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012142 }
developer1d57d002022-10-12 18:03:15 +080012143
12144 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12145 if (ret != RETURN_OK) {
12146 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12147 return RETURN_ERR;
12148 }
12149
12150 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12151 if (ret != RETURN_OK) {
12152 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12153 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012154 }
12155
developer1d57d002022-10-12 18:03:15 +080012156 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12157 if (ret != RETURN_OK) {
12158 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12159 return RETURN_ERR;
12160 }
developer06a01d92022-09-07 16:32:39 +080012161
developer1d57d002022-10-12 18:03:15 +080012162 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12163 if (ret != RETURN_OK) {
12164 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12165 return RETURN_ERR;
12166 }
developer06a01d92022-09-07 16:32:39 +080012167
developer1d57d002022-10-12 18:03:15 +080012168 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12169 if (ret != RETURN_OK) {
12170 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12171 return RETURN_ERR;
12172 }
12173
12174 if (vap_info->u.bss_info.mac_filter_enable == false)
12175 acl_mode = 0;
12176 else {
12177 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list)
12178 acl_mode = 2;
12179 else
12180 acl_mode = 1;
12181 }
12182
12183 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12184 if (ret != RETURN_OK) {
12185 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12186 return RETURN_ERR;
12187 }
12188
12189 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12190 if (ret != RETURN_OK) {
12191 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12192 return RETURN_ERR;
12193 }
12194
12195 memset(buf, 0, sizeof(buf));
12196 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12197 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12198 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12199 if (ret != RETURN_OK) {
12200 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12201 return RETURN_ERR;
12202 }
12203
12204 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12205 if (ret != RETURN_OK) {
12206 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12207 return RETURN_ERR;
12208 }
12209
12210 wifi_setApEnable(vap_info->vap_index, TRUE);
12211 multiple_set = FALSE;
12212
12213 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12214 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12215 if (ret != RETURN_OK) {
12216 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12217 return RETURN_ERR;
12218 }
12219
12220 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12221 if (ret != RETURN_OK) {
12222 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12223 return RETURN_ERR;
12224 }
developer06a01d92022-09-07 16:32:39 +080012225
developer1d57d002022-10-12 18:03:15 +080012226 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012227 }
12228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12229 return RETURN_OK;
12230}
12231
12232int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12233{
12234 char *token, *next;
12235 const char s[2] = ",";
12236 int count =0;
12237
12238 /* get the first token */
12239 token = strtok_r(pchannels, s, &next);
12240
12241 /* walk through other tokens */
12242 while( token != NULL && count < MAX_CHANNELS) {
12243 chlistptr->channels_list[count++] = atoi(token);
12244 token = strtok_r(NULL, s, &next);
12245 }
12246
12247 return count;
12248}
12249
12250static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12251{
12252 INT status;
12253 wifi_channels_list_t *chlistp;
12254 CHAR output_string[64];
12255 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012256 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012257 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012258
12259 if(rcap == NULL)
12260 {
12261 return RETURN_ERR;
12262 }
12263
12264 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012265 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012266
developer1e5aa162022-09-13 16:06:24 +080012267 if (band == band_2_4)
12268 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12269 else if (band == band_5)
12270 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12271 else if (band == band_6)
12272 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012273
12274 chlistp = &(rcap->channel_list[0]);
12275 memset(pchannels, 0, sizeof(pchannels));
12276
12277 /* possible number of radio channels */
12278 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12279 {
12280 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12281 }
12282 /* Number of channels and list*/
12283 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12284
12285 /* autoChannelSupported */
12286 /* always ON with wifi_getRadioAutoChannelSupported */
12287 rcap->autoChannelSupported = TRUE;
12288
12289 /* DCSSupported */
12290 /* always ON with wifi_getRadioDCSSupported */
12291 rcap->DCSSupported = TRUE;
12292
12293 /* zeroDFSSupported - TBD */
12294 rcap->zeroDFSSupported = FALSE;
12295
12296 /* Supported Country List*/
12297 memset(output_string, 0, sizeof(output_string));
12298 status = wifi_getRadioCountryCode(radioIndex, output_string);
12299 if( status != 0 ) {
12300 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12301 return RETURN_ERR;
12302 } else {
12303 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12304 }
12305 if(!strcmp(output_string,"US")){
12306 rcap->countrySupported[0] = wifi_countrycode_US;
12307 rcap->countrySupported[1] = wifi_countrycode_CA;
12308 } else if (!strcmp(output_string,"CA")) {
12309 rcap->countrySupported[0] = wifi_countrycode_CA;
12310 rcap->countrySupported[1] = wifi_countrycode_US;
12311 } else {
12312 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12313 }
12314
12315 rcap->numcountrySupported = 2;
12316
12317 /* csi */
12318 rcap->csi.maxDevices = 8;
12319 rcap->csi.soudingFrameSupported = TRUE;
12320
developer033b37b2022-10-18 11:27:46 +080012321 phyId = radio_index_to_phy(radioIndex);
12322 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012323
12324 /* channelWidth - all supported bandwidths */
12325 int i=0;
12326 rcap->channelWidth[i] = 0;
12327 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12328 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12329 WIFI_CHANNELBANDWIDTH_40MHZ);
12330
12331 }
developer1e5aa162022-09-13 16:06:24 +080012332 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012333 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12334 WIFI_CHANNELBANDWIDTH_40MHZ |
12335 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12336 }
12337
12338
12339 /* mode - all supported variants */
12340 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12341 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012342 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 +080012343 }
12344 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012345 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12346 }
12347 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12348 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012349 }
12350 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12351 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12352
12353 /* supportedBitRate - all supported bitrates */
12354 rcap->supportedBitRate[i] = 0;
12355 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12356 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12357 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12358 }
developer1e5aa162022-09-13 16:06:24 +080012359 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012360 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12361 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12362 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12363 }
12364
12365
12366 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12367 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12368 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12369 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12370 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12371 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12372 rcap->cipherSupported = 0;
12373 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12374 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12375
12376 return RETURN_OK;
12377}
12378
12379INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12380{
12381 INT status, radioIndex;
12382 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12383 int iter = 0;
12384 unsigned int j;
12385 wifi_interface_name_idex_map_t *iface_info;
12386
12387 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12388
12389 memset(cap, 0, sizeof(wifi_hal_capability_t));
12390
12391 /* version */
12392 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12393 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12394
12395 /* number of radios platform property */
12396 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12397 _syscmd(cmd, output, sizeof(output));
developer033b37b2022-10-18 11:27:46 +080012398 cap->wifi_prop.numRadios = atoi(output) > MAX_RADIOS ? MAX_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012399
12400 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12401 {
12402 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12403 if (status != 0) {
12404 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12405 return RETURN_ERR;
12406 }
12407
12408 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12409 {
developer033b37b2022-10-18 11:27:46 +080012410 if (iter >= MAX_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012411 {
12412 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12413 return RETURN_ERR;
12414 }
12415 iface_info = &cap->wifi_prop.interface_map[iter];
12416 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12417 iface_info->rdk_radio_index = radioIndex;
12418 memset(output, 0, sizeof(output));
12419 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12420 {
12421 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12422 }
12423 // TODO: bridge name
12424 // TODO: vlan id
12425 // TODO: primary
12426 iface_info->index = array_index_to_vap_index(radioIndex, j);
12427 memset(output, 0, sizeof(output));
12428 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12429 {
12430 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12431 }
12432 iter++;
12433 }
12434 }
12435
12436 cap->BandSteeringSupported = FALSE;
12437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12438 return RETURN_OK;
12439}
12440
developer9df4e652022-10-11 11:27:38 +080012441INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12442{
12443 struct params h_config={0};
12444 char config_file[64] = {0};
12445
12446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12447
12448 h_config.name = "okc";
12449 h_config.value = okc_enable?"1":"0";
12450
12451 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12452 wifi_hostapdWrite(config_file, &h_config, 1);
12453 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12454
12455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12456 return RETURN_OK;
12457}
12458
12459INT wifi_setSAEMFP(int ap_index, BOOL enable)
12460{
12461 struct params h_config={0};
12462 char config_file[64] = {0};
12463 char buf[128] = {0};
12464
12465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12466
12467 h_config.name = "sae_require_mfp";
12468 h_config.value = enable?"1":"0";
12469
12470 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12471 wifi_hostapdWrite(config_file, &h_config, 1);
12472 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12473
12474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12475 return RETURN_OK;
12476}
12477
12478INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12479{
12480 struct params h_config={0};
12481 char config_file[64] = {0};
12482 char buf[128] = {0};
12483
12484 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12485
12486 h_config.name = "sae_pwe";
12487 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12488 h_config.value = buf;
12489
12490 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12491 wifi_hostapdWrite(config_file, &h_config, 1);
12492 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12493
12494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12495 return RETURN_OK;
12496}
12497
12498INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12499{
12500 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12501 struct params h_config={0};
12502 char config_file[64] = {0};
12503
12504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12505
12506 h_config.name = "wpa_disable_eapol_key_retries";
12507 h_config.value = disable_EAPOL_retries?"1":"0";
12508
12509 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12510 wifi_hostapdWrite(config_file, &h_config, 1);
12511 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12512
12513 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12514 return RETURN_OK;
12515}
12516
developer06a01d92022-09-07 16:32:39 +080012517INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12518{
developer587c1b62022-09-27 15:58:59 +080012519 char buf[128] = {0};
12520 char config_file[128] = {0};
12521 char password[64] = {0};
12522 char mfp[32] = {0};
12523 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012524 BOOL okc_enable = FALSE;
12525 BOOL sae_MFP = FALSE;
12526 BOOL disable_EAPOL_retries = TRUE;
12527 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012528 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012529 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012530
12531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12532
12533 multiple_set = TRUE;
12534 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12535 if (security->mode == wifi_security_mode_none) {
12536 strcpy(wpa_mode, "None");
12537 } else if (security->mode == wifi_security_mode_wpa_personal)
12538 strcpy(wpa_mode, "WPA-Personal");
12539 else if (security->mode == wifi_security_mode_wpa2_personal)
12540 strcpy(wpa_mode, "WPA2-Personal");
12541 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12542 strcpy(wpa_mode, "WPA-WPA2-Personal");
12543 else if (security->mode == wifi_security_mode_wpa_enterprise)
12544 strcpy(wpa_mode, "WPA-Enterprise");
12545 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12546 strcpy(wpa_mode, "WPA2-Enterprise");
12547 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12548 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012549 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012550 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012551 okc_enable = TRUE;
12552 sae_MFP = TRUE;
12553 sae_pwe = 2;
12554 disable_EAPOL_retries = FALSE;
12555 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012556 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012557 okc_enable = TRUE;
12558 sae_MFP = TRUE;
12559 sae_pwe = 2;
12560 disable_EAPOL_retries = FALSE;
12561 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012562 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012563 sae_MFP = TRUE;
12564 sae_pwe = 2;
12565 disable_EAPOL_retries = FALSE;
12566 }
12567
12568 band = wifi_index_to_band(ap_index);
12569 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12570 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12571 return RETURN_ERR;
12572 }
developer587c1b62022-09-27 15:58:59 +080012573
12574 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012575 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012576 wifi_setSAEMFP(ap_index, sae_MFP);
12577 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012578 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012579
developer9df4e652022-10-11 11:27:38 +080012580 if (security->mode != wifi_security_mode_none) {
12581 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12582 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12583 password[63] = '\0';
12584 wifi_setApSecurityKeyPassphrase(ap_index, password);
12585 }
12586 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12587 params.name = "sae_password";
12588 params.value = security->u.key.key;
12589 wifi_hostapdWrite(config_file, &params, 1);
12590 }
12591 }
developer587c1b62022-09-27 15:58:59 +080012592
12593 if (security->mode != wifi_security_mode_none) {
12594 memset(&params, 0, sizeof(params));
12595 params.name = "wpa_pairwise";
12596 if (security->encr == wifi_encryption_tkip)
12597 params.value = "TKIP";
12598 else if (security->encr == wifi_encryption_aes)
12599 params.value = "CCMP";
12600 else if (security->encr == wifi_encryption_aes_tkip)
12601 params.value = "TKIP CCMP";
12602 wifi_hostapdWrite(config_file, &params, 1);
12603 }
12604
12605 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012606 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012607 else if (security->mfp == wifi_mfp_cfg_optional)
12608 strcpy(mfp, "Optional");
12609 else if (security->mfp == wifi_mfp_cfg_required)
12610 strcpy(mfp, "Required");
12611 wifi_setApSecurityMFPConfig(ap_index, mfp);
12612
12613 memset(&params, 0, sizeof(params));
12614 params.name = "transition_disable";
12615 if (security->wpa3_transition_disable == TRUE)
12616 params.value = "0x01";
12617 else
12618 params.value = "0x00";
12619 wifi_hostapdWrite(config_file, &params, 1);
12620
12621 memset(&params, 0, sizeof(params));
12622 params.name = "wpa_group_rekey";
12623 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12624 params.value = buf;
12625 wifi_hostapdWrite(config_file, &params, 1);
12626
12627 memset(&params, 0, sizeof(params));
12628 params.name = "wpa_strict_rekey";
12629 params.value = security->strict_rekey?"1":"0";
12630 wifi_hostapdWrite(config_file, &params, 1);
12631
12632 memset(&params, 0, sizeof(params));
12633 params.name = "wpa_pairwise_update_count";
12634 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12635 params.value = buf;
12636 wifi_hostapdWrite(config_file, &params, 1);
12637
12638 memset(&params, 0, sizeof(params));
12639 params.name = "disable_pmksa_caching";
12640 params.value = security->disable_pmksa_caching?"1":"0";
12641 wifi_hostapdWrite(config_file, &params, 1);
12642
12643 wifi_setApEnable(ap_index, FALSE);
12644 wifi_setApEnable(ap_index, TRUE);
12645
12646 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12647
developer06a01d92022-09-07 16:32:39 +080012648 return RETURN_OK;
12649}
12650
12651INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12652{
developer9df4e652022-10-11 11:27:38 +080012653 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012654 char config_file[128] = {0};
12655 int disable = 0;
12656 // struct params params = {0};
12657
12658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12659 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12660 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12661 security->mode = wifi_security_mode_none;
12662 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012663 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012664 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012665 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012666 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012667 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012668 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012669 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012670 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012671 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012672 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012673 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012674 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012675 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012676 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012677 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012678 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012679 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012680 security->mode = wifi_security_mode_wpa3_enterprise;
12681 }
12682
12683 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12684 if (security->mode == wifi_security_mode_none)
12685 security->encr = wifi_encryption_none;
12686 else {
12687 if (strcmp(buf, "TKIP") == 0)
12688 security->encr = wifi_encryption_tkip;
12689 else if (strcmp(buf, "CCMP") == 0)
12690 security->encr = wifi_encryption_aes;
12691 else
12692 security->encr = wifi_encryption_aes_tkip;
12693 }
12694
developer9df4e652022-10-11 11:27:38 +080012695 if (security->mode != wifi_encryption_none) {
12696 memset(buf, 0, sizeof(buf));
12697 // wpa3 can use one or both configs as password, so we check sae_password first.
12698 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12699 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12700 security->u.key.type = wifi_security_key_type_sae;
12701 } else {
12702 security->u.key.type = wifi_security_key_type_psk;
12703 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12704 }
12705 strncpy(security->u.key.key, buf, sizeof(buf));
12706 security->u.key.key[255] = '\0';
12707 }
12708
developer587c1b62022-09-27 15:58:59 +080012709 memset(buf, 0, sizeof(buf));
12710 wifi_getApSecurityMFPConfig(ap_index, buf);
12711 if (strcmp(buf, "Disabled") == 0)
12712 security->mfp = wifi_mfp_cfg_disabled;
12713 else if (strcmp(buf, "Optional") == 0)
12714 security->mfp = wifi_mfp_cfg_optional;
12715 else if (strcmp(buf, "Required") == 0)
12716 security->mfp = wifi_mfp_cfg_required;
12717
12718 memset(buf, 0, sizeof(buf));
12719 security->wpa3_transition_disable = FALSE;
12720 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12721 disable = strtol(buf, NULL, 16);
12722 if (disable != 0)
12723 security->wpa3_transition_disable = TRUE;
12724
12725 memset(buf, 0, sizeof(buf));
12726 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12727 if (strlen(buf) == 0)
12728 security->rekey_interval = 86400;
12729 else
12730 security->rekey_interval = strtol(buf, NULL, 10);
12731
12732 memset(buf, 0, sizeof(buf));
12733 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12734 if (strlen(buf) == 0)
12735 security->strict_rekey = 1;
12736 else
12737 security->strict_rekey = strtol(buf, NULL, 10);
12738
12739 memset(buf, 0, sizeof(buf));
12740 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12741 if (strlen(buf) == 0)
12742 security->eapol_key_retries = 4;
12743 else
12744 security->eapol_key_retries = strtol(buf, NULL, 10);
12745
12746 memset(buf, 0, sizeof(buf));
12747 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12748 if (strlen(buf) == 0)
12749 security->disable_pmksa_caching = FALSE;
12750 else
12751 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12752
12753 /* TODO
12754 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12755 */
12756 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12757 security->eap_identity_req_timeout = 0;
12758 security->eap_identity_req_retries = 0;
12759 security->eap_req_timeout = 0;
12760 security->eap_req_retries = 0;
12761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012762 return RETURN_OK;
12763}
12764
12765#endif /* WIFI_HAL_VERSION_3 */
12766
12767#ifdef WIFI_HAL_VERSION_3_PHASE2
12768INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12769{
developer13df9332022-09-27 16:53:22 +080012770 char cmd[128] = {0};
12771 char buf[128] = {0};
12772 char *mac_addr = NULL;
12773 BOOL status = FALSE;
12774 size_t len = 0;
12775
12776 if(ap_index > MAX_APS)
12777 return RETURN_ERR;
12778
12779 *output_numDevices = 0;
12780 wifi_getApEnable(ap_index, &status);
12781 if (status == FALSE)
12782 return RETURN_OK;
12783
12784 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12785 _syscmd(cmd, buf, sizeof(buf));
12786
12787 mac_addr = strtok(buf, "\n");
12788 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12789 *output_numDevices = i + 1;
12790 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12791 addr_ptr = output_deviceMacAddressArray[i];
12792 mac_addr_aton(addr_ptr, mac_addr);
12793 mac_addr = strtok(NULL, "\n");
12794 }
12795
12796 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012797}
12798#else
12799INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12800{
12801 char cmd[128];
12802 BOOL status = false;
12803
12804 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12805 return RETURN_ERR;
12806
12807 output_buf[0] = '\0';
12808
12809 wifi_getApEnable(ap_index,&status);
12810 if (!status)
12811 return RETURN_OK;
12812
12813 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12814 _syscmd(cmd, output_buf, output_buf_size);
12815
12816 return RETURN_OK;
12817}
12818#endif
developer2f513ab2022-09-13 14:26:06 +080012819
12820INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12821{
12822 char output[16]={'\0'};
12823 char config_file[MAX_BUF_SIZE] = {0};
12824
12825 if (!enable)
12826 return RETURN_ERR;
12827
12828 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12829 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12830
12831 if (strlen(output) == 0)
12832 *enable = FALSE;
12833 else if (strncmp(output, "1", 1) == 0)
12834 *enable = TRUE;
12835 else
12836 *enable = FALSE;
12837
12838 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12839 return RETURN_OK;
12840}
developer2d9c30f2022-09-13 15:06:14 +080012841
12842INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12843{
developer033b37b2022-10-18 11:27:46 +080012844 if (NULL == output_enable || radioIndex >=MAX_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080012845 return RETURN_ERR;
12846 *output_enable=TRUE;
12847 return RETURN_OK;
12848}
developerfd7d2892022-09-13 16:44:53 +080012849
12850INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12851{
12852 char cmd[128] = {0};
12853 char buf[128] = {0};
12854 char line[128] = {0};
12855 size_t len = 0;
12856 ssize_t read = 0;
12857 FILE *f = NULL;
12858 int index = 0;
12859 int exp = 0;
12860 int mantissa = 0;
12861 int duration = 0;
12862 int radio_index = 0;
12863 int max_radio_num = 0;
12864 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080012865 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080012866 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12867
12868 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080012869
developerfd7d2892022-09-13 16:44:53 +080012870 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080012871
12872 phyId = radio_index_to_phy(radio_index);
12873 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080012874 _syscmd(cmd, buf, sizeof(buf));
12875 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12876 if (*numSessionReturned > maxNumberSessions)
12877 *numSessionReturned = maxNumberSessions;
12878 else if (*numSessionReturned < 1) {
12879 *numSessionReturned = 0;
12880 return RETURN_OK;
12881 }
12882
developer033b37b2022-10-18 11:27:46 +080012883 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
developerfd7d2892022-09-13 16:44:53 +080012884 if ((f = popen(cmd, "r")) == NULL) {
12885 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12886 return RETURN_ERR;
12887 }
12888
12889 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12890 while((read = fgets(line, sizeof(line), f)) != NULL) {
12891 char *tmp = NULL;
12892 strcpy(buf, line);
12893 tmp = strtok(buf, " ");
12894 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12895 tmp = strtok(NULL, " ");
12896 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12897 tmp = strtok(NULL, " ");
12898 if (strstr(tmp, "t")) {
12899 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12900 }
12901 if (strstr(tmp, "a")) {
12902 twtSessions[index].twtParameters.operation.announced = TRUE;
12903 }
12904 tmp = strtok(NULL, " ");
12905 exp = strtol(tmp, NULL, 10);
12906 tmp = strtok(NULL, " ");
12907 mantissa = strtol(tmp, NULL, 10);
12908 tmp = strtok(NULL, " ");
12909 duration = strtol(tmp, NULL, 10);
12910
12911 // only implicit supported
12912 twtSessions[index].twtParameters.operation.implicit = TRUE;
12913 // only individual agreement supported
12914 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12915
12916 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12917 twt_wake_interval = mantissa * (1 << exp);
12918 if (twt_wake_interval/mantissa != (1 << exp)) {
12919 // Overflow handling
12920 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12921 } else {
12922 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12923 }
12924 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12925 index++;
12926 }
12927
12928 pclose(f);
12929 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12930 return RETURN_OK;
12931}