blob: e03e332aa0b621b9ba41cbefb9ea50ccbe7919e7 [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"
developer454b9462022-09-13 15:29:16 +080077#define GUARD_INTERVAL_FILE "/tmp/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"
developer454b9462022-09-13 15:29:16 +080083
developer06a01d92022-09-07 16:32:39 +080084#define DRIVER_2GHZ "ath9k"
85#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080086#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080087
88/*
89 MAX_APS - Number of all AP available in system
90 2x Home AP
91 2x Backhaul AP
92 2x Guest AP
93 2x Secure Onboard AP
94 2x Service AP
95
96*/
97#define MAX_APS 10
98#define NUMBER_OF_RADIOS 2
99
100#ifndef AP_PREFIX
101#define AP_PREFIX "wifi"
102#endif
103
104#ifndef RADIO_PREFIX
105#define RADIO_PREFIX "wlan"
106#endif
107
108#define MAX_BUF_SIZE 128
109#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800110#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800111
112//Uncomment to enable debug logs
113//#define WIFI_DEBUG
114
115#ifdef WIFI_DEBUG
116#define wifi_dbg_printf printf
117#define WIFI_ENTRY_EXIT_DEBUG printf
118#else
119#define wifi_dbg_printf(format, args...) printf("")
120#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
121#endif
122
123#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
124#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
125#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
126#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
127#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
128#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
129#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
130#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
131#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
132#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
133
134#define HOSTAPD_HT_CAPAB_20 "[SHORT-GI-20]"
135#define HOSTAPD_HT_CAPAB_40 "[SHORT-GI-20][SHORT-GI-40]"
136
137#define BW_FNAME "/nvram/bw_file.txt"
138
139#define PS_MAX_TID 16
140
141static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
142 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
143 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
144 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
146 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
147 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
148 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
149 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
150 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
151 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
152 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
153 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
154 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
155 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
156 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
157 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
158};
159
160typedef unsigned long long u64;
161
162/* Enum to define WiFi Bands */
163typedef enum
164{
165 band_invalid = -1,
166 band_2_4 = 0,
167 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800168 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800169} wifi_band;
170
developerdb744382022-09-13 15:34:54 +0800171typedef enum {
172 WIFI_MODE_A = 0x01,
173 WIFI_MODE_B = 0x02,
174 WIFI_MODE_G = 0x04,
175 WIFI_MODE_N = 0x08,
176 WIFI_MODE_AC = 0x10,
177 WIFI_MODE_AX = 0x20,
178} wifi_ieee80211_Mode;
179
developer06a01d92022-09-07 16:32:39 +0800180#ifdef WIFI_HAL_VERSION_3
181
182// Return number of elements in array
183#ifndef ARRAY_SIZE
184#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
185#endif /* ARRAY_SIZE */
186
187#ifndef ARRAY_AND_SIZE
188#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
189#endif /* ARRAY_AND_SIZE */
190
191#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
192
193typedef struct {
194 int32_t value;
195 int32_t param;
196 intptr_t key;
197 intptr_t data;
198} wifi_secur_list;
199
200wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
201wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
202char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
203
204static wifi_secur_list map_security[] =
205{
206 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
207 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
208 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
215};
216
217wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
218{
219 wifi_secur_list *item;
220 int i;
221
222 for (item = list,i = 0;i < list_sz; item++, i++) {
223 if ((int)(item->key) == key) {
224 return item;
225 }
226 }
227
228 return NULL;
229}
230
231char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
232{
233 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
234
235 if (!item) {
236 return "";
237 }
238
239 return (char *)(item->data);
240}
241
242wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
243{
244 wifi_secur_list *item;
245 int i;
246
247 for (item = list,i = 0;i < list_sz; item++, i++) {
248 if (strcmp((char *)(item->data), str) == 0) {
249 return item;
250 }
251 }
252
253 return NULL;
254}
255#endif /* WIFI_HAL_VERSION_3 */
256
257#ifdef HAL_NETLINK_IMPL
258typedef struct {
259 int id;
260 struct nl_sock* socket;
261 struct nl_cb* cb;
262} Netlink;
263
264static int mac_addr_aton(unsigned char *mac_addr, char *arg)
265{
266 unsigned int mac_addr_int[6]={};
267 sscanf(arg, "%x:%x:%x:%x:%x:%x", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
268 mac_addr[0] = mac_addr_int[0];
269 mac_addr[1] = mac_addr_int[1];
270 mac_addr[2] = mac_addr_int[2];
271 mac_addr[3] = mac_addr_int[3];
272 mac_addr[4] = mac_addr_int[4];
273 mac_addr[5] = mac_addr_int[5];
274 return 0;
275}
276
277static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
278{
279 unsigned int mac_addr_int[6]={};
280 mac_addr_int[0] = arg[0];
281 mac_addr_int[1] = arg[1];
282 mac_addr_int[2] = arg[2];
283 mac_addr_int[3] = arg[3];
284 mac_addr_int[4] = arg[4];
285 mac_addr_int[5] = arg[5];
286 snprintf(mac_addr, 20, "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
287 return;
288}
289
290static int ieee80211_frequency_to_channel(int freq)
291{
292 if (freq == 2484)
293 return 14;
294 else if (freq < 2484)
295 return (freq - 2407) / 5;
296 else if (freq >= 4910 && freq <= 4980)
297 return (freq - 4000) / 5;
298 else if (freq <= 45000)
299 return (freq - 5000) / 5;
300 else if (freq >= 58320 && freq <= 64800)
301 return (freq - 56160) / 2160;
302 else
303 return 0;
304}
305
306static int initSock80211(Netlink* nl) {
307 nl->socket = nl_socket_alloc();
308 if (!nl->socket) {
309 fprintf(stderr, "Failing to allocate the sock\n");
310 return -ENOMEM;
311 }
312
313 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
314
315 if (genl_connect(nl->socket)) {
316 fprintf(stderr, "Failed to connect\n");
317 nl_close(nl->socket);
318 nl_socket_free(nl->socket);
319 return -ENOLINK;
320 }
321
322 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
323 if (nl->id< 0) {
324 fprintf(stderr, "interface not found.\n");
325 nl_close(nl->socket);
326 nl_socket_free(nl->socket);
327 return -ENOENT;
328 }
329
330 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
331 if ((!nl->cb)) {
332 fprintf(stderr, "Failed to allocate netlink callback.\n");
333 nl_close(nl->socket);
334 nl_socket_free(nl->socket);
335 return ENOMEM;
336 }
337
338 return nl->id;
339}
340
341static int nlfree(Netlink *nl)
342{
343 nl_cb_put(nl->cb);
344 nl_close(nl->socket);
345 nl_socket_free(nl->socket);
346 return 0;
347}
348
349static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
350 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
351 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
352 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
353};
354
355static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
356};
357
358static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
359};
360
361typedef struct _wifi_channelStats_loc {
362 INT array_size;
363 INT ch_number;
364 BOOL ch_in_pool;
365 INT ch_noise;
366 BOOL ch_radar_noise;
367 INT ch_max_80211_rssi;
368 INT ch_non_80211_noise;
369 INT ch_utilization;
370 ULLONG ch_utilization_total;
371 ULLONG ch_utilization_busy;
372 ULLONG ch_utilization_busy_tx;
373 ULLONG ch_utilization_busy_rx;
374 ULLONG ch_utilization_busy_self;
375 ULLONG ch_utilization_busy_ext;
376} wifi_channelStats_t_loc;
377
378typedef struct wifi_device_info {
379 INT wifi_devIndex;
380 UCHAR wifi_devMacAddress[6];
381 CHAR wifi_devIPAddress[64];
382 BOOL wifi_devAssociatedDeviceAuthentiationState;
383 INT wifi_devSignalStrength;
384 INT wifi_devTxRate;
385 INT wifi_devRxRate;
386} wifi_device_info_t;
387
388#endif
389
390//For 5g Alias Interfaces
391static BOOL priv_flag = TRUE;
392static BOOL pub_flag = TRUE;
393static BOOL Radio_flag = TRUE;
394//wifi_setApBeaconRate(1, beaconRate);
395
396struct params
397{
398 char * name;
399 char * value;
400};
401
402static int _syscmd(char *cmd, char *retBuf, int retBufSize)
403{
404 FILE *f;
405 char *ptr = retBuf;
406 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
407
408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
409 if((f = popen(cmd, "r")) == NULL) {
410 fprintf(stderr,"\npopen %s error\n", cmd);
411 return RETURN_ERR;
412 }
413
414 while(!feof(f))
415 {
416 *ptr = 0;
417 if(bufSize>=128) {
418 bufbytes=128;
419 } else {
420 bufbytes=bufSize-1;
421 }
422
423 fgets(ptr,bufbytes,f);
424 readbytes=strlen(ptr);
425
426 if(!readbytes)
427 break;
428
429 bufSize-=readbytes;
430 ptr += readbytes;
431 }
432 cmd_ret = pclose(f);
433 retBuf[retBufSize-1]=0;
434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
435
436 return cmd_ret >> 8;
437}
438
developerc707e972022-09-13 15:38:02 +0800439wifi_band wifi_index_to_band(int apIndex)
440{
441 char cmd[128] = {0};
442 char buf[64] = {0};
443 int freq = 0;
444 wifi_band band = band_invalid;
445
446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
447 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
448 _syscmd(cmd, buf, sizeof(buf));
449 freq = strtol(buf, NULL, 10);
450 if (freq > 2401 && freq < 2495)
451 band = band_2_4;
452 else if (freq > 5160 && freq < 5915)
453 band = band_5;
454 else if (freq > 5955 && freq < 7125)
455 band = band_6;
456
457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
458 return band;
459}
460
developer06a01d92022-09-07 16:32:39 +0800461static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
462{
463 char cmd[MAX_CMD_SIZE]={'\0'};
464 char buf[MAX_BUF_SIZE]={'\0'};
465 int ret = 0;
466
467 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
468 ret = _syscmd(cmd, buf, sizeof(buf));
469 if ((ret != 0) && (strlen(buf) == 0))
470 return -1;
471 snprintf(output, output_size, "%s", buf);
472
473 return 0;
474}
475
476static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
477{
478 char cmd[MAX_CMD_SIZE]={'\0'};
479 char buf[MAX_BUF_SIZE]={'\0'};
480
481 for(int i=0;i<item_count;i++)
482 {
483 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
484 if (strlen(buf) == 0) //Insert
485 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
486 else //Update
487 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
488 if(_syscmd(cmd, buf, sizeof(buf)))
489 return -1;
490 }
491
492 return 0;
493}
494
495static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
496{
497 char cmd[MAX_CMD_SIZE]="", output[32]="";
498 FILE *fp;
499 int i;
500 //NOTE RELOAD should be done in ApplySSIDSettings
501
502 for(i=0; i<item_count; i++, list++)
503 {
504 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
505 if((fp = popen(cmd, "r"))==NULL)
506 {
507 perror("popen failed");
508 return -1;
509 }
510 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
511 {
512 pclose(fp);
513 perror("fgets failed");
514 return -1;
515 }
516 pclose(fp);
517 }
518 return 0;
519}
520
521static int wifi_reloadAp(int apIndex)
522{
523 char cmd[MAX_CMD_SIZE]="";
524 char buf[MAX_BUF_SIZE]="";
525
526 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
527 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
528 return RETURN_ERR;
529
530 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
531 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
532 return RETURN_ERR;
533
534 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
535 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
536 return RETURN_ERR;
537
538 return RETURN_OK;
539}
540
541
542//For Getting Current Interface Name from corresponding hostapd configuration
543void GetInterfaceName(char *interface_name, char *conf_file)
544{
545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
546 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
548}
549
550INT File_Reading(CHAR *file, char *Value)
551{
552 FILE *fp = NULL;
553 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
554 int count = 0;
555
556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
557 fp = popen(file,"r");
558 if(fp == NULL)
559 return RETURN_ERR;
560
561 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
562 {
563 for(count=0;buf[count]!='\n';count++)
564 copy_buf[count]=buf[count];
565 copy_buf[count]='\0';
566 }
567 strcpy(Value,copy_buf);
568 pclose(fp);
569 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
570
571 return RETURN_OK;
572}
573
574void wifi_RestartHostapd_2G()
575{
576 int Public2GApIndex = 4;
577
578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
579 wifi_setApEnable(Public2GApIndex, FALSE);
580 wifi_setApEnable(Public2GApIndex, TRUE);
581 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
582}
583
584void wifi_RestartHostapd_5G()
585{
586 int Public5GApIndex = 5;
587
588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
589 wifi_setApEnable(Public5GApIndex, FALSE);
590 wifi_setApEnable(Public5GApIndex, TRUE);
591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
592}
593
594void wifi_RestartPrivateWifi_2G()
595{
596 int PrivateApIndex = 0;
597
598 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
599 wifi_setApEnable(PrivateApIndex, FALSE);
600 wifi_setApEnable(PrivateApIndex, TRUE);
601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
602}
603
604void wifi_RestartPrivateWifi_5G()
605{
606 int Private5GApIndex = 1;
607
608 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
609 wifi_setApEnable(Private5GApIndex, FALSE);
610 wifi_setApEnable(Private5GApIndex, TRUE);
611 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
612}
613
614static int writeBandWidth(int radioIndex,char *bw_value)
615{
616 char buf[MAX_BUF_SIZE];
617 char cmd[MAX_CMD_SIZE];
618
619 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
620 if(_syscmd(cmd, buf, sizeof(buf)))
621 {
622 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
623 _syscmd(cmd, buf, sizeof(buf));
624 return RETURN_OK;
625 }
626
627 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
628 _syscmd(cmd,buf,sizeof(buf));
629 return RETURN_OK;
630}
631
632static int readBandWidth(int radioIndex,char *bw_value)
633{
634 char buf[MAX_BUF_SIZE];
635 char cmd[MAX_CMD_SIZE];
636 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
637 _syscmd(cmd,buf,sizeof(buf));
638 if(NULL!=strstr(buf,"20MHz"))
639 {
640 strcpy(bw_value,"20MHz");
641 }
642 else if(NULL!=strstr(buf,"40MHz"))
643 {
644 strcpy(bw_value,"40MHz");
645 }
646 else if(NULL!=strstr(buf,"80MHz"))
647 {
648 strcpy(bw_value,"80MHz");
649 }
650 else
651 {
652 return RETURN_ERR;
653 }
654 return RETURN_OK;
655}
656
developer5f222492022-09-13 15:21:52 +0800657// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800658INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
659{
developer5f222492022-09-13 15:21:52 +0800660 struct params params={'\0'};
661 char config_file[MAX_BUF_SIZE] = {0};
662 char buf[MAX_BUF_SIZE] = {'\0'};
663
664 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
665 if (strlen (beaconRate) < 5)
666 return RETURN_ERR;
667 // Copy the numeric value
668 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
669 buf[strlen(beaconRate) - 4] = '\0';
670
671 params.name = "beacon_rate";
672 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
673 if (strncmp(buf, "5.5", 3) == 0) {
674 snprintf(buf, sizeof(buf), "55");
675 params.value = buf;
676 } else {
677 strcat(buf, "0");
678 params.value = buf;
679 }
680
681 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
682 wifi_hostapdWrite(config_file, &params, 1);
683 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
684 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
685
686 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800687}
688
689INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
690{
developer5f222492022-09-13 15:21:52 +0800691 char config_file[MAX_BUF_SIZE] = {'\0'};
692 char temp_output[MAX_BUF_SIZE] = {'\0'};
693 char buf[MAX_BUF_SIZE] = {'\0'};
694 float rate = 0;
695
696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
697 if (NULL == beaconRate)
698 return RETURN_ERR;
699
700 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
701 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
702 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
703 if(strlen(buf) > 0) {
704 rate = atof(buf)/10;
705 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
706 } else {
707 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
708 }
709 strncpy(beaconRate, temp_output, sizeof(temp_output));
710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
711
712 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800713}
714
715INT wifi_setLED(INT radioIndex, BOOL enable)
716{
717 return 0;
718}
719INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
720{
721 return RETURN_OK;
722}
723/**********************************************************************************
724 *
725 * Wifi Subsystem level function prototypes
726 *
727**********************************************************************************/
728//---------------------------------------------------------------------------------------------------
729//Wifi system api
730//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
731INT wifi_getHalVersion(CHAR *output_string) //RDKB
732{
733 if(!output_string)
734 return RETURN_ERR;
735 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
736
737 return RETURN_OK;
738}
739
740
741/* wifi_factoryReset() function */
742/**
743* @description Clears internal variables to implement a factory reset of the Wi-Fi
744* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
745*
746* @param None
747*
748* @return The status of the operation.
749* @retval RETURN_OK if successful.
750* @retval RETURN_ERR if any error is detected
751*
752* @execution Synchronous
753* @sideeffect None
754*
755* @note This function must not suspend and must not invoke any blocking system
756* calls. It should probably just send a message to a driver event handler task.
757*
758*/
759INT wifi_factoryReset()
760{
761 char cmd[128];
762
763 /*delete running hostapd conf files*/
764 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
765 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
766 system(cmd);
767 system("systemctl restart hostapd.service");
768
769 return RETURN_OK;
770}
771
772/* wifi_factoryResetRadios() function */
773/**
774* @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.
775*
776* @param None
777* @return The status of the operation
778* @retval RETURN_OK if successful
779* @retval RETURN_ERR if any error is detected
780*
781* @execution Synchronous
782*
783* @sideeffect None
784*
785* @note This function must not suspend and must not invoke any blocking system
786* calls. It should probably just send a message to a driver event handler task.
787*
788*/
789INT wifi_factoryResetRadios()
790{
791 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
792 return RETURN_OK;
793
794 return RETURN_ERR;
795}
796
797
798/* wifi_factoryResetRadio() function */
799/**
800* @description Restore selected radio parameters without touching access point parameters
801*
802* @param radioIndex - Index of Wi-Fi Radio channel
803*
804* @return The status of the operation.
805* @retval RETURN_OK if successful.
806* @retval RETURN_ERR if any error is detected
807*
808* @execution Synchronous.
809* @sideeffect None.
810*
811* @note This function must not suspend and must not invoke any blocking system
812* calls. It should probably just send a message to a driver event handler task.
813*
814*/
815INT wifi_factoryResetRadio(int radioIndex) //RDKB
816{
developer5ff7f5f2022-09-13 15:12:16 +0800817 system("systemctl stop hostapd.service");
818
developer06a01d92022-09-07 16:32:39 +0800819 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
820 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800821 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800822 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800823 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800824 else
825 return RETURN_ERR;
826
developer5ff7f5f2022-09-13 15:12:16 +0800827 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800828 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
829 return RETURN_OK;
830}
831
832/* wifi_initRadio() function */
833/**
834* Description: This function call initializes the specified radio.
835* Implementation specifics may dictate the functionality since
836* different hardware implementations may have different initilization requirements.
837* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
838*
839* @return The status of the operation.
840* @retval RETURN_OK if successful.
841* @retval RETURN_ERR if any error is detected
842*
843* @execution Synchronous.
844* @sideeffect None.
845*
846* @note This function must not suspend and must not invoke any blocking system
847* calls. It should probably just send a message to a driver event handler task.
848*
849*/
850INT wifi_initRadio(INT radioIndex)
851{
852 //TODO: Initializes the wifi subsystem (for specified radio)
853 return RETURN_OK;
854}
855void macfilter_init()
856{
857 char count[4]={'\0'};
858 char buf[253]={'\0'};
859 char tmp[19]={'\0'};
860 int dev_count,block,mac_entry=0;
861 char res[4]={'\0'};
862 char acl_file_path[64] = {'\0'};
863 FILE *fp = NULL;
864 int index=0;
865 char iface[10]={'\0'};
866 char config_file[MAX_BUF_SIZE] = {0};
867
868
869 sprintf(acl_file_path,"/tmp/mac_filter.sh");
870
871 fp=fopen(acl_file_path,"w+");
872 sprintf(buf,"#!/bin/sh \n");
873 fprintf(fp,"%s\n",buf);
874
875 system("chmod 0777 /tmp/mac_filter.sh");
876
877 for(index=0;index<=1;index++)
878 {
879 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
880 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
881 sprintf(buf,"syscfg get %dcountfilter",index);
882 _syscmd(buf,count,sizeof(count));
883 mac_entry=atoi(count);
884
885 sprintf(buf,"syscfg get %dblockall",index);
886 _syscmd(buf,res,sizeof(res));
887 block = atoi(res);
888
889 //Allow only those macs mentioned in ACL
890 if(block==1)
891 {
892 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
893 fprintf(fp,"%s\n",buf);
894 for(dev_count=1;dev_count<=mac_entry;dev_count++)
895 {
896 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
897 _syscmd(buf,tmp,sizeof(tmp));
898 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
899 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
900 fprintf(fp,"%s\n",buf);
901 }
902 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
903 fprintf(fp,"%s\n",buf);
904 }
905
906 //Block all the macs mentioned in ACL
907 else if(block==2)
908 {
909 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
910 fprintf(fp,"%s\n",buf);
911
912 for(dev_count=1;dev_count<=mac_entry;dev_count++)
913 {
914 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
915 _syscmd(buf,tmp,sizeof(tmp));
916 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
917 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
918 fprintf(fp,"%s\n",buf);
919 }
920 }
921 }
922 fclose(fp);
923}
924
925// Initializes the wifi subsystem (all radios)
926INT wifi_init() //RDKB
927{
928 char interface[MAX_BUF_SIZE]={'\0'};
929 char bridge_name[MAX_BUF_SIZE]={'\0'};
930 INT len=0;
931
932 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
933 //Not intitializing macfilter for Turris-Omnia Platform for now
934 //macfilter_init();
935
936 system("/usr/sbin/iw reg set US");
937 system("systemctl start hostapd.service");
938 sleep(2);//sleep to wait for hostapd to start
939
940 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
941
942 return RETURN_OK;
943}
944
945/* wifi_reset() function */
946/**
947* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
948* Implementation specifics may dictate what is actualy reset since
949* different hardware implementations may have different requirements.
950* Parameters : None
951*
952* @return The status of the operation.
953* @retval RETURN_OK if successful.
954* @retval RETURN_ERR if any error is detected
955*
956* @execution Synchronous.
957* @sideeffect None.
958*
959* @note This function must not suspend and must not invoke any blocking system
960* calls. It should probably just send a message to a driver event handler task.
961*
962*/
963INT wifi_reset()
964{
965 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800966 system("systemctl stop hostapd.service");
967 sleep(2);
968 system("systemctl start hostapd.service");
969 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800970 return RETURN_OK;
971}
972
973/* wifi_down() function */
974/**
975* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
976* Implementation specifics may dictate some functionality since
977* different hardware implementations may have different requirements.
978*
979* @param None
980*
981* @return The status of the operation
982* @retval RETURN_OK if successful
983* @retval RETURN_ERR if any error is detected
984*
985* @execution Synchronous
986* @sideeffect None
987*
988* @note This function must not suspend and must not invoke any blocking system
989* calls. It should probably just send a message to a driver event handler task.
990*
991*/
992INT wifi_down()
993{
994 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +0800995 system("systemctl stop hostapd.service");
996 sleep(2);
developer06a01d92022-09-07 16:32:39 +0800997 return RETURN_OK;
998}
999
1000
1001/* wifi_createInitialConfigFiles() function */
1002/**
1003* @description This function creates wifi configuration files. The format
1004* and content of these files are implementation dependent. This function call is
1005* used to trigger this task if necessary. Some implementations may not need this
1006* function. If an implementation does not need to create config files the function call can
1007* do nothing and return RETURN_OK.
1008*
1009* @param None
1010*
1011* @return The status of the operation
1012* @retval RETURN_OK if successful
1013* @retval RETURN_ERR if any error is detected
1014*
1015* @execution Synchronous
1016* @sideeffect None
1017*
1018* @note This function must not suspend and must not invoke any blocking system
1019* calls. It should probably just send a message to a driver event handler task.
1020*
1021*/
1022INT wifi_createInitialConfigFiles()
1023{
1024 //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)
1025 return RETURN_OK;
1026}
1027
1028// outputs the country code to a max 64 character string
1029INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1030{
developer7543b3b2022-09-13 13:47:17 +08001031 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1032 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001033 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001034
1035 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1036 _syscmd(cmd, buf, sizeof(buf));
1037 if(strlen(buf) > 0)
1038 snprintf(output_string, 64, "%s", buf);
1039 else
1040 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001041
1042 return RETURN_OK;
1043}
1044
1045INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1046{
1047 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001048 char str[MAX_BUF_SIZE]={'\0'};
1049 char cmd[MAX_CMD_SIZE]={'\0'};
1050 struct params params;
1051 char config_file[MAX_BUF_SIZE] = {0};
1052
1053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1054 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1055 return RETURN_ERR;
1056
1057 params.name = "country_code";
1058 params.value = CountryCode;
1059 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1060 int ret = wifi_hostapdWrite(config_file, &params, 1);
1061 if (ret) {
1062 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1063 ,__func__, ret);
1064 }
1065
1066 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1067 if (ret) {
1068 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1069 ,__func__, ret);
1070 }
1071 wifi_reloadAp(radioIndex);
1072 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1073
developer06a01d92022-09-07 16:32:39 +08001074 return RETURN_OK;
1075}
1076
developera748dcf2022-09-13 15:56:48 +08001077INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1078{
1079 char channel_util_file[64] = {0};
1080 char cmd[128] = {0};
1081 char buf[128] = {0};
1082 char line[128] = {0};
1083 char *param = NULL, *value = NULL;
1084 int read = 0;
1085 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1086 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1087 size_t len = 0;
1088 FILE *f = NULL;
1089
1090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1091
1092 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1093 _syscmd(cmd, buf, sizeof(buf));
1094 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1095
1096 memset(cmd, 0, sizeof(cmd));
1097 memset(buf, 0, sizeof(buf));
1098 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1099 if ((f = popen(cmd, "r")) == NULL) {
1100 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1101 return RETURN_ERR;
1102 }
1103
1104 read = getline(&line, &len, f);
1105 while (read != -1) {
1106 param = strtok(line, ":\t");
1107 value = strtok(NULL, " ");
1108 if(strstr(param, "frequency") != NULL) {
1109 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1110 }
1111 if(strstr(param, "noise") != NULL) {
1112 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1113 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1114 }
1115 if(strstr(param, "channel active time") != NULL) {
1116 ActiveTime = strtol(value, NULL, 10);
1117 }
1118 if(strstr(param, "channel busy time") != NULL) {
1119 BusyTime = strtol(value, NULL, 10);
1120 }
1121 if(strstr(param, "channel transmit time") != NULL) {
1122 TransmitTime = strtol(value, NULL, 10);
1123 }
1124 read = getline(&line, &len, f);
1125 }
1126 pclose(f);
1127
1128 // The file should store the last active, busy and transmit time
1129 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1130 f = fopen(channel_util_file, "r");
1131 if (f != NULL) {
1132 read = getline(&line, &len, f);
1133 preActiveTime = strtol(line, NULL, 10);
1134 read = getline(&line, &len, f);
1135 preBusyTime = strtol(line, NULL, 10);
1136 read = getline(&line, &len, f);
1137 preTransmitTime = strtol(line, NULL, 10);
1138 fclose(f);
1139 }
1140
1141 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1142 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1143
1144 f = fopen(channel_util_file, "w");
1145 if (f != NULL) {
1146 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1147 fclose(f);
1148 }
1149 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1150 return RETURN_OK;
1151}
1152
developer06a01d92022-09-07 16:32:39 +08001153/**********************************************************************************
1154 *
1155 * Wifi radio level function prototypes
1156 *
1157**********************************************************************************/
1158
1159//Get the total number of radios in this wifi subsystem
1160INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1161{
1162 if (NULL == output)
1163 return RETURN_ERR;
1164 *output = 2;
1165
1166 return RETURN_OK;
1167}
1168
1169//Get the total number of SSID entries in this wifi subsystem
1170INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1171{
1172 if (NULL == output)
1173 return RETURN_ERR;
1174 *output = MAX_APS;
1175
1176 return RETURN_OK;
1177}
1178
1179//Get the Radio enable config parameter
1180INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1181{
1182 char interface_path[MAX_CMD_SIZE] = {0};
1183 FILE *fp = NULL;
1184
1185 if (NULL == output_bool)
1186 return RETURN_ERR;
1187
1188 *output_bool = FALSE;
1189 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1190 return RETURN_ERR;
1191
1192 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1193 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001194 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001195 {
developercf48e482022-09-13 14:49:50 +08001196 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001197 }
1198 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001199 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1200 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1201 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001202
developercf48e482022-09-13 14:49:50 +08001203 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1204 *output_bool = TRUE;
1205 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001206 return RETURN_OK;
1207}
1208
1209INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1210{
1211 char cmd[MAX_CMD_SIZE] = {0};
1212 char buf[MAX_CMD_SIZE] = {0};
1213 int apIndex, ret;
1214 FILE *fp = NULL;
1215
1216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1217 if(enable==FALSE)
1218 {
1219 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1220 {
1221 //Detaching %s%d from hostapd daemon
1222 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1223 _syscmd(cmd, buf, sizeof(buf));
1224 if(strncmp(buf, "OK", 2))
1225 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1226 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1227 _syscmd(cmd, buf, sizeof(buf));
1228 }
developer456aa3e2022-09-13 14:27:36 +08001229 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001230 _syscmd(cmd, buf, sizeof(buf));
1231 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001232 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001233 }
1234 else
1235 {
developer456aa3e2022-09-13 14:27:36 +08001236 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001237 _syscmd(cmd, buf, sizeof(buf));
1238 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001239 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001240 sleep(1);
1241 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1242 {
1243 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1244 fp = fopen(cmd, "r");
1245 if(!fp)
1246 {
1247 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1248 _syscmd(cmd, buf, sizeof(buf));
1249 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1250 _syscmd(cmd, buf, sizeof(buf));
1251 }
1252 if(fp)
1253 fclose(fp);
1254 }
1255 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1256 {
1257 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1258 ret = _syscmd(cmd, buf, sizeof(buf));
1259 if ( ret == RETURN_ERR)
1260 {
1261 fprintf(stderr, "VAP interface creation failed\n");
1262 continue;
1263 }
1264 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1265 _syscmd(cmd, buf, sizeof(buf));
1266 if(*buf == '1')
1267 {
1268 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1269 radioIndex, apIndex);
1270 _syscmd(cmd, buf, sizeof(buf));
1271 if(strncmp(buf, "OK", 2))
1272 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1273 }
1274 }
1275 }
1276
1277 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1278 return RETURN_OK;
1279}
1280
1281//Get the Radio enable status
1282INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1283{
1284 if (NULL == output_bool)
1285 return RETURN_ERR;
1286
1287 return wifi_getRadioEnable(radioIndex, output_bool);
1288}
1289
1290//Get the Radio Interface name from platform, eg "wlan0"
1291INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1292{
1293 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1294 return RETURN_ERR;
1295 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1296
1297 return RETURN_OK;
1298}
1299
1300//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1301//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.
1302INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1303{
1304 char cmd[1024] = {0};
1305 char buf[1024] = {0};
1306 char HConf_file[MAX_BUF_SIZE] = {'\0'};
1307 char interface_name[50] = {0};
1308
1309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1310 if (NULL == output_string)
1311 return RETURN_ERR;
1312
1313 sprintf(HConf_file,"%s%d%s","/nvram/hostapd",radioIndex,".conf");
1314 GetInterfaceName(interface_name,HConf_file);
1315
1316 sprintf(cmd, "iwconfig %s | grep 'Bit Rate' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1,2", interface_name);
1317 _syscmd(cmd, buf, sizeof(buf));
1318
1319 if(strlen(buf) > 0)
1320 snprintf(output_string, 64, "%s", buf);
1321 else
1322 {
1323 wifi_getRadioOperatingChannelBandwidth(radioIndex,buf);
1324 if((strcmp(buf,"20MHz") == 0) && (radioIndex == 0))
1325 strcpy(output_string,"144 Mb/s");
1326 else if((strcmp(buf,"20MHz") == 0) && (radioIndex == 1))
1327 strcpy(output_string,"54 Mb/s");
1328 else if((strcmp(buf,"40MHz") == 0) && (radioIndex == 1))
1329 strcpy(output_string,"300 Mb/s");
1330 //TODO: CHECK VALID VALUE
1331 }
1332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1333
1334 return RETURN_OK;
1335}
1336#if 0
1337INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1338{
1339 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1340 char cmd[64];
1341 char buf[1024];
1342 int apIndex;
1343
1344 if (NULL == output_string)
1345 return RETURN_ERR;
1346
1347 apIndex=(radioIndex==0)?0:1;
1348
1349 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1350 _syscmd(cmd,buf, sizeof(buf));
1351
1352 snprintf(output_string, 64, "%s", buf);
1353 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1354 return RETURN_OK;
1355}
1356#endif
1357
1358
1359//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1360//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.
1361INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1362{
developer963da0c2022-09-13 15:58:27 +08001363 wifi_band band = band_invalid;
1364
developer06a01d92022-09-07 16:32:39 +08001365 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1366 if (NULL == output_string)
1367 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001368
1369 band = wifi_index_to_band(radioIndex);
1370
1371 memset(output_string, 0, 10);
1372 if (band == band_2_4)
1373 strcpy(output_string, "2.4GHz");
1374 else if (band == band_5)
1375 strcpy(output_string, "5GHz");
1376 else if (band == band_6)
1377 strcpy(output_string, "6GHz");
1378 else
1379 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1381
1382 return RETURN_OK;
1383#if 0
1384 char buf[MAX_BUF_SIZE]={'\0'};
1385 char str[MAX_BUF_SIZE]={'\0'};
1386 char cmd[MAX_CMD_SIZE]={'\0'};
1387 char *ch=NULL;
1388 char *ch2=NULL;
1389
1390 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1391 if (NULL == output_string)
1392 return RETURN_ERR;
1393
1394
1395 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1396
1397 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1398 {
1399 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1400 return RETURN_ERR;
1401 }
1402 ch=strchr(buf,'\n');
1403 *ch='\0';
1404 ch=strchr(buf,'=');
1405 if(ch==NULL)
1406 return RETURN_ERR;
1407
1408
1409 ch++;
1410
1411 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1412 strcpy(buf,"0");
1413 if(strlen(ch) == 1)
1414 ch=strcat(buf,ch);
1415
1416
1417 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1418
1419 if(_syscmd(cmd,str,64) == RETURN_ERR)
1420 {
1421 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1422 return RETURN_ERR;
1423 }
1424
1425
1426 ch2=strchr(str,'\n');
1427 //replace \n with \0
1428 *ch2='\0';
1429 ch2=strchr(str,'=');
1430 if(ch2==NULL)
1431 {
1432 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1433 return RETURN_ERR;
1434 }
1435 else
1436 wifi_dbg_printf("%s",ch2+1);
1437
1438
1439 ch2++;
1440
1441
1442 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1443
1444 memset(buf,'\0',sizeof(buf));
1445 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1446 {
1447 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1448 return RETURN_ERR;
1449 }
1450 if (strstr(buf,"2.4") != NULL )
1451 strcpy(output_string,"2.4GHz");
1452 else if(strstr(buf,"5.") != NULL )
1453 strcpy(output_string,"5GHz");
1454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1455
1456 return RETURN_OK;
1457#endif
1458}
1459
1460//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1461//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.
1462INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1463{
1464 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1465 if (NULL == output_string)
1466 return RETURN_ERR;
1467 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1468 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1469
1470 return RETURN_OK;
1471#if 0
1472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1473 char buf[MAX_BUF_SIZE]={'\0'};
1474 char str[MAX_BUF_SIZE]={'\0'};
1475 char cmd[MAX_CMD_SIZE]={'\0'};
1476 char *ch=NULL;
1477 char *ch2=NULL;
1478 char ch1[5]="0";
1479
1480 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1481
1482 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1483 {
1484 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1485 return RETURN_ERR;
1486 }
1487
1488 ch=strchr(buf,'\n');
1489 *ch='\0';
1490 ch=strchr(buf,'=');
1491 if(ch==NULL)
1492 return RETURN_ERR;
1493 ch++;
1494
1495 if(strlen(ch)==1)
1496 {
1497 strcat(ch1,ch);
1498
1499 }
1500 else
1501 {
1502 strcpy(ch1,ch);
1503 }
1504
1505
1506
1507 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1508 if(_syscmd(cmd,str,64) == RETURN_ERR)
1509 {
1510 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1511 return RETURN_ERR;
1512 }
1513
1514
1515 ch2=strchr(str,'\n');
1516 //replace \n with \0
1517 *ch2='\0';
1518 ch2=strchr(str,'=');
1519 if(ch2==NULL)
1520 {
1521 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1522 return RETURN_ERR;
1523 }
1524 else
1525 wifi_dbg_printf("%s",ch2+1);
1526 ch2++;
1527
1528
1529 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1530 memset(buf,'\0',sizeof(buf));
1531 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1532 {
1533 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1534 return RETURN_ERR;
1535 }
1536
1537
1538 if(strstr(buf,"2.4")!=NULL)
1539 {
1540 strcpy(output_string,"2.4GHz");
1541 }
1542 if(strstr(buf,"5.")!=NULL)
1543 {
1544 strcpy(output_string,"5GHz");
1545 }
1546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1547 return RETURN_OK;
1548#endif
1549}
1550
1551//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1552//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.
1553INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1554{
developer963da0c2022-09-13 15:58:27 +08001555 char cmd[128]={0};
1556 char buf[128]={0};
1557 char temp_output[128] = {0};
1558 wifi_band band;
1559
1560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001561 if (NULL == output_string)
1562 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001563
1564 band = wifi_index_to_band(radioIndex);
1565 if (band == band_2_4) {
1566 strcat(temp_output, "b,g,");
1567 } else if (band == band_5) {
1568 strcat(temp_output, "a,");
1569 }
1570
1571 // ht capabilities
1572 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
1573 _syscmd(cmd, buf, sizeof(buf));
1574 if (strncmp(buf, "0x00", 4) != 0) {
1575 strcat(temp_output, "n,");
1576 }
developer06a01d92022-09-07 16:32:39 +08001577
developer963da0c2022-09-13 15:58:27 +08001578 // vht capabilities
1579 if (band == band_5) {
1580 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1581 _syscmd(cmd, buf, sizeof(buf));
1582 if (strncmp(buf, "0x00000000", 10) != 0) {
1583 strcat(temp_output, "ac,");
1584 }
1585 }
1586
1587 // he capabilities
1588 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", radioIndex);
1589 _syscmd(cmd, buf, sizeof(buf));
1590 if (strncmp (buf, "0x0000", 6) != 0) {
1591 strcat(temp_output, "ax,");
1592 }
1593
1594 // Remove the last comma
1595 if (strlen(temp_output) != 0)
1596 temp_output[strlen(temp_output)-1] = '\0';
1597 strncpy(output_string, temp_output, strlen(temp_output));
1598 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001599 return RETURN_OK;
1600}
1601
1602//Get the radio operating mode, and pure mode flag. eg: "ac"
1603//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.
1604INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1605{
1606 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1607 if (NULL == output_string)
1608 return RETURN_ERR;
1609
1610 if (radioIndex == 0) {
1611 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1612 *gOnly = FALSE;
1613 *nOnly = TRUE;
1614 *acOnly = FALSE;
1615 } else {
1616 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1617 *gOnly = FALSE;
1618 *nOnly = FALSE;
1619 *acOnly = FALSE;
1620 }
1621 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1622
1623 return RETURN_OK;
1624#if 0
1625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1626 char buf[64] = {0};
1627 char config_file[MAX_BUF_SIZE] = {0};
1628
1629 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1630 return RETURN_ERR;
1631
1632 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1633 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1634
1635 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1636 if (strlen(buf) == 0)
1637 {
1638 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1639 return RETURN_ERR;
1640 }
1641 if(strcmp(buf,"g")==0)
1642 {
1643 wifi_dbg_printf("\nG\n");
1644 *gOnly=TRUE;
1645 *nOnly=FALSE;
1646 *acOnly=FALSE;
1647 }
1648 else if(strcmp(buf,"n")==0)
1649 {
1650 wifi_dbg_printf("\nN\n");
1651 *gOnly=FALSE;
1652 *nOnly=TRUE;
1653 *acOnly=FALSE;
1654 }
1655 else if(strcmp(buf,"ac")==0)
1656 {
1657 wifi_dbg_printf("\nac\n");
1658 *gOnly=FALSE;
1659 *nOnly=FALSE;
1660 *acOnly=TRUE;
1661 }
1662 /* hostapd-5G.conf has "a" as hw_mode */
1663 else if(strcmp(buf,"a")==0)
1664 {
1665 wifi_dbg_printf("\na\n");
1666 *gOnly=FALSE;
1667 *nOnly=FALSE;
1668 *acOnly=FALSE;
1669 }
1670 else
1671 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1672
1673 //for a,n mode
1674 if(radioIndex == 1)
1675 {
1676 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1677 if(strcmp(buf,"1")==0)
1678 {
1679 strncpy(output_string, "n", 1);
1680 *nOnly=FALSE;
1681 }
1682 }
1683
1684 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1686 return RETURN_OK;
1687#endif
1688}
1689
developerdb744382022-09-13 15:34:54 +08001690INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1691{
1692 char cmd[128] = {0};
1693 char buf[64] = {0};
1694 char config_file[64] = {0};
1695 wifi_band band;
1696
1697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1698 if(NULL == output_string || NULL == pureMode)
1699 return RETURN_ERR;
1700
1701 // grep all of the ieee80211 protocol config set to 1
1702 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1703 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1704 _syscmd(cmd, buf, sizeof(buf));
1705
1706 band = wifi_index_to_band(radioIndex);
1707 // puremode is a bit map
1708 *pureMode = 0;
1709 if (band == band_2_4) {
1710 strcat(output_string, "b,g");
1711 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1712 if (strstr(buf, "n") != NULL) {
1713 strcat(output_string, ",n");
1714 *pureMode |= WIFI_MODE_N;
1715 }
1716 if (strstr(buf, "ax") != NULL) {
1717 strcat(output_string, ",ax");
1718 *pureMode |= WIFI_MODE_AX;
1719 }
1720 } else if (band == band_5) {
1721 strcat(output_string, "a");
1722 *pureMode |= WIFI_MODE_A;
1723 if (strstr(buf, "n") != NULL) {
1724 strcat(output_string, ",n");
1725 *pureMode |= WIFI_MODE_N;
1726 }
1727 if (strstr(buf, "ac") != NULL) {
1728 strcat(output_string, ",ac");
1729 *pureMode |= WIFI_MODE_AC;
1730 }
1731 if (strstr(buf, "ax") != NULL) {
1732 strcat(output_string, ",ax");
1733 *pureMode |= WIFI_MODE_AX;
1734 }
1735 } else if (band == band_6) {
1736 if (strstr(buf, "ax") != NULL) {
1737 strcat(output_string, "ax");
1738 *pureMode |= WIFI_MODE_AX;
1739 }
1740 }
1741
1742 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1743 return RETURN_OK;
1744}
1745
1746// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001747INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1748{
1749 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1750 if (strcmp (channelMode,"11A") == 0)
1751 {
1752 writeBandWidth(radioIndex,"20MHz");
1753 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1754 printf("\nChannel Mode is 802.11a (5GHz)\n");
1755 }
1756 else if (strcmp (channelMode,"11NAHT20") == 0)
1757 {
1758 writeBandWidth(radioIndex,"20MHz");
1759 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1760 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1761 }
1762 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1763 {
1764 writeBandWidth(radioIndex,"40MHz");
1765 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1766 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1767 }
1768 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1769 {
1770 writeBandWidth(radioIndex,"40MHz");
1771 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1772 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1773 }
1774 else if (strcmp (channelMode,"11ACVHT20") == 0)
1775 {
1776 writeBandWidth(radioIndex,"20MHz");
1777 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1778 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1779 }
1780 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1781 {
1782 writeBandWidth(radioIndex,"40MHz");
1783 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1784 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1785 }
1786 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1787 {
1788 writeBandWidth(radioIndex,"40MHz");
1789 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1790 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1791 }
1792 else if (strcmp (channelMode,"11ACVHT80") == 0)
1793 {
1794 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1795 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1796 }
1797 else if (strcmp (channelMode,"11ACVHT160") == 0)
1798 {
1799 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1800 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1801 }
1802 else if (strcmp (channelMode,"11B") == 0)
1803 {
1804 writeBandWidth(radioIndex,"20MHz");
1805 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1806 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1807 }
1808 else if (strcmp (channelMode,"11G") == 0)
1809 {
1810 writeBandWidth(radioIndex,"20MHz");
1811 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1812 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1813 }
1814 else if (strcmp (channelMode,"11NGHT20") == 0)
1815 {
1816 writeBandWidth(radioIndex,"20MHz");
1817 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1818 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1819 }
1820 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1821 {
1822 writeBandWidth(radioIndex,"40MHz");
1823 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1824 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1825 }
1826 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1827 {
1828 writeBandWidth(radioIndex,"40MHz");
1829 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1830 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1831 }
1832 else
1833 {
1834 return RETURN_ERR;
1835 }
1836 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1837
1838 return RETURN_OK;
1839}
1840
developerdb744382022-09-13 15:34:54 +08001841// Set the radio operating mode, and pure mode flag.
1842INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1843{
1844 int num_hostapd_support_mode = 3; // n, ac, ax
1845 struct params list[num_hostapd_support_mode];
1846 char config_file[64] = {0};
1847 char bandwidth[16] = {0};
1848 int mode_check_bit = 1 << 3; // n mode
1849 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1850
1851 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1852 // Set radio mode
1853 list[0].name = "ieee80211n";
1854 list[1].name = "ieee80211ac";
1855 list[2].name = "ieee80211ax";
1856 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1857
1858 // check the bit map from n to ax, and set hostapd config
1859 if (mode & WIFI_MODE_N)
1860 list[0].value = "1";
1861 else
1862 list[0].value = "0";
1863 if (mode & WIFI_MODE_AC)
1864 list[1].value = "1";
1865 else
1866 list[1].value = "0";
1867 if (mode & WIFI_MODE_AX)
1868 list[2].value = "1";
1869 else
1870 list[2].value = "0";
1871 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1872
1873 if (channelMode == NULL || strlen(channelMode) == 0)
1874 return RETURN_OK;
1875 // Set bandwidth
1876 if (strstr(channelMode, "40") != NULL)
1877 strcpy(bandwidth, "40MHz");
1878 else if (strstr(channelMode, "80") != NULL)
1879 strcpy(bandwidth, "80MHz");
1880 else if (strstr(channelMode, "160") != NULL)
1881 strcpy(bandwidth, "160MHz");
1882 else // 11A, 11B, 11G....
1883 strcpy(bandwidth, "20MHz");
1884
1885 writeBandWidth(radioIndex, bandwidth);
1886 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1887
1888 wifi_reloadAp(radioIndex);
1889 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1890
1891 return RETURN_OK;
1892}
1893
developer06a01d92022-09-07 16:32:39 +08001894//Get the list of supported channel. eg: "1-11"
1895//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.
1896INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
1897{
developer6318ed52022-09-13 15:17:58 +08001898 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001899 if (NULL == output_string)
1900 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08001901 char cmd[256] = {0};
1902 char buf[128] = {0};
1903 BOOL dfs_enable = false;
1904 // Parse possible channel number and separate them with commas.
1905 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
1906 if (dfs_enable)
1907 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
1908 else
1909 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
1910
1911 _syscmd(cmd,buf,sizeof(buf));
1912 strncpy(output_string, buf, sizeof(buf));
1913
1914 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1915 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08001916#if 0
1917 char IFName[50] ={0};
1918 char buf[MAX_BUF_SIZE] = {0};
1919 char cmd[MAX_CMD_SIZE] = {0};
1920 int count = 0;
1921 if (NULL == output_string)
1922 return RETURN_ERR;
1923
1924 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
1925 if(radioIndex == 0)
1926 {
1927 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
1928 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
1929 }
1930 else if(radioIndex == 1)
1931 {
1932 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
1933 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep '5\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
1934 }
1935 _syscmd(cmd, buf, sizeof(buf));
1936 if(strlen(buf) > 0)
1937 strcpy(output_string,buf);
1938 else
1939 strcpy(output_string,"0");
1940#endif
1941 return RETURN_OK;
1942}
1943
1944//Get the list for used channel. eg: "1,6,9,11"
1945//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.
1946INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
1947{
1948 if (NULL == output_string)
1949 return RETURN_ERR;
1950 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
1951#if 0
1952 char IFName[50] ={0};
1953 char buf[MAX_BUF_SIZE] = {0};
1954 char cmd[MAX_CMD_SIZE] = {0};
1955 if (NULL == output_string)
1956 return RETURN_ERR;
1957
1958 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
1959 if(radioIndex == 0)
1960 {
1961 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
1962 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
1963 }
1964 else if(radioIndex == 1)
1965 {
1966 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
1967 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 5'\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 |tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
1968 }
1969 _syscmd(cmd,buf, sizeof(buf));
1970 if(strlen(buf) > 0)
1971 strcpy(output_string,buf);
1972 else
1973 strcpy(output_string,"0");
1974#endif
1975 return RETURN_OK;
1976}
1977
1978//Get the running channel number
1979INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
1980{
developerda1ed692022-09-13 13:59:20 +08001981#ifdef MTK_IMPL
1982 if(!wifi_getApChannel(radioIndex, output_ulong))
1983 return RETURN_OK;
1984 else
1985 return RETURN_ERR;
1986#else
developer06a01d92022-09-07 16:32:39 +08001987 char cmd[1024] = {0}, buf[5] = {0};
1988
1989 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1990 if (NULL == output_ulong)
1991 return RETURN_ERR;
1992
1993 snprintf(cmd, sizeof(cmd),
1994 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
1995 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
1996 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
1997 _syscmd(cmd, buf, sizeof(buf));
1998
1999 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2000 if (*output_ulong <= 0) {
2001 *output_ulong = 0;
2002 return RETURN_ERR;
2003 }
2004
2005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2006 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002007#endif
developer06a01d92022-09-07 16:32:39 +08002008}
2009
2010
2011INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2012{
2013 char cmd[1024] = {0}, buf[5] = {0};
2014 char interface_name[50] = {0};
2015
2016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2017 if (NULL == output_ulong)
2018 return RETURN_ERR;
2019
2020 wifi_getApName(apIndex,interface_name);
2021 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2022 _syscmd(cmd,buf,sizeof(buf));
2023 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2024 if (*output_ulong == 0) {
2025 return RETURN_ERR;
2026 }
2027
2028 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2029 return RETURN_OK;
2030}
2031
2032//Storing the previous channel value
2033INT wifi_storeprevchanval(INT radioIndex)
2034{
2035 char buf[256] = {0};
2036 char output[4]={'\0'};
2037 char config_file[MAX_BUF_SIZE] = {0};
2038 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2039 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2040 if(radioIndex == 0)
2041 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2042 else if(radioIndex == 1)
2043 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2044 system(buf);
2045 Radio_flag = FALSE;
2046 return RETURN_OK;
2047}
2048
2049//Set the running channel number
2050INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2051{
2052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2053 struct params params={'\0'};
2054 char str_channel[4]={'\0'};
2055 struct params list;
2056 char config_file[MAX_BUF_SIZE] = {0};
2057
2058 list.name = "channel";
2059
2060 if(Radio_flag == TRUE)
2061 wifi_storeprevchanval(radioIndex); //for autochannel
2062
2063 if(radioIndex == 0)
2064 {
2065 switch(channel)
2066 {
2067 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2068 sprintf(str_channel,"%ld", channel);
2069 list.value = str_channel;
2070 break;
2071 default:
2072 return RETURN_ERR;
2073 }
2074 }
2075 else if(radioIndex == 1)
2076 {
2077 switch(channel)
2078 {
2079 case 36: case 40: case 44: case 48: case 52: case 56: case 60: case 64: case 144: case 149: case 153: case 157: case 161: case 165: case 169:
2080 sprintf(str_channel,"%ld", channel);
2081 list.value = str_channel;
2082 break;
2083 default:
2084 return RETURN_ERR;
2085 }
2086 }
2087
2088 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2089 {
2090 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2091 wifi_hostapdWrite(config_file,&list,1);
2092 }
2093
2094 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2095 return RETURN_OK;
2096 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2097 }
2098
2099INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2100{
2101 struct params list;
2102 char str_idx[16];
2103 char config_file[MAX_BUF_SIZE];
2104
2105 list.name = "vht_oper_centr_freq_seg0_idx";
2106 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2107 list.value = str_idx;
2108
2109 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2110 {
2111 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2112 wifi_hostapdWrite(config_file, &list, 1);
2113 }
2114
2115 return RETURN_OK;
2116}
2117
2118//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2119//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2120INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2121{
2122 //Set to wifi config only. Wait for wifi reset to apply.
2123 char buf[256] = {0};
2124 char str_channel[256] = {0};
2125 int count = 0;
2126 ULONG Value = 0;
2127 FILE *fp = NULL;
2128 if(enable == TRUE)
2129 {
2130 if(radioIndex == 0)
2131 {
2132 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2133 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2134 }
2135 else if(radioIndex == 1)
2136 {
2137 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2138 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2139 }
2140 if(fp == NULL) //first time boot-up
2141 {
2142 if(radioIndex == 0)
2143 Value = 6;
2144 else if(radioIndex == 1)
2145 Value = 36;
2146 }
2147 else
2148 {
2149 if(fgets(buf,sizeof(buf),fp) != NULL)
2150 {
2151 for(count = 0;buf[count]!='\n';count++)
2152 str_channel[count] = buf[count];
2153 str_channel[count] = '\0';
2154 Value = atol(str_channel);
2155 printf("%sValue is %ld \n",__FUNCTION__,Value);
2156 pclose(fp);
2157 }
2158 }
2159 Radio_flag = FALSE;//for storing previous channel value
2160 wifi_setRadioChannel(radioIndex,Value);
2161 return RETURN_OK;
2162 }
2163 return RETURN_ERR;
2164}
2165
2166INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2167{
2168 if (NULL == output_bool)
2169 return RETURN_ERR;
2170 *output_bool=FALSE;
2171 return RETURN_OK;
2172}
2173
2174INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2175{
2176 if (NULL == output_bool)
2177 return RETURN_ERR;
2178 *output_bool=FALSE;
2179 return RETURN_OK;
2180}
2181
2182INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2183{
2184 //Set to wifi config only. Wait for wifi reset to apply.
2185 return RETURN_OK;
2186}
2187
2188INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2189{
2190 return RETURN_OK;
2191}
2192
2193INT wifi_factoryResetAP(int apIndex)
2194{
2195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2196 //factory reset is not done for now on Turris
2197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2198 return RETURN_OK;
2199}
2200
2201//To set Band Steering AP group
2202//To-do
2203INT wifi_setBandSteeringApGroup(char *ApGroup)
2204{
2205 return RETURN_OK;
2206}
2207
2208INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2209{
developer5f222492022-09-13 15:21:52 +08002210 struct params params={0};
2211 char config_file[MAX_BUF_SIZE] = {'\0'};
2212 char buf[MAX_BUF_SIZE] = {'\0'};
2213
2214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2215 if (dtimInterval < 1 || dtimInterval > 255) {
2216 return RETURN_ERR;
2217 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2218 }
2219
2220 params.name = "dtim_period";
2221 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2222 params.value = buf;
2223
2224 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2225 wifi_hostapdWrite(config_file, &params, 1);
2226 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2227
2228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2229 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002230}
2231
2232//Check if the driver support the Dfs
2233INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2234{
2235 if (NULL == output_bool)
2236 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002237 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002238 return RETURN_OK;
2239}
2240
2241//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.
2242//The value of this parameter is a comma seperated list of channel number
2243INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2244{
2245 if (NULL == output_pool)
2246 return RETURN_ERR;
2247 if (radioIndex==1)
2248 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2249 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2250
2251 return RETURN_OK;
2252}
2253
2254INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2255{
2256 //Set to wifi config. And apply instantly.
2257 return RETURN_OK;
2258}
2259
2260INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2261{
2262 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2263 return RETURN_ERR;
2264 *output_interval_seconds=1800;
2265 *output_dwell_milliseconds=40;
2266
2267 return RETURN_OK;
2268}
2269
2270INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2271{
2272 //Set to wifi config. And apply instantly.
2273 return RETURN_OK;
2274}
2275
2276//Get the Dfs enable status
2277INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2278{
developer9964b5b2022-09-13 15:59:34 +08002279 char buf[16] = {0};
2280 FILE *f = NULL;
2281 wifi_band band;
2282
2283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2284
2285 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002286 if (NULL == output_bool)
2287 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002288
2289 band = wifi_index_to_band(radioIndex);
2290 if (band != band_5)
2291 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002292
developer9964b5b2022-09-13 15:59:34 +08002293 f = fopen(DFS_ENABLE_FILE, "r");
2294 if (f != NULL) {
2295 fgets(buf, 2, f);
2296 if (strncmp(buf, "0", 0) == 0)
2297 *output_bool = FALSE;
2298 fclose(f);
2299 }
2300 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002301 return RETURN_OK;
2302}
2303
2304//Set the Dfs enable status
2305INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2306{
developer9964b5b2022-09-13 15:59:34 +08002307 char buf[128] = {0};
2308 char config_file[128] = {0};
2309 FILE *f = NULL;
2310 struct params params={0};
2311 wifi_band band;
2312
2313 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2314
2315 band = wifi_index_to_band(radioIndex);
2316 if (band != band_5)
2317 return RETURN_OK;
2318
2319 f = fopen(DFS_ENABLE_FILE, "w");
2320 if (f == NULL)
2321 return RETURN_ERR;
2322 fprintf(f, "%d", enable);
2323 fclose(f);
2324
2325 params.name = "acs_exclude_dfs";
2326 sprintf(buf, "%d", enable?"1":"0");
2327 params.value = buf;
2328 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2329 wifi_hostapdWrite(config_file, &params, 1);
2330 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2331
2332 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2333
2334 wifi_reloadAp(radioIndex);
2335
2336 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002337}
2338
2339//Check if the driver support the AutoChannelRefreshPeriod
2340INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2341{
2342 if (NULL == output_bool)
2343 return RETURN_ERR;
2344 *output_bool=FALSE; //not support
2345
2346 return RETURN_OK;
2347}
2348
2349//Get the ACS refresh period in seconds
2350INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2351{
2352 if (NULL == output_ulong)
2353 return RETURN_ERR;
2354 *output_ulong=300;
2355
2356 return RETURN_OK;
2357}
2358
2359//Set the ACS refresh period in seconds
2360INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2361{
2362 return RETURN_ERR;
2363}
2364
2365//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2366//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.
2367INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2368{
developer70490032022-09-13 15:45:20 +08002369 char cmd[128] = {0}, buf[64] = {0};
2370 char interface_name[64] = {0};
2371 int ret = 0, len=0;
2372 BOOL radio_enable = FALSE;
2373
2374 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2375
developer06a01d92022-09-07 16:32:39 +08002376 if (NULL == output_string)
2377 return RETURN_ERR;
2378
developer70490032022-09-13 15:45:20 +08002379 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2380 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002381
developer70490032022-09-13 15:45:20 +08002382 if (radio_enable != TRUE)
2383 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002384
developer70490032022-09-13 15:45:20 +08002385 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002386 ret = _syscmd(cmd, buf, sizeof(buf));
2387 len = strlen(buf);
2388 if((ret != 0) || (len == 0))
2389 {
2390 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2391 return RETURN_ERR;
2392 }
2393
2394 buf[len-1] = '\0';
2395 snprintf(output_string, 64, "%sMHz", buf);
2396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2397
2398#if 0
2399 //TODO: revisit below implementation
2400 char output_buf[8]={0};
2401 char bw_value[10];
2402 char config_file[MAX_BUF_SIZE] = {0};
2403
2404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2405 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2406 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2407 readBandWidth(radioIndex,bw_value);
2408
2409 if(strstr (output_buf,"0") != NULL )
2410 {
2411 strcpy(output_string,bw_value);
2412 }
2413 else if (strstr (output_buf,"1") != NULL)
2414 {
2415 strcpy(output_string,"80MHz");
2416 }
2417 else if (strstr (output_buf,"2") != NULL)
2418 {
2419 strcpy(output_string,"160MHz");
2420 }
2421 else if (strstr (output_buf,"3") != NULL)
2422 {
2423 strcpy(output_string,"80+80");
2424 }
2425 else
2426 {
2427 strcpy(output_string,"Auto");
2428 }
2429 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2430#endif
2431
2432 return RETURN_OK;
2433}
2434
2435//Set the Operating Channel Bandwidth.
2436INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181 //AP only
2437{
2438 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2439 char config_file[MAX_BUF_SIZE];
2440 struct params params[4];
2441 struct params *pptr = params;
2442
2443 if(NULL == output_string)
2444 return RETURN_ERR;
2445
2446 pptr->name = "vht_oper_chwidth";
2447 if(strcmp(output_string,"20MHz") == 0) // This piece of code only support for wifi hal api's validation
2448 pptr->value="0";
2449 else if(strcmp(output_string,"40MHz") == 0)
2450 pptr->value="0";
2451 else if(strcmp(output_string,"80MHz") == 0)
2452 pptr->value="1";
2453 else if(strcmp(output_string,"160MHz") == 0)
2454 pptr->value="2";
2455 else if(strcmp(output_string,"80+80") == 0)
2456 pptr->value="3";
2457 else
2458 {
2459 printf("Invalid Bandwidth \n");
2460 return RETURN_ERR;
2461 }
2462
2463 pptr++; // added vht_oper_chwidth
2464
2465 if(radioIndex == 1)
2466 {
2467 pptr->name= "ieee80211n";
2468 if(strcmp(output_string,"20MHz") == 0)
2469 pptr->value="0";
2470 else if(strcmp(output_string,"40MHz") == 0)
2471 pptr->value="1";
2472 else if(strcmp(output_string,"80MHz") == 0)
2473 pptr->value="1";
2474 else
2475 pptr->value="0";
2476
2477 pptr++; // added ieee80211n
2478
2479 pptr->name="ieee80211ac";
2480 if(strcmp(output_string,"80MHz") == 0)
2481 pptr->value="1";
2482 else
2483 pptr->value="0";
2484 pptr++;
2485 }
2486
2487 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2488 {
2489 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2490 wifi_hostapdWrite(config_file, params, (pptr - params));
2491 }
2492
2493 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2494 return RETURN_OK;
2495}
2496
2497//Getting current radio extension channel
2498INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2499{
2500 CHAR buf[150] = {0};
2501 CHAR cmd[150] = {0};
2502 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2503 _syscmd(cmd, buf, sizeof(buf));
2504 if(NULL != strstr(buf,"HT40+"))
2505 strcpy(Value,"AboveControlChannel");
2506 else if(NULL != strstr(buf,"HT40-"))
2507 strcpy(Value,"BelowControlChannel");
2508 return RETURN_OK;
2509}
2510
2511//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2512//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.
2513INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2514{
2515 if (NULL == output_string)
2516 return RETURN_ERR;
2517
2518 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2519#if 0
2520 CHAR Value[100] = {0};
2521 if (NULL == output_string)
2522 return RETURN_ERR;
2523 if(radioIndex == 0)
2524 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2525 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2526 {
2527 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2528 if(strcmp(Value,"40MHz") == 0)
2529 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2530 else
2531 strcpy(Value,"Auto");
2532 }
2533 strcpy(output_string,Value);
2534#endif
2535
2536 return RETURN_OK;
2537}
2538
2539//Set the extension channel.
2540INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2541{
2542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2543 struct params params={'\0'};
2544 char config_file[MAX_BUF_SIZE] = {0};
2545 char ext_channel[127]={'\0'};
2546
2547 params.name = "ht_capab";
2548
2549 if(radioIndex == 0)
2550 {
2551 if(NULL!= strstr(string,"Above"))
2552 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40+]");
2553 else if(NULL!= strstr(string,"Below"))
2554 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40-]");
2555 else
2556 strcpy(ext_channel, HOSTAPD_HT_CAPAB_20);
2557 }
2558 else if(radioIndex == 1)
2559 {
2560 if(NULL!= strstr(string,"Above"))
2561 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40+]");
2562 else if(NULL!= strstr(string,"Below"))
2563 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40-]");
2564 else
2565 strcpy(ext_channel, HOSTAPD_HT_CAPAB_20);
2566 }
2567
2568 params.value = ext_channel;
2569 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2570 {
2571 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2572 wifi_hostapdWrite(config_file, &params, 1);
2573 }
2574
2575 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2577 return RETURN_OK;
2578}
2579
2580//Get the guard interval value. eg "400nsec" or "800nsec"
2581//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.
2582INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2583{
developer454b9462022-09-13 15:29:16 +08002584 wifi_guard_interval_t GI;
2585
2586 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2587
2588 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002589 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002590
2591 if (GI == wifi_guard_interval_400)
2592 strcpy(output_string, "400nsec");
2593 else if (GI == wifi_guard_interval_800)
2594 strcpy(output_string, "800nsec");
2595 else if (GI == wifi_guard_interval_1600)
2596 strcpy(output_string, "1600nsec");
2597 else if (GI == wifi_guard_interval_3200)
2598 strcpy(output_string, "3200nsec");
2599 else
2600 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002601
developer454b9462022-09-13 15:29:16 +08002602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002603 return RETURN_OK;
2604}
2605
2606//Set the guard interval value.
2607INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2608{
developer454b9462022-09-13 15:29:16 +08002609 wifi_guard_interval_t GI;
2610 int ret = 0;
2611
2612 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2613
2614 if (strcmp(string, "400nsec") == 0)
2615 GI = wifi_guard_interval_400;
2616 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2617 GI = wifi_guard_interval_800;
2618 else if (strcmp(string , "1600nsec") == 0)
2619 GI = wifi_guard_interval_1600;
2620 else if (strcmp(string , "3200nsec") == 0)
2621 GI = wifi_guard_interval_3200;
2622
2623 ret = wifi_setGuardInterval(radioIndex, GI);
2624
2625 if (ret == RETURN_ERR) {
2626 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2627 return RETURN_ERR;
2628 }
2629
2630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2631 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002632}
2633
2634//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2635INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2636{
2637 if (NULL == output_int)
2638 return RETURN_ERR;
2639 *output_int=(radioIndex==0)?1:3;
2640
2641 return RETURN_OK;
2642}
2643
2644//Set the Modulation Coding Scheme index
2645INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2646{
2647 return RETURN_ERR;
2648}
2649
2650//Get supported Transmit Power list, eg : "0,25,50,75,100"
2651//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.
2652INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2653{
2654 if (NULL == output_list)
2655 return RETURN_ERR;
2656 snprintf(output_list, 64,"0,25,50,75,100");
2657 return RETURN_OK;
2658}
2659
developera5005b62022-09-13 15:43:35 +08002660//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002661//The transmite power level is in units of full power for this radio.
2662INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2663{
2664 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002665 char buf[16]={0};
2666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002667
developera5005b62022-09-13 15:43:35 +08002668 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002669 return RETURN_ERR;
2670
developera5005b62022-09-13 15:43:35 +08002671 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 +08002672 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002673
developera5005b62022-09-13 15:43:35 +08002674 *output_ulong = strtol(buf, NULL, 10);
2675
2676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002677 return RETURN_OK;
2678}
2679
2680//Set Transmit Power
2681//The transmite power level is in units of full power for this radio.
2682INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2683{
developera5005b62022-09-13 15:43:35 +08002684 char *support;
developer06a01d92022-09-07 16:32:39 +08002685 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002686 char buf[128]={0};
2687 char txpower_str[64] = {0};
2688 int txpower = 0;
2689 int maximum_tx = 0;
2690
2691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002692
developera5005b62022-09-13 15:43:35 +08002693 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 +08002694 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002695 maximum_tx = strtol(buf, NULL, 10);
2696
2697 // Get the Tx power supported list and check that is the input in the list
2698 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2699 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2700 support = strtok(buf, ",");
2701 while(true)
2702 {
2703 if(support == NULL) { // input not in the list
2704 wifi_dbg_printf("Input value is invalid.\n");
2705 return RETURN_ERR;
2706 }
2707 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2708 break;
2709 }
2710 support = strtok(NULL, ",");
2711 }
2712 txpower = TransmitPower*maximum_tx/100;
2713 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2714 _syscmd(cmd, buf, sizeof(buf));
2715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002716
2717 return RETURN_OK;
2718}
2719
2720//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2721INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2722{
2723 if (NULL == Supported)
2724 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002725 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002726
2727 return RETURN_OK;
2728}
2729
2730//Get 80211h feature enable
2731INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2732{
developer3885fec2022-09-13 15:13:47 +08002733 char buf[64]={'\0'};
2734 char config_file[64] = {'\0'};
2735
2736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2737 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002738 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002739
2740 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2741 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002742
developer3885fec2022-09-13 15:13:47 +08002743 if (strncmp(buf, "1", 1) == 0)
2744 *enable = TRUE;
2745 else
2746 *enable = FALSE;
2747
2748 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002749 return RETURN_OK;
2750}
2751
2752//Set 80211h feature enable
2753INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2754{
developer3885fec2022-09-13 15:13:47 +08002755 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2756 struct params params={'\0'};
2757 char config_file[MAX_BUF_SIZE] = {0};
2758
2759 params.name = "ieee80211h";
2760
2761 if (enable) {
2762 params.value = "1";
2763 } else {
2764 params.value = "0";
2765 }
2766
2767 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2768 wifi_hostapdWrite(config_file, &params, 1);
2769
2770 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2771 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2772 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002773}
2774
2775//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.
2776INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2777{
2778 if (NULL == output)
2779 return RETURN_ERR;
2780 *output=100;
2781
2782 return RETURN_OK;
2783}
2784
2785//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.
2786INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2787{
2788 if (NULL == output)
2789 return RETURN_ERR;
2790 *output = -99;
2791
2792 return RETURN_OK;
2793}
2794
2795INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2796{
2797 return RETURN_ERR;
2798}
2799
2800
2801//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2802INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2803{
developer5f222492022-09-13 15:21:52 +08002804 char cmd[MAX_BUF_SIZE]={'\0'};
2805 char buf[MAX_CMD_SIZE]={'\0'};
2806
2807 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2808 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002809 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002810
2811 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
2812 _syscmd(cmd, buf, sizeof(buf));
2813 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08002814
developer5f222492022-09-13 15:21:52 +08002815 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002816 return RETURN_OK;
2817}
2818
2819INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
2820{
developer5f222492022-09-13 15:21:52 +08002821 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2822 struct params params={'\0'};
2823 char buf[MAX_BUF_SIZE] = {'\0'};
2824 char config_file[MAX_BUF_SIZE] = {'\0'};
2825
2826 params.name = "beacon_int";
2827 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
2828 params.value = buf;
2829
2830 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2831 wifi_hostapdWrite(config_file, &params, 1);
2832
2833 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2835 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002836}
2837
2838//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.
2839INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
2840{
developer06a01d92022-09-07 16:32:39 +08002841 //TODO: need to revisit below implementation
2842 char *temp;
developere9d0abd2022-09-13 15:40:57 +08002843 char temp_output[128] = {0};
2844 char temp_TransmitRates[64] = {0};
2845 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08002846
2847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2848 if (NULL == output)
2849 return RETURN_ERR;
2850 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08002851 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
2852
2853 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
2854 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
2855 } else {
2856 temp = strtok(temp_TransmitRates," ");
2857 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08002858 {
developere9d0abd2022-09-13 15:40:57 +08002859 // Convert 100 kbps to Mbps
2860 temp[strlen(temp)-1]=0;
2861 if((temp[0]=='5') && (temp[1]=='\0'))
2862 {
2863 temp="5.5";
2864 }
2865 strcat(temp_output,temp);
2866 temp = strtok(NULL," ");
2867 if(temp!=NULL)
2868 {
2869 strcat(temp_output,",");
2870 }
developer06a01d92022-09-07 16:32:39 +08002871 }
developere9d0abd2022-09-13 15:40:57 +08002872 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08002873 }
developer06a01d92022-09-07 16:32:39 +08002874 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002875 return RETURN_OK;
2876}
2877
2878INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
2879{
2880 char *temp;
2881 char temp1[128];
2882 char temp_output[128];
2883 char temp_TransmitRates[128];
2884 char set[128];
2885 char sub_set[128];
2886 int set_count=0,subset_count=0;
2887 int set_index=0,subset_index=0;
2888 char *token;
2889 int flag=0, i=0;
2890 struct params params={'\0'};
2891 char config_file[MAX_BUF_SIZE] = {0};
2892
2893 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2894 if(NULL == TransmitRates)
2895 return RETURN_ERR;
2896 strcpy(sub_set,TransmitRates);
2897
2898 //Allow only supported Data transmit rate to be set
2899 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
2900 token = strtok(sub_set,",");
2901 while( token != NULL ) /* split the basic rate to be set, by comma */
2902 {
2903 sub_set[subset_count]=atoi(token);
2904 subset_count++;
2905 token=strtok(NULL,",");
2906 }
2907 token=strtok(set,",");
2908 while(token!=NULL) /* split the supported rate by comma */
2909 {
2910 set[set_count]=atoi(token);
2911 set_count++;
2912 token=strtok(NULL,",");
2913 }
2914 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
2915 {
2916 for(set_index=0;set_index < set_count;set_index++)
2917 {
2918 flag=0;
2919 if(sub_set[subset_index]==set[set_index])
2920 break;
2921 else
2922 flag=1; /* No match found */
2923 }
2924 if(flag==1)
2925 return RETURN_ERR; //If value not found return Error
2926 }
2927 strcpy(temp_TransmitRates,TransmitRates);
2928
2929 for(i=0;i<strlen(temp_TransmitRates);i++)
2930 {
2931 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
2932 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
2933 {
2934 continue;
2935 }
2936 else
2937 {
2938 return RETURN_ERR;
2939 }
2940 }
2941 strcpy(temp_output,"");
2942 temp = strtok(temp_TransmitRates,",");
2943 while(temp!=NULL)
2944 {
2945 strcpy(temp1,temp);
2946 if(radioIndex==1)
2947 {
2948 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
2949 {
2950 return RETURN_ERR;
2951 }
2952 }
2953
2954 if(strcmp(temp,"5.5")==0)
2955 {
2956 strcpy(temp1,"55");
2957 }
2958 else
2959 {
2960 strcat(temp1,"0");
2961 }
2962 strcat(temp_output,temp1);
2963 temp = strtok(NULL,",");
2964 if(temp!=NULL)
2965 {
2966 strcat(temp_output," ");
2967 }
2968 }
2969 strcpy(TransmitRates,temp_output);
2970
2971 params.name= "basic_rates";
2972 params.value =TransmitRates;
2973
2974 wifi_dbg_printf("\n%s:",__func__);
2975 wifi_dbg_printf("\nparams.value=%s\n",params.value);
2976 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
2977 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2978 wifi_hostapdWrite(config_file,&params,1);
2979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2980 return RETURN_OK;
2981}
2982
2983//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
2984INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
2985{
2986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2987 FILE *fp = NULL;
2988 char path[256] = {0}, output_string[256] = {0};
2989 int count = 0;
2990 char *interface = NULL;
2991
2992 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
2993 if (fp == NULL)
2994 {
2995 printf("Failed to run command in Function %s\n", __FUNCTION__);
2996 return RETURN_ERR;
2997 }
2998 if (fgets(path, sizeof(path) - 1, fp) != NULL)
2999 {
3000 interface = strchr(path, '=');
3001
3002 if (interface != NULL)
3003 {
3004 strcpy(output_string, interface + 1);
3005 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3006 interface_name[count] = output_string[count];
3007
3008 interface_name[count] = '\0';
3009 }
3010 }
3011 pclose(fp);
3012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3013 return RETURN_OK;
3014}
3015
3016INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3017{
3018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3019 output_struct->radio_BytesSent = 0;
3020 output_struct->radio_BytesReceived = 0;
3021 output_struct->radio_PacketsSent = 0;
3022 output_struct->radio_PacketsReceived = 0;
3023 output_struct->radio_ErrorsSent = 0;
3024 output_struct->radio_ErrorsReceived = 0;
3025 output_struct->radio_DiscardPacketsSent = 0;
3026 output_struct->radio_DiscardPacketsReceived = 0;
3027 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3028 return RETURN_OK;
3029}
3030
3031
3032INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3033{
3034 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3035 CHAR buf[MAX_CMD_SIZE] = {0};
3036 CHAR Value[MAX_BUF_SIZE] = {0};
3037 FILE *fp = NULL;
3038
3039 if (ifname == NULL || strlen(ifname) <= 1)
3040 return RETURN_OK;
3041
3042 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3043 system(buf);
3044
3045 fp = fopen("/tmp/Radio_Stats.txt", "r");
3046 if(fp == NULL)
3047 {
3048 printf("/tmp/Radio_Stats.txt not exists \n");
3049 return RETURN_ERR;
3050 }
3051 fclose(fp);
3052
3053 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3054 File_Reading(buf, Value);
3055 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3056
3057 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3058 File_Reading(buf, Value);
3059 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3060
3061 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3062 File_Reading(buf, Value);
3063 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3064
3065 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3066 File_Reading(buf, Value);
3067 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3068
3069 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3070 File_Reading(buf, Value);
3071 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3072
3073 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3074 File_Reading(buf, Value);
3075 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3076
3077 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3078 File_Reading(buf, Value);
3079 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3080
3081 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3082 File_Reading(buf, Value);
3083 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3084
3085 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3086 return RETURN_OK;
3087}
3088
3089INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3090{
3091 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3092 CHAR buf[MAX_CMD_SIZE] = {0};
3093 FILE *fp = NULL;
3094 INT count = 0;
3095
3096 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3097 {
3098 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3099 File_Reading(buf, status);
3100 }
3101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3102 return RETURN_OK;
3103}
3104
3105//Get detail radio traffic static info
3106INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3107{
3108
3109#if 0
3110 //ifconfig radio_x
3111 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3112 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3113 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3114 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3115
3116 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3117 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3118 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.
3119 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.
3120
3121 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3122 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].
3123 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3124 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.
3125 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
3126 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
3127 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
3128 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
3129 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
3130
3131 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
3132 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
3133 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
3134 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.
3135
3136 return RETURN_OK;
3137#endif
3138
3139 CHAR private_interface_name[MAX_BUF_SIZE] = {0}, public_interface_name[MAX_BUF_SIZE] = {0};
3140 CHAR private_interface_status[MAX_BUF_SIZE] = {0}, public_interface_status[MAX_BUF_SIZE] = {0};
3141 char buf[MAX_BUF_SIZE] = {0};
3142 char cmd[MAX_CMD_SIZE] = {0};
3143 wifi_radioTrafficStats2_t private_radioTrafficStats = {0}, public_radioTrafficStats = {0};
3144
3145 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3146 if (NULL == output_struct)
3147 return RETURN_ERR;
3148
3149 if (radioIndex == 0) //2.4GHz ?
3150 {
3151
3152 GetInterfaceName(private_interface_name, "/nvram/hostapd0.conf");
3153
3154 GetIfacestatus(private_interface_name, private_interface_status);
3155
3156 sprintf(cmd, "%s", "cat /nvram/hostapd0.conf | grep bss=");
3157 File_Reading(cmd, buf);
3158
3159 if (buf[0] == '#')
3160 {
3161 GetInterfaceName(public_interface_name, "/nvram/hostapd4.conf");
3162 }
3163 else
3164 {
3165 GetInterfaceName_virtualInterfaceName_2G(public_interface_name);
3166 }
3167
3168 GetIfacestatus(public_interface_name, public_interface_status);
3169
3170 if (strcmp(private_interface_status, "1") == 0)
3171 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3172 else
3173 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3174
3175 if (strcmp(public_interface_status, "1") == 0)
3176 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3177 else
3178 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3179 }
3180 else if (radioIndex == 1) //5GHz ?
3181 {
3182 GetInterfaceName(private_interface_name, "/nvram/hostapd1.conf");
3183 GetIfacestatus(private_interface_name, private_interface_status);
3184
3185 GetInterfaceName(public_interface_name, "/nvram/hostapd5.conf");
3186 GetIfacestatus(public_interface_name, public_interface_status);
3187
3188 if (strcmp(private_interface_status, "1") == 0)
3189 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3190 else
3191 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3192
3193 if (strcmp(public_interface_status, "1") == 0)
3194 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3195 else
3196 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3197 }
3198
3199 output_struct->radio_BytesSent = private_radioTrafficStats.radio_BytesSent + public_radioTrafficStats.radio_BytesSent;
3200 output_struct->radio_BytesReceived = private_radioTrafficStats.radio_BytesReceived + public_radioTrafficStats.radio_BytesReceived;
3201 output_struct->radio_PacketsSent = private_radioTrafficStats.radio_PacketsSent + public_radioTrafficStats.radio_PacketsSent;
3202 output_struct->radio_PacketsReceived = private_radioTrafficStats.radio_PacketsReceived + public_radioTrafficStats.radio_PacketsReceived;
3203 output_struct->radio_ErrorsSent = private_radioTrafficStats.radio_ErrorsSent + public_radioTrafficStats.radio_ErrorsSent;
3204 output_struct->radio_ErrorsReceived = private_radioTrafficStats.radio_ErrorsReceived + public_radioTrafficStats.radio_ErrorsReceived;
3205 output_struct->radio_DiscardPacketsSent = private_radioTrafficStats.radio_DiscardPacketsSent + public_radioTrafficStats.radio_DiscardPacketsSent;
3206 output_struct->radio_DiscardPacketsReceived = private_radioTrafficStats.radio_DiscardPacketsReceived + public_radioTrafficStats.radio_DiscardPacketsReceived;
3207
3208 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3209 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].
3210 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3211 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.
3212 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
3213 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
3214 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
3215 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
3216 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
3217
3218 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
3219 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
3220 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
3221 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.
3222
3223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3224
3225 return RETURN_OK;
3226}
3227
3228//Set radio traffic static Measureing rules
3229INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3230{
3231 //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
3232 // Else, save the MeasuringRate and MeasuringInterval for future usage
3233
3234 return RETURN_OK;
3235}
3236
3237//To start or stop RadioTrafficStats
3238INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3239{
3240 //zqiu: If the RadioTrafficStats process running
3241 // if(enable)
3242 // return RETURN_OK.
3243 // else
3244 // Stop RadioTrafficStats process
3245 // Else
3246 // if(enable)
3247 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3248 // else
3249 // return RETURN_OK.
3250
3251 return RETURN_OK;
3252}
3253
3254//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
3255INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3256{
3257 //zqiu: Please ignor signalIndex.
3258 if (NULL == SignalLevel)
3259 return RETURN_ERR;
3260 *SignalLevel=(radioIndex==0)?-19:-19;
3261
3262 return RETURN_OK;
3263}
3264
3265//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3266INT wifi_applyRadioSettings(INT radioIndex)
3267{
3268 return RETURN_OK;
3269}
3270
3271//Get the radio index assocated with this SSID entry
3272INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3273{
3274 if (NULL == radioIndex)
3275 return RETURN_ERR;
3276 *radioIndex=ssidIndex%2;
3277
3278 return RETURN_OK;
3279}
3280
3281//Device.WiFi.SSID.{i}.Enable
3282//Get SSID enable configuration parameters (not the SSID enable status)
3283INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3284{
3285 if (NULL == output_bool)
3286 return RETURN_ERR;
3287
3288 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3289 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3290 return wifi_getApEnable(ssidIndex, output_bool);
3291}
3292
3293//Device.WiFi.SSID.{i}.Enable
3294//Set SSID enable configuration parameters
3295INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3296{
3297 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3298 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3299 return wifi_setApEnable(ssidIndex, enable);
3300}
3301
3302//Device.WiFi.SSID.{i}.Status
3303//Get the SSID enable status
3304INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3305{
3306 char cmd[MAX_CMD_SIZE]={0};
3307 char buf[MAX_BUF_SIZE]={0};
3308 BOOL output_bool;
3309
3310 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3311 if (NULL == output_string)
3312 return RETURN_ERR;
3313 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3314 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3315
3316 wifi_getApEnable(ssidIndex,&output_bool);
3317 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3318
3319 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3320 return RETURN_OK;
3321}
3322
3323// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3324INT wifi_getSSIDName(INT apIndex, CHAR *output)
3325{
3326 char config_file[MAX_BUF_SIZE] = {0};
3327
3328 if (NULL == output)
3329 return RETURN_ERR;
3330
3331 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3332 wifi_hostapdRead(config_file,"ssid",output,32);
3333
3334 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3335 return RETURN_OK;
3336}
3337
3338// Set a max 32 byte string and sets an internal variable to the SSID name
3339INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3340{
3341 char str[MAX_BUF_SIZE]={'\0'};
3342 char cmd[MAX_CMD_SIZE]={'\0'};
3343 struct params params;
3344 char config_file[MAX_BUF_SIZE] = {0};
3345
3346 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3347 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3348 return RETURN_ERR;
3349
3350 params.name = "ssid";
3351 params.value = ssid_string;
3352 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3353 wifi_hostapdWrite(config_file, &params, 1);
3354 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3355 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3356
3357 return RETURN_OK;
3358}
3359
3360//Get the BSSID
3361INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3362{
3363 char cmd[MAX_CMD_SIZE]="";
3364
3365 if (NULL == output_string)
3366 return RETURN_ERR;
3367
3368 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3369 {
3370 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3371 _syscmd(cmd, output_string, 64);
3372 return RETURN_OK;
3373 }
3374 strncpy(output_string, "\0", 1);
3375
3376 return RETURN_ERR;
3377}
3378
3379//Get the MAC address associated with this Wifi SSID
3380INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3381{
3382 wifi_getBaseBSSID(ssidIndex,output_string);
3383 return RETURN_OK;
3384}
3385
3386//Get the basic SSID traffic static info
3387//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3388//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3389INT wifi_applySSIDSettings(INT ssidIndex)
3390{
3391 BOOL status = false;
3392 char cmd[MAX_CMD_SIZE] = {0};
3393 char buf[MAX_CMD_SIZE] = {0};
3394 int apIndex, ret;
3395 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3396
3397 wifi_getApEnable(ssidIndex,&status);
3398 // Do not apply when ssid index is disabled
3399 if (status == false)
3400 return RETURN_OK;
3401
3402 /* Doing full remove and add for ssid Index
3403 * Not all hostapd options are supported with reload
3404 * for example macaddr_acl
3405 */
3406 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3407 return RETURN_ERR;
3408
3409 ret = wifi_setApEnable(ssidIndex,true);
3410
3411 /* Workaround for hostapd issue with multiple bss definitions
3412 * when first created interface will be removed
3413 * then all vaps other vaps on same phy are removed
3414 * after calling setApEnable to false readd all enabled vaps */
3415 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3416 apIndex = 2*i+radioIndex;
3417 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3418 _syscmd(cmd, buf, sizeof(buf));
3419 if(*buf == '1')
3420 wifi_setApEnable(apIndex, true);
3421 }
3422
3423 return ret;
3424}
3425
developera3c68b92022-09-13 15:27:29 +08003426struct channels_noise {
3427 int channel;
3428 int noise;
3429};
3430
3431// Return noise array for each channel
3432int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3433{
3434 FILE *f = NULL;
3435 char cmd[128] = {0};
3436 char *line = NULL;
3437 size_t len = 0;
3438 ssize_t read = 0;
3439 int tmp = 0, arr_index = -1;
3440
3441 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3442
3443 if ((f = popen(cmd, "r")) == NULL) {
3444 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3445 return RETURN_ERR;
3446 }
3447 line = malloc(sizeof(char) * 256);
3448 while((read = getline(&line, &len, f)) != -1) {
3449 sscanf(line, "%d", &tmp);
3450 if (tmp > 0) { // channel frequency, the first line must be frequency
3451 arr_index++;
3452 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3453 } else { // noise
3454 channels_noise_arr[arr_index].noise = tmp;
3455 }
3456 }
3457 free(line);
3458 pclose(f);
3459 return RETURN_OK;
3460}
3461
developer06a01d92022-09-07 16:32:39 +08003462//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3463//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3464INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3465{
developera3c68b92022-09-13 15:27:29 +08003466 int index = -1;
3467 wifi_neighbor_ap2_t *scan_array = NULL;
3468 char cmd[256]={0};
3469 char buf[128]={0};
3470 char file_name[32] = {0};
3471 char filter_SSID[32] = {0};
3472 int freq=0;
3473 FILE *f = NULL;
3474 size_t len=0;
3475 ssize_t read = 0;
3476 char *line =NULL;
3477 // int noise_arr[channels_num] = {0};
3478 int channels_num = 0;
3479 int vht_channel_width = 0;
3480 bool get_nosie_ret = false;
3481 bool filter_enable = false;
3482 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003483
3484 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003485
3486 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3487 f = fopen(file_name, "r");
3488 if (f != NULL) {
3489 fgets(filter_SSID, sizeof(file_name), f);
3490 if (strlen(filter_SSID) != 0)
3491 filter_enable = true;
3492 fclose(f);
3493 }
3494
3495 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003496 _syscmd(cmd, buf, sizeof(buf));
developera3c68b92022-09-13 15:27:29 +08003497 channels_num = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003498
developera3c68b92022-09-13 15:27:29 +08003499 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3500 get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer06a01d92022-09-07 16:32:39 +08003501
developera3c68b92022-09-13 15:27:29 +08003502 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3503 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE160' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
3504 fprintf(stderr, "cmd: %s\n", cmd);
3505 if ((f = popen(cmd, "r")) == NULL) {
3506 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3507 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003508 }
developera3c68b92022-09-13 15:27:29 +08003509 line = malloc(sizeof(char) * 256);
3510 while ((read = getline(&line, &len, f)) != -1) {
3511 if(strstr(line, "BSS") != NULL) { // new neighbor info
3512 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3513 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3514 // 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 +08003515
developera3c68b92022-09-13 15:27:29 +08003516 if (!filter_BSS) {
3517 index++;
3518 wifi_neighbor_ap2_t *tmp;
3519 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3520 if (tmp == NULL) { // no more memory to use
3521 index--;
3522 wifi_dbg_printf("%s: realloc failed\n", __func__);
3523 break;
3524 }
3525 scan_array = tmp;
3526 }
3527 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3528
3529 filter_BSS = false;
3530 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3531 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3532 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3533 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3534 } else if (strstr(line, "freq") != NULL) {
3535 sscanf(line," freq: %d", &freq);
3536 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3537
3538 if (freq >= 2412 && freq <= 2484) {
3539 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3540 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3541 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3542 }
3543 else if (freq >= 5160 && freq <= 5805) {
3544 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3545 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3546 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3547 }
3548
3549 scan_array[index].ap_Noise = 0;
3550 if (get_nosie_ret) {
3551 for (int i = 0; i < channels_num; i++) {
3552 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3553 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3554 break;
3555 }
3556 }
3557 }
3558 } else if (strstr(line, "beacon interval") != NULL) {
3559 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3560 } else if (strstr(line, "signal") != NULL) {
3561 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3562 } else if (strstr(line,"SSID") != NULL) {
3563 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3564 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3565 filter_BSS = true;
3566 }
3567 } else if (strstr(line, "Supported rates") != NULL) {
3568 char SRate[80] = {0}, *tmp = NULL;
3569 memset(buf, 0, sizeof(buf));
3570 strcpy(SRate, line);
3571 tmp = strtok(SRate, ":");
3572 tmp = strtok(NULL, ":");
3573 strcpy(buf, tmp);
3574 memset(SRate, 0, sizeof(SRate));
3575
3576 tmp = strtok(buf, " \n");
3577 while (tmp != NULL) {
3578 strcat(SRate, tmp);
3579 if (SRate[strlen(SRate) - 1] == '*') {
3580 SRate[strlen(SRate) - 1] = '\0';
3581 }
3582 strcat(SRate, ",");
3583
3584 tmp = strtok(NULL, " \n");
3585 }
3586 SRate[strlen(SRate) - 1] = '\0';
3587 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3588 } else if (strstr(line, "DTIM") != NULL) {
3589 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3590 } else if (strstr(line, "VHT capabilities") != NULL) {
3591 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3592 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3593 } else if (strstr(line, "HT capabilities") != NULL) {
3594 strcat(scan_array[index].ap_SupportedStandards, ",n");
3595 strcpy(scan_array[index].ap_OperatingStandards, "n");
3596 } else if (strstr(line, "VHT operation") != NULL) {
3597 read = getline(&line, &len, f);
3598 sscanf(line," * channel width: %d", &vht_channel_width);
3599 if(vht_channel_width == 1) {
3600 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3601 } else {
3602 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3603 }
3604 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3605 continue;
3606 } else if (strstr(line, "HT operation") != NULL) {
3607 read = getline(&line, &len, f);
3608 sscanf(line," * secondary channel offset: %s", &buf);
3609 if (!strcmp(buf, "above")) {
3610 //40Mhz +
3611 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3612 }
3613 else if (!strcmp(buf, "below")) {
3614 //40Mhz -
3615 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3616 } else {
3617 //20Mhz
3618 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3619 }
3620 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3621 continue;
3622 } else if (strstr(line, "HE capabilities") != NULL) {
3623 strncat(scan_array[index].ap_SupportedStandards, ",ax", strlen(",ax"));
3624 strncpy(scan_array[index].ap_OperatingStandards, "ax", strlen("ax"));
3625 } else if (strstr(line, "HE PHY Capabilities") != NULL) {
3626 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3627 if (strstr(line, "HE40/2.4GHz") != NULL)
3628 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS", strlen("11AXHE40PLUS"));
3629 else
3630 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20", strlen("11AXHE20"));
3631 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
3632 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80", strlen("11AXHE80")); // AP must always support
3633 read = getline(&line, &len, f);
3634 if (strstr(line, "HE160/5GHz") != NULL)
3635 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160", strlen("11AXHE160"));
3636 }
3637 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3638 continue;
3639 } else if (strstr(line, "WPA") != NULL) {
3640 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3641 } else if (strstr(line, "RSN") != NULL) {
3642 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3643 } else if (strstr(line, "Group cipher") != NULL) {
3644 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3645 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3646 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3647 }
3648 }
3649 }
3650
3651 if (!filter_BSS) {
3652 *output_array_size = index + 1;
3653 } else {
3654 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3655 *output_array_size = index;
3656 }
3657 *neighbor_ap_array = scan_array;
3658 free(line);
3659 pclose(f);
developer06a01d92022-09-07 16:32:39 +08003660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003661 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003662}
3663
3664//>> Deprecated: used for old RDKB code.
3665INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3666{
3667 INT status = RETURN_ERR;
3668
3669 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3670 output_struct->wifi_PLCPErrorCount = 0;
3671 output_struct->wifi_FCSErrorCount = 0;
3672 output_struct->wifi_InvalidMACCount = 0;
3673 output_struct->wifi_PacketsOtherReceived = 0;
3674 output_struct->wifi_Noise = 0;
3675 status = RETURN_OK;
3676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3677 return status;
3678}
3679
3680INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3681{
3682 char cmd[128];
3683 char buf[1280];
3684 char *pos = NULL;
3685
3686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3687 if (NULL == output_struct)
3688 return RETURN_ERR;
3689
3690 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3691
3692 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3693 _syscmd(cmd, buf, sizeof(buf));
3694
3695 pos = buf;
3696 if ((pos = strstr(pos, "RX packets:")) == NULL)
3697 return RETURN_ERR;
3698 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3699
3700 if ((pos = strstr(pos, "TX packets:")) == NULL)
3701 return RETURN_ERR;
3702 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3703
3704 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3705 return RETURN_ERR;
3706 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3707
3708 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3709 return RETURN_ERR;
3710 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3711
3712 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3713 _syscmd(cmd, buf, sizeof(buf));
3714 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3715
3716#if 0
3717 //TODO: need to revisit below implementation
3718 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3719 char interface_name[MAX_BUF_SIZE] = {0};
3720 char interface_status[MAX_BUF_SIZE] = {0};
3721 char Value[MAX_BUF_SIZE] = {0};
3722 char buf[MAX_CMD_SIZE] = {0};
3723 char cmd[MAX_CMD_SIZE] = {0};
3724 FILE *fp = NULL;
3725
3726 if (NULL == output_struct) {
3727 return RETURN_ERR;
3728 }
3729
3730 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3731
3732 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3733 {
3734 if(apIndex == 0) //private_wifi for 2.4G
3735 {
3736 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3737 }
3738 else if(apIndex == 1) //private_wifi for 5G
3739 {
3740 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3741 }
3742 else if(apIndex == 4) //public_wifi for 2.4G
3743 {
3744 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3745 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3746 {
3747 return RETURN_ERR;
3748 }
3749 if(buf[0] == '#')//tp-link
3750 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3751 else//tenda
3752 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3753 }
3754 else if(apIndex == 5) //public_wifi for 5G
3755 {
3756 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3757 }
3758
3759 GetIfacestatus(interface_name, interface_status);
3760
3761 if(0 != strcmp(interface_status, "1"))
3762 return RETURN_ERR;
3763
3764 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3765 system(cmd);
3766
3767 fp = fopen("/tmp/SSID_Stats.txt", "r");
3768 if(fp == NULL)
3769 {
3770 printf("/tmp/SSID_Stats.txt not exists \n");
3771 return RETURN_ERR;
3772 }
3773 fclose(fp);
3774
3775 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3776 File_Reading(buf, Value);
3777 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3778
3779 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3780 File_Reading(buf, Value);
3781 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3782
3783 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3784 File_Reading(buf, Value);
3785 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3786
3787 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3788 File_Reading(buf, Value);
3789 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3790
3791 /* There is no specific parameter from caller to associate the value wifi_Associations */
3792 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3793 //_syscmd(cmd, buf, sizeof(buf));
3794 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3795 }
3796#endif
3797 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3798 return RETURN_OK;
3799}
3800
3801INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3802{
3803 char interface_name[MAX_BUF_SIZE] = {0};
3804 char interface_status[MAX_BUF_SIZE] = {0};
3805 char Value[MAX_BUF_SIZE] = {0};
3806 char buf[MAX_CMD_SIZE] = {0};
3807 char cmd[MAX_CMD_SIZE] = {0};
3808 FILE *fp = NULL;
3809
3810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3811 if (NULL == output_struct)
3812 return RETURN_ERR;
3813
3814 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3815
3816 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3817 {
3818 if(apIndex == 0) //private_wifi for 2.4G
3819 {
3820 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3821 }
3822 else if(apIndex == 1) //private_wifi for 5G
3823 {
3824 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3825 }
3826 else if(apIndex == 4) //public_wifi for 2.4G
3827 {
3828 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3829 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3830 {
3831 return RETURN_ERR;
3832 }
3833 if(buf[0] == '#')
3834 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3835 else
3836 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3837 }
3838 else if(apIndex == 5) //public_wifi for 5G
3839 {
3840 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3841 }
3842
3843 GetIfacestatus(interface_name, interface_status);
3844
3845 if(0 != strcmp(interface_status, "1"))
3846 return RETURN_ERR;
3847
3848 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3849 system(cmd);
3850
3851 fp = fopen("/tmp/SSID_Stats.txt", "r");
3852 if(fp == NULL)
3853 {
3854 printf("/tmp/SSID_Stats.txt not exists \n");
3855 return RETURN_ERR;
3856 }
3857 fclose(fp);
3858
3859 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3860 File_Reading(buf, Value);
3861 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
3862
3863 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3864 File_Reading(buf, Value);
3865 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
3866
3867 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3868 File_Reading(buf, Value);
3869 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
3870
3871 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3872 File_Reading(buf, Value);
3873 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
3874 }
3875
3876 output_struct->wifi_UnicastPacketsSent = 0;
3877 output_struct->wifi_UnicastPacketsReceived = 0;
3878 output_struct->wifi_MulticastPacketsSent = 0;
3879 output_struct->wifi_MulticastPacketsReceived = 0;
3880 output_struct->wifi_BroadcastPacketsSent = 0;
3881 output_struct->wifi_BroadcastPacketsRecevied = 0;
3882 output_struct->wifi_UnknownPacketsReceived = 0;
3883
3884 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3885 return RETURN_OK;
3886}
3887
3888INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
3889{
3890 INT status = RETURN_ERR;
3891
3892 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3893 //Below values should get updated from hal
3894 output_struct->wifi_RetransCount=0;
3895 output_struct->wifi_FailedRetransCount=0;
3896 output_struct->wifi_RetryCount=0;
3897 output_struct->wifi_MultipleRetryCount=0;
3898 output_struct->wifi_ACKFailureCount=0;
3899 output_struct->wifi_AggregatedPacketCount=0;
3900
3901 status = RETURN_OK;
3902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3903
3904 return status;
3905}
3906
3907INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
3908{
3909 INT status = RETURN_ERR;
3910 UINT index;
3911 wifi_neighbor_ap_t *pt=NULL;
3912
3913 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3914 *output_array_size=2;
3915 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
3916 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
3917 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
3918 strcpy(pt->ap_Radio,"");
3919 strcpy(pt->ap_SSID,"");
3920 strcpy(pt->ap_BSSID,"");
3921 strcpy(pt->ap_Mode,"");
3922 pt->ap_Channel=1;
3923 pt->ap_SignalStrength=0;
3924 strcpy(pt->ap_SecurityModeEnabled,"");
3925 strcpy(pt->ap_EncryptionMode,"");
3926 strcpy(pt->ap_OperatingFrequencyBand,"");
3927 strcpy(pt->ap_SupportedStandards,"");
3928 strcpy(pt->ap_OperatingStandards,"");
3929 strcpy(pt->ap_OperatingChannelBandwidth,"");
3930 pt->ap_BeaconPeriod=1;
3931 pt->ap_Noise=0;
3932 strcpy(pt->ap_BasicDataTransferRates,"");
3933 strcpy(pt->ap_SupportedDataTransferRates,"");
3934 pt->ap_DTIMPeriod=1;
3935 pt->ap_ChannelUtilization = 1;
3936 }
3937
3938 status = RETURN_OK;
3939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3940
3941 return status;
3942}
3943
3944//----------------- AP HAL -------------------------------
3945
3946//>> Deprecated: used for old RDKB code.
3947INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
3948{
3949 if (NULL == output_ulong || NULL == output_struct)
3950 return RETURN_ERR;
3951 *output_ulong = 0;
3952 *output_struct = NULL;
3953 return RETURN_OK;
3954}
3955
3956#ifdef HAL_NETLINK_IMPL
3957static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
3958 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3959 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3960 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
3961 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
3962 char mac_addr[20];
3963 static int count=0;
3964 int rate=0;
3965
3966 wifi_device_info_t *out = (wifi_device_info_t*)arg;
3967
3968 nla_parse(tb,
3969 NL80211_ATTR_MAX,
3970 genlmsg_attrdata(gnlh, 0),
3971 genlmsg_attrlen(gnlh, 0),
3972 NULL);
3973
3974 if(!tb[NL80211_ATTR_STA_INFO]) {
3975 fprintf(stderr, "sta stats missing!\n");
3976 return NL_SKIP;
3977 }
3978
3979
3980 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
3981 fprintf(stderr, "failed to parse nested attributes!\n");
3982 return NL_SKIP;
3983 }
3984
3985 //devIndex starts from 1
3986 if( ++count == out->wifi_devIndex )
3987 {
3988 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
3989 //Getting the mac addrress
3990 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
3991
3992 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
3993 fprintf(stderr, "failed to parse nested rate attributes!");
3994 return NL_SKIP;
3995 }
3996
3997 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
3998 if(rinfo[NL80211_RATE_INFO_BITRATE])
3999 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4000 out->wifi_devTxRate = rate/10;
4001 }
4002
4003 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4004 fprintf(stderr, "failed to parse nested rate attributes!");
4005 return NL_SKIP;
4006 }
4007
4008 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4009 if(rinfo[NL80211_RATE_INFO_BITRATE])
4010 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4011 out->wifi_devRxRate = rate/10;
4012 }
4013 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4014 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4015
4016 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4017 count = 0; //starts the count for next cycle
4018 return NL_STOP;
4019 }
4020
4021 return NL_SKIP;
4022
4023}
4024#endif
4025
4026INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4027{
4028#ifdef HAL_NETLINK_IMPL
4029 Netlink nl;
4030 char if_name[10];
4031
4032 wifi_device_info_t info;
4033 info.wifi_devIndex = devIndex;
4034
4035 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4036
4037 nl.id = initSock80211(&nl);
4038
4039 if (nl.id < 0) {
4040 fprintf(stderr, "Error initializing netlink \n");
4041 return -1;
4042 }
4043
4044 struct nl_msg* msg = nlmsg_alloc();
4045
4046 if (!msg) {
4047 fprintf(stderr, "Failed to allocate netlink message.\n");
4048 nlfree(&nl);
4049 return -2;
4050 }
4051
4052 genlmsg_put(msg,
4053 NL_AUTO_PORT,
4054 NL_AUTO_SEQ,
4055 nl.id,
4056 0,
4057 NLM_F_DUMP,
4058 NL80211_CMD_GET_STATION,
4059 0);
4060
4061 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4062 nl_send_auto(nl.socket, msg);
4063 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4064 nl_recvmsgs(nl.socket, nl.cb);
4065 nlmsg_free(msg);
4066 nlfree(&nl);
4067
4068 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4069 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4070 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4071 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4072 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4073 return RETURN_OK;
4074#else
4075 //iw utility to retrieve station information
4076#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4077#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4078#define MACFILE "/tmp/wifi_AssoMac.txt"
4079#define TXRATEFILE "/tmp/wifi_txrate.txt"
4080#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4081 FILE *file = NULL;
4082 char if_name[10] = {'\0'};
4083 char pipeCmd[256] = {'\0'};
4084 char line[256];
4085 int count,device = 0;
4086
4087 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4088
4089 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4090 file = popen(pipeCmd, "r");
4091
4092 if(file == NULL)
4093 return RETURN_ERR; //popen failed
4094
4095 fgets(line, sizeof line, file);
4096 device = atoi(line);
4097 pclose(file);
4098
4099 if(device == 0)
4100 return RETURN_ERR; //No devices are connected
4101
4102 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4103 system(pipeCmd);
4104
4105 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4106
4107 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4108
4109 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4110
4111 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4112
4113 //devIndex starts from 1, ++count
4114 if((file = fopen(SIGNALFILE, "r")) != NULL )
4115 {
4116 for(count =0;fgets(line, sizeof line, file) != NULL;)
4117 {
4118 if (++count == devIndex)
4119 {
4120 output_struct->wifi_devSignalStrength = atoi(line);
4121 break;
4122 }
4123 }
4124 fclose(file);
4125 }
4126 else
4127 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4128
4129 if((file = fopen(MACFILE, "r")) != NULL )
4130 {
4131 for(count =0;fgets(line, sizeof line, file) != NULL;)
4132 {
4133 if (++count == devIndex)
4134 {
4135 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]);
4136 break;
4137 }
4138 }
4139 fclose(file);
4140 }
4141 else
4142 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4143
4144 if((file = fopen(TXRATEFILE, "r")) != NULL )
4145 {
4146 for(count =0;fgets(line, sizeof line, file) != NULL;)
4147 {
4148 if (++count == devIndex)
4149 {
4150 output_struct->wifi_devTxRate = atoi(line);
4151 break;
4152 }
4153 }
4154 fclose(file);
4155 }
4156 else
4157 fprintf(stderr,"fopen wifi_txrate.txt failed");
4158
4159 if((file = fopen(RXRATEFILE, "r")) != NULL)
4160 {
4161 for(count =0;fgets(line, sizeof line, file) != NULL;)
4162 {
4163 if (++count == devIndex)
4164 {
4165 output_struct->wifi_devRxRate = atoi(line);
4166 break;
4167 }
4168 }
4169 fclose(file);
4170 }
4171 else
4172 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4173
4174 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4175
4176 return RETURN_OK;
4177#endif
4178}
4179
4180INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4181{
4182 if (NULL == device)
4183 return RETURN_ERR;
4184 return RETURN_OK;
4185}
4186//<<
4187
4188
4189//--------------wifi_ap_hal-----------------------------
4190//enables CTS protection for the radio used by this AP
4191INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4192{
4193 //save config and Apply instantly
4194 return RETURN_ERR;
4195}
4196
4197// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4198INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4199{
developer463d39a2022-09-13 15:32:51 +08004200 char config_file[64] = {'\0'};
4201 char buf[64] = {'\0'};
4202 struct params list;
4203
4204 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4205 list.name = "ht_coex";
4206 snprintf(buf, sizeof(buf), "%d", enable);
4207 list.value = buf;
4208
4209 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4210 wifi_hostapdWrite(config_file, &list, 1);
4211 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4212
4213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4214
4215 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004216}
4217
4218//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4219INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4220{
developerea4bcce2022-09-13 15:26:13 +08004221 char config_file[MAX_BUF_SIZE] = {'\0'};
4222 char buf[MAX_BUF_SIZE] = {'\0'};
4223 struct params list;
4224
4225 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4226 if (threshold < 256 || threshold > 2346 )
4227 return RETURN_ERR;
4228 list.name = "fragm_threshold";
4229 snprintf(buf, sizeof(buf), "%d", threshold);
4230 list.value = buf;
4231
4232 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4233 wifi_hostapdWrite(config_file, &list, 1);
4234 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004235
developerea4bcce2022-09-13 15:26:13 +08004236 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004237
4238 return RETURN_OK;
4239}
4240
4241// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4242INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4243{
developer51a927d2022-09-13 15:42:22 +08004244 char config_file[64] = {'\0'};
4245 char cmd[128] = {'\0'};
4246 char buf[64] = {'\0'};
4247 char stbc_config[16] = {'\0'};
4248 wifi_band band;
4249 int iterator = 0;
4250 BOOL current_stbc = FALSE;
4251
4252 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4253
4254 band = wifi_index_to_band(radioIndex);
4255 if (band == band_invalid)
4256 return RETURN_ERR;
4257
4258 if (band == band_2_4)
4259 iterator = 1;
4260 else if (band == band_5)
4261 iterator = 2;
4262 else
4263 return RETURN_OK;
4264
4265 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4266
4267 // set ht and vht config
4268 for (int i = 0; i < iterator; i++) {
4269 memset(stbc_config, 0, sizeof(stbc_config));
4270 memset(cmd, 0, sizeof(cmd));
4271 memset(buf, 0, sizeof(buf));
4272 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4273 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4274 _syscmd(cmd, buf, sizeof(buf));
4275 if (strlen(buf) != 0)
4276 current_stbc = TRUE;
4277 if (current_stbc == STBC_Enable)
4278 continue;
4279
4280 if (STBC_Enable == TRUE) {
4281 // Append the STBC flags in capab config
4282 memset(cmd, 0, sizeof(cmd));
4283 if (i == 0)
4284 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4285 else
4286 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4287 _syscmd(cmd, buf, sizeof(buf));
4288 } else if (STBC_Enable == FALSE) {
4289 // Remove the STBC flags and remain other flags in capab
4290 memset(cmd, 0, sizeof(cmd));
4291 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4292 _syscmd(cmd, buf, sizeof(buf));
4293 memset(cmd, 0, sizeof(cmd));
4294 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4295 _syscmd(cmd, buf, sizeof(buf));
4296 }
4297 }
4298
4299 wifi_reloadAp(radioIndex);
4300
4301 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4302 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004303}
4304
4305// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4306INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4307{
4308 return RETURN_ERR;
4309}
4310
4311// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4312INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4313{
4314 //Apply instantly
4315 return RETURN_ERR;
4316}
4317
4318//P2 // outputs the number of Tx streams
4319INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4320{
developer2de97692022-09-26 14:00:03 +08004321 char buf[8] = {0};
4322 char cmd[128] = {0};
4323
4324 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4325
4326 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4327 _syscmd(cmd, buf, sizeof(buf));
4328
4329 // if there is no record, output the max number of spatial streams
4330 if (strlen(buf) == 0) {
4331 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4332 _syscmd(cmd, buf, sizeof(buf));
4333 }
4334
4335 *output_int = (INT)strtol(buf, NULL, 10);
4336
4337 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4338
4339 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004340}
4341
4342//P2 // sets the number of Tx streams to an enviornment variable
4343INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4344{
developer2de97692022-09-26 14:00:03 +08004345 char cmd[128] = {0};
4346 char buf[128] = {0};
4347 char chain_mask_file[128] = {0};
4348 FILE *f = NULL;
4349
4350 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4351
4352 if (numStreams == 0) {
4353 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4354 return RETURN_ERR;
4355 }
4356 wifi_setRadioEnable(radioIndex, FALSE);
4357 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4358 _syscmd(cmd, buf, sizeof(buf));
4359
4360 if (strlen(buf) > 0) {
4361 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4362 return RETURN_ERR;
4363 }
4364 wifi_setRadioEnable(radioIndex, TRUE);
4365
4366 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4367 f = fopen(chain_mask_file, "w");
4368 if (f == NULL) {
4369 fprintf(stderr, "%s: fopen failed.\n", __func__);
4370 return RETURN_ERR;
4371 }
4372 fprintf(f, "%d", numStreams);
4373 fclose(f);
4374 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4375 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004376}
4377
4378//P2 // outputs the number of Rx streams
4379INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4380{
developer2de97692022-09-26 14:00:03 +08004381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4382 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4383 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004384 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004385 }
4386 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004387 return RETURN_OK;
4388}
4389
4390//P2 // sets the number of Rx streams to an enviornment variable
4391INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4392{
developer2de97692022-09-26 14:00:03 +08004393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4394 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4395 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4396 return RETURN_ERR;
4397 }
4398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004399 return RETURN_ERR;
4400}
4401
4402//Get radio RDG enable setting
4403INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4404{
4405 if (NULL == output_bool)
4406 return RETURN_ERR;
4407 *output_bool = TRUE;
4408 return RETURN_OK;
4409}
4410
4411//Get radio RDG enable setting
4412INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4413{
4414 if (NULL == output_bool)
4415 return RETURN_ERR;
4416 *output_bool = TRUE;
4417 return RETURN_OK;
4418}
4419
4420//Set radio RDG enable setting
4421INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4422{
4423 return RETURN_ERR;
4424}
4425
4426//Get radio ADDBA enable setting
4427INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4428{
4429 if (NULL == output_bool)
4430 return RETURN_ERR;
4431 *output_bool = TRUE;
4432 return RETURN_OK;
4433}
4434
4435//Set radio ADDBA enable setting
4436INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4437{
4438 return RETURN_ERR;
4439}
4440
4441//Get radio auto block ack enable setting
4442INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4443{
4444 if (NULL == output_bool)
4445 return RETURN_ERR;
4446 *output_bool = TRUE;
4447 return RETURN_OK;
4448}
4449
4450//Set radio auto block ack enable setting
4451INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4452{
4453 return RETURN_ERR;
4454}
4455
4456//Get radio 11n pure mode enable support
4457INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4458{
4459 if (NULL == output_bool)
4460 return RETURN_ERR;
4461 *output_bool = TRUE;
4462 return RETURN_OK;
4463}
4464
4465//Get radio 11n pure mode enable setting
4466INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4467{
4468 if (NULL == output_bool)
4469 return RETURN_ERR;
4470 *output_bool = TRUE;
4471 return RETURN_OK;
4472}
4473
4474//Set radio 11n pure mode enable setting
4475INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4476{
4477 return RETURN_ERR;
4478}
4479
4480//Get radio IGMP snooping enable setting
4481INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4482{
developer81bf2ed2022-09-13 15:31:14 +08004483 char cmd[128]={0};
4484 char buf[4]={0};
4485 bool bridge = FALSE, mac80211 = FALSE;
4486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4487
4488 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004489 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004490
4491 *output_bool = FALSE;
4492
4493 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4494 _syscmd(cmd, buf, sizeof(buf));
4495 if (strncmp(buf, "1", 1) == 0)
4496 bridge = TRUE;
4497
4498 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4499 _syscmd(cmd, buf, sizeof(buf));
4500 if (strncmp(buf, "1", 1) == 0)
4501 mac80211 = TRUE;
4502
4503 if (bridge && mac80211)
4504 *output_bool = TRUE;
4505
4506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004507 return RETURN_OK;
4508}
4509
4510//Set radio IGMP snooping enable setting
4511INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4512{
developer81bf2ed2022-09-13 15:31:14 +08004513 char cmd[128]={0};
4514 char buf[4]={0};
4515
4516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4517
4518 // bridge
4519 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4520 _syscmd(cmd, buf, sizeof(buf));
4521
4522 // mac80211
4523 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4524 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4525 _syscmd(cmd, buf, sizeof(buf));
4526 }
4527 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4528 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004529}
4530
4531//Get the Reset count of radio
4532INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4533{
4534 if (NULL == output_int)
4535 return RETURN_ERR;
4536 *output_int = (radioIndex==0)? 1: 3;
4537
4538 return RETURN_OK;
4539}
4540
4541
4542//---------------------------------------------------------------------------------------------------
4543//
4544// Additional Wifi AP level APIs used for Access Point devices
4545//
4546//---------------------------------------------------------------------------------------------------
4547
4548// creates a new ap and pushes these parameters to the hardware
4549INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4550{
4551 char buf[1024];
4552 char cmd[128];
4553
4554 if (NULL == essid)
4555 return RETURN_ERR;
4556
4557 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4558 _syscmd(cmd, buf, sizeof(buf));
4559
4560 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4561 _syscmd(cmd, buf, sizeof(buf));
4562
4563 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4564
4565 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4566 _syscmd(cmd, buf, sizeof(buf));
4567
4568 return RETURN_OK;
4569}
4570
4571// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4572INT wifi_deleteAp(INT apIndex)
4573{
4574 char buf[1024];
4575 char cmd[128];
4576
4577 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4578 _syscmd(cmd, buf, sizeof(buf));
4579
4580 wifi_removeApSecVaribles(apIndex);
4581
4582 return RETURN_OK;
4583}
4584
4585// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4586INT wifi_getApName(INT apIndex, CHAR *output_string)
4587{
4588 if(NULL == output_string)
4589 return RETURN_ERR;
4590
4591 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4592 return RETURN_OK;
4593}
4594
4595// Outputs the index number in that corresponds to the SSID string
4596INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4597{
4598 CHAR *pos = NULL;
4599
4600 *output_int = -1;
4601 pos = strstr(inputSsidString, AP_PREFIX);
4602 if(pos)
4603 {
4604 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4605 return RETURN_OK;
4606 }
4607 return RETURN_ERR;
4608}
4609
4610INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4611{
4612 return wifi_getIndexFromName(inputSsidString, output_int);
4613}
4614
4615// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4616INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4617{
4618 char buf[MAX_BUF_SIZE] = {0};
4619 char cmd[MAX_CMD_SIZE] = {0};
4620 char config_file[MAX_BUF_SIZE] = {0};
4621
4622 if(NULL == output_string)
4623 return RETURN_ERR;
4624
4625 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4626 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4627 if((strcmp(buf,"3")==0))
4628 snprintf(output_string, 32, "WPAand11i");
4629 else if((strcmp(buf,"2")==0))
4630 snprintf(output_string, 32, "11i");
4631 else if((strcmp(buf,"1")==0))
4632 snprintf(output_string, 32, "WPA");
4633 else
4634 snprintf(output_string, 32, "None");
4635
4636 return RETURN_OK;
4637}
4638
4639// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4640INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4641{
4642 char config_file[MAX_BUF_SIZE] = {0};
4643 struct params list;
4644
4645 if (NULL == beaconTypeString)
4646 return RETURN_ERR;
4647 list.name = "wpa";
4648 list.value = "0";
4649
4650 if((strcmp(beaconTypeString,"WPAand11i")==0))
4651 list.value="3";
4652 else if((strcmp(beaconTypeString,"11i")==0))
4653 list.value="2";
4654 else if((strcmp(beaconTypeString,"WPA")==0))
4655 list.value="1";
4656
4657 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4658 wifi_hostapdWrite(config_file, &list, 1);
4659 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4660 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4661 return RETURN_OK;
4662}
4663
4664// sets the beacon interval on the hardware for this AP
4665INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4666{
developer5f222492022-09-13 15:21:52 +08004667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4668 struct params params={'\0'};
4669 char buf[MAX_BUF_SIZE] = {'\0'};
4670 char config_file[MAX_BUF_SIZE] = {'\0'};
4671
4672 params.name = "beacon_int";
4673 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4674 params.value = buf;
4675
4676 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4677 wifi_hostapdWrite(config_file, &params, 1);
4678
4679 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4681 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004682}
4683
4684INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4685{
4686 //save config and apply instantly
4687 return RETURN_ERR;
4688}
4689
4690// Get the packet size threshold supported.
4691INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4692{
4693 //save config and apply instantly
4694 if (NULL == output_bool)
4695 return RETURN_ERR;
4696 *output_bool = FALSE;
4697 return RETURN_OK;
4698}
4699
4700// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4701INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4702{
4703 char cmd[128];
4704 char buf[512];
4705
4706 if (threshold > 0)
4707 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4708 else
4709 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4710 _syscmd(cmd, buf, sizeof(buf));
4711
4712 return RETURN_OK;
4713}
4714
4715// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4716INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4717{
4718 if (NULL == output_string)
4719 return RETURN_ERR;
4720 snprintf(output_string, 32, "TKIPandAESEncryption");
4721 return RETURN_OK;
4722
4723}
4724
4725// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4726INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4727{
4728 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4729 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4730
4731 if(NULL == output_string)
4732 return RETURN_ERR;
4733
4734 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4735 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4736
4737 if(strcmp(buf,"0")==0)
4738 {
4739 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4740 snprintf(output_string, 32, "None");
4741 return RETURN_OK;
4742 }
4743 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4744 param_name = "rsn_pairwise";
4745 else if((strcmp(buf,"1")==0))
4746 param_name = "wpa_pairwise";
4747 else
4748 return RETURN_ERR;
4749 memset(output_string,'\0',32);
4750 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4751 wifi_hostapdRead(config_file,param_name,output_string,32);
4752 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4753
4754 if(strcmp(output_string,"TKIP") == 0)
4755 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4756 else if(strcmp(output_string,"CCMP") == 0)
4757 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4758 else if(strcmp(output_string,"TKIP CCMP") == 0)
4759 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4760
4761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4762 return RETURN_OK;
4763}
4764
4765// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4766INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4767{
4768 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4769 struct params params={'\0'};
4770 char output_string[32];
4771 char config_file[MAX_BUF_SIZE] = {0};
4772
4773 memset(output_string,'\0',32);
4774 wifi_getApWpaEncryptionMode(apIndex,output_string);
4775
4776 if(strcmp(encMode, "TKIPEncryption") == 0)
4777 params.value = "TKIP";
4778 else if(strcmp(encMode,"AESEncryption") == 0)
4779 params.value = "CCMP";
4780 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4781 params.value = "TKIP CCMP";
4782
4783 if((strcmp(output_string,"WPAand11i")==0))
4784 {
4785 params.name = "wpa_pairwise";
4786 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4787 wifi_hostapdWrite(config_file, &params, 1);
4788 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4789
4790 params.name,"rsn_pairwise";
4791 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4792 wifi_hostapdWrite(config_file, &params, 1);
4793 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4794
4795 return RETURN_OK;
4796 }
4797 else if((strcmp(output_string,"11i")==0))
4798 {
4799 params.name = "rsn_pairwise";
4800 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4801 wifi_hostapdWrite(config_file, &params, 1);
4802 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4803 return RETURN_OK;
4804 }
4805 else if((strcmp(output_string,"WPA")==0))
4806 {
4807 params.name = "wpa_pairwise";
4808 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4809 wifi_hostapdWrite(config_file, &params, 1);
4810 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4811 return RETURN_OK;
4812 }
4813
4814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4815 return RETURN_OK;
4816}
4817
4818// deletes internal security varable settings for this ap
4819INT wifi_removeApSecVaribles(INT apIndex)
4820{
4821 //TODO: remove the entry in hostapd config file
4822 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4823 //_syscmd(cmd, buf, sizeof(buf));
4824
4825 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4826 //_syscmd(cmd, buf, sizeof(buf));
4827 return RETURN_ERR;
4828}
4829
4830// changes the hardware settings to disable encryption on this ap
4831INT wifi_disableApEncryption(INT apIndex)
4832{
4833 //Apply instantly
4834 return RETURN_ERR;
4835}
4836
4837// set the authorization mode on this ap
4838// mode mapping as: 1: open, 2: shared, 4:auto
4839INT wifi_setApAuthMode(INT apIndex, INT mode)
4840{
4841 //Apply instantly
4842 return RETURN_ERR;
4843}
4844
4845// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4846INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4847{
4848 //save to wifi config, and wait for wifi restart to apply
4849 struct params params={'\0'};
4850 char config_file[MAX_BUF_SIZE] = {0};
4851 int ret;
4852
4853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4854 if(authMode == NULL)
4855 return RETURN_ERR;
4856
4857 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
4858 params.name = "wpa_key_mgmt";
4859
4860 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
4861 params.value = "WPA-PSK";
4862 else if(strcmp(authMode,"EAPAuthentication") == 0)
4863 params.value = "WPA-EAP";
4864 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
4865 return RETURN_OK; //This is taken careof in beaconType
4866
4867 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4868 ret=wifi_hostapdWrite(config_file,&params,1);
4869 if(!ret)
4870 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
4871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4872
4873 return ret;
4874}
4875
4876// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4877INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4878{
4879 //save to wifi config, and wait for wifi restart to apply
4880 char BeaconType[50] = {0};
4881 char config_file[MAX_BUF_SIZE] = {0};
4882
4883 *authMode = 0;
4884 wifi_getApBeaconType(apIndex,BeaconType);
4885 printf("%s____%s \n",__FUNCTION__,BeaconType);
4886
4887 if(strcmp(BeaconType,"None") == 0)
4888 strcpy(authMode,"None");
4889 else
4890 {
4891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4892 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
4893 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
4894 if(strcmp(authMode,"WPA-PSK") == 0)
4895 strcpy(authMode,"SharedAuthentication");
4896 else if(strcmp(authMode,"WPA-EAP") == 0)
4897 strcpy(authMode,"EAPAuthentication");
4898 }
4899
4900 return RETURN_OK;
4901}
4902
4903// Outputs the number of stations associated per AP
4904INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
4905{
4906 char cmd[128]={0};
4907 char buf[128]={0};
4908 BOOL status = false;
4909
4910 if(apIndex > MAX_APS)
4911 return RETURN_ERR;
4912
4913 wifi_getApEnable(apIndex,&status);
4914 if (!status)
4915 return RETURN_OK;
4916
4917 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
4918 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
4919 _syscmd(cmd, buf, sizeof(buf));
4920 sscanf(buf,"%lu", output_ulong);
4921
4922 return RETURN_OK;
4923}
4924
4925// manually removes any active wi-fi association with the device specified on this ap
4926INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
4927{
4928 char buf[126]={'\0'};
4929
4930 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
4931 system(buf);
4932
4933 return RETURN_OK;
4934}
4935
4936// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
4937INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
4938{
4939 if(NULL == output_int)
4940 return RETURN_ERR;
4941 *output_int = apIndex%2;
4942 return RETURN_OK;
4943}
4944
4945// sets the radio index for the specific ap
4946INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
4947{
4948 //set to config only and wait for wifi reset to apply settings
4949 return RETURN_ERR;
4950}
4951
4952// Get the ACL MAC list per AP
4953INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4954{
4955 char cmd[MAX_CMD_SIZE]={'\0'};
4956 int ret = 0;
4957
4958 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4959 ret = _syscmd(cmd,macArray,buf_size);
4960 if (ret != 0)
4961 return RETURN_ERR;
4962
4963 return RETURN_OK;
4964}
4965
developere6aafda2022-09-13 14:59:28 +08004966INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4967{
4968 char cmd[MAX_CMD_SIZE]={'\0'};
4969 int ret = 0;
4970
4971 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4972 ret = _syscmd(cmd,macArray,buf_size);
4973 if (ret != 0)
4974 return RETURN_ERR;
4975
4976 return RETURN_OK;
4977}
4978
4979
developer06a01d92022-09-07 16:32:39 +08004980// Get the list of stations associated per AP
4981INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
4982{
4983 char cmd[128];
4984
4985 if(apIndex > 3) //Currently supporting apIndex upto 3
4986 return RETURN_ERR;
4987 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
4988 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
4989 _syscmd(cmd, macArray, buf_size);
4990
4991 return RETURN_OK;
4992}
4993
4994// adds the mac address to the filter list
4995//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4996INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4997{
4998 char cmd[MAX_CMD_SIZE]={'\0'};
4999 char buf[MAX_BUF_SIZE]={'\0'};
5000
5001#if 0
5002 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5003 if(_syscmd(cmd,buf,sizeof(buf)))
5004 return RETURN_ERR;
5005#endif
5006 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5007 if(_syscmd(cmd,buf,sizeof(buf)))
5008 return RETURN_ERR;
5009
5010 return RETURN_OK;
5011}
5012
5013// deletes the mac address from the filter list
5014//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5015INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5016{
5017 char cmd[MAX_CMD_SIZE]={'\0'};
5018 char buf[MAX_BUF_SIZE]={'\0'};
5019
5020#if 0
5021 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5022 if(_syscmd(cmd,buf,sizeof(buf)))
5023 return RETURN_ERR;
5024
5025#endif
5026 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5027 if(_syscmd(cmd,buf,sizeof(buf)))
5028 return RETURN_ERR;
5029
5030 return RETURN_OK;
5031}
5032
5033// outputs the number of devices in the filter list
5034INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5035{
developere6aafda2022-09-13 14:59:28 +08005036 char cmd[MAX_BUF_SIZE]={0};
5037 char buf[MAX_CMD_SIZE]={0};
5038
5039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5040 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005041 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005042
5043 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5044 _syscmd(cmd, buf, sizeof(buf));
5045
5046 *output_uint = atoi(buf);
5047
5048 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5049 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005050}
5051
5052INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5053{
5054 char cmd[128]={'\0'};
5055 char buf[128]={'\0'};
5056
5057 if(strcmp(action,"DENY")==0)
5058 {
5059 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5060 system(buf);
5061 return RETURN_OK;
5062 }
5063
5064 if(strcmp(action,"ALLOW")==0)
5065 {
5066 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5067 system(buf);
5068 return RETURN_OK;
5069 }
5070
5071 return RETURN_ERR;
5072
5073}
5074
5075// enable kick for devices on acl black list
5076INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5077{
5078 char aclArray[512] = {0}, *acl = NULL;
5079 char assocArray[512] = {0}, *asso = NULL;
5080
developere6aafda2022-09-13 14:59:28 +08005081 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005082 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5083
5084 // if there are no devices connected there is nothing to do
5085 if (strlen(assocArray) < 17)
5086 return RETURN_OK;
5087
5088 if (enable == TRUE)
5089 {
5090 //kick off the MAC which is in ACL array (deny list)
5091 acl = strtok(aclArray, "\r\n");
5092 while (acl != NULL) {
5093 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5094 wifi_kickApAssociatedDevice(apIndex, acl);
5095
5096 acl = strtok(NULL, "\r\n");
5097 }
developere6aafda2022-09-13 14:59:28 +08005098 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005099 }
5100 else
5101 {
developere6aafda2022-09-13 14:59:28 +08005102 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005103 }
5104
5105#if 0
5106 //TODO: need to revisit below implementation
5107 char aclArray[512]={0}, *acl=NULL;
5108 char assocArray[512]={0}, *asso=NULL;
5109 char buf[256]={'\0'};
5110 char action[10]={'\0'};
5111 FILE *fr=NULL;
5112 char interface[10]={'\0'};
5113 char config_file[MAX_BUF_SIZE] = {0};
5114
5115 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5116 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5117 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5118 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5119
5120 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5121 system(buf);
5122 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5123 system(buf);
5124 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5125 system(buf);
5126 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5127 system(buf);
5128 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5129 system(buf);
5130
5131 if ( enable == TRUE )
5132 {
5133 int device_count=0;
5134 strcpy(action,"DENY");
5135 //kick off the MAC which is in ACL array (deny list)
5136 acl = strtok (aclArray,",");
5137 while (acl != NULL) {
5138 if(strlen(acl)>=17)
5139 {
5140 apply_rules(apIndex, acl,action,interface);
5141 device_count++;
5142 //Register mac to be blocked ,in syscfg.db persistent storage
5143 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5144 system(buf);
5145 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5146 system(buf);
5147 system("syscfg commit");
5148
5149 wifi_kickApAssociatedDevice(apIndex, acl);
5150 }
5151 acl = strtok (NULL, ",");
5152 }
5153 }
5154 else
5155 {
5156 int device_count=0;
5157 char cmdmac[20]={'\0'};
5158 strcpy(action,"ALLOW");
5159 //kick off the MAC which is not in ACL array (allow list)
5160 acl = strtok (aclArray,",");
5161 while (acl != NULL) {
5162 if(strlen(acl)>=17)
5163 {
5164 apply_rules(apIndex, acl,action,interface);
5165 device_count++;
5166 //Register mac to be Allowed ,in syscfg.db persistent storage
5167 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5168 system(buf);
5169 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5170 system(buf);
5171 sprintf(cmdmac,"%s",acl);
5172 }
5173 acl = strtok (NULL, ",");
5174 }
5175 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5176 system(buf);
5177
5178 //Disconnect the mac which is not in ACL
5179 asso = strtok (assocArray,",");
5180 while (asso != NULL) {
5181 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5182 wifi_kickApAssociatedDevice(apIndex, asso);
5183 asso = strtok (NULL, ",");
5184 }
5185 }
5186#endif
5187 return RETURN_OK;
5188}
5189
5190INT wifi_setPreferPrivateConnection(BOOL enable)
5191{
5192 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5193 char buf[1024] = {0};
5194
5195 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5196 if(enable == TRUE)
5197 {
5198 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5199 sprintf(buf,"ifconfig %s down" ,interface_name);
5200 system(buf);
5201 memset(buf,0,sizeof(buf));
5202 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5203 sprintf(buf,"ifconfig %s down" ,interface_name);
5204 system(buf);
5205 }
5206 else
5207 {
5208 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5209 if(strcmp(ssid_cur_value,"1") == 0)
5210 wifi_RestartPrivateWifi_5G();
5211 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5212 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5213 if(strcmp(ssid_cur_value,"1") == 0)
5214 wifi_RestartHostapd_2G();
5215 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5216 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5217 if(strcmp(ssid_cur_value,"1") == 0)
5218 wifi_RestartHostapd_5G();
5219 }
5220 return RETURN_OK;
5221}
5222
5223// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5224INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5225{
5226 int items = 1;
5227 struct params list[2];
5228 char buf[MAX_BUF_SIZE] = {0};
5229 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005230 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005231
5232 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005233
developer10adcc12022-09-13 14:39:17 +08005234 if (filterMode == 0) {
5235 sprintf(buf, "%d", 0);
5236 list[0].value = buf;
5237
5238 char cmd[128], rtn[128];
5239 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5240 _syscmd(cmd, rtn, sizeof(rtn));
5241 memset(cmd,0,sizeof(cmd));
5242 // Delete deny_mac_file in hostapd configuration
5243 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5244 _syscmd(cmd, rtn, sizeof(rtn));
5245 }
5246 else if (filterMode == 1) {
5247 sprintf(buf, "%d", filterMode);
5248 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005249 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5250 list[1].name = "accept_mac_file";
5251 list[1].value = acl_file;
5252 items = 2;
developer10adcc12022-09-13 14:39:17 +08005253 } else if (filterMode == 2) {
5254 //TODO: deny_mac_file
5255 sprintf(buf, "%d", 0);
5256 list[0].value = buf;
5257 list[1].name = "deny_mac_file";
5258 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5259 list[1].value = deny_file;
5260 items = 2;
5261 } else {
5262 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005263 }
developer10adcc12022-09-13 14:39:17 +08005264
developer06a01d92022-09-07 16:32:39 +08005265 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5266 wifi_hostapdWrite(config_file, list, items);
5267
5268 return RETURN_OK;
5269
5270#if 0
5271 if(apIndex==0 || apIndex==1)
5272 {
5273 //set the filtermode
5274 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5275 system(buf);
5276 system("syscfg commit");
5277
5278 if(filterMode==0)
5279 {
5280 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5281 system(buf);
5282 return RETURN_OK;
5283 }
5284 }
5285 return RETURN_OK;
5286#endif
5287}
5288
5289// 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.
5290INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5291{
5292 return RETURN_ERR;
5293}
5294
5295// gets the vlan ID for this ap from an internal enviornment variable
5296INT wifi_getApVlanID(INT apIndex, INT *output_int)
5297{
5298 if(apIndex=0)
5299 {
5300 *output_int=100;
5301 return RETURN_OK;
5302 }
5303
5304 return RETURN_ERR;
5305}
5306
5307// sets the vlan ID for this ap to an internal enviornment variable
5308INT wifi_setApVlanID(INT apIndex, INT vlanId)
5309{
5310 //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)
5311 return RETURN_ERR;
5312}
5313
5314// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5315INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5316{
5317 snprintf(bridgeName, 32, "brlan0");
5318 snprintf(IP, 32, "10.0.0.1");
5319 snprintf(subnet, 32, "255.255.255.0");
5320
5321 return RETURN_OK;
5322}
5323
5324//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5325INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5326{
5327 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5328 return RETURN_ERR;
5329}
5330
5331// reset the vlan configuration for this ap
5332INT wifi_resetApVlanCfg(INT apIndex)
5333{
developerf5fef612022-09-20 19:38:26 +08005334 char original_config_file[64] = {0};
5335 char current_config_file[64] = {0};
5336 char buf[64] = {0};
5337 char cmd[64] = {0};
5338 char vlan_file[64] = {0};
5339 char vlan_tagged_interface[16] = {0};
5340 char vlan_bridge[16] = {0};
5341 char vlan_naming[16] = {0};
5342 struct params list[4] = {0};
5343 wifi_band band;
5344
5345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5346
5347 band = wifi_index_to_band(apIndex);
5348 if (band == band_2_4)
5349 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5350 else if (band = band_5)
5351 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5352 else if (band = band_6)
5353 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5354
5355 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5356
5357 if (strlen(vlan_file) == 0)
5358 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005359
developerf5fef612022-09-20 19:38:26 +08005360 // The file should exist or this vap would not work.
5361 if (access(vlan_file, F_OK) != 0) {
5362 sprintf(cmd, "touch %s", vlan_file);
5363 _syscmd(cmd, buf, sizeof(buf));
5364 }
5365 list[0].name = "vlan_file";
5366 list[0].value = vlan_file;
5367
5368 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5369 list[1].name = "vlan_tagged_interface";
5370 list[1].value = vlan_tagged_interface;
5371
5372 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5373 list[2].name = "vlan_bridge";
5374 list[2].value = vlan_bridge;
5375
5376 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5377 list[3].name = "vlan_naming";
5378 list[3].value = vlan_naming;
5379
5380 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5381 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005382 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005383 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005384
developerf5fef612022-09-20 19:38:26 +08005385 // restart this ap
5386 wifi_setApEnable(apIndex, FALSE);
5387 wifi_setApEnable(apIndex, TRUE);
5388
5389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5390
5391 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005392}
5393
5394// 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.
5395INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5396{
5397 return RETURN_ERR;
5398}
5399
5400// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5401INT wifi_startHostApd()
5402{
5403 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5404 system("systemctl start hostapd.service");
5405 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5406 return RETURN_OK;
5407 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5408}
5409
5410// stops hostapd
5411INT wifi_stopHostApd()
5412{
5413 char cmd[128] = {0};
5414 char buf[128] = {0};
5415
5416 sprintf(cmd,"systemctl stop hostapd");
5417 _syscmd(cmd, buf, sizeof(buf));
5418
5419 return RETURN_OK;
5420}
5421
5422// restart hostapd dummy function
5423INT wifi_restartHostApd()
5424{
5425 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5426 system("systemctl restart hostapd-global");
5427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5428
5429 return RETURN_OK;
5430}
5431
5432static int align_hostapd_config(int index)
5433{
5434 ULONG lval;
5435 wifi_getRadioChannel(index%2, &lval);
5436 wifi_setRadioChannel(index%2, lval);
5437}
5438
5439// sets the AP enable status variable for the specified ap.
5440INT wifi_setApEnable(INT apIndex, BOOL enable)
5441{
5442 char config_file[MAX_BUF_SIZE] = {0};
5443 char cmd[MAX_CMD_SIZE] = {0};
5444 char buf[MAX_BUF_SIZE] = {0};
5445 BOOL status;
5446
5447 wifi_getApEnable(apIndex,&status);
5448 if (enable == status)
5449 return RETURN_OK;
5450
5451 if (enable == TRUE) {
5452 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5453 align_hostapd_config(apIndex);
5454 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5455 //Hostapd will bring up this interface
5456 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5457 _syscmd(cmd, buf, sizeof(buf));
5458 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5459 _syscmd(cmd, buf, sizeof(buf));
5460 }
5461 else {
5462 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5463 _syscmd(cmd, buf, sizeof(buf));
5464 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5465 _syscmd(cmd, buf, sizeof(buf));
5466 }
5467 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5468 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5469 _syscmd(cmd, buf, sizeof(buf));
5470 //Wait for wifi up/down to apply
5471 return RETURN_OK;
5472}
5473
5474// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5475INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5476{
5477 char cmd[MAX_CMD_SIZE] = {'\0'};
5478 char buf[MAX_BUF_SIZE] = {'\0'};
5479
5480 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5481 return RETURN_ERR;
5482
5483 *output_bool = 0;
5484
5485 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5486 {
developer70490032022-09-13 15:45:20 +08005487 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005488 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5489 }
5490
5491 return RETURN_OK;
5492}
5493
5494// Outputs the AP "Enabled" "Disabled" status from driver
5495INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5496{
5497 char cmd[128] = {0};
5498 char buf[128] = {0};
5499 BOOL output_bool;
5500
5501 if ( NULL == output_string)
5502 return RETURN_ERR;
5503 wifi_getApEnable(apIndex,&output_bool);
5504
5505 if(output_bool == 1)
5506 snprintf(output_string, 32, "Up");
5507 else
5508 snprintf(output_string, 32, "Disable");
5509
5510 return RETURN_OK;
5511}
5512
5513//Indicates whether or not beacons include the SSID name.
5514// outputs a 1 if SSID on the AP is enabled, else outputs 0
5515INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5516{
5517 //get the running status
5518 char config_file[MAX_BUF_SIZE] = {0};
5519 char buf[16] = {0};
5520
5521 if (!output)
5522 return RETURN_ERR;
5523
5524 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5525 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5526 *output = (strncmp("0",buf,1) == 0);
5527
5528 return RETURN_OK;
5529}
5530
5531// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5532INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5533{
5534 //store the config, apply instantly
5535 char config_file[MAX_BUF_SIZE] = {0};
5536 struct params list;
5537
5538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5539 list.name = "ignore_broadcast_ssid";
5540 list.value = enable?"0":"1";
5541
5542 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5543 wifi_hostapdWrite(config_file, &list, 1);
5544 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5545 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005546 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5548
5549 return RETURN_OK;
5550}
5551
5552//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5553INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5554{
5555 //get the running status
5556 if(!output_uint)
5557 return RETURN_ERR;
5558 *output_uint=16;
5559 return RETURN_OK;
5560}
5561
5562INT wifi_setApRetryLimit(INT apIndex, UINT number)
5563{
5564 //apply instantly
5565 return RETURN_ERR;
5566}
5567
5568//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5569INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5570{
5571 if(!output)
5572 return RETURN_ERR;
5573 *output=TRUE;
5574 return RETURN_OK;
5575}
5576
5577//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5578INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5579{
5580 //get the running status from driver
5581 if(!output)
5582 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005583
5584 char config_file[MAX_BUF_SIZE] = {0};
5585 char buf[16] = {0};
5586
5587 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5588 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5589 if (strncmp("1",buf,1) == 0)
5590 *output = TRUE;
5591 else
5592 *output = FALSE;
5593
developer06a01d92022-09-07 16:32:39 +08005594 return RETURN_OK;
5595}
5596
5597//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5598INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5599{
5600 //get the running status from driver
5601 if(!output)
5602 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005603
5604 char config_file[MAX_BUF_SIZE] = {0};
5605 char buf[16] = {0};
5606
5607 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5608 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5609 if (strncmp("1",buf,1) == 0)
5610 *output = TRUE;
5611 else
5612 *output = FALSE;
5613
developer06a01d92022-09-07 16:32:39 +08005614 return RETURN_OK;
5615}
5616
5617// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5618INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5619{
5620 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005621 char config_file[MAX_BUF_SIZE] = {0};
5622 struct params list;
5623
5624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5625 list.name = "wmm_enabled";
5626 list.value = enable?"1":"0";
5627
5628 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5629 wifi_hostapdWrite(config_file, &list, 1);
5630 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5631 wifi_reloadAp(apIndex);
5632 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5633
5634 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005635}
5636
5637//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.
5638INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5639{
5640 //get the running status from driver
5641 if(!output)
5642 return RETURN_ERR;
5643 *output=TRUE;
5644 return RETURN_OK;
5645}
5646
5647// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5648INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5649{
5650 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005651 char config_file[MAX_BUF_SIZE] = {0};
5652 struct params list;
5653
5654 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5655 list.name = "uapsd_advertisement_enabled";
5656 list.value = enable?"1":"0";
5657
5658 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5659 wifi_hostapdWrite(config_file, &list, 1);
5660 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5661 wifi_reloadAp(apIndex);
5662 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5663
5664 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005665}
5666
5667// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
5668INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5669{
5670 //save config and apply instantly.
5671 return RETURN_ERR;
5672}
5673
5674//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.
5675INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5676{
5677 //get the running status from driver
5678 if(!output_uint)
5679 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005680
5681 char output[16]={'\0'};
5682 char config_file[MAX_BUF_SIZE] = {0};
5683
5684 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5685 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5686 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5687 else {
5688 int device_num = atoi(output);
5689 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5690 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5691 return RETURN_ERR;
5692 }
5693 else {
5694 *output_uint = device_num;
5695 }
5696 }
5697
developer06a01d92022-09-07 16:32:39 +08005698 return RETURN_OK;
5699}
5700
5701INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5702{
5703 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005704 char str[MAX_BUF_SIZE]={'\0'};
5705 char cmd[MAX_CMD_SIZE]={'\0'};
5706 struct params params;
5707 char config_file[MAX_BUF_SIZE] = {0};
5708
5709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5710 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5711 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5712 return RETURN_ERR;
5713 }
5714 sprintf(str, "%d", number);
5715 params.name = "max_num_sta";
5716 params.value = str;
5717
5718 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5719 int ret = wifi_hostapdWrite(config_file, &params, 1);
5720 if (ret) {
5721 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5722 ,__func__, ret);
5723 }
5724
5725 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5726 if (ret) {
5727 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5728 ,__func__, ret);
5729 }
5730 wifi_reloadAp(apIndex);
5731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5732
5733 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005734}
5735
5736//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.
5737INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5738{
5739 //get the current threshold
5740 if(!output_uint)
5741 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005742 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5743 if (*output_uint == 0)
5744 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005745 return RETURN_OK;
5746}
5747
5748INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5749{
5750 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08005751 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
5752 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005753 return RETURN_ERR;
5754}
5755
5756//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.
5757INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
5758{
5759 if(!output_uint)
5760 return RETURN_ERR;
5761 *output_uint = 3;
5762 return RETURN_OK;
5763}
5764
5765//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
5766INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
5767{
5768 if(!output_uint)
5769 return RETURN_ERR;
5770 *output_uint = 3;
5771 return RETURN_OK;
5772}
5773
5774//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.
5775INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
5776{
5777 if(!output_in_seconds)
5778 return RETURN_ERR;
5779 *output_in_seconds = 0;
5780 return RETURN_OK;
5781}
5782
5783//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
5784INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
5785{
5786 if(!output || apIndex>=MAX_APS)
5787 return RETURN_ERR;
5788 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
5789 snprintf(output, 128, "None,WPA2-Personal");
5790 return RETURN_OK;
5791}
5792
5793//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
5794INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
5795{
5796 char config_file[MAX_BUF_SIZE] = {0};
5797 char buf[32] = {0};
5798 if (!output)
5799 return RETURN_ERR;
5800
5801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5802 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5803
5804 strcpy(output,"None");//Copying "None" to output string for default case
5805 if((strcmp(buf, "3")==0))
5806 snprintf(output, 32, "WPA-WPA2-Personal");
5807 else if((strcmp(buf, "2")==0))
5808 snprintf(output, 32, "WPA2-Personal");
5809 else if((strcmp(buf, "1")==0))
5810 snprintf(output, 32, "WPA-Personal");
5811 //TODO: need to handle enterprise authmode
5812
5813 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5814 return RETURN_OK;
5815#if 0
5816 //TODO: need to revisit below implementation
5817 char securityType[32], authMode[32];
5818 int enterpriseMode=0;
5819
5820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5821 if(!output)
5822 return RETURN_ERR;
5823
5824 wifi_getApBeaconType(apIndex, securityType);
5825 strcpy(output,"None");//By default, copying "None" to output string
5826 if (strncmp(securityType,"None", strlen("None")) == 0)
5827 return RETURN_OK;
5828
5829 wifi_getApBasicAuthenticationMode(apIndex, authMode);
5830 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
5831
5832 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
5833 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
5834 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
5835 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
5836 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
5837 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
5838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5839
5840 return RETURN_OK;
5841#endif
5842}
5843
5844INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
5845{
5846 char securityType[32];
5847 char authMode[32];
5848
5849 //store settings and wait for wifi up to apply
5850 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5851 if(!encMode)
5852 return RETURN_ERR;
5853
5854 printf("%s: apIndex %d, encMode %s\n",__func__, apIndex, encMode);
5855 if (strcmp(encMode, "None")==0)
5856 {
5857 strcpy(securityType,"None");
5858 strcpy(authMode,"None");
5859 }
5860 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
5861 {
5862 strcpy(securityType,"WPAand11i");
5863 strcpy(authMode,"PSKAuthentication");
5864 }
5865 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
5866 {
5867 strcpy(securityType,"WPAand11i");
5868 strcpy(authMode,"EAPAuthentication");
5869 }
5870 else if (strcmp(encMode, "WPA-Personal")==0)
5871 {
5872 strcpy(securityType,"WPA");
5873 strcpy(authMode,"PSKAuthentication");
5874 }
5875 else if (strcmp(encMode, "WPA-Enterprise")==0)
5876 {
5877 strcpy(securityType,"WPA");
5878 strcpy(authMode,"EAPAuthentication");
5879 }
5880 else if (strcmp(encMode, "WPA2-Personal")==0)
5881 {
5882 strcpy(securityType,"11i");
5883 strcpy(authMode,"PSKAuthentication");
5884 }
5885 else if (strcmp(encMode, "WPA2-Enterprise")==0)
5886 {
5887 strcpy(securityType,"11i");
5888 strcpy(authMode,"EAPAuthentication");
5889 }
5890 else
5891 {
5892 strcpy(securityType,"None");
5893 strcpy(authMode,"None");
5894 }
5895 wifi_setApBeaconType(apIndex, securityType);
5896 wifi_setApBasicAuthenticationMode(apIndex, authMode);
5897 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5898
5899 return RETURN_OK;
5900}
5901
5902
5903//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
5904// output_string must be pre-allocated as 64 character string by caller
5905// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5906INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
5907{
5908 char buf[16];
5909 char config_file[MAX_BUF_SIZE] = {0};
5910
5911 if(output_string==NULL)
5912 return RETURN_ERR;
5913
5914 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5915 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5916
5917 if(strcmp(buf,"0")==0)
5918 {
5919 printf("wpa_mode is %s ......... \n",buf);
5920 return RETURN_ERR;
5921 }
5922
5923 wifi_dbg_printf("\nFunc=%s\n",__func__);
5924 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5925 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5926 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5927
5928 return RETURN_OK;
5929}
5930
5931// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
5932// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5933INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
5934{
5935 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5936 struct params params={'\0'};
5937 int ret;
5938 char config_file[MAX_BUF_SIZE] = {0};
5939
5940 if(NULL == preSharedKey)
5941 return RETURN_ERR;
5942
5943 params.name = "wpa_passphrase";
5944
5945 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
5946 {
5947 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5948 return RETURN_ERR;
5949 }
5950 params.value = preSharedKey;
5951 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5952 ret = wifi_hostapdWrite(config_file, &params, 1);
5953 if(!ret)
5954 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5955 return ret;
5956 //TODO: call hostapd_cli for dynamic_config_control
5957}
5958
5959//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
5960// outputs the passphrase, maximum 63 characters
5961INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
5962{
5963 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
5964
5965 wifi_dbg_printf("\nFunc=%s\n",__func__);
5966 if (NULL == output_string)
5967 return RETURN_ERR;
5968
5969 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5970 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5971 if(strcmp(buf,"0")==0)
5972 {
5973 printf("wpa_mode is %s ......... \n",buf);
5974 return RETURN_ERR;
5975 }
5976
5977 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5978 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5979
5980 return RETURN_OK;
5981}
5982
5983// sets the passphrase enviornment variable, max 63 characters
5984INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
5985{
5986 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5987 struct params params={'\0'};
5988 char config_file[MAX_BUF_SIZE] = {0};
5989 int ret;
5990
5991 if(NULL == passPhrase)
5992 return RETURN_ERR;
5993
5994 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
5995 {
5996 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5997 return RETURN_ERR;
5998 }
5999 params.name = "wpa_passphrase";
6000 params.value = passPhrase;
6001 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6002 ret=wifi_hostapdWrite(config_file,&params,1);
6003 if(!ret)
6004 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6005
6006 return ret;
6007}
6008
6009//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.
6010INT wifi_setApSecurityReset(INT apIndex)
6011{
developer8d583982022-09-20 11:28:22 +08006012 char original_config_file[64] = {0};
6013 char current_config_file[64] = {0};
6014 char buf[64] = {0};
6015 char cmd[64] = {0};
6016 char wpa[4] = {0};
6017 char wpa_psk[64] = {0};
6018 char wpa_passphrase[64] = {0};
6019 char wpa_psk_file[128] = {0};
6020 char wpa_key_mgmt[64] = {0};
6021 char wpa_pairwise[32] = {0};
6022 wifi_band band;
6023 struct params list[6];
6024
6025 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6026
6027 band = wifi_index_to_band(apIndex);
6028 if (band == band_2_4)
6029 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6030 else if (band = band_5)
6031 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6032 else if (band = band_6)
6033 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6034 else
6035 return RETURN_ERR;
6036
6037 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6038 list[0].name = "wpa";
6039 list[0].value = wpa;
6040
6041 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6042 list[1].name = "wpa_psk";
6043 list[1].value = wpa_psk;
6044
6045 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6046 list[2].name = "wpa_passphrase";
6047 list[2].value = wpa_passphrase;
6048
6049 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6050
6051 if (strlen(wpa_psk_file) == 0)
6052 strcpy(wpa_psk_file, PSK_FILE);
6053
6054 if (access(wpa_psk_file, F_OK) != 0) {
6055 sprintf(cmd, "touch %s", wpa_psk_file);
6056 _syscmd(cmd, buf, sizeof(buf));
6057 }
6058 list[3].name = "wpa_psk_file";
6059 list[3].value = wpa_psk_file;
6060
6061 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6062 list[4].name = "wpa_key_mgmt";
6063 list[4].value = wpa_key_mgmt;
6064
6065 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6066 list[5].name = "wpa_pairwise";
6067 list[5].value = wpa_pairwise;
6068
6069 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6070 wifi_hostapdWrite(current_config_file, list, 6);
6071
6072 wifi_setApEnable(apIndex, FALSE);
6073 wifi_setApEnable(apIndex, TRUE);
6074
6075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6076 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006077}
6078
6079//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).
6080INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6081{
developer8f2ddd52022-09-13 15:39:24 +08006082 char config_file[64] = {0};
6083 char buf[64] = {0};
6084 char cmd[256] = {0};
6085
6086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6087
developer06a01d92022-09-07 16:32:39 +08006088 if(!IP_output || !Port_output || !RadiusSecret_output)
6089 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006090
developer8f2ddd52022-09-13 15:39:24 +08006091 // Read the first matched config
6092 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6093 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6094 _syscmd(cmd, buf, sizeof(buf));
6095 strncpy(IP_output, buf, 64);
6096
6097 memset(buf, 0, sizeof(buf));
6098 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6099 _syscmd(cmd, buf, sizeof(buf));
6100 *Port_output = atoi(buf);
6101
6102 memset(buf, 0, sizeof(buf));
6103 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6104 _syscmd(cmd, buf, sizeof(buf));
6105 strncpy(RadiusSecret_output, buf, 64);
6106
6107 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006108 return RETURN_OK;
6109}
6110
6111INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6112{
developer8f2ddd52022-09-13 15:39:24 +08006113 char config_file[64] = {0};
6114 char port_str[8] = {0};
6115 char cmd[256] = {0};
6116 char buf[128] = {0};
6117
6118 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6119
6120 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6121
6122 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6123 _syscmd(cmd, buf, sizeof(buf));
6124 memset(cmd, 0, sizeof(cmd));
6125
6126 snprintf(port_str, sizeof(port_str), "%d", port);
6127 if (strlen(buf) == 0)
6128 // Append
6129 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6130 "auth_server_addr=%s\\n"
6131 "auth_server_port=%s\\n"
6132 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6133 else {
6134 // Delete the three lines setting after the "# radius 1" comment
6135 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6136 _syscmd(cmd, buf, sizeof(buf));
6137 memset(cmd, 0, sizeof(cmd));
6138 // Use "# radius 1" comment to find the location to insert the radius setting
6139 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6140 "# radius 1\\n"
6141 "auth_server_addr=%s\\n"
6142 "auth_server_port=%s\\n"
6143 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6144 }
6145 if(_syscmd(cmd, buf, sizeof(buf))) {
6146 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6147 return RETURN_ERR;
6148 }
6149
6150 wifi_reloadAp(apIndex);
6151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6152 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006153}
6154
6155INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6156{
developer8f2ddd52022-09-13 15:39:24 +08006157 char config_file[64] = {0};
6158 char buf[64] = {0};
6159 char cmd[256] = {0};
6160
6161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6162
developer06a01d92022-09-07 16:32:39 +08006163 if(!IP_output || !Port_output || !RadiusSecret_output)
6164 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006165
6166 // Read the second matched config
6167 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6168 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6169 _syscmd(cmd, buf, sizeof(buf));
6170 strncpy(IP_output, buf, 64);
6171
6172 memset(buf, 0, sizeof(buf));
6173 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6174 _syscmd(cmd, buf, sizeof(buf));
6175 *Port_output = atoi(buf);
6176
6177 memset(buf, 0, sizeof(buf));
6178 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6179 _syscmd(cmd, buf, sizeof(buf));
6180 strncpy(RadiusSecret_output, buf, 64);
6181
6182 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006183 return RETURN_OK;
6184}
6185
6186INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6187{
developer8f2ddd52022-09-13 15:39:24 +08006188 char config_file[64] = {0};
6189 char port_str[8] = {0};
6190 char cmd[256] = {0};
6191 char buf[128] = {0};
6192
6193 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6194
6195 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6196
6197 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6198 _syscmd(cmd, buf, sizeof(buf));
6199 memset(cmd, 0, sizeof(cmd));
6200
6201 snprintf(port_str, sizeof(port_str), "%d", port);
6202 if (strlen(buf) == 0)
6203 // Append
6204 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6205 "auth_server_addr=%s\\n"
6206 "auth_server_port=%s\\n"
6207 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6208 else {
6209 // Delete the three lines setting after the "# radius 2" comment
6210 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6211 _syscmd(cmd, buf, sizeof(buf));
6212 memset(cmd, 0, sizeof(cmd));
6213 // Use "# radius 2" comment to find the location to insert the radius setting
6214 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6215 "# radius 2\\n"
6216 "auth_server_addr=%s\\n"
6217 "auth_server_port=%s\\n"
6218 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6219 }
6220 if(_syscmd(cmd, buf, sizeof(buf))) {
6221 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6222 return RETURN_ERR;
6223 }
6224
6225 wifi_reloadAp(apIndex);
6226 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6227 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006228}
6229
6230//RadiusSettings
6231INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6232{
6233 if(!output)
6234 return RETURN_ERR;
6235
6236 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6237 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6238 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6239 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6240 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6241 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.
6242 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6243 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6244 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6245 //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.
6246
6247 return RETURN_OK;
6248}
6249
6250INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6251{
6252 //store the paramters, and apply instantly
6253 return RETURN_ERR;
6254}
6255
6256//Device.WiFi.AccessPoint.{i}.WPS.Enable
6257//Enables or disables WPS functionality for this access point.
6258// outputs the WPS enable state of this ap in output_bool
6259INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6260{
6261 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6262 if(!output_bool || !(apIndex==0 || apIndex==1))
6263 return RETURN_ERR;
6264 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6265 _syscmd(cmd, buf, sizeof(buf));
6266 if(strstr(buf, "configured"))
6267 *output_bool=TRUE;
6268 else
6269 *output_bool=FALSE;
6270
6271 return RETURN_OK;
6272}
6273
6274//Device.WiFi.AccessPoint.{i}.WPS.Enable
6275// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6276INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6277{
6278 char config_file[MAX_BUF_SIZE] = {0};
6279 struct params params;
6280
6281 if(!(apIndex==0 || apIndex==1))
6282 return RETURN_ERR;
6283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6284 //store the paramters, and wait for wifi up to apply
6285 params.name = "wps_state";
6286 params.value = enable ? "2":"0";
6287
6288 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6289 wifi_hostapdWrite(config_file, &params, 1);
6290 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6291 wifi_reloadAp(apIndex);
6292
6293 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6294 return RETURN_OK;
6295}
6296
6297//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
6298INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6299{
6300 if(!output)
6301 return RETURN_ERR;
6302 snprintf(output, 128, "PushButton,PIN");
6303 return RETURN_OK;
6304}
6305
6306//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6307//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.
6308// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6309INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6310{
6311 if(!output)
6312 return RETURN_ERR;
6313 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6314
6315 return RETURN_OK;
6316}
6317
6318//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6319// 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
6320INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6321{
6322 //apply instantly. No setting need to be stored.
6323 char methods[MAX_BUF_SIZE], *token, *next_token;
6324 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6325 struct params params;
6326
6327 if(!methodString || !(apIndex==0 || apIndex==1))
6328 return RETURN_ERR;
6329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6330 //store the paramters, and wait for wifi up to apply
6331
6332 snprintf(methods, sizeof(methods), "%s", methodString);
6333 for(token=methods; *token; token=next_token)
6334 {
6335 strtok_r(token, ",", &next_token);
6336 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6337 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6338 else if(*token=='E')
6339 {
6340 if(!strcmp(methods, "Ethernet"))
6341 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6342 else if(!strcmp(methods, "ExternalNFCToken"))
6343 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6344 else
6345 printf("%s: Unknown WpsConfigMethod\n", __func__);
6346 }
6347 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6348 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6349 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6350 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6351 else if(*token=='P' )
6352 {
6353 if(!strcmp(token, "PushButton"))
6354 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6355 else if(!strcmp(token, "PIN"))
6356 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6357 else
6358 printf("%s: Unknown WpsConfigMethod\n", __func__);
6359 }
6360 else
6361 printf("%s: Unknown WpsConfigMethod\n", __func__);
6362 }
6363 params.name = "config_methods";
6364 params.value = config_methods;
6365 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6366 wifi_hostapdWrite(config_file, &params, 1);
6367 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6369
6370 return RETURN_OK;
6371}
6372
6373// outputs the pin value, ulong_pin must be allocated by the caller
6374INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6375{
6376 char buf[MAX_BUF_SIZE] = {0};
6377 char cmd[MAX_CMD_SIZE] = {0};
6378
6379 if(!output_ulong || !(apIndex==0 || apIndex==1))
6380 return RETURN_ERR;
6381 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6382 _syscmd(cmd, buf, sizeof(buf));
6383 if(strlen(buf) > 0)
6384 *output_ulong=strtoul(buf, NULL, 10);
6385
6386 return RETURN_OK;
6387}
6388
6389// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6390INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6391{
6392 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6393 char ap_pin[16] = {0};
6394 char buf[MAX_BUF_SIZE] = {0};
6395 char config_file[MAX_BUF_SIZE] = {0};
6396 ULONG prev_pin = 0;
6397 struct params params;
6398
6399 if(!(apIndex==0 || apIndex==1))
6400 return RETURN_ERR;
6401 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6402 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6403 params.name = "ap_pin";
6404 params.value = ap_pin;
6405 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6406 wifi_hostapdWrite(config_file, &params, 1);
6407 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6409
6410 return RETURN_OK;
6411}
6412
6413// Output string is either Not configured or Configured, max 32 characters
6414INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6415{
6416 char cmd[MAX_CMD_SIZE];
6417 char buf[MAX_BUF_SIZE]={0};
6418
6419 if(!output_string || !(apIndex==0 || apIndex==1))
6420 return RETURN_ERR;
6421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6422 snprintf(output_string, 32, "Not configured");
6423 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6424 _syscmd(cmd, buf, sizeof(buf));
6425
developer348e3d92022-09-13 14:48:41 +08006426 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006427 snprintf(output_string, 32, "Configured");
6428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6429
6430 return RETURN_OK;
6431}
6432
6433// sets the WPS pin for this AP
6434INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6435{
6436 char cmd[MAX_CMD_SIZE];
6437 char buf[MAX_BUF_SIZE]={0};
6438 BOOL enable;
6439
6440 if(!(apIndex==0 || apIndex==1))
6441 return RETURN_ERR;
6442 wifi_getApEnable(apIndex, &enable);
6443 if (!enable)
6444 return RETURN_ERR;
6445 wifi_getApWpsEnable(apIndex, &enable);
6446 if (!enable)
6447 return RETURN_ERR;
6448
6449 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6450 _syscmd(cmd, buf, sizeof(buf));
6451 if((strstr(buf, "OK"))!=NULL)
6452 return RETURN_OK;
6453
6454 return RETURN_ERR;
6455}
6456
6457// This function is called when the WPS push button has been pressed for this AP
6458INT wifi_setApWpsButtonPush(INT apIndex)
6459{
6460 char cmd[MAX_CMD_SIZE];
6461 char buf[MAX_BUF_SIZE]={0};
6462 BOOL enable=FALSE;
6463
6464 if(!(apIndex==0 || apIndex==1))
6465 return RETURN_ERR;
6466 wifi_getApEnable(apIndex, &enable);
6467 if (!enable)
6468 return RETURN_ERR;
6469
6470 wifi_getApWpsEnable(apIndex, &enable);
6471 if (!enable)
6472 return RETURN_ERR;
6473
6474 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6475 _syscmd(cmd, buf, sizeof(buf));
6476
6477 if((strstr(buf, "OK"))!=NULL)
6478 return RETURN_OK;
6479 return RETURN_ERR;
6480}
6481
6482// cancels WPS mode for this AP
6483INT wifi_cancelApWPS(INT apIndex)
6484{
6485 char cmd[MAX_CMD_SIZE];
6486 char buf[MAX_BUF_SIZE]={0};
6487
6488 if(!(apIndex==0 || apIndex==1))
6489 return RETURN_ERR;
6490 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6491 _syscmd(cmd,buf, sizeof(buf));
6492
6493 if((strstr(buf, "OK"))!=NULL)
6494 return RETURN_OK;
6495 return RETURN_ERR;
6496}
6497
6498//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6499//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6500INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6501{
6502 FILE *f;
6503 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6504 char cmd[256], buf[2048];
6505 char *param , *value, *line=NULL;
6506 size_t len = 0;
6507 ssize_t nread;
6508 wifi_associated_dev_t *dev=NULL;
6509
6510 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6511 *associated_dev_array = NULL;
6512 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6513 _syscmd(cmd,buf,sizeof(buf));
6514 *output_array_size = atoi(buf);
6515
6516 if (*output_array_size <= 0)
6517 return RETURN_OK;
6518
6519 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6520 *associated_dev_array = dev;
6521 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6522 _syscmd(cmd,buf,sizeof(buf));
6523 f = fopen("/tmp/connected_devices.txt", "r");
6524 if (f==NULL)
6525 {
6526 *output_array_size=0;
6527 return RETURN_ERR;
6528 }
6529 while ((nread = getline(&line, &len, f)) != -1)
6530 {
6531 param = strtok(line,"=");
6532 value = strtok(NULL,"=");
6533
6534 if( strcmp("flags",param) == 0 )
6535 {
6536 value[strlen(value)-1]='\0';
6537 if(strstr (value,"AUTHORIZED") != NULL )
6538 {
6539 dev[auth_temp].cli_AuthenticationState = 1;
6540 dev[auth_temp].cli_Active = 1;
6541 auth_temp++;
6542 read_flag=1;
6543 }
6544 }
6545 if(read_flag==1)
6546 {
6547 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6548 {
6549 value[strlen(value)-1]='\0';
6550 sscanf(value, "%x:%x:%x:%x:%x:%x",
6551 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6552 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6553 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6554 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6555 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6556 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6557 mac_temp++;
6558 read_flag=0;
6559 }
6560 }
6561 }
6562 *output_array_size = auth_temp;
6563 auth_temp=0;
6564 mac_temp=0;
6565 free(line);
6566 fclose(f);
6567 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6568 return RETURN_OK;
6569}
6570
6571#define MACADDRESS_SIZE 6
6572
6573INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6574{
6575 FILE *fp = NULL;
6576 char str[MAX_BUF_SIZE] = {0};
6577 int wificlientindex = 0 ;
6578 int count = 0;
6579 int signalstrength = 0;
6580 int arr[MACADDRESS_SIZE] = {0};
6581 unsigned char mac[MACADDRESS_SIZE] = {0};
6582 UINT wifi_count = 0;
6583 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6584 char pipeCmd[MAX_CMD_SIZE] = {0};
6585
6586 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6587 *output_array_size = 0;
6588 *associated_dev_array = NULL;
6589
6590 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6591 fp = popen(pipeCmd, "r");
6592 if (fp == NULL)
6593 {
6594 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6595 return RETURN_ERR;
6596 }
6597
6598 /* Read the output a line at a time - output it. */
6599 fgets(str, sizeof(str)-1, fp);
6600 wifi_count = (unsigned int) atoi ( str );
6601 *output_array_size = wifi_count;
6602 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6603 pclose(fp);
6604
6605 if(wifi_count == 0)
6606 {
6607 return RETURN_OK;
6608 }
6609 else
6610 {
6611 wifi_associated_dev3_t* temp = NULL;
6612 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6613 if(temp == NULL)
6614 {
6615 printf("Error Statement. Insufficient memory \n");
6616 return RETURN_ERR;
6617 }
6618
6619 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6620 system(pipeCmd);
6621 memset(pipeCmd,0,sizeof(pipeCmd));
6622 if(apIndex == 0)
6623 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6624 else if(apIndex == 1)
6625 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6626 system(pipeCmd);
6627
6628 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6629 if(fp == NULL)
6630 {
6631 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6632 return RETURN_ERR;
6633 }
6634 fclose(fp);
6635
6636 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6637 fp = popen(pipeCmd, "r");
6638 if(fp)
6639 {
6640 for(count =0 ; count < wifi_count; count++)
6641 {
6642 fgets(str, MAX_BUF_SIZE, fp);
6643 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6644 {
6645 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6646 {
6647 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6648
6649 }
6650 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6651 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]);
6652 }
6653 temp[count].cli_AuthenticationState = 1; //TODO
6654 temp[count].cli_Active = 1; //TODO
6655 }
6656 pclose(fp);
6657 }
6658
6659 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6660 fp = popen(pipeCmd, "r");
6661 if(fp)
6662 {
6663 pclose(fp);
6664 }
6665 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6666 if(fp)
6667 {
6668 for(count =0 ; count < wifi_count ;count++)
6669 {
6670 fgets(str, MAX_BUF_SIZE, fp);
6671 signalstrength = atoi(str);
6672 temp[count].cli_SignalStrength = signalstrength;
6673 temp[count].cli_RSSI = signalstrength;
6674 temp[count].cli_SNR = signalstrength + 95;
6675 }
6676 pclose(fp);
6677 }
6678
6679
6680 if((apIndex == 0) || (apIndex == 4))
6681 {
6682 for(count =0 ; count < wifi_count ;count++)
6683 {
6684 strcpy(temp[count].cli_OperatingStandard,"g");
6685 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6686 }
6687
6688 //BytesSent
6689 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6690 fp = popen(pipeCmd, "r");
6691 if(fp)
6692 {
6693 pclose(fp);
6694 }
6695 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6696 if(fp)
6697 {
6698 for (count = 0; count < wifi_count; count++)
6699 {
6700 fgets(str, MAX_BUF_SIZE, fp);
6701 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6702 }
6703 pclose(fp);
6704 }
6705
6706 //BytesReceived
6707 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6708 fp = popen(pipeCmd, "r");
6709 if (fp)
6710 {
6711 pclose(fp);
6712 }
6713 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6714 if (fp)
6715 {
6716 for (count = 0; count < wifi_count; count++)
6717 {
6718 fgets(str, MAX_BUF_SIZE, fp);
6719 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
6720 }
6721 pclose(fp);
6722 }
6723
6724 //PacketsSent
6725 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
6726 fp = popen(pipeCmd, "r");
6727 if (fp)
6728 {
6729 pclose(fp);
6730 }
6731
6732 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
6733 if (fp)
6734 {
6735 for (count = 0; count < wifi_count; count++)
6736 {
6737 fgets(str, MAX_BUF_SIZE, fp);
6738 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
6739 }
6740 pclose(fp);
6741 }
6742
6743 //PacketsReceived
6744 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
6745 fp = popen(pipeCmd, "r");
6746 if (fp)
6747 {
6748 pclose(fp);
6749 }
6750 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
6751 if (fp)
6752 {
6753 for (count = 0; count < wifi_count; count++)
6754 {
6755 fgets(str, MAX_BUF_SIZE, fp);
6756 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
6757 }
6758 pclose(fp);
6759 }
6760
6761 //ErrorsSent
6762 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6763 fp = popen(pipeCmd, "r");
6764 if (fp)
6765 {
6766 pclose(fp);
6767 }
6768 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6769 if (fp)
6770 {
6771 for (count = 0; count < wifi_count; count++)
6772 {
6773 fgets(str, MAX_BUF_SIZE, fp);
6774 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6775 }
6776 pclose(fp);
6777 }
6778
6779 //ErrorsSent
6780 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6781 fp = popen(pipeCmd, "r");
6782 if (fp)
6783 {
6784 pclose(fp);
6785 }
6786 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6787 if (fp)
6788 {
6789 for (count = 0; count < wifi_count; count++)
6790 {
6791 fgets(str, MAX_BUF_SIZE, fp);
6792 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6793 }
6794 pclose(fp);
6795 }
6796
6797 //LastDataDownlinkRate
6798 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
6799 fp = popen(pipeCmd, "r");
6800 if (fp)
6801 {
6802 pclose(fp);
6803 }
6804 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
6805 if (fp)
6806 {
6807 for (count = 0; count < wifi_count; count++)
6808 {
6809 fgets(str, MAX_BUF_SIZE, fp);
6810 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
6811 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
6812 }
6813 pclose(fp);
6814 }
6815
6816 //LastDataUplinkRate
6817 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
6818 fp = popen(pipeCmd, "r");
6819 if (fp)
6820 {
6821 pclose(fp);
6822 }
6823 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
6824 if (fp)
6825 {
6826 for (count = 0; count < wifi_count; count++)
6827 {
6828 fgets(str, MAX_BUF_SIZE, fp);
6829 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
6830 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
6831 }
6832 pclose(fp);
6833 }
6834
6835 }
6836 else if ((apIndex == 1) || (apIndex == 5))
6837 {
6838 for (count = 0; count < wifi_count; count++)
6839 {
6840 strcpy(temp[count].cli_OperatingStandard, "a");
6841 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
6842 temp[count].cli_BytesSent = 0;
6843 temp[count].cli_BytesReceived = 0;
6844 temp[count].cli_LastDataUplinkRate = 0;
6845 temp[count].cli_LastDataDownlinkRate = 0;
6846 temp[count].cli_PacketsSent = 0;
6847 temp[count].cli_PacketsReceived = 0;
6848 temp[count].cli_ErrorsSent = 0;
6849 }
6850 }
6851
6852 for (count = 0; count < wifi_count; count++)
6853 {
6854 temp[count].cli_Retransmissions = 0;
6855 temp[count].cli_DataFramesSentAck = 0;
6856 temp[count].cli_DataFramesSentNoAck = 0;
6857 temp[count].cli_MinRSSI = 0;
6858 temp[count].cli_MaxRSSI = 0;
6859 strncpy(temp[count].cli_InterferenceSources, "", 64);
6860 memset(temp[count].cli_IPAddress, 0, 64);
6861 temp[count].cli_RetransCount = 0;
6862 temp[count].cli_FailedRetransCount = 0;
6863 temp[count].cli_RetryCount = 0;
6864 temp[count].cli_MultipleRetryCount = 0;
6865 }
6866 *associated_dev_array = temp;
6867 }
6868 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6869 return RETURN_OK;
6870}
6871
6872int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
6873{
6874 FILE *fp = NULL;
6875 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
6876 char cmd[MAX_CMD_SIZE];
6877 int count = 0;
6878
6879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6880 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
6881 fp = popen(cmd,"r");
6882 if(fp == NULL)
6883 {
6884 printf("Failed to run command in Function %s\n",__FUNCTION__);
6885 return 0;
6886 }
6887 if(fgets(path, sizeof(path)-1, fp) != NULL)
6888 {
6889 for(count=0;path[count]!='\n';count++)
6890 status[count]=path[count];
6891 status[count]='\0';
6892 }
6893 strcpy(wifi_status,status);
6894 pclose(fp);
6895 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6896 return RETURN_OK;
6897}
6898
6899/* #define HOSTAPD_STA_PARAM_ENTRIES 29
6900struct hostapd_sta_param {
6901 char key[50];
6902 char value[100];
6903}
6904
6905static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
6906 int i = 0;
6907
6908 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
6909 if (strncmp(params[i].key,key,50) == 0){
6910 return &params[i].value;
6911 }
6912 i++;
6913 }
6914 return NULL;
6915
6916} */
6917
6918static unsigned int count_occurences(const char *buf, const char *word)
6919{
6920 unsigned int n = 0;
6921 char *ptr = strstr(buf, word);
6922
6923 while (ptr++) {
6924 n++;
6925 ptr = strstr(ptr, word);
6926 }
6927
6928 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
6929 return n;
6930}
6931
6932static const char *get_line_from_str_buf(const char *buf, char *line)
6933{
6934 int i;
6935 int n = strlen(buf);
6936
6937 for (i = 0; i < n; i++) {
6938 line[i] = buf[i];
6939 if (buf[i] == '\n') {
6940 line[i] = '\0';
6941 return &buf[i + 1];
6942 }
6943 }
6944
6945 return NULL;
6946}
6947
6948INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6949{
6950 unsigned int assoc_cnt = 0;
6951 char interface_name[50] = {0};
6952 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
6953 char cmd[MAX_CMD_SIZE] = {'\0'};
6954 char line[256] = {'\0'};
6955 int i = 0;
6956 int ret = 0;
6957 const char *ptr = NULL;
6958 char *key = NULL;
6959 char *val = NULL;
6960 wifi_associated_dev3_t *temp = NULL;
6961 int rssi;
6962
6963 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6964
6965 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
6966 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
6967 return RETURN_ERR;
6968 }
6969
6970 // Example filtered output of 'iw dev' command:
6971 // Station 0a:69:72:10:d2:fa (on wifi0)
6972 // signal avg:-67 [-71, -71] dBm
6973 // Station 28:c2:1f:25:5f:99 (on wifi0)
6974 // signal avg:-67 [-71, -70] dBm
6975 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
6976 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
6977 return RETURN_ERR;
6978 }
6979
6980 ret = _syscmd(cmd, buf, sizeof(buf));
6981 if (ret == RETURN_ERR) {
6982 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
6983 return RETURN_ERR;
6984 }
6985
6986 *output_array_size = count_occurences(buf, "Station");
6987 if (*output_array_size == 0) return RETURN_OK;
6988
6989 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
6990 if (temp == NULL) {
6991 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
6992 return RETURN_ERR;
6993 }
6994 *associated_dev_array = temp;
6995
6996 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
6997 ptr = get_line_from_str_buf(buf, line);
6998 i = -1;
6999 while (ptr) {
7000 if (strstr(line, "Station")) {
7001 i++;
7002 key = strtok(line, " ");
7003 val = strtok(NULL, " ");
7004 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7005 &temp[i].cli_MACAddress[0],
7006 &temp[i].cli_MACAddress[1],
7007 &temp[i].cli_MACAddress[2],
7008 &temp[i].cli_MACAddress[3],
7009 &temp[i].cli_MACAddress[4],
7010 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7011 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7012 free(*associated_dev_array);
7013 return RETURN_ERR;
7014 }
7015 }
7016 else if (i < 0) {
7017 ptr = get_line_from_str_buf(ptr, line);
7018 continue; // We didn't detect 'station' entry yet
7019 }
7020 else if (strstr(line, "signal avg")) {
7021 key = strtok(line, ":");
7022 val = strtok(NULL, " ");
7023 if (sscanf(val, "%d", &rssi) <= 0 ) {
7024 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7025 free(*associated_dev_array);
7026 return RETURN_ERR;
7027 }
7028 temp[i].cli_RSSI = rssi;
7029 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7030 }
7031 // Here other fields can be parsed if added to filter of 'iw dev' command
7032
7033 ptr = get_line_from_str_buf(ptr, line);
7034 };
7035
7036 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7037
7038 return RETURN_OK;
7039}
7040
7041#if 0
7042//To-do
7043INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7044{
7045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7046
7047 //Using different approach to get required WiFi Parameters from system available commands
7048#if 0
7049 FILE *f;
7050 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7051 char cmd[256], buf[2048];
7052 char *param , *value, *line=NULL;
7053 size_t len = 0;
7054 ssize_t nread;
7055 wifi_associated_dev3_t *dev=NULL;
7056 *associated_dev_array = NULL;
7057 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7058 _syscmd(cmd,buf,sizeof(buf));
7059 *output_array_size = atoi(buf);
7060
7061 if (*output_array_size <= 0)
7062 return RETURN_OK;
7063
7064 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7065 *associated_dev_array = dev;
7066 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7067 _syscmd(cmd,buf,sizeof(buf));
7068 f = fopen("/tmp/connected_devices.txt", "r");
7069 if (f==NULL)
7070 {
7071 *output_array_size=0;
7072 return RETURN_ERR;
7073 }
7074 while ((nread = getline(&line, &len, f)) != -1)
7075 {
7076 param = strtok(line,"=");
7077 value = strtok(NULL,"=");
7078
7079 if( strcmp("flags",param) == 0 )
7080 {
7081 value[strlen(value)-1]='\0';
7082 if(strstr (value,"AUTHORIZED") != NULL )
7083 {
7084 dev[auth_temp].cli_AuthenticationState = 1;
7085 dev[auth_temp].cli_Active = 1;
7086 auth_temp++;
7087 read_flag=1;
7088 }
7089 }
7090 if(read_flag==1)
7091 {
7092 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7093 {
7094 value[strlen(value)-1]='\0';
7095 sscanf(value, "%x:%x:%x:%x:%x:%x",
7096 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7097 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7098 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7099 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7100 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7101 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7102
7103 }
7104 else if( strcmp("rx_packets",param) == 0 )
7105 {
7106 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7107 }
7108
7109 else if( strcmp("tx_packets",param) == 0 )
7110 {
7111 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7112 }
7113
7114 else if( strcmp("rx_bytes",param) == 0 )
7115 {
7116 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7117 }
7118
7119 else if( strcmp("tx_bytes",param) == 0 )
7120 {
7121 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7122 mac_temp++;
7123 read_flag=0;
7124 }
7125 }
7126 }
7127
7128 *output_array_size = auth_temp;
7129 auth_temp=0;
7130 mac_temp=0;
7131 free(line);
7132 fclose(f);
7133#endif
7134 char interface_name[MAX_BUF_SIZE] = {0};
7135 char wifi_status[MAX_BUF_SIZE] = {0};
7136 char hostapdconf[MAX_BUF_SIZE] = {0};
7137
7138 wifi_associated_dev3_t *dev_array = NULL;
7139 ULONG wifi_count = 0;
7140
7141 *associated_dev_array = NULL;
7142 *output_array_size = 0;
7143
7144 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7145 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7146 {
7147 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7148
7149 GetInterfaceName(interface_name, hostapdconf);
7150
7151 if(strlen(interface_name) > 1)
7152 {
7153 wifihal_interfacestatus(wifi_status,interface_name);
7154 if(strcmp(wifi_status,"RUNNING") == 0)
7155 {
7156 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7157
7158 *associated_dev_array = dev_array;
7159 *output_array_size = wifi_count;
7160 }
7161 else
7162 {
7163 *associated_dev_array = NULL;
7164 }
7165 }
7166 }
7167
7168 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7169 return RETURN_OK;
7170}
7171#endif
7172
7173/* getIPAddress function */
7174/**
7175* @description Returning IpAddress of the Matched String
7176*
7177* @param
7178* @str Having MacAddress
7179* @ipaddr Having ipaddr
7180* @return The status of the operation
7181* @retval RETURN_OK if successful
7182* @retval RETURN_ERR if any error is detected
7183*
7184*/
7185
7186INT getIPAddress(char *str,char *ipaddr)
7187{
7188 FILE *fp = NULL;
7189 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7190 int LeaseTime = 0,ret = 0;
7191 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7192 {
7193 return RETURN_ERR;
7194 }
7195
7196 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7197 {
7198 /*
7199 Sample:sss
7200 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7201 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7202 */
7203 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7204 &(LeaseTime),
7205 phyAddr,
7206 ipAddr,
7207 hostName
7208 );
7209 if(ret != 4)
7210 continue;
7211 if(strcmp(str,phyAddr) == 0)
7212 strcpy(ipaddr,ipAddr);
7213 }
7214 return RETURN_OK;
7215}
7216
7217/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7218/**
7219* @description Returning Inactive wireless connected clients informations
7220*
7221* @param
7222* @filename Holding private_wifi 2g/5g content files
7223* @associated_dev_array Having inactiv wireless clients informations
7224* @output_array_size Returning Inactive wireless counts
7225* @return The status of the operation
7226* @retval RETURN_OK if successful
7227* @retval RETURN_ERR if any error is detected
7228*
7229*/
7230
7231INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7232{
7233 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7234 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7235 FILE *fp = NULL;
7236 int arr[MACADDRESS_SIZE] = {0};
7237 unsigned char mac[MACADDRESS_SIZE] = {0};
7238 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7239 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7240 fp = popen(buf,"r");
7241 if(fp == NULL)
7242 return RETURN_ERR;
7243 else
7244 {
7245 fgets(path,sizeof(path),fp);
7246 maccount = atoi(path);
7247 }
7248 pclose(fp);
7249 *output_array_size = maccount;
7250 wifi_associated_dev3_t* temp = NULL;
7251 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7252 *associated_dev_array = temp;
7253 if(temp == NULL)
7254 {
7255 printf("Error Statement. Insufficient memory \n");
7256 return RETURN_ERR;
7257 }
7258 memset(buf,0,sizeof(buf));
7259 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7260 fp = popen(buf,"r");
7261 for(count = 0; count < maccount ; count++)
7262 {
7263 fgets(path,sizeof(path),fp);
7264 for(i = 0; path[i]!='\n';i++)
7265 str[i]=path[i];
7266 str[i]='\0';
7267 getIPAddress(str,ipaddr);
7268 memset(buf,0,sizeof(buf));
7269 if(strlen(ipaddr) > 0)
7270 {
7271 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7272 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7273 {
7274 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7275 {
7276 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7277 {
7278 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7279
7280 }
7281 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7282 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]);
7283 }
7284 temp[count].cli_AuthenticationState = 0; //TODO
7285 temp[count].cli_Active = 0; //TODO
7286 temp[count].cli_SignalStrength = 0;
7287 }
7288 else //Active wireless clients info
7289 {
7290 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7291 {
7292 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7293 {
7294 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7295
7296 }
7297 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7298 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]);
7299 }
7300 temp[count].cli_Active = 1;
7301 }
7302 }
7303 memset(ipaddr,0,sizeof(ipaddr));
7304 }
7305 pclose(fp);
7306 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7307 return RETURN_OK;
7308}
7309//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7310//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7311//To get Band Steering Capability
7312INT wifi_getBandSteeringCapability(BOOL *support)
7313{
7314 *support = FALSE;
7315 return RETURN_OK;
7316}
7317
7318
7319//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7320//To get Band Steering enable status
7321INT wifi_getBandSteeringEnable(BOOL *enable)
7322{
7323 *enable = FALSE;
7324 return RETURN_OK;
7325}
7326
7327//To turn on/off Band steering
7328INT wifi_setBandSteeringEnable(BOOL enable)
7329{
7330 return RETURN_OK;
7331}
7332
7333//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7334//To get Band Steering AP group
7335INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7336{
7337 if (NULL == output_ApGroup)
7338 return RETURN_ERR;
7339
7340 strcpy(output_ApGroup, "1,2");
7341 return RETURN_OK;
7342}
7343
7344//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7345//to set and read the band steering BandUtilizationThreshold parameters
7346INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7347{
7348 return RETURN_ERR;
7349}
7350
7351INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7352{
7353 return RETURN_ERR;
7354}
7355
7356//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7357//to set and read the band steering RSSIThreshold parameters
7358INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7359{
7360 return RETURN_ERR;
7361}
7362
7363INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7364{
7365 return RETURN_ERR;
7366}
7367
7368
7369//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7370//to set and read the band steering physical modulation rate threshold parameters
7371INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7372{
7373 //If chip is not support, return -1
7374 return RETURN_ERR;
7375}
7376
7377INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7378{
7379 //If chip is not support, return -1
7380 return RETURN_ERR;
7381}
7382
7383//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7384//to set and read the inactivity time (in seconds) for steering under overload condition
7385INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7386{
7387 return RETURN_ERR;
7388}
7389
7390INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7391{
7392 return RETURN_ERR;
7393}
7394
7395//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7396//to set and read the inactivity time (in seconds) for steering under Idle condition
7397INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7398{
7399 return RETURN_ERR;
7400}
7401
7402INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7403{
7404 return RETURN_ERR;
7405}
7406
7407//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7408//pClientMAC[64]
7409//pSourceSSIDIndex[64]
7410//pDestSSIDIndex[64]
7411//pSteeringReason[256]
7412INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7413{
7414 //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
7415 *pSteeringTime=time(NULL);
7416 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7417 return RETURN_OK;
7418}
7419
7420INT wifi_ifConfigDown(INT apIndex)
7421{
7422 INT status = RETURN_OK;
7423 char cmd[64];
7424
7425 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7426 printf("%s: %s\n", __func__, cmd);
7427 system(cmd);
7428
7429 return status;
7430}
7431
7432INT wifi_ifConfigUp(INT apIndex)
7433{
7434 char cmd[128];
7435 char buf[1024];
7436
7437 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7438 _syscmd(cmd, buf, sizeof(buf));
7439 return 0;
7440}
7441
7442//>> Deprecated. Replace with wifi_applyRadioSettings
7443INT wifi_pushBridgeInfo(INT apIndex)
7444{
7445 char ip[32];
7446 char subnet[32];
7447 char bridge[32];
7448 int vlanId;
7449 char cmd[128];
7450 char buf[1024];
7451
7452 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7453 wifi_getApVlanID(apIndex,&vlanId);
7454
7455 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7456 _syscmd(cmd,buf, sizeof(buf));
7457
7458 return 0;
7459}
7460
7461INT wifi_pushChannel(INT radioIndex, UINT channel)
7462{
7463 char cmd[128];
7464 char buf[1024];
7465 int apIndex;
7466
7467 apIndex=(radioIndex==0)?0:1;
7468 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7469 _syscmd(cmd,buf, sizeof(buf));
7470
7471 return 0;
7472}
7473
7474INT wifi_pushChannelMode(INT radioIndex)
7475{
7476 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7477 return RETURN_ERR;
7478}
7479
7480INT wifi_pushDefaultValues(INT radioIndex)
7481{
7482 //Apply Comcast specified default radio settings instantly
7483 //AMPDU=1
7484 //AMPDUFrames=32
7485 //AMPDULim=50000
7486 //txqueuelen=1000
7487
7488 return RETURN_ERR;
7489}
7490
7491INT wifi_pushTxChainMask(INT radioIndex)
7492{
7493 //Apply default TxChainMask instantly
7494 return RETURN_ERR;
7495}
7496
7497INT wifi_pushRxChainMask(INT radioIndex)
7498{
7499 //Apply default RxChainMask instantly
7500 return RETURN_ERR;
7501}
7502
7503INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7504{
7505 INT status;
7506
7507 status = wifi_setSSIDName(apIndex,ssid);
7508 wifi_setApEnable(apIndex,FALSE);
7509 wifi_setApEnable(apIndex,TRUE);
7510
7511 return status;
7512}
7513
7514INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7515{
7516 //Apply default Ssid Advertisement instantly
7517 return RETURN_ERR;
7518}
7519
7520INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7521{
7522 INT status = RETURN_ERR;
7523 *output = 0;
7524 return RETURN_ERR;
7525}
7526
7527INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7528{
7529 return RETURN_OK;
7530}
7531
7532INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7533{
7534 return RETURN_OK;
7535}
7536
7537//To-do
7538INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7539{
developereb199ae2022-09-13 14:04:27 +08007540 char output[16]={'\0'};
7541 char config_file[MAX_BUF_SIZE] = {0};
7542
7543 if (!output_string)
7544 return RETURN_ERR;
7545
7546 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7547 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7548
7549 if (strlen(output) == 0)
7550 snprintf(output_string, 64, "Disabled");
7551 else if (strncmp(output, "0", 1) == 0)
7552 snprintf(output_string, 64, "Disabled");
7553 else if (strncmp(output, "1", 1) == 0)
7554 snprintf(output_string, 64, "Optional");
7555 else if (strncmp(output, "2", 1) == 0)
7556 snprintf(output_string, 64, "Required");
7557 else {
7558 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7559 return RETURN_ERR;
7560 }
7561
7562 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007563 return RETURN_OK;
7564}
7565INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7566{
developereb199ae2022-09-13 14:04:27 +08007567 char str[MAX_BUF_SIZE]={'\0'};
7568 char cmd[MAX_CMD_SIZE]={'\0'};
7569 struct params params;
7570 char config_file[MAX_BUF_SIZE] = {0};
7571
7572 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7573 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7574 return RETURN_ERR;
7575
7576 params.name = "ieee80211w";
7577 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7578 params.value = "0";
7579 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7580 params.value = "1";
7581 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7582 params.value = "2";
7583 else{
7584 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7585 return RETURN_ERR;
7586 }
7587 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7588 wifi_hostapdWrite(config_file, &params, 1);
7589 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007590 return RETURN_OK;
7591}
7592INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7593{
7594 char output[16]={'\0'};
7595 char config_file[MAX_BUF_SIZE] = {0};
7596
7597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7598 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7599 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7600
7601 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7602 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7603
7604 return RETURN_OK;
7605}
7606
7607INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7608{
7609 return RETURN_OK;
7610}
7611
7612INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7613{
7614 return RETURN_OK;
7615}
7616
7617INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7618{
7619 return RETURN_OK;
7620}
7621
7622INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7623{
7624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7625 char config_file[MAX_BUF_SIZE] = {0};
7626
7627 if (NULL == output)
7628 return RETURN_ERR;
7629 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7630 wifi_hostapdRead(config_file,"hw_mode",output,64);
7631
7632 if(strcmp(output,"b")==0)
7633 sprintf(output, "%s", "1,2,5.5,11");
7634 else if (strcmp(output,"a")==0)
7635 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7636 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7637 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7638
7639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7640 return RETURN_OK;
7641}
7642
7643INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7644{
7645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7646 char *temp;
7647 char temp_output[128];
7648 char temp_TransmitRates[128];
7649 char config_file[MAX_BUF_SIZE] = {0};
7650
7651 if (NULL == output)
7652 return RETURN_ERR;
7653
7654 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7655 wifi_hostapdRead(config_file,"supported_rates",output,64);
7656
7657 strcpy(temp_TransmitRates,output);
7658 strcpy(temp_output,"");
7659 temp = strtok(temp_TransmitRates," ");
7660 while(temp!=NULL)
7661 {
7662 temp[strlen(temp)-1]=0;
7663 if((temp[0]=='5') && (temp[1]=='\0'))
7664 {
7665 temp="5.5";
7666 }
7667 strcat(temp_output,temp);
7668 temp = strtok(NULL," ");
7669 if(temp!=NULL)
7670 {
7671 strcat(temp_output,",");
7672 }
7673 }
7674 strcpy(output,temp_output);
7675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7676
7677 return RETURN_OK;
7678}
7679
7680INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7681{
7682 return RETURN_OK;
7683}
7684
7685
7686INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7687{
7688 int i=0;
7689 char *temp;
7690 char temp1[128];
7691 char temp_output[128];
7692 char temp_TransmitRates[128];
7693 struct params params={'\0'};
7694 char config_file[MAX_BUF_SIZE] = {0};
7695
7696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7697 if(NULL == output)
7698 return RETURN_ERR;
7699
7700 strcpy(temp_TransmitRates,output);
7701
7702 for(i=0;i<strlen(temp_TransmitRates);i++)
7703 {
7704 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7705 {
7706 continue;
7707 }
7708 else
7709 {
7710 return RETURN_ERR;
7711 }
7712 }
7713 strcpy(temp_output,"");
7714 temp = strtok(temp_TransmitRates," ");
7715 while(temp!=NULL)
7716 {
7717 strcpy(temp1,temp);
7718 if(wlanIndex==1)
7719 {
7720 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
7721 {
7722 return RETURN_ERR;
7723 }
7724 }
7725
7726 if(strcmp(temp,"5.5")==0)
7727 {
7728 strcpy(temp1,"55");
7729 }
7730 else
7731 {
7732 strcat(temp1,"0");
7733 }
7734 strcat(temp_output,temp1);
7735 temp = strtok(NULL," ");
7736 if(temp!=NULL)
7737 {
7738 strcat(temp_output," ");
7739 }
7740 }
7741 strcpy(output,temp_output);
7742
7743
7744 params.name = "supported_rates";
7745 params.value = output;
7746
7747 wifi_dbg_printf("\n%s:",__func__);
7748 wifi_dbg_printf("params.value=%s\n",params.value);
7749 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7750 wifi_hostapdWrite(config_file,&params,1);
7751 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7752
7753 return RETURN_OK;
7754}
7755
7756
7757static char *sncopy(char *dst, int dst_sz, const char *src)
7758{
7759 if (src && dst && dst_sz > 0) {
7760 strncpy(dst, src, dst_sz);
7761 dst[dst_sz - 1] = '\0';
7762 }
7763 return dst;
7764}
7765
7766static int util_get_sec_chan_offset(int channel, const char* ht_mode)
7767{
7768 if (0 == strcmp(ht_mode, "HT40") ||
7769 0 == strcmp(ht_mode, "HT80") ||
7770 0 == strcmp(ht_mode, "HT160")) {
7771 switch (channel) {
7772 case 1 ... 7:
7773 case 36:
7774 case 44:
7775 case 52:
7776 case 60:
7777 case 100:
7778 case 108:
7779 case 116:
7780 case 124:
7781 case 132:
7782 case 140:
7783 case 149:
7784 case 157:
7785 return 1;
7786 case 8 ... 13:
7787 case 40:
7788 case 48:
7789 case 56:
7790 case 64:
7791 case 104:
7792 case 112:
7793 case 120:
7794 case 128:
7795 case 136:
7796 case 144:
7797 case 153:
7798 case 161:
7799 return -1;
7800 default:
7801 return -EINVAL;
7802 }
7803 }
7804
7805 return -EINVAL;
7806}
7807
7808static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
7809{
7810 if (NULL == hw_mode) return;
7811
7812 if (0 == strcmp(hw_mode, "ac"))
7813 sncopy(bw_mode, bw_mode_len, "ht vht");
7814
7815 if (0 == strcmp(hw_mode, "n"))
7816 sncopy(bw_mode, bw_mode_len, "ht");
7817
7818 return;
7819}
7820
7821static int util_chan_to_freq(int chan)
7822{
7823 if (chan == 14)
7824 return 2484;
7825 else if (chan < 14)
7826 return 2407 + chan * 5;
7827 else if (chan >= 182 && chan <= 196)
7828 return 4000 + chan * 5;
7829 else
7830 return 5000 + chan * 5;
7831 return 0;
7832}
7833
7834const int *util_unii_5g_chan2list(int chan, int width)
7835{
7836 static const int lists[] = {
7837 // <width>, <chan1>, <chan2>..., 0,
7838 20, 36, 0,
7839 20, 40, 0,
7840 20, 44, 0,
7841 20, 48, 0,
7842 20, 52, 0,
7843 20, 56, 0,
7844 20, 60, 0,
7845 20, 64, 0,
7846 20, 100, 0,
7847 20, 104, 0,
7848 20, 108, 0,
7849 20, 112, 0,
7850 20, 116, 0,
7851 20, 120, 0,
7852 20, 124, 0,
7853 20, 128, 0,
7854 20, 132, 0,
7855 20, 136, 0,
7856 20, 140, 0,
7857 20, 144, 0,
7858 20, 149, 0,
7859 20, 153, 0,
7860 20, 157, 0,
7861 20, 161, 0,
7862 20, 165, 0,
7863 40, 36, 40, 0,
7864 40, 44, 48, 0,
7865 40, 52, 56, 0,
7866 40, 60, 64, 0,
7867 40, 100, 104, 0,
7868 40, 108, 112, 0,
7869 40, 116, 120, 0,
7870 40, 124, 128, 0,
7871 40, 132, 136, 0,
7872 40, 140, 144, 0,
7873 40, 149, 153, 0,
7874 40, 157, 161, 0,
7875 80, 36, 40, 44, 48, 0,
7876 80, 52, 56, 60, 64, 0,
7877 80, 100, 104, 108, 112, 0,
7878 80, 116, 120, 124, 128, 0,
7879 80, 132, 136, 140, 144, 0,
7880 80, 149, 153, 157, 161, 0,
7881 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
7882 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
7883 -1 // final delimiter
7884 };
7885 const int *start;
7886 const int *p;
7887
7888 for (p = lists; *p != -1; p++) {
7889 if (*p == width) {
7890 for (start = ++p; *p != 0; p++) {
7891 if (*p == chan)
7892 return start;
7893 }
7894 }
7895 // move to the end of channel list of given width
7896 while (*p != 0) {
7897 p++;
7898 }
7899 }
7900
7901 return NULL;
7902}
7903
7904static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
7905{
7906 if (NULL == ht_mode)
7907 return 0;
7908
7909 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
7910 const int *chans = util_unii_5g_chan2list(channel, width);
7911 int sum = 0;
7912 int cnt = 0;
7913
7914 if (NULL == chans)
7915 return 0;
7916
7917 while (*chans) {
7918 sum += *chans;
7919 cnt++;
7920 chans++;
7921 }
7922 return sum / cnt;
7923}
7924
7925static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
7926{
7927 BOOL onlyG, onlyN, onlyA;
7928 CHAR tmp[64];
7929 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
7930 if (ret == RETURN_OK) {
7931 sncopy(hw_mode, hw_mode_size, tmp);
7932 }
7933 return ret;
7934}
7935
7936INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
7937{
7938 // Sample commands:
7939 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
7940 // hostapd_cli -i wifi0 chan_switch 30 2437
7941 char cmd[MAX_CMD_SIZE] = {0};
7942 char buf[MAX_BUF_SIZE] = {0};
7943 int freq = 0, ret = 0;
7944 char center_freq1_str[32] = ""; // center_freq1=%d
7945 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
7946 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
7947 char hw_mode[16] = ""; // n|ac
7948 char bw_mode[16] = ""; // ht|ht vht
7949 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
7950 int sec_chan_offset;
7951 int width;
7952
7953 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7954
7955 freq = util_chan_to_freq(channel);
7956
7957 // Get radio mode HT20|HT40|HT80 etc.
7958 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
7959 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
7960 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
7961 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
7962 if (sec_chan_offset != -EINVAL)
7963 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
7964
7965
7966 // Provide bandwith if specified
7967 if (channel_width_MHz > 20) {
7968 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
7969 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
7970 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
7971
7972 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
7973 }
7974
7975 int center_chan = 0;
7976 if (channel_width_MHz > 20) {
7977 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
7978 if (center_chan > 0) {
7979 int center_freq1 = util_chan_to_freq(center_chan);
7980 if (center_freq1)
7981 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
7982 }
7983 }
7984
7985 {
7986 // Only the first AP, other are hanging on the same radio
7987 int apIndex = radioIndex;
7988 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
7989 AP_PREFIX, apIndex, csa_beacon_count, freq,
7990 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
7991 wifi_dbg_printf("execute: '%s'\n", cmd);
7992 ret = _syscmd(cmd, buf, sizeof(buf));
7993 }
7994
7995 wifi_setRadioChannel(radioIndex, channel);
7996
7997 char *ext_str = "None";
7998 if (sec_chan_offset == 1) ext_str = "Above";
7999 else if (sec_chan_offset == -1) ext_str = "Below";
8000 wifi_setRadioExtChannel(radioIndex, ext_str);
8001
8002 wifi_setRadioCenterChannel(radioIndex, center_chan);
8003
8004 char mhz_str[16];
8005 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8006 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8007
8008 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8009
8010 return RETURN_OK;
8011}
8012
8013INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8014{
8015 char cmd[1024] = {0};
8016 char buf[1024] = {0};
8017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8018 wifi_neighbor_ap2_t *scan_array = NULL;
8019 int scan_count=0;
8020 int i =0;
8021 int freq=0;
8022 size_t len=0;
8023 FILE *f = NULL;
8024 ssize_t read = 0;
8025 char *line =NULL;
8026 char radio_ifname[64];
8027 char secondary_chan[64];
8028 int vht_channel_width = 0;
8029
8030 if(wifi_getRadioIfName(radio_index,radio_ifname)!=RETURN_OK)
8031 return RETURN_ERR;
8032
8033 /* sched_start is not supported on open source ath9k ath10k firmware
8034 * Using active scan as a workaround */
8035 sprintf(cmd,"iw dev %s scan |grep '^BSS\\|SSID:\\|freq:\\|signal:\\|HT operation:\\|secondary channel offset:\\|* channel width:'", radio_ifname);
8036 if((f = popen(cmd, "r")) == NULL) {
8037 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8038 return RETURN_ERR;
8039 }
8040 read = getline(&line, &len, f);
8041 while (read != -1) {
8042 if(strncmp(line,"BSS",3) == 0) {
8043 i = scan_count;
8044 scan_count++;
8045 scan_array = realloc(scan_array,sizeof(wifi_neighbor_ap2_t)*scan_count);
8046 memset(&(scan_array[i]),0, sizeof(wifi_neighbor_ap2_t));
8047 sscanf(line,"BSS %17s", scan_array[i].ap_BSSID);
8048
8049 read = getline(&line, &len, f);
8050 sscanf(line," freq: %d", &freq);
8051 scan_array[i].ap_Channel = ieee80211_frequency_to_channel(freq);
8052
8053 read = getline(&line, &len, f);
8054 sscanf(line," signal: %d", &(scan_array[i].ap_SignalStrength));
8055
8056 read = getline(&line, &len, f);
8057 sscanf(line," SSID: %s", scan_array[i].ap_SSID);
8058 wifi_dbg_printf("%s:Discovered BSS %s, %d, %d , %s\n", __func__, scan_array[i].ap_BSSID, scan_array[i].ap_Channel,scan_array[i].ap_SignalStrength, scan_array[i].ap_SSID);
8059 read = getline(&line, &len, f);
8060 if(strncmp(line,"BSS",3)==0) {
8061 // No HT and no VHT => 20Mhz
8062 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11%s", radio_index%1 ? "A": "G");
8063 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
8064 continue;
8065 }
8066 if(strncmp(line," HT operation:",14)!= 0) {
8067 wifi_dbg_printf("HT output parsing error (%s)\n", line);
8068 goto output_error;
8069 }
8070
8071 read = getline(&line, &len, f);
8072 sscanf(line," * secondary channel offset: %s", &secondary_chan);
8073
8074 if(!strcmp(secondary_chan, "no")) {
8075 //20Mhz
8076 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
8077 }
8078
8079 if(!strcmp(secondary_chan, "above")) {
8080 //40Mhz +
8081 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
8082 }
8083
8084 if(!strcmp(secondary_chan, "below")) {
8085 //40Mhz -
8086 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8087 }
8088
8089
8090 read = getline(&line, &len, f);
8091 if(strncmp(line," VHT operation:",15) !=0) {
8092 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
8093 // No VHT
8094 continue;
8095 }
8096 read = getline(&line, &len, f);
8097 sscanf(line," * channel width: %d", &vht_channel_width);
8098 if(vht_channel_width == 1) {
8099 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT80");
8100 } else {
8101 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT40");
8102 }
8103
8104 }
8105 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
8106 read = getline(&line, &len, f);
8107 }
8108 wifi_dbg_printf("%s:Counted BSS: %d\n",__func__, scan_count);
8109 *output_array_size = scan_count;
8110 *neighbor_ap_array = scan_array;
8111 free(line);
8112 pclose(f);
8113 return RETURN_OK;
8114
8115output_error:
8116 pclose(f);
8117 free(line);
8118 free(scan_array);
8119 return RETURN_ERR;
8120}
8121INT wifi_getApAssociatedDeviceStats(
8122 INT apIndex,
8123 mac_address_t *clientMacAddress,
8124 wifi_associated_dev_stats_t *associated_dev_stats,
8125 u64 *handle)
8126{
8127 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8128 char interface_name[50] = {0};
8129 char cmd[1024] = {0};
8130 char mac_str[18] = {0};
8131 char *key = NULL;
8132 char *val = NULL;
8133 FILE *f = NULL;
8134 char *line = NULL;
8135 size_t len = 0;
8136 ssize_t read = 0;
8137
8138 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8139 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8140 return RETURN_ERR;
8141 }
8142
8143 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8144 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8145 if((f = popen(cmd, "r")) == NULL) {
8146 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8147 return RETURN_ERR;
8148 }
8149
8150 while ((read = getline(&line, &len, f)) != -1) {
8151 key = strtok(line,":");
8152 val = strtok(NULL,":");
8153
8154 if(!strncmp(key,"rx bytes",8))
8155 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8156 if(!strncmp(key,"tx bytes",8))
8157 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8158 if(!strncmp(key,"rx packets",10))
8159 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8160 if(!strncmp(key,"tx packets",10))
8161 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8162 if(!strncmp(key,"tx retries",10))
8163 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8164 if(!strncmp(key,"tx failed",9))
8165 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8166 if(!strncmp(key,"rx drop misc",13))
8167 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8168 if(!strncmp(key,"rx bitrate",10)) {
8169 val = strtok(val, " ");
8170 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8171 }
8172 if(!strncmp(key,"tx bitrate",10)) {
8173 val = strtok(val, " ");
8174 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8175 }
8176 }
8177 free(line);
8178 pclose(f);
8179 return RETURN_OK;
8180}
8181
8182INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8183{
8184 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8185
8186 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8187 if (NULL == output_string)
8188 return RETURN_ERR;
8189
8190 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8191 _syscmd(cmd, buf, sizeof(buf));
8192
8193 //size of SSID name restricted to value less than 32 bytes
8194 snprintf(output_string, 32, "%s", buf);
8195 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8196
8197 return RETURN_OK;
8198}
8199
8200INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8201{
8202 //char cmd[MAX_CMD_SIZE] = {0};
8203 char config_file[MAX_BUF_SIZE] = {0};
8204 char buf[32] = {0};
8205
8206 if (!output_filterMode)
8207 return RETURN_ERR;
8208
8209 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8210 //_syscmd(cmd, buf, sizeof(buf));
8211 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8212 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008213 if(strlen(buf) == 0) {
8214 *output_filterMode = 0;
8215 }
8216 else {
8217 int macaddr_acl_mode = strtol(buf, NULL, 10);
8218 if (macaddr_acl_mode == 1) {
8219 *output_filterMode = 1;
8220 } else if (macaddr_acl_mode == 0) {
8221 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8222 if (strlen(buf) == 0) {
8223 *output_filterMode = 0;
8224 } else {
8225 *output_filterMode = 2;
8226 }
8227 } else {
8228 return RETURN_ERR;
8229 }
8230 }
developer06a01d92022-09-07 16:32:39 +08008231
8232 return RETURN_OK;
8233}
8234
8235INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8236{
8237 FILE *fp = NULL;
8238 char str[MAX_BUF_SIZE] = {0};
8239 int wificlientindex = 0 ;
8240 int count = 0;
8241 int signalstrength = 0;
8242 int arr[MACADDRESS_SIZE] = {0};
8243 unsigned char mac[MACADDRESS_SIZE] = {0};
8244 UINT wifi_count = 0;
8245 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8246 char pipeCmd[MAX_CMD_SIZE] = {0};
8247
8248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8249 *output_array_size = 0;
8250 *associated_dev_array = NULL;
8251 char interface_name[50] = {0};
8252
8253 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8254 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8255 return RETURN_ERR;
8256 }
8257
8258 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8259 fp = popen(pipeCmd, "r");
8260 if (fp == NULL)
8261 {
8262 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8263 return RETURN_ERR;
8264 }
8265
8266 /* Read the output a line at a time - output it. */
8267 fgets(str, sizeof(str)-1, fp);
8268 wifi_count = (unsigned int) atoi ( str );
8269 *output_array_size = wifi_count;
8270 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8271 pclose(fp);
8272
8273 if(wifi_count == 0)
8274 {
8275 return RETURN_OK;
8276 }
8277 else
8278 {
8279 wifi_associated_dev2_t* temp = NULL;
8280 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8281 *associated_dev_array = temp;
8282 if(temp == NULL)
8283 {
8284 printf("Error Statement. Insufficient memory \n");
8285 return RETURN_ERR;
8286 }
8287
8288 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8289 system(pipeCmd);
8290
8291 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8292 if(fp == NULL)
8293 {
8294 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8295 return RETURN_ERR;
8296 }
8297 fclose(fp);
8298
8299 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8300 fp = popen(pipeCmd, "r");
8301 if(fp)
8302 {
8303 for(count =0 ; count < wifi_count; count++)
8304 {
8305 fgets(str, MAX_BUF_SIZE, fp);
8306 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8307 {
8308 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8309 {
8310 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8311
8312 }
8313 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8314 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]);
8315 }
8316 temp[count].cli_AuthenticationState = 1; //TODO
8317 temp[count].cli_Active = 1; //TODO
8318 }
8319 pclose(fp);
8320 }
8321
8322 //Updating RSSI per client
8323 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8324 fp = popen(pipeCmd, "r");
8325 if(fp)
8326 {
8327 pclose(fp);
8328 }
8329 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8330 if(fp)
8331 {
8332 for(count =0 ; count < wifi_count ;count++)
8333 {
8334 fgets(str, MAX_BUF_SIZE, fp);
8335 signalstrength = atoi(str);
8336 temp[count].cli_RSSI = signalstrength;
8337 }
8338 pclose(fp);
8339 }
8340
8341
8342 //LastDataDownlinkRate
8343 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8344 fp = popen(pipeCmd, "r");
8345 if (fp)
8346 {
8347 pclose(fp);
8348 }
8349 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8350 if (fp)
8351 {
8352 for (count = 0; count < wifi_count; count++)
8353 {
8354 fgets(str, MAX_BUF_SIZE, fp);
8355 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8356 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8357 }
8358 pclose(fp);
8359 }
8360
8361 //LastDataUplinkRate
8362 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8363 fp = popen(pipeCmd, "r");
8364 if (fp)
8365 {
8366 pclose(fp);
8367 }
8368 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8369 if (fp)
8370 {
8371 for (count = 0; count < wifi_count; count++)
8372 {
8373 fgets(str, MAX_BUF_SIZE, fp);
8374 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8375 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8376 }
8377 pclose(fp);
8378 }
8379 }
8380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8381 return RETURN_OK;
8382
8383}
8384
8385INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8386{
8387#if 0
8388 /*char buf[1024] = {0};
8389 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8390 _syscmd(cmd, buf, sizeof(buf));*/
8391
8392 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8393 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8394 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8395 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8396
8397 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.
8398 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].
8399 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].
8400 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].
8401 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8402 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8403
8404 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8405 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8406 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8407 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.
8408 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.
8409 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.
8410 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.
8411 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.
8412 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.
8413 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.
8414 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8415#endif
8416
8417 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008418 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008419 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008420 char pipeCmd[128] = {0};
8421 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008422 wifi_ssidTrafficStats2_t *out = output_struct;
8423
developerce736392022-09-13 15:24:34 +08008424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008425 if (!output_struct)
8426 return RETURN_ERR;
8427
developerce736392022-09-13 15:24:34 +08008428 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8429 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8430 GetInterfaceName(interface_name, HConf_file);
8431 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008432
developer06a01d92022-09-07 16:32:39 +08008433 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008434 if (fp == NULL) {
8435 fprintf(stderr, "%s: popen failed\n", __func__);
8436 return RETURN_ERR;
8437 }
8438 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008439
developerce736392022-09-13 15:24:34 +08008440 if (strlen(str) == 0) // interface not exist
8441 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008442
developerce736392022-09-13 15:24:34 +08008443 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8444 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008445 pclose(fp);
8446
developerce736392022-09-13 15:24:34 +08008447 memset(str, 0, sizeof(str));
8448 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008449 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008450 if (fp == NULL) {
8451 fprintf(stderr, "%s: popen failed\n", __func__);
8452 return RETURN_ERR;
8453 }
8454 fgets(str, sizeof(str), fp);
8455
8456 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8457 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008458 pclose(fp);
developerce736392022-09-13 15:24:34 +08008459
8460 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8461 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8462
8463 // Not supported
8464 output_struct->ssid_RetransCount = 0;
8465 output_struct->ssid_FailedRetransCount = 0;
8466 output_struct->ssid_RetryCount = 0;
8467 output_struct->ssid_MultipleRetryCount = 0;
8468 output_struct->ssid_ACKFailureCount = 0;
8469 output_struct->ssid_AggregatedPacketCount = 0;
8470
developer06a01d92022-09-07 16:32:39 +08008471 return RETURN_OK;
8472}
8473
8474//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).
8475INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8476{
8477 char output_val[16]={'\0'};
8478 char config_file[MAX_BUF_SIZE] = {0};
8479
8480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8481 if (!output)
8482 return RETURN_ERR;
8483 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8484 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8485
8486 if( strcmp(output_val,"1") == 0 )
8487 *output = TRUE;
8488 else
8489 *output = FALSE;
8490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8491
8492 return RETURN_OK;
8493}
8494
8495INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8496{
8497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8498 char str[MAX_BUF_SIZE]={'\0'};
8499 char string[MAX_BUF_SIZE]={'\0'};
8500 char cmd[MAX_CMD_SIZE]={'\0'};
8501 char *ch;
8502 char config_file[MAX_BUF_SIZE] = {0};
8503 struct params params;
8504
8505 if(enable == TRUE)
8506 strcpy(string,"1");
8507 else
8508 strcpy(string,"0");
8509
8510 params.name = "ap_isolate";
8511 params.value = string;
8512
8513 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8514 wifi_hostapdWrite(config_file,&params,1);
8515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8516
8517 return RETURN_OK;
8518}
8519
8520INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8521{
8522 if (NULL == output_dBm)
8523 return RETURN_ERR;
8524
8525 *output_dBm = 0;
8526 return RETURN_OK;
8527}
8528
8529INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8530{
8531 return RETURN_OK;
8532}
8533INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8534{
8535 return RETURN_OK;
8536}
8537INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8538{
8539 return RETURN_OK;
8540}
8541INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8542{
8543 return RETURN_OK;
8544}
8545INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8546{
8547 return RETURN_OK;
8548}
8549INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8550{
8551 char config_file[MAX_BUF_SIZE] = {0};
8552 struct params list;
8553
8554 list.name = "bss_transition";
8555 list.value = activate?"1":"0";
8556 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8557 wifi_hostapdWrite(config_file, &list, 1);
8558
8559 return RETURN_OK;
8560}
8561wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8562
8563void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8564{
8565 return;
8566}
8567
8568INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8569{
8570 // TODO Implement me!
8571 return RETURN_OK;
8572}
8573
8574INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8575{
developera3c68b92022-09-13 15:27:29 +08008576 char file_name[128] = {0};
8577 char buf[128] = {0};
8578 FILE *f = NULL;
8579
8580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8581
8582 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8583 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8584 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8585 f = fopen(file_name, "w");
8586 if (f == NULL)
8587 return RETURN_ERR;
8588 // For mode == 0 is to disable filter, just don't write to the file.
8589 if (mode)
8590 fprintf(f, "%s", essid);
8591
8592 fclose(f);
8593 }
8594 } else { // special case, need to set AP's SSID as filter for each radio.
8595 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8596 f = fopen(file_name, "w");
8597 if (f == NULL)
8598 return RETURN_ERR;
8599
8600 // For mode == 0 is to disable filter, just don't write to the file.
8601 if (mode)
8602 fprintf(f, "%s", essid);
8603
8604 fclose(f);
8605 }
8606
8607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008608 return RETURN_OK;
8609}
8610
8611INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8612{
8613 // TODO Implement me!
8614 //Apply wifi_pushRadioChannel() instantly
8615 return RETURN_ERR;
8616}
8617
8618INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8619{
8620 // TODO Implement me!
8621 return RETURN_OK;
8622}
8623
8624#ifdef HAL_NETLINK_IMPL
8625static int tidStats_callback(struct nl_msg *msg, void *arg) {
8626 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8627 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8628 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8629 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
8630 int rem , tid_index = 0;
8631
8632 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
8633 wifi_associated_dev_tid_entry_t *stats_entry;
8634
8635 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
8636 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
8637 };
8638 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
8639 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
8640 };
8641
8642 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8643 genlmsg_attrlen(gnlh, 0), NULL);
8644
8645
8646 if (!tb[NL80211_ATTR_STA_INFO]) {
8647 fprintf(stderr, "station stats missing!\n");
8648 return NL_SKIP;
8649 }
8650
8651 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
8652 tb[NL80211_ATTR_STA_INFO],
8653 stats_policy)) {
8654 fprintf(stderr, "failed to parse nested attributes!\n");
8655 return NL_SKIP;
8656 }
8657
8658 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
8659 {
8660 stats_entry = &out->tid_array[tid_index];
8661
8662 stats_entry->tid = tid_index;
8663 stats_entry->ac = _tid_ac_index_get[tid_index];
8664
8665 if(sinfo[NL80211_STA_INFO_TID_STATS])
8666 {
8667 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
8668 printf("failed to parse nested stats attributes!");
8669 return NL_SKIP;
8670 }
8671 }
8672 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8673 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8674
8675 if(tid_index < (PS_MAX_TID - 1))
8676 tid_index++;
8677 }
8678 //ToDo: sum_time_ms, ewma_time_ms
8679 return NL_SKIP;
8680}
8681#endif
8682
8683INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
8684{
8685#ifdef HAL_NETLINK_IMPL
8686 Netlink nl;
8687 char if_name[10];
8688
8689 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8690
8691 nl.id = initSock80211(&nl);
8692
8693 if (nl.id < 0) {
8694 fprintf(stderr, "Error initializing netlink \n");
8695 return -1;
8696 }
8697
8698 struct nl_msg* msg = nlmsg_alloc();
8699
8700 if (!msg) {
8701 fprintf(stderr, "Failed to allocate netlink message.\n");
8702 nlfree(&nl);
8703 return -2;
8704 }
8705
8706 genlmsg_put(msg,
8707 NL_AUTO_PORT,
8708 NL_AUTO_SEQ,
8709 nl.id,
8710 0,
8711 0,
8712 NL80211_CMD_GET_STATION,
8713 0);
8714
8715 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8716 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8717 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
8718 nl_send_auto(nl.socket, msg);
8719 nl_recvmsgs(nl.socket, nl.cb);
8720 nlmsg_free(msg);
8721 nlfree(&nl);
8722 return RETURN_OK;
8723#else
8724//iw implementation
8725#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
8726#define TOTAL_MAX_LINES 50
8727
8728 char buf[256] = {'\0'}; /* or other suitable maximum line size */
8729 char if_name[10];
8730 FILE *fp=NULL;
8731 char pipeCmd[1024]= {'\0'};
8732 int lines,tid_index=0;
8733 char mac_addr[20] = {'\0'};
8734
8735 wifi_associated_dev_tid_entry_t *stats_entry;
8736
8737 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8738 strcpy(mac_addr,clientMacAddress);
8739
8740 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
8741 fp= popen(pipeCmd,"r");
8742 if(fp == NULL)
8743 {
8744 perror("popen for station dump failed\n");
8745 return RETURN_ERR;
8746 }
8747 pclose(fp);
8748
8749 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
8750 fp=popen(pipeCmd,"r");
8751 if(fp == NULL)
8752 {
8753 perror("popen for grep station failed\n");
8754 return RETURN_ERR;
8755 }
8756 else if(fgets(buf,sizeof(buf),fp) != NULL)
8757 lines=atoi(buf);
8758 else
8759 {
8760 pclose(fp);
8761 fprintf(stderr,"No devices are connected \n");
8762 return RETURN_ERR;
8763 }
8764 pclose(fp);
8765
8766 if(lines == 1)
8767 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
8768
8769 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
8770 {
8771 stats_entry = &tid_stats->tid_array[tid_index];
8772 stats_entry->tid = tid_index;
8773
8774 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);
8775
8776 fp=popen(pipeCmd,"r");
8777 if(fp ==NULL)
8778 {
8779 perror("Failed to read from tid file \n");
8780 return RETURN_ERR;
8781 }
8782 else if(fgets(buf,sizeof(buf),fp) != NULL)
8783 stats_entry->num_msdus = atol(buf);
8784
8785 pclose(fp);
8786 stats_entry->ac = _tid_ac_index_get[tid_index];
8787// TODO:
8788// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
8789// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
8790 }
8791 return RETURN_OK;
8792#endif
8793}
8794
8795
8796INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
8797{
8798 // TODO Implement me!
8799 return RETURN_OK;
8800}
8801
8802
8803INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
8804{
8805 // TODO Implement me!
8806 return RETURN_ERR;
8807}
8808
8809INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
8810{
8811 // TODO Implement me!
8812 return RETURN_ERR;
8813}
8814
8815INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8816{
8817 // TODO Implement me!
8818 return RETURN_ERR;
8819}
8820
8821INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8822{
8823 // TODO Implement me!
8824 return RETURN_ERR;
8825}
8826
8827INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
8828{
8829 // TODO Implement me!
8830 return RETURN_ERR;
8831}
8832
8833INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
8834{
8835 // TODO Implement me!
8836 return RETURN_ERR;
8837}
8838
8839INT wifi_steering_eventUnregister(void)
8840{
8841 // TODO Implement me!
8842 return RETURN_ERR;
8843}
8844
8845INT wifi_delApAclDevices(INT apIndex)
8846{
8847#if 0
8848 char cmd[MAX_BUF_SIZE] = {0};
8849 char buf[MAX_BUF_SIZE] = {0};
8850
8851 /* Not reset proof solution */
8852 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
8853 if(_syscmd(cmd,buf,sizeof(buf)))
8854 return RETURN_ERR;
8855#endif
developere6aafda2022-09-13 14:59:28 +08008856 char cmd[MAX_CMD_SIZE]={0};
8857 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08008858
developere6aafda2022-09-13 14:59:28 +08008859 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8860 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
8861 if(_syscmd(cmd, buf, sizeof(buf)))
8862 return RETURN_ERR;
8863 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008864
8865 return RETURN_OK;
8866}
8867
8868#ifdef HAL_NETLINK_IMPL
8869static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
8870 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8871 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8872 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8873 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8874 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8875 char mac_addr[20],dev[20];
8876
8877 nla_parse(tb,
8878 NL80211_ATTR_MAX,
8879 genlmsg_attrdata(gnlh, 0),
8880 genlmsg_attrlen(gnlh, 0),
8881 NULL);
8882
8883 if(!tb[NL80211_ATTR_STA_INFO]) {
8884 fprintf(stderr, "sta stats missing!\n");
8885 return NL_SKIP;
8886 }
8887
8888 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8889 fprintf(stderr, "failed to parse nested attributes!\n");
8890 return NL_SKIP;
8891 }
8892 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8893
8894 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8895
8896 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
8897 fprintf(stderr, "failed to parse nested rate attributes!");
8898 return NL_SKIP;
8899 }
8900
8901 if(sinfo[NL80211_STA_INFO_TID_STATS])
8902 {
8903 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8904 printf("failed to parse nested stats attributes!");
8905 return NL_SKIP;
8906 }
8907 }
8908
8909 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
8910 {
8911 printf("Type is VHT\n");
8912 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8913 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8914
8915 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8916 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
8917 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8918 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8919 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8920 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8921 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8922 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8923 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
8924 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8925 }
8926 else
8927 {
8928 printf(" OFDM or CCK \n");
8929 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8930 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
8931 }
8932
8933 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
8934 if(rinfo[NL80211_RATE_INFO_MCS])
8935 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
8936 }
8937 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
8938 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
8939 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
8940 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
8941
8942 if(stats_info[NL80211_TID_STATS_RX_MSDU])
8943 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
8944
8945 if (sinfo[NL80211_STA_INFO_SIGNAL])
8946 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
8947 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
8948 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
8949 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
8950 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
8951 //rssi_array need to be filled
8952 return NL_SKIP;
8953}
8954#endif
8955
8956INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
8957{
8958#ifdef HAL_NETLINK_IMPL
8959 Netlink nl;
8960 char if_name[10];
8961
8962 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
8963
8964 if (*output_array_size <= 0)
8965 return RETURN_OK;
8966
8967 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8968 nl.id = initSock80211(&nl);
8969
8970 if (nl.id < 0) {
8971 fprintf(stderr, "Error initializing netlink \n");
8972 return 0;
8973 }
8974
8975 struct nl_msg* msg = nlmsg_alloc();
8976
8977 if (!msg) {
8978 fprintf(stderr, "Failed to allocate netlink message.\n");
8979 nlfree(&nl);
8980 return 0;
8981 }
8982
8983 genlmsg_put(msg,
8984 NL_AUTO_PORT,
8985 NL_AUTO_SEQ,
8986 nl.id,
8987 0,
8988 0,
8989 NL80211_CMD_GET_STATION,
8990 0);
8991
8992 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
8993 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8994 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
8995 nl_send_auto(nl.socket, msg);
8996 nl_recvmsgs(nl.socket, nl.cb);
8997 nlmsg_free(msg);
8998 nlfree(&nl);
8999 return RETURN_OK;
9000#else
9001 //TODO Implement me
9002 return RETURN_OK;
9003#endif
9004}
9005
9006#ifdef HAL_NETLINK_IMPL
9007static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9008 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9009 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9010 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9011 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9012 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9013 char mac_addr[20],dev[20];
9014
9015 nla_parse(tb,
9016 NL80211_ATTR_MAX,
9017 genlmsg_attrdata(gnlh, 0),
9018 genlmsg_attrlen(gnlh, 0),
9019 NULL);
9020
9021 if(!tb[NL80211_ATTR_STA_INFO]) {
9022 fprintf(stderr, "sta stats missing!\n");
9023 return NL_SKIP;
9024 }
9025
9026 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9027 fprintf(stderr, "failed to parse nested attributes!\n");
9028 return NL_SKIP;
9029 }
9030
9031 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9032
9033 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9034
9035 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9036 fprintf(stderr, "failed to parse nested rate attributes!");
9037 return NL_SKIP;
9038 }
9039
9040 if(sinfo[NL80211_STA_INFO_TID_STATS])
9041 {
9042 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9043 printf("failed to parse nested stats attributes!");
9044 return NL_SKIP;
9045 }
9046 }
9047 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9048 {
9049 printf("Type is VHT\n");
9050 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9051 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9052
9053 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9054 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9055 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9056 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9057 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9058 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9059 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9060 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9061 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9062 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9063 }
9064 else
9065 {
9066 printf(" OFDM or CCK \n");
9067 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9068 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9069 }
9070
9071 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9072 if(rinfo[NL80211_RATE_INFO_MCS])
9073 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9074 }
9075
9076 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9077 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9078 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9079 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9080
9081 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9082 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9083 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9084
9085 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9086 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9087
9088 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9089 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9090
9091 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9092 ((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]);
9093
9094 return NL_SKIP;
9095}
9096#endif
9097
9098INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9099{
9100#ifdef HAL_NETLINK_IMPL
9101 Netlink nl;
9102 char if_name[10];
9103
9104 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9105
9106 if (*output_array_size <= 0)
9107 return RETURN_OK;
9108
9109 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9110
9111 nl.id = initSock80211(&nl);
9112
9113 if(nl.id < 0) {
9114 fprintf(stderr, "Error initializing netlink \n");
9115 return 0;
9116 }
9117
9118 struct nl_msg* msg = nlmsg_alloc();
9119
9120 if(!msg) {
9121 fprintf(stderr, "Failed to allocate netlink message.\n");
9122 nlfree(&nl);
9123 return 0;
9124 }
9125
9126 genlmsg_put(msg,
9127 NL_AUTO_PORT,
9128 NL_AUTO_SEQ,
9129 nl.id,
9130 0,
9131 0,
9132 NL80211_CMD_GET_STATION,
9133 0);
9134
9135 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9136 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9137 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9138 nl_send_auto(nl.socket, msg);
9139 nl_recvmsgs(nl.socket, nl.cb);
9140 nlmsg_free(msg);
9141 nlfree(&nl);
9142 return RETURN_OK;
9143#else
9144 //TODO Implement me
9145 return RETURN_OK;
9146#endif
9147}
9148
9149INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9150{
9151 // TODO Implement me!
9152 char buf[MAX_BUF_SIZE] = {0};
9153 char config_file[MAX_BUF_SIZE] = {0};
9154
9155 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9156 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9157 *activate = (strncmp("1",buf,1) == 0);
9158
9159 return RETURN_OK;
9160}
9161
9162INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9163{
9164 char config_file[MAX_BUF_SIZE] = {0};
9165 struct params list;
9166
9167 list.name = "rrm_neighbor_report";
9168 list.value = activate?"1":"0";
9169 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9170 wifi_hostapdWrite(config_file, &list, 1);
9171
9172 return RETURN_OK;
9173}
9174
9175INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9176{
9177 char buf[32] = {0};
9178 char config_file[MAX_BUF_SIZE] = {0};
9179
9180 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9181 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9182 *activate = (strncmp("1",buf,1) == 0);
9183
9184 return RETURN_OK;
9185}
9186#undef HAL_NETLINK_IMPL
9187#ifdef HAL_NETLINK_IMPL
9188static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9189 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9190 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9191 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9192 char dev[20];
9193 int freq =0 ;
9194 static int i=0;
9195
9196 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9197
9198 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9199 };
9200
9201 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9202
9203 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9204
9205 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9206 fprintf(stderr, "survey data missing!\n");
9207 return NL_SKIP;
9208 }
9209
9210 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9211 {
9212 fprintf(stderr, "failed to parse nested attributes!\n");
9213 return NL_SKIP;
9214 }
9215
9216
9217 if(out[0].array_size == 1 )
9218 {
9219 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9220 {
9221 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9222 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9223 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9224
9225 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9226 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9227 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9228 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9229 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9230 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9231 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9232 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9233 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9234 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9235 if (sinfo[NL80211_SURVEY_INFO_TIME])
9236 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9237 return NL_STOP;
9238 }
9239 }
9240 else
9241 {
9242 if ( i <= out[0].array_size )
9243 {
9244 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9245 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9246 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9247
9248 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9249 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9250 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9251 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9252 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9253 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9254 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9255 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9256 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9257 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9258 if (sinfo[NL80211_SURVEY_INFO_TIME])
9259 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9260 }
9261 }
9262
9263 i++;
9264 return NL_SKIP;
9265}
9266#endif
9267
9268static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9269{
9270 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9271 FILE *fp;
9272
9273 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9274 {
9275 printf("Creating Frequency-Channel Map\n");
9276 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9277 }
9278 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9279 if((fp = popen(command, "r")))
9280 {
9281 fgets(output, sizeof(output), fp);
9282 *freqMHz = atoi(output);
9283 fclose(fp);
9284 }
9285
9286 return 0;
9287}
9288
9289static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9290{
9291 int freqMHz = -1;
9292 char cmd[MAX_CMD_SIZE] = {'\0'};
9293
9294 ieee80211_channel_to_frequency(channel, &freqMHz);
9295 if (freqMHz == -1) {
9296 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9297 return -1;
9298 }
9299
9300 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9301 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9302 radioIndex, freqMHz);
9303 return -1;
9304 }
9305
9306 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9307 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9308 return -1;
9309 }
9310
9311 return 0;
9312}
9313
9314static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9315{
9316 const char *ptr = buf;
9317 char *key = NULL;
9318 char *val = NULL;
9319 char line[256] = { '\0' };
9320
9321 while (ptr = get_line_from_str_buf(ptr, line)) {
9322 if (strstr(line, "Frequency")) continue;
9323
9324 key = strtok(line, ":");
9325 val = strtok(NULL, " ");
9326 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9327
9328 if (!strcmp(key, "noise")) {
9329 sscanf(val, "%d", &stats->ch_noise);
9330 if (stats->ch_noise == 0) {
9331 // Workaround for missing noise information.
9332 // Assume -95 for 2.4G and -103 for 5G
9333 if (radioIndex == 0) stats->ch_noise = -95;
9334 if (radioIndex == 1) stats->ch_noise = -103;
9335 }
9336 }
9337 else if (!strcmp(key, "channel active time")) {
9338 sscanf(val, "%llu", &stats->ch_utilization_total);
9339 }
9340 else if (!strcmp(key, "channel busy time")) {
9341 sscanf(val, "%llu", &stats->ch_utilization_busy);
9342 }
9343 else if (!strcmp(key, "channel receive time")) {
9344 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9345 }
9346 else if (!strcmp(key, "channel transmit time")) {
9347 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9348 }
9349 };
9350
9351 return 0;
9352}
9353
9354INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9355{
9356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9357#ifdef HAL_NETLINK_IMPL
9358 Netlink nl;
9359 wifi_channelStats_t_loc local[array_size];
9360 char if_name[10];
9361
9362 local[0].array_size = array_size;
9363
9364 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9365
9366 nl.id = initSock80211(&nl);
9367
9368 if (nl.id < 0) {
9369 fprintf(stderr, "Error initializing netlink \n");
9370 return -1;
9371 }
9372
9373 struct nl_msg* msg = nlmsg_alloc();
9374
9375 if (!msg) {
9376 fprintf(stderr, "Failed to allocate netlink message.\n");
9377 nlfree(&nl);
9378 return -2;
9379 }
9380
9381 genlmsg_put(msg,
9382 NL_AUTO_PORT,
9383 NL_AUTO_SEQ,
9384 nl.id,
9385 0,
9386 NLM_F_DUMP,
9387 NL80211_CMD_GET_SURVEY,
9388 0);
9389
9390 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9391 nl_send_auto(nl.socket, msg);
9392 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9393 nl_recvmsgs(nl.socket, nl.cb);
9394 nlmsg_free(msg);
9395 nlfree(&nl);
9396 //Copying the Values
9397 for(int i=0;i<array_size;i++)
9398 {
9399 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9400 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9401 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9402 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9403 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9404 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9405 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9406 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9407 }
9408#else
9409 ULONG channel = 0;
9410 int i;
9411 int number_of_channels = array_size;
9412 char buf[512];
9413 INT ret;
9414 wifi_channelStats_t tmp_stats;
9415
9416 if (number_of_channels == 0) {
9417 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9418 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9419 return RETURN_ERR;
9420 }
9421 number_of_channels = 1;
9422 input_output_channelStats_array[0].ch_number = channel;
9423 }
9424
9425 for (i = 0; i < number_of_channels; i++) {
9426
9427 input_output_channelStats_array[i].ch_noise = 0;
9428 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9429 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9430 input_output_channelStats_array[i].ch_utilization_busy = 0;
9431 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9432 input_output_channelStats_array[i].ch_utilization_total = 0;
9433
9434 memset(buf, 0, sizeof(buf));
9435 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9436 return RETURN_ERR;
9437 }
9438 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9439 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9440 return RETURN_ERR;
9441 }
9442
9443 // XXX: fake missing 'self' counter which is not available in iw survey output
9444 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9445 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9446
9447 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9448 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9449 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9450 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9451 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9452
9453 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",
9454 __func__,
9455 input_output_channelStats_array[i].ch_number,
9456 input_output_channelStats_array[i].ch_noise,
9457 input_output_channelStats_array[i].ch_utilization_total,
9458 input_output_channelStats_array[i].ch_utilization_busy,
9459 input_output_channelStats_array[i].ch_utilization_busy_rx,
9460 input_output_channelStats_array[i].ch_utilization_busy_tx,
9461 input_output_channelStats_array[i].ch_utilization_busy_self,
9462 input_output_channelStats_array[i].ch_utilization_busy_ext);
9463 }
9464#endif
9465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9466 return RETURN_OK;
9467}
9468#define HAL_NETLINK_IMPL
9469
9470/* Hostapd events */
9471
9472#ifndef container_of
9473#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9474#define container_of(ptr, type, member) \
9475 ((type *)((char *)ptr - offset_of(type, member)))
9476#endif /* container_of */
9477
9478struct ctrl {
9479 char sockpath[128];
9480 char sockdir[128];
9481 char bss[IFNAMSIZ];
9482 char reply[4096];
9483 int ssid_index;
9484 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9485 void (*overrun)(struct ctrl *ctrl);
9486 struct wpa_ctrl *wpa;
9487 unsigned int ovfl;
9488 size_t reply_len;
9489 int initialized;
9490 ev_timer retry;
9491 ev_timer watchdog;
9492 ev_stat stat;
9493 ev_io io;
9494};
9495static wifi_newApAssociatedDevice_callback clients_connect_cb;
9496static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9497static struct ctrl wpa_ctrl[MAX_APS];
9498static int initialized;
9499
9500static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9501{
9502 char cbuf[256] = {};
9503 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9504 struct cmsghdr *cmsg;
9505 unsigned int ovfl = ctrl->ovfl;
9506 unsigned int drop;
9507
9508 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9509 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9510 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9511 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9512
9513 drop = ovfl - ctrl->ovfl;
9514 ctrl->ovfl = ovfl;
9515
9516 return drop;
9517}
9518
9519static void ctrl_close(struct ctrl *ctrl)
9520{
9521 if (ctrl->io.cb)
9522 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9523 if (ctrl->retry.cb)
9524 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9525 if (!ctrl->wpa)
9526 return;
9527
9528 wpa_ctrl_detach(ctrl->wpa);
9529 wpa_ctrl_close(ctrl->wpa);
9530 ctrl->wpa = NULL;
9531 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9532}
9533
9534static void ctrl_process(struct ctrl *ctrl)
9535{
9536 const char *str;
9537 int drops;
9538 int level;
9539 int err;
9540
9541 /* Example events:
9542 *
9543 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9544 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9545 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9546 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9547 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9548 */
9549 if (!(str = index(ctrl->reply, '>')))
9550 return;
9551 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9552 return;
9553
9554 str++;
9555
9556 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9557 if (!(str = index(ctrl->reply, ' ')))
9558 return;
9559 wifi_associated_dev_t sta;
9560 memset(&sta, 0, sizeof(sta));
9561
9562 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9563 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9564 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9565
9566 sta.cli_Active=true;
9567
9568 (clients_connect_cb)(ctrl->ssid_index, &sta);
9569 goto handled;
9570 }
9571
9572 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9573 if (!(str = index(ctrl->reply, ' ')))
9574 return;
9575
9576 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9577 goto handled;
9578 }
9579
9580 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9581 printf("CTRL_WPA: handle TERMINATING event\n");
9582 goto retry;
9583 }
9584
9585 if (strncmp("AP-DISABLED", str, 11) == 0) {
9586 printf("CTRL_WPA: handle AP-DISABLED\n");
9587 goto retry;
9588 }
9589
9590 printf("Event not supported!!\n");
9591
9592handled:
9593
9594 if ((drops = ctrl_get_drops(ctrl))) {
9595 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9596 if (ctrl->overrun)
9597 ctrl->overrun(ctrl);
9598 }
9599
9600 return;
9601
9602retry:
9603 printf("WPA_CTRL: closing\n");
9604 ctrl_close(ctrl);
9605 printf("WPA_CTRL: retrying from ctrl prcoess\n");
9606 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
9607}
9608
9609static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
9610{
9611 struct ctrl *ctrl = container_of(io, struct ctrl, io);
9612 int err;
9613
9614 memset(ctrl->reply, 0, sizeof(ctrl->reply));
9615 ctrl->reply_len = sizeof(ctrl->reply) - 1;
9616 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
9617 ctrl->reply[ctrl->reply_len] = 0;
9618 if (err < 0) {
9619 if (errno == EAGAIN || errno == EWOULDBLOCK)
9620 return;
9621 ctrl_close(ctrl);
9622 ev_timer_again(EV_A_ &ctrl->retry);
9623 return;
9624 }
9625
9626 ctrl_process(ctrl);
9627}
9628
9629static int ctrl_open(struct ctrl *ctrl)
9630{
9631 int fd;
9632
9633 if (ctrl->wpa)
9634 return 0;
9635
9636 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
9637 if (!ctrl->wpa)
9638 goto err;
9639
9640 if (wpa_ctrl_attach(ctrl->wpa) < 0)
9641 goto err_close;
9642
9643 fd = wpa_ctrl_get_fd(ctrl->wpa);
9644 if (fd < 0)
9645 goto err_detach;
9646
9647 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
9648 goto err_detach;
9649
9650 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
9651 ev_io_start(EV_DEFAULT_ &ctrl->io);
9652
9653 return 0;
9654
9655err_detach:
9656 wpa_ctrl_detach(ctrl->wpa);
9657err_close:
9658 wpa_ctrl_close(ctrl->wpa);
9659err:
9660 ctrl->wpa = NULL;
9661 return -1;
9662}
9663
9664static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
9665{
9666 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
9667
9668 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
9669 ctrl_open(ctrl);
9670}
9671
9672static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
9673{
9674 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
9675
9676 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
9677 if (ctrl_open(ctrl) == 0) {
9678 printf("WPA_CTRL: retry successful\n");
9679 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9680 }
9681}
9682
9683int ctrl_enable(struct ctrl *ctrl)
9684{
9685 if (ctrl->wpa)
9686 return 0;
9687
9688 if (!ctrl->stat.cb) {
9689 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
9690 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
9691 }
9692
9693 if (!ctrl->retry.cb) {
9694 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
9695 }
9696
9697 return ctrl_open(ctrl);
9698}
9699
9700static void
9701ctrl_msg_cb(char *buf, size_t len)
9702{
9703 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
9704
9705 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
9706 ctrl_process(ctrl);
9707}
9708
9709static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
9710{
9711 int err;
9712
9713 if (!ctrl->wpa)
9714 return -1;
9715 if (*reply_len < 2)
9716 return -1;
9717
9718 (*reply_len)--;
9719 ctrl->reply_len = sizeof(ctrl->reply);
9720 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
9721 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
9722 if (err < 0)
9723 return err;
9724
9725 if (ctrl->reply_len > *reply_len)
9726 ctrl->reply_len = *reply_len;
9727
9728 *reply_len = ctrl->reply_len;
9729 memcpy(reply, ctrl->reply, *reply_len);
9730 reply[*reply_len - 1] = 0;
9731 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
9732 return 0;
9733}
9734
9735static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
9736{
9737 const char *pong = "PONG";
9738 const char *ping = "PING";
9739 char reply[1024];
9740 size_t len = sizeof(reply);
9741 int err;
9742 ULONG s, snum;
9743 INT ret;
9744 BOOL status;
9745
9746 printf("WPA_CTRL: watchdog cb\n");
9747
9748 ret = wifi_getSSIDNumberOfEntries(&snum);
9749 if (ret != RETURN_OK) {
9750 printf("%s: failed to get SSID count", __func__);
9751 return;
9752 }
9753
9754 if (snum > MAX_APS) {
9755 printf("more ssid than supported! %lu\n", snum);
9756 return;
9757 }
9758
9759 for (s = 0; s < snum; s++) {
9760 if (wifi_getApEnable(s, &status) != RETURN_OK) {
9761 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
9762 continue;
9763 }
9764 if (status == false) continue;
9765
9766 memset(reply, 0, sizeof(reply));
9767 len = sizeof(reply);
9768 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
9769 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
9770 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
9771 continue;
9772
9773 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
9774 ctrl_close(&wpa_ctrl[s]);
9775 printf("WPA_CTRL: ev_timer_again %d\n", s);
9776 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
9777 }
9778}
9779
9780static int init_wpa()
9781{
9782 int ret = 0, i = 0;
9783 ULONG s, snum;
9784
9785 ret = wifi_getSSIDNumberOfEntries(&snum);
9786 if (ret != RETURN_OK) {
9787 printf("%s: failed to get SSID count", __func__);
9788 return RETURN_ERR;
9789 }
9790
9791 if (snum > MAX_APS) {
9792 printf("more ssid than supported! %lu\n", snum);
9793 return RETURN_ERR;
9794 }
9795
9796 for (s = 0; s < snum; s++) {
9797 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
9798 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
9799 wpa_ctrl[s].ssid_index = s;
9800 ctrl_enable(&wpa_ctrl[s]);
9801 }
9802
9803 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
9804 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
9805
9806 initialized = 1;
9807 printf("WPA_CTRL: initialized\n");
9808
9809 return RETURN_OK;
9810}
9811
9812void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
9813{
9814 clients_connect_cb = callback_proc;
9815 if (!initialized)
9816 init_wpa();
9817}
9818
9819void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
9820{
9821 clients_disconnect_cb = callback_proc;
9822 if (!initialized)
9823 init_wpa();
9824}
9825
9826INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
9827{
9828 // TODO Implement me!
9829 return RETURN_ERR;
9830}
9831
9832INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
9833{
9834 // TODO Implement me!
9835 return RETURN_ERR;
9836}
9837
9838INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
9839{
9840 int i;
9841 char cmd[256];
9842 char channel_numbers_buf[256];
9843 char dfs_state_buf[256];
9844 char line[256];
9845 const char *ptr;
9846
9847 memset(cmd, 0, sizeof(cmd));
9848 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
9849 memset(line, 0, sizeof(line));
9850 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9851 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
9852
9853 if (radioIndex == 0) { // 2.4G - all allowed
9854 if (outputMapSize < 11) {
9855 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
9856 return RETURN_ERR;
9857 }
9858
9859 for (i = 0; i < 11; i++) {
9860 outputMap[i].ch_number = i + 1;
9861 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9862 }
9863
9864 return RETURN_OK;
9865 }
9866
9867 if (radioIndex == 1) { // 5G
9868// Example output of iw list:
9869//
9870// Frequencies:
9871// * 5180 MHz [36] (17.0 dBm)
9872// * 5200 MHz [40] (17.0 dBm)
9873// * 5220 MHz [44] (17.0 dBm)
9874// * 5240 MHz [48] (17.0 dBm)
9875// * 5260 MHz [52] (23.0 dBm) (radar detection)
9876// DFS state: usable (for 78930 sec)
9877// DFS CAC time: 60000 ms
9878// * 5280 MHz [56] (23.0 dBm) (radar detection)
9879// DFS state: usable (for 78930 sec)
9880// DFS CAC time: 60000 ms
9881// * 5300 MHz [60] (23.0 dBm) (radar detection)
9882// DFS state: usable (for 78930 sec)
9883// DFS CAC time: 60000 ms
9884// * 5320 MHz [64] (23.0 dBm) (radar detection)
9885// DFS state: usable (for 78930 sec)
9886// DFS CAC time: 60000 ms
9887// * 5500 MHz [100] (disabled)
9888// * 5520 MHz [104] (disabled)
9889// * 5540 MHz [108] (disabled)
9890// * 5560 MHz [112] (disabled)
9891//
9892// Below command should fetch channel numbers of each enabled channel in 5GHz band:
9893 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
9894 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
9895 return RETURN_ERR;
9896 }
9897
9898 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
9899 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9900 return RETURN_ERR;
9901 }
9902
9903 ptr = channel_numbers_buf;
9904 i = 0;
9905 while (ptr = get_line_from_str_buf(ptr, line)) {
9906 if (i >= outputMapSize) {
9907 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
9908 return RETURN_ERR;
9909 }
9910 sscanf(line, "%d", &outputMap[i].ch_number);
9911
9912 memset(cmd, 0, sizeof(cmd));
9913 // Below command should fetch string for DFS state (usable, available or unavailable)
9914 // Example line: "DFS state: usable (for 78930 sec)"
9915 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) {
9916 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
9917 return RETURN_ERR;
9918 }
9919
9920 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9921 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
9922 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9923 return RETURN_ERR;
9924 }
9925
9926 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
9927
9928 if (!strcmp(dfs_state_buf, "usable")) {
9929 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
9930 } else if (!strcmp(dfs_state_buf, "available")) {
9931 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
9932 } else if (!strcmp(dfs_state_buf, "unavailable")) {
9933 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
9934 } else {
9935 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9936 }
9937 i++;
9938 }
9939
9940 return RETURN_OK;
9941 }
9942
9943 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
9944 return RETURN_ERR;
9945}
9946
9947INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
9948{
9949 // TODO Implement me!
9950 return RETURN_ERR;
9951}
9952
9953INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
9954{
9955 return RETURN_OK;
9956}
9957
9958INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
9959{
9960 // TODO Implement me!
9961 return RETURN_ERR;
9962}
9963
9964INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
9965{
9966 // TODO API refrence Implementaion is present on RPI hal
9967 return RETURN_ERR;
9968}
9969
9970INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
9971{
developera5005b62022-09-13 15:43:35 +08009972 char cmd[128]={'\0'};
9973 char buf[128]={'\0'};
9974 char *support;
9975 int maximum_tx = 0, current_tx = 0;
9976
9977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9978 if(txpwr_pcntg == NULL)
9979 return RETURN_ERR;
9980
9981 // Get the maximum tx power of the device
9982 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
9983 _syscmd(cmd, buf, sizeof(buf));
9984 maximum_tx = strtol(buf, NULL, 10);
9985
9986 // Get the current tx power
9987 memset(cmd, 0, sizeof(cmd));
9988 memset(buf, 0, sizeof(buf));
9989 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
9990 _syscmd(cmd, buf, sizeof(buf));
9991 current_tx = strtol(buf, NULL, 10);
9992
9993 // Get the power supported list and find the current power percentage in supported list
9994 memset(buf, 0, sizeof(buf));
9995 wifi_getRadioTransmitPowerSupported(apIndex, buf);
9996 support = strtok(buf, ",");
9997 while(true)
9998 {
9999 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10000 *txpwr_pcntg = 0;
10001 wifi_dbg_printf("current power is not in supported list\n");
10002 return RETURN_ERR;
10003 }
10004 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10005 if (tmp == current_tx) {
10006 *txpwr_pcntg = strtol(support, NULL, 10);
10007 break;
10008 }
10009 support = strtok(NULL, ",");
10010 }
10011 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010012 return RETURN_OK;
10013}
10014
10015INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10016{
10017 //Zero-wait DFS not supported
10018 return RETURN_ERR;
10019}
10020
10021INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10022{
10023 //Zero-wait DFS not supported
10024 return RETURN_ERR;
10025}
10026
10027INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10028{
10029 *supported = false;
10030 return RETURN_OK;
10031}
10032
developer454b9462022-09-13 15:29:16 +080010033INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10034{
10035 char cmd[128] = {0};
10036 char buf[64] = {0};
10037 char band_str[8] = {0};
10038 char GI[8] = {0};
10039 int tmp = 0;
10040 BOOL ax_mode = FALSE;
10041 BOOL short_GI = FALSE;
10042 FILE *f = NULL;
10043 wifi_band band;
10044
10045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10046
10047 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
10048 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10049 return RETURN_ERR;
10050 }
10051 if (strstr(buf, "ax") != NULL)
10052 ax_mode = TRUE;
10053
10054 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
10055 short_GI = TRUE;
10056 strcpy(GI, "0.4");
10057 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10058 strcpy(GI, "1.6");
10059 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10060 strcpy(GI, "3.2");
10061 else // default
10062 strcpy(GI, "0.8");
10063
10064 band = wifi_index_to_band(radio_index);
10065 if (band == band_2_4)
10066 strcpy(band_str, "2.4");
10067 else if (band == band_5)
10068 strcpy(band_str, "5");
10069 else if (band == band_6)
10070 strcpy(band_str, "6");
10071 else {
10072 wifi_dbg_printf("%s: invalid band\n");
10073 return RETURN_ERR;
10074 }
10075
10076 if (ax_mode == TRUE)
10077 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10078 else
10079 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10080 _syscmd(cmd, buf, sizeof(buf));
10081
10082 // Record GI for get GI function
10083 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10084 f = fopen(buf, "w");
10085 if (f != NULL) {
10086 fprintf(f, "%s", GI);
10087 }
10088 fclose(f);
10089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10090 return RETURN_OK;
10091}
10092
10093INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10094{
10095 char buf[32] = {0};
10096 char cmd[64] = {0};
10097
10098 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10099
10100 if (guard_interval == NULL)
10101 return RETURN_ERR;
10102
10103 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10104 _syscmd(cmd, buf, sizeof(buf));
10105
10106 if (strncmp(buf, "0.4", 3) == 0)
10107 *guard_interval = wifi_guard_interval_400;
10108 else if (strncmp(buf, "0.8", 3) == 0)
10109 *guard_interval = wifi_guard_interval_800;
10110 else if (strncmp(buf, "1.6", 3) == 0)
10111 *guard_interval = wifi_guard_interval_1600;
10112 else if (strncmp(buf, "3.2", 3) == 0)
10113 *guard_interval = wifi_guard_interval_3200;
10114 else
10115 *guard_interval = wifi_guard_interval_auto;
10116
10117 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10118 return RETURN_OK;
10119}
10120
developer06a01d92022-09-07 16:32:39 +080010121/* multi-psk support */
10122INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10123{
10124 char cmd[256];
10125
10126 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10127 AP_PREFIX,
10128 apIndex,
10129 mac[0],
10130 mac[1],
10131 mac[2],
10132 mac[3],
10133 mac[4],
10134 mac[5]
10135 );
10136 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10137 _syscmd(cmd, key->wifi_keyId, 64);
10138
10139
10140 return RETURN_OK;
10141}
10142
10143INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10144{
10145 FILE *fd = NULL;
10146 char fname[100];
10147 char cmd[128] = {0};
10148 char out[64] = {0};
10149 wifi_key_multi_psk_t * key = NULL;
10150 if(keysNumber < 0)
10151 return RETURN_ERR;
10152
10153 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10154 fd = fopen(fname, "w");
10155 if (!fd) {
10156 return RETURN_ERR;
10157 }
10158 key= (wifi_key_multi_psk_t *) keys;
10159 for(int i=0; i<keysNumber; ++i, key++) {
10160 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10161 }
10162 fclose(fd);
10163
10164 //reload file
10165 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10166 _syscmd(cmd, out, 64);
10167 return RETURN_OK;
10168}
10169
10170INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10171{
10172 FILE *fd = NULL;
10173 char fname[100];
10174 char * line = NULL;
10175 char * pos = NULL;
10176 size_t len = 0;
10177 ssize_t read = 0;
10178 INT ret = RETURN_OK;
10179 wifi_key_multi_psk_t *keys_it = NULL;
10180
10181 if (keysNumber < 1) {
10182 return RETURN_ERR;
10183 }
10184
10185 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10186 fd = fopen(fname, "r");
10187 if (!fd) {
10188 return RETURN_ERR;
10189 }
10190
10191 if (keys == NULL) {
10192 ret = RETURN_ERR;
10193 goto close;
10194 }
10195
10196 keys_it = keys;
10197 while ((read = getline(&line, &len, fd)) != -1) {
10198 //Strip trailing new line if present
10199 if (read > 0 && line[read-1] == '\n') {
10200 line[read-1] = '\0';
10201 }
10202
10203 if(strcmp(line,"keyid=")) {
10204 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10205 if (!(pos = index(line, ' '))) {
10206 ret = RETURN_ERR;
10207 goto close;
10208 }
10209 pos++;
10210 //Here should be 00:00:00:00:00:00
10211 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10212 printf("Not supported MAC: %s\n", pos);
10213 }
10214 if (!(pos = index(pos, ' '))) {
10215 ret = RETURN_ERR;
10216 goto close;
10217 }
10218 pos++;
10219
10220 //The rest is PSK
10221 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10222 keys_it++;
10223
10224 if(--keysNumber <= 0)
10225 break;
10226 }
10227 }
10228
10229close:
10230 free(line);
10231 fclose(fd);
10232 return ret;
10233}
10234/* end of multi-psk support */
10235
10236INT wifi_setNeighborReports(UINT apIndex,
10237 UINT numNeighborReports,
10238 wifi_NeighborReport_t *neighborReports)
10239{
10240 char cmd[256] = { 0 };
10241 char hex_bssid[13] = { 0 };
10242 char bssid[18] = { 0 };
10243 char nr[256] = { 0 };
10244 char ssid[256];
10245 char hex_ssid[256];
10246 INT ret;
10247
10248 /*rmeove all neighbors*/
10249 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10250 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);
10251 system(cmd);
10252
10253 for(unsigned int i = 0; i < numNeighborReports; i++)
10254 {
10255 memset(ssid, 0, sizeof(ssid));
10256 ret = wifi_getSSIDName(apIndex, ssid);
10257 if (ret != RETURN_OK)
10258 return RETURN_ERR;
10259
10260 memset(hex_ssid, 0, sizeof(hex_ssid));
10261 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10262 sprintf(hex_ssid + k,"%02x", ssid[j]);
10263
10264 snprintf(hex_bssid, sizeof(hex_bssid),
10265 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10266 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10267 snprintf(bssid, sizeof(bssid),
10268 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10269 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10270
10271 snprintf(nr, sizeof(nr),
10272 "%s" // bssid
10273 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10274 "%02hhx" // operclass
10275 "%02hhx" // channel
10276 "%02hhx", // phy_mode
10277 hex_bssid,
10278 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10279 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10280 neighborReports[i].opClass,
10281 neighborReports[i].channel,
10282 neighborReports[i].phyTable);
10283
10284 snprintf(cmd, sizeof(cmd),
10285 "hostapd_cli set_neighbor "
10286 "%s " // bssid
10287 "ssid=%s " // ssid
10288 "nr=%s " // nr
10289 "-i %s%d",
10290 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10291
10292 if (WEXITSTATUS(system(cmd)) != 0)
10293 {
10294 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10295 }
10296 }
10297
10298 return RETURN_OK;
10299}
10300
10301INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10302{
10303 return RETURN_OK;
10304}
10305
10306#ifdef _WIFI_HAL_TEST_
10307int main(int argc,char **argv)
10308{
10309 int index;
10310 INT ret=0;
10311 char buf[1024]="";
10312
10313 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10314 if(argc<3)
10315 {
10316 if(argc==2)
10317 {
10318 if(!strcmp(argv[1], "init"))
10319 return wifi_init();
10320 if(!strcmp(argv[1], "reset"))
10321 return wifi_reset();
10322 if(!strcmp(argv[1], "wifi_getHalVersion"))
10323 {
10324 char buffer[64];
10325 if(wifi_getHalVersion(buffer)==RETURN_OK)
10326 printf("Version: %s\n", buffer);
10327 else
10328 printf("Error in wifi_getHalVersion\n");
10329 return RETURN_OK;
10330 }
10331 }
10332 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10333 exit(-1);
10334 }
10335
10336 index = atoi(argv[2]);
10337 if(strstr(argv[1], "wifi_getApName")!=NULL)
10338 {
10339 wifi_getApName(index,buf);
10340 printf("Ap name is %s \n",buf);
10341 return 0;
10342 }
10343 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10344 {
10345 BOOL b = FALSE;
10346 BOOL *output_bool = &b;
10347 wifi_getRadioAutoChannelEnable(index,output_bool);
10348 printf("Channel enabled = %d \n",b);
10349 return 0;
10350 }
10351 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10352 {
10353 wifi_getApWpaEncryptionMode(index,buf);
10354 printf("encryption enabled = %s\n",buf);
10355 return 0;
10356 }
10357 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10358 {
10359 BOOL b = FALSE;
10360 BOOL *output_bool = &b;
10361 wifi_getApSsidAdvertisementEnable(index,output_bool);
10362 printf("advertisment enabled = %d\n",b);
10363 return 0;
10364 }
10365 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10366 {
10367 if(argc <= 3 )
10368 {
10369 printf("Insufficient arguments \n");
10370 exit(-1);
10371 }
10372
10373 char sta[20] = {'\0'};
10374 ULLONG handle= 0;
10375 strcpy(sta,argv[3]);
10376 mac_address_t st;
10377 mac_addr_aton(st,sta);
10378
10379 wifi_associated_dev_tid_stats_t tid_stats;
10380 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10381 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10382 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);
10383 }
10384
10385 if(strstr(argv[1], "getApEnable")!=NULL) {
10386 BOOL enable;
10387 ret=wifi_getApEnable(index, &enable);
10388 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10389 }
10390 else if(strstr(argv[1], "setApEnable")!=NULL) {
10391 BOOL enable = atoi(argv[3]);
10392 ret=wifi_setApEnable(index, enable);
10393 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10394 }
10395 else if(strstr(argv[1], "getApStatus")!=NULL) {
10396 char status[64];
10397 ret=wifi_getApStatus(index, status);
10398 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
10399 }
10400 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
10401 {
10402 wifi_getSSIDNameStatus(index,buf);
10403 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
10404 return 0;
10405 }
10406 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
10407 wifi_ssidTrafficStats2_t stats={0};
10408 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
10409 printf("%s %d: returns %d\n", argv[1], index, ret);
10410 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
10411 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
10412 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
10413 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
10414 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
10415 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
10416 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
10417 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
10418 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
10419 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
10420 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
10421 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
10422 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
10423 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
10424 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
10425 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
10426 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
10427 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
10428 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
10429 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
10430 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
10431 }
10432 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
10433 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
10434 UINT array_size=0;
10435 UINT i=0;
10436 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
10437 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10438 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
10439 printf(" neighbor %d:\n", i);
10440 printf(" ap_SSID =%s\n", pt->ap_SSID);
10441 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
10442 printf(" ap_Mode =%s\n", pt->ap_Mode);
10443 printf(" ap_Channel =%d\n", pt->ap_Channel);
10444 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
10445 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10446 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
10447 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
10448 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
10449 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
10450 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10451 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
10452 printf(" ap_Noise =%d\n", pt->ap_Noise);
10453 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
10454 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
10455 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
10456 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
10457 }
10458 if(neighbor_ap_array)
10459 free(neighbor_ap_array); //make sure to free the list
10460 }
10461 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
10462 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
10463 UINT array_size=0;
10464 UINT i=0;
10465 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
10466 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10467 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
10468 printf(" associated_dev %d:\n", i);
10469 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
10470 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
10471 printf(" cli_SNR =%d\n", pt->cli_SNR);
10472 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
10473 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
10474 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
10475 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
10476 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
10477 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
10478 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
10479 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
10480 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
10481 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
10482 }
10483 if(associated_dev_array)
10484 free(associated_dev_array); //make sure to free the list
10485 }
10486
10487 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
10488 {
10489#define MAX_ARRAY_SIZE 64
10490 int i, array_size;
10491 char *p, *ch_str;
10492 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
10493
10494 if(argc != 5)
10495 {
10496 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
10497 exit(-1);
10498 }
10499 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
10500
10501 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
10502 {
10503 strtok_r(ch_str, ",", &p);
10504 input_output_channelStats_array[i].ch_number = atoi(ch_str);
10505 }
10506 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
10507 if(!array_size)
10508 array_size=1;//Need to print current channel statistics
10509 for(i=0; i<array_size; i++)
10510 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
10511 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
10512 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
10513 input_output_channelStats_array[i].ch_number,\
10514 input_output_channelStats_array[i].ch_noise,\
10515 input_output_channelStats_array[i].ch_utilization_busy_rx,\
10516 input_output_channelStats_array[i].ch_utilization_busy_tx,\
10517 input_output_channelStats_array[i].ch_utilization_busy,\
10518 input_output_channelStats_array[i].ch_utilization_busy_ext,\
10519 input_output_channelStats_array[i].ch_utilization_total);
10520 }
10521
10522 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
10523 {
10524 if(argc <= 3 )
10525 {
10526 printf("Insufficient arguments \n");
10527 exit(-1);
10528 }
10529 char mac_addr[20] = {'\0'};
10530 wifi_device_t output_struct;
10531 int dev_index = atoi(argv[3]);
10532
10533 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
10534 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
10535 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);
10536 }
10537
10538 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
10539 {
10540 if (argc <= 3)
10541 {
10542 printf("Insufficient arguments\n");
10543 exit(-1);
10544 }
10545 char args[256];
10546 wifi_NeighborReport_t *neighborReports;
10547
10548 neighborReports = calloc(argc - 2, sizeof(neighborReports));
10549 if (!neighborReports)
10550 {
10551 printf("Failed to allocate memory");
10552 exit(-1);
10553 }
10554
10555 for (int i = 3; i < argc; ++i)
10556 {
10557 char *val;
10558 int j = 0;
10559 memset(args, 0, sizeof(args));
10560 strncpy(args, argv[i], sizeof(args));
10561 val = strtok(args, ";");
10562 while (val != NULL)
10563 {
10564 if (j == 0)
10565 {
10566 mac_addr_aton(neighborReports[i - 3].bssid, val);
10567 } else if (j == 1)
10568 {
10569 neighborReports[i - 3].info = strtol(val, NULL, 16);
10570 } else if (j == 2)
10571 {
10572 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
10573 } else if (j == 3)
10574 {
10575 neighborReports[i - 3].channel = strtol(val, NULL, 16);
10576 } else if (j == 4)
10577 {
10578 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
10579 } else {
10580 printf("Insufficient arguments]n\n");
10581 exit(-1);
10582 }
10583 val = strtok(NULL, ";");
10584 j++;
10585 }
10586 }
10587
10588 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
10589 if (ret != RETURN_OK)
10590 {
10591 printf("wifi_setNeighborReports ret = %d", ret);
10592 exit(-1);
10593 }
10594 }
10595 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
10596 {
10597 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
10598 printf("%s.\n", buf);
10599 else
10600 printf("Error returned\n");
10601 }
10602 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
10603 {
10604 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
10605 printf("%s.\n", buf);
10606 else
10607 printf("Error returned\n");
10608 }
10609 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
10610 {
10611 if (argc <= 2)
10612 {
10613 printf("Insufficient arguments\n");
10614 exit(-1);
10615 }
10616 char buf[64]= {'\0'};
10617 wifi_getRadioOperatingChannelBandwidth(index,buf);
10618 printf("Current bandwidth is %s \n",buf);
10619 return 0;
10620 }
10621 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
10622 {
10623 if (argc <= 5)
10624 {
10625 printf("Insufficient arguments\n");
10626 exit(-1);
10627 }
10628 UINT channel = atoi(argv[3]);
10629 UINT width = atoi(argv[4]);
10630 UINT beacon = atoi(argv[5]);
10631 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
10632 printf("Result = %d", ret);
10633 }
10634
10635 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10636 return 0;
10637}
10638
10639#endif
10640
10641#ifdef WIFI_HAL_VERSION_3
10642
10643INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10644{
10645 // The only par-radio parameter is a channel number, however there's a 'dynamic' API
10646 // to change it ("wifi_pushRadioChannel2()") that is used instead.
10647 return RETURN_OK;
10648}
10649
10650INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10651{
10652 INT ret;
10653 char band[128];
10654 ULONG channel;
10655 BOOL enabled;
10656 char buf[256];
10657
10658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10659 printf("Entering %s index = %d\n", __func__, (int)index);
10660
10661 ret = wifi_getRadioEnable(index, &enabled);
10662 if (ret != RETURN_OK)
10663 {
10664 printf("%s: cannot get enabled state for radio index %d\n", __func__,
10665 index);
10666 return RETURN_ERR;
10667 }
10668 operationParam->enable = enabled;
10669
10670 memset(band, 0, sizeof(band));
10671 ret = wifi_getRadioOperatingFrequencyBand(index, band);
10672 if (ret != RETURN_OK)
10673 {
10674 printf("%s: cannot get radio band for radio index %d\n", __func__, index);
10675 return RETURN_ERR;
10676 }
10677
10678 if (!strcmp(band, "2.4GHz"))
10679 {
10680 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
10681 operationParam->variant = WIFI_80211_VARIANT_N;
10682 }
10683 else if (!strcmp(band, "5GHz"))
10684 {
10685 operationParam->band = WIFI_FREQUENCY_5_BAND;
10686 operationParam->variant = WIFI_80211_VARIANT_AC;
10687 }
10688 else
10689 {
10690 printf("%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
10691 band);
10692 }
10693
10694 memset(buf, 0, sizeof(buf));
10695 ret = wifi_getRadioOperatingChannelBandwidth(index, buf); // XXX: handle errors
10696 // XXX: only handle 20/40/80 modes for now
10697 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
10698 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
10699 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
10700 else
10701 {
10702 printf("%s: Unknown HT mode: '%s'\n", __func__, buf);
10703 operationParam->channelWidth = 0;
10704 }
10705
10706 ret = wifi_getRadioChannel(index, &channel);
10707 if (ret != RETURN_OK)
10708 {
10709 printf("%s: Failed to get channel number for radio index %d\n", __func__, index);
10710 channel = 0;
10711 }
10712 operationParam->channel = channel;
10713 operationParam->csa_beacon_count = 15; // XXX: hardcoded for now
10714
10715 operationParam->countryCode = wifi_countrycode_US; // XXX: hardcoded for now
10716
10717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10718 return RETURN_OK;
10719}
10720
10721static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
10722{
10723 if (radioIndex != 0 && radioIndex != 1)
10724 {
10725 printf("%s: Wrong radio index (%d)\n", __func__, index);
10726 return -1;
10727 }
10728
10729 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
10730 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
10731
10732 return (arrayIndex * 2) + radioIndex;
10733}
10734
10735INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
10736{
10737 INT ret;
10738 int i;
10739 BOOL enabled = false;
10740 char buf[256];
10741 wifi_secur_list *secur_item;
10742 int vap_index;
10743 INT mode;
10744 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
10745
10746 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10747 printf("Entering %s index = %d\n", __func__, (int)index);
10748
10749 map->vap_array[index].radio_index = index;
10750 for (i = 0; i < 5; i++)
10751 {
10752 vap_index = array_index_to_vap_index(index, i);
10753 if (vap_index < 0)
10754 {
10755 return RETURN_ERR;
10756 }
10757
10758 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
10759
10760 map->vap_array[i].vap_index = vap_index;
10761
10762 memset(buf, 0, sizeof(buf));
10763 wifi_getApName(vap_index, buf); // XXX: error handling
10764 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
10765
10766 ret = wifi_getSSIDEnable(vap_index, &enabled);
10767 if (ret != RETURN_OK)
10768 {
10769 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
10770 return RETURN_ERR;
10771 }
10772 map->vap_array[i].u.bss_info.enabled = enabled;
10773
10774 memset(buf, 0, sizeof(buf));
10775 wifi_getBaseBSSID(vap_index, buf);
10776 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10777 &map->vap_array[i].u.bss_info.bssid[0],
10778 &map->vap_array[i].u.bss_info.bssid[1],
10779 &map->vap_array[i].u.bss_info.bssid[2],
10780 &map->vap_array[i].u.bss_info.bssid[3],
10781 &map->vap_array[i].u.bss_info.bssid[4],
10782 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
10783
10784 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
10785 map->vap_array[i].u.bss_info.showSsid = enabled;
10786
10787 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
10788 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
10789 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
10790
10791 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
10792 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
10793
10794 memset(buf, 0, sizeof(buf));
10795 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
10796 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
10797
10798 wifi_getApSecurityModeEnabled(vap_index, buf);
10799
10800 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
10801 {
10802 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
10803 return RETURN_ERR;
10804 }
10805 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
10806
10807 memset(buf, 0, sizeof(buf));
10808 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
10809 strncpy(map->vap_array[i].u.bss_info.security.u.key.key, buf, sizeof(map->vap_array[i].u.bss_info.security.u.key.key) - 1);
10810
10811 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
10812 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
10813
10814 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
10815 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
10816
10817 wifi_getApIsolationEnable(vap_index, &enabled);
10818 map->vap_array[i].u.bss_info.isolation = enabled;
10819 }
10820 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10821 return RETURN_OK;
10822}
10823
10824INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
10825{
10826 unsigned int i;
10827 wifi_vap_info_t *vap_info = NULL;
10828 int acl_mode;
10829 char *sec_str = NULL;
10830
10831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10832 printf("Entering %s index = %d\n", __func__, (int)index);
10833 for (i = 0; i < map->num_vaps; i++)
10834 {
10835 vap_info = &map->vap_array[i];
10836 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
10837
10838 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
10839 else
10840 {
10841 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
10842 else acl_mode = 1;
10843 }
10844 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
10845 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
10846 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
10847
10848 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
10849 if (sec_str)
10850 {
10851 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
10852 }
10853 else
10854 {
10855 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
10856 }
10857
10858 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
10859 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
10860
10861 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
10862 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
10863
10864 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
10865
10866 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
10867 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
10868 }
10869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10870 return RETURN_OK;
10871}
10872
10873int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
10874{
10875 char *token, *next;
10876 const char s[2] = ",";
10877 int count =0;
10878
10879 /* get the first token */
10880 token = strtok_r(pchannels, s, &next);
10881
10882 /* walk through other tokens */
10883 while( token != NULL && count < MAX_CHANNELS) {
10884 chlistptr->channels_list[count++] = atoi(token);
10885 token = strtok_r(NULL, s, &next);
10886 }
10887
10888 return count;
10889}
10890
10891static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
10892{
10893 INT status;
10894 wifi_channels_list_t *chlistp;
10895 CHAR output_string[64];
10896 CHAR pchannels[128];
10897
10898 if(rcap == NULL)
10899 {
10900 return RETURN_ERR;
10901 }
10902
10903 rcap->numSupportedFreqBand = 1;
10904 if (1 == radioIndex)
10905 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
10906 else
10907 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
10908
10909
10910 chlistp = &(rcap->channel_list[0]);
10911 memset(pchannels, 0, sizeof(pchannels));
10912
10913 /* possible number of radio channels */
10914 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
10915 {
10916 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
10917 }
10918 /* Number of channels and list*/
10919 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
10920
10921 /* autoChannelSupported */
10922 /* always ON with wifi_getRadioAutoChannelSupported */
10923 rcap->autoChannelSupported = TRUE;
10924
10925 /* DCSSupported */
10926 /* always ON with wifi_getRadioDCSSupported */
10927 rcap->DCSSupported = TRUE;
10928
10929 /* zeroDFSSupported - TBD */
10930 rcap->zeroDFSSupported = FALSE;
10931
10932 /* Supported Country List*/
10933 memset(output_string, 0, sizeof(output_string));
10934 status = wifi_getRadioCountryCode(radioIndex, output_string);
10935 if( status != 0 ) {
10936 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
10937 return RETURN_ERR;
10938 } else {
10939 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
10940 }
10941 if(!strcmp(output_string,"US")){
10942 rcap->countrySupported[0] = wifi_countrycode_US;
10943 rcap->countrySupported[1] = wifi_countrycode_CA;
10944 } else if (!strcmp(output_string,"CA")) {
10945 rcap->countrySupported[0] = wifi_countrycode_CA;
10946 rcap->countrySupported[1] = wifi_countrycode_US;
10947 } else {
10948 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
10949 }
10950
10951 rcap->numcountrySupported = 2;
10952
10953 /* csi */
10954 rcap->csi.maxDevices = 8;
10955 rcap->csi.soudingFrameSupported = TRUE;
10956
10957 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
10958
10959 /* channelWidth - all supported bandwidths */
10960 int i=0;
10961 rcap->channelWidth[i] = 0;
10962 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
10963 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
10964 WIFI_CHANNELBANDWIDTH_40MHZ);
10965
10966 }
10967 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
10968 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
10969 WIFI_CHANNELBANDWIDTH_40MHZ |
10970 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
10971 }
10972
10973
10974 /* mode - all supported variants */
10975 // rcap->mode[i] = WIFI_80211_VARIANT_H;
10976 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
10977 rcap->mode[i] = (WIFI_80211_VARIANT_N);
10978 }
10979 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
10980 rcap->mode[i] = ( WIFI_80211_VARIANT_AC );
10981 }
10982 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
10983 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
10984
10985 /* supportedBitRate - all supported bitrates */
10986 rcap->supportedBitRate[i] = 0;
10987 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
10988 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
10989 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
10990 }
10991 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
10992 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
10993 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
10994 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
10995 }
10996
10997
10998 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
10999 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11000 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11001 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11002 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11003 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11004 rcap->cipherSupported = 0;
11005 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11006 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11007
11008 return RETURN_OK;
11009}
11010
11011INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11012{
11013 INT status, radioIndex;
11014 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11015 int iter = 0;
11016 unsigned int j;
11017 wifi_interface_name_idex_map_t *iface_info;
11018
11019 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11020
11021 memset(cap, 0, sizeof(wifi_hal_capability_t));
11022
11023 /* version */
11024 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11025 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11026
11027 /* number of radios platform property */
11028 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11029 _syscmd(cmd, output, sizeof(output));
11030 cap->wifi_prop.numRadios = atoi(output);
11031
11032 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11033 {
11034 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11035 if (status != 0) {
11036 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11037 return RETURN_ERR;
11038 }
11039
11040 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11041 {
11042 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11043 {
11044 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11045 return RETURN_ERR;
11046 }
11047 iface_info = &cap->wifi_prop.interface_map[iter];
11048 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11049 iface_info->rdk_radio_index = radioIndex;
11050 memset(output, 0, sizeof(output));
11051 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11052 {
11053 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11054 }
11055 // TODO: bridge name
11056 // TODO: vlan id
11057 // TODO: primary
11058 iface_info->index = array_index_to_vap_index(radioIndex, j);
11059 memset(output, 0, sizeof(output));
11060 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11061 {
11062 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11063 }
11064 iter++;
11065 }
11066 }
11067
11068 cap->BandSteeringSupported = FALSE;
11069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11070 return RETURN_OK;
11071}
11072
11073INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11074{
11075 //TODO
11076 return RETURN_OK;
11077}
11078
11079INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
11080{
11081 //TODO
11082 return RETURN_OK;
11083}
11084
11085#endif /* WIFI_HAL_VERSION_3 */
11086
11087#ifdef WIFI_HAL_VERSION_3_PHASE2
11088INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
11089{
11090 return RETURN_OK;
11091}
11092#else
11093INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
11094{
11095 char cmd[128];
11096 BOOL status = false;
11097
11098 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
11099 return RETURN_ERR;
11100
11101 output_buf[0] = '\0';
11102
11103 wifi_getApEnable(ap_index,&status);
11104 if (!status)
11105 return RETURN_OK;
11106
11107 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
11108 _syscmd(cmd, output_buf, output_buf_size);
11109
11110 return RETURN_OK;
11111}
11112#endif
developer2f513ab2022-09-13 14:26:06 +080011113
11114INT wifi_getProxyArp(INT apIndex, BOOL *enable)
11115{
11116 char output[16]={'\0'};
11117 char config_file[MAX_BUF_SIZE] = {0};
11118
11119 if (!enable)
11120 return RETURN_ERR;
11121
11122 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
11123 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
11124
11125 if (strlen(output) == 0)
11126 *enable = FALSE;
11127 else if (strncmp(output, "1", 1) == 0)
11128 *enable = TRUE;
11129 else
11130 *enable = FALSE;
11131
11132 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
11133 return RETURN_OK;
11134}
developer2d9c30f2022-09-13 15:06:14 +080011135
11136INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
11137{
11138 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
11139 return RETURN_ERR;
11140 *output_enable=TRUE;
11141 return RETURN_OK;
11142}