blob: da84f6d429b1a571064ffb1196345b066ce89007 [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"
76#define DRIVER_2GHZ "ath9k"
77#define DRIVER_5GHZ "ath10k_pci"
78
79/*
80 MAX_APS - Number of all AP available in system
81 2x Home AP
82 2x Backhaul AP
83 2x Guest AP
84 2x Secure Onboard AP
85 2x Service AP
86
87*/
88#define MAX_APS 10
89#define NUMBER_OF_RADIOS 2
90
91#ifndef AP_PREFIX
92#define AP_PREFIX "wifi"
93#endif
94
95#ifndef RADIO_PREFIX
96#define RADIO_PREFIX "wlan"
97#endif
98
99#define MAX_BUF_SIZE 128
100#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800101#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800102
103//Uncomment to enable debug logs
104//#define WIFI_DEBUG
105
106#ifdef WIFI_DEBUG
107#define wifi_dbg_printf printf
108#define WIFI_ENTRY_EXIT_DEBUG printf
109#else
110#define wifi_dbg_printf(format, args...) printf("")
111#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
112#endif
113
114#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
115#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
116#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
117#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
118#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
119#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
120#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
121#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
122#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
123#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
124
125#define HOSTAPD_HT_CAPAB_20 "[SHORT-GI-20]"
126#define HOSTAPD_HT_CAPAB_40 "[SHORT-GI-20][SHORT-GI-40]"
127
128#define BW_FNAME "/nvram/bw_file.txt"
129
130#define PS_MAX_TID 16
131
132static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
133 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
134 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
135 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
136 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
137 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
138 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
139 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
140 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
141 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
142 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
143 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
145 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
146 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
147 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
148 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
149};
150
151typedef unsigned long long u64;
152
153/* Enum to define WiFi Bands */
154typedef enum
155{
156 band_invalid = -1,
157 band_2_4 = 0,
158 band_5 = 1,
159} wifi_band;
160
161#ifdef WIFI_HAL_VERSION_3
162
163// Return number of elements in array
164#ifndef ARRAY_SIZE
165#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
166#endif /* ARRAY_SIZE */
167
168#ifndef ARRAY_AND_SIZE
169#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
170#endif /* ARRAY_AND_SIZE */
171
172#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
173
174typedef struct {
175 int32_t value;
176 int32_t param;
177 intptr_t key;
178 intptr_t data;
179} wifi_secur_list;
180
181wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
182wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
183char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
184
185static wifi_secur_list map_security[] =
186{
187 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
188 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
189 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
190 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
191 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
192 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
193 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
194 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
195 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
196};
197
198wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
199{
200 wifi_secur_list *item;
201 int i;
202
203 for (item = list,i = 0;i < list_sz; item++, i++) {
204 if ((int)(item->key) == key) {
205 return item;
206 }
207 }
208
209 return NULL;
210}
211
212char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
213{
214 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
215
216 if (!item) {
217 return "";
218 }
219
220 return (char *)(item->data);
221}
222
223wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
224{
225 wifi_secur_list *item;
226 int i;
227
228 for (item = list,i = 0;i < list_sz; item++, i++) {
229 if (strcmp((char *)(item->data), str) == 0) {
230 return item;
231 }
232 }
233
234 return NULL;
235}
236#endif /* WIFI_HAL_VERSION_3 */
237
238#ifdef HAL_NETLINK_IMPL
239typedef struct {
240 int id;
241 struct nl_sock* socket;
242 struct nl_cb* cb;
243} Netlink;
244
245static int mac_addr_aton(unsigned char *mac_addr, char *arg)
246{
247 unsigned int mac_addr_int[6]={};
248 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);
249 mac_addr[0] = mac_addr_int[0];
250 mac_addr[1] = mac_addr_int[1];
251 mac_addr[2] = mac_addr_int[2];
252 mac_addr[3] = mac_addr_int[3];
253 mac_addr[4] = mac_addr_int[4];
254 mac_addr[5] = mac_addr_int[5];
255 return 0;
256}
257
258static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
259{
260 unsigned int mac_addr_int[6]={};
261 mac_addr_int[0] = arg[0];
262 mac_addr_int[1] = arg[1];
263 mac_addr_int[2] = arg[2];
264 mac_addr_int[3] = arg[3];
265 mac_addr_int[4] = arg[4];
266 mac_addr_int[5] = arg[5];
267 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]);
268 return;
269}
270
271static int ieee80211_frequency_to_channel(int freq)
272{
273 if (freq == 2484)
274 return 14;
275 else if (freq < 2484)
276 return (freq - 2407) / 5;
277 else if (freq >= 4910 && freq <= 4980)
278 return (freq - 4000) / 5;
279 else if (freq <= 45000)
280 return (freq - 5000) / 5;
281 else if (freq >= 58320 && freq <= 64800)
282 return (freq - 56160) / 2160;
283 else
284 return 0;
285}
286
287static int initSock80211(Netlink* nl) {
288 nl->socket = nl_socket_alloc();
289 if (!nl->socket) {
290 fprintf(stderr, "Failing to allocate the sock\n");
291 return -ENOMEM;
292 }
293
294 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
295
296 if (genl_connect(nl->socket)) {
297 fprintf(stderr, "Failed to connect\n");
298 nl_close(nl->socket);
299 nl_socket_free(nl->socket);
300 return -ENOLINK;
301 }
302
303 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
304 if (nl->id< 0) {
305 fprintf(stderr, "interface not found.\n");
306 nl_close(nl->socket);
307 nl_socket_free(nl->socket);
308 return -ENOENT;
309 }
310
311 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
312 if ((!nl->cb)) {
313 fprintf(stderr, "Failed to allocate netlink callback.\n");
314 nl_close(nl->socket);
315 nl_socket_free(nl->socket);
316 return ENOMEM;
317 }
318
319 return nl->id;
320}
321
322static int nlfree(Netlink *nl)
323{
324 nl_cb_put(nl->cb);
325 nl_close(nl->socket);
326 nl_socket_free(nl->socket);
327 return 0;
328}
329
330static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
331 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
332 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
333 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
334};
335
336static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
337};
338
339static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
340};
341
342typedef struct _wifi_channelStats_loc {
343 INT array_size;
344 INT ch_number;
345 BOOL ch_in_pool;
346 INT ch_noise;
347 BOOL ch_radar_noise;
348 INT ch_max_80211_rssi;
349 INT ch_non_80211_noise;
350 INT ch_utilization;
351 ULLONG ch_utilization_total;
352 ULLONG ch_utilization_busy;
353 ULLONG ch_utilization_busy_tx;
354 ULLONG ch_utilization_busy_rx;
355 ULLONG ch_utilization_busy_self;
356 ULLONG ch_utilization_busy_ext;
357} wifi_channelStats_t_loc;
358
359typedef struct wifi_device_info {
360 INT wifi_devIndex;
361 UCHAR wifi_devMacAddress[6];
362 CHAR wifi_devIPAddress[64];
363 BOOL wifi_devAssociatedDeviceAuthentiationState;
364 INT wifi_devSignalStrength;
365 INT wifi_devTxRate;
366 INT wifi_devRxRate;
367} wifi_device_info_t;
368
369#endif
370
371//For 5g Alias Interfaces
372static BOOL priv_flag = TRUE;
373static BOOL pub_flag = TRUE;
374static BOOL Radio_flag = TRUE;
375//wifi_setApBeaconRate(1, beaconRate);
376
377struct params
378{
379 char * name;
380 char * value;
381};
382
383static int _syscmd(char *cmd, char *retBuf, int retBufSize)
384{
385 FILE *f;
386 char *ptr = retBuf;
387 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
388
389 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
390 if((f = popen(cmd, "r")) == NULL) {
391 fprintf(stderr,"\npopen %s error\n", cmd);
392 return RETURN_ERR;
393 }
394
395 while(!feof(f))
396 {
397 *ptr = 0;
398 if(bufSize>=128) {
399 bufbytes=128;
400 } else {
401 bufbytes=bufSize-1;
402 }
403
404 fgets(ptr,bufbytes,f);
405 readbytes=strlen(ptr);
406
407 if(!readbytes)
408 break;
409
410 bufSize-=readbytes;
411 ptr += readbytes;
412 }
413 cmd_ret = pclose(f);
414 retBuf[retBufSize-1]=0;
415 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
416
417 return cmd_ret >> 8;
418}
419
420static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
421{
422 char cmd[MAX_CMD_SIZE]={'\0'};
423 char buf[MAX_BUF_SIZE]={'\0'};
424 int ret = 0;
425
426 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
427 ret = _syscmd(cmd, buf, sizeof(buf));
428 if ((ret != 0) && (strlen(buf) == 0))
429 return -1;
430 snprintf(output, output_size, "%s", buf);
431
432 return 0;
433}
434
435static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
436{
437 char cmd[MAX_CMD_SIZE]={'\0'};
438 char buf[MAX_BUF_SIZE]={'\0'};
439
440 for(int i=0;i<item_count;i++)
441 {
442 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
443 if (strlen(buf) == 0) //Insert
444 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
445 else //Update
446 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
447 if(_syscmd(cmd, buf, sizeof(buf)))
448 return -1;
449 }
450
451 return 0;
452}
453
454static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
455{
456 char cmd[MAX_CMD_SIZE]="", output[32]="";
457 FILE *fp;
458 int i;
459 //NOTE RELOAD should be done in ApplySSIDSettings
460
461 for(i=0; i<item_count; i++, list++)
462 {
463 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
464 if((fp = popen(cmd, "r"))==NULL)
465 {
466 perror("popen failed");
467 return -1;
468 }
469 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
470 {
471 pclose(fp);
472 perror("fgets failed");
473 return -1;
474 }
475 pclose(fp);
476 }
477 return 0;
478}
479
480static int wifi_reloadAp(int apIndex)
481{
482 char cmd[MAX_CMD_SIZE]="";
483 char buf[MAX_BUF_SIZE]="";
484
485 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
486 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
487 return RETURN_ERR;
488
489 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
490 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
491 return RETURN_ERR;
492
493 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
494 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
495 return RETURN_ERR;
496
497 return RETURN_OK;
498}
499
500
501//For Getting Current Interface Name from corresponding hostapd configuration
502void GetInterfaceName(char *interface_name, char *conf_file)
503{
504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
505 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
507}
508
509INT File_Reading(CHAR *file, char *Value)
510{
511 FILE *fp = NULL;
512 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
513 int count = 0;
514
515 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
516 fp = popen(file,"r");
517 if(fp == NULL)
518 return RETURN_ERR;
519
520 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
521 {
522 for(count=0;buf[count]!='\n';count++)
523 copy_buf[count]=buf[count];
524 copy_buf[count]='\0';
525 }
526 strcpy(Value,copy_buf);
527 pclose(fp);
528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
529
530 return RETURN_OK;
531}
532
533void wifi_RestartHostapd_2G()
534{
535 int Public2GApIndex = 4;
536
537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
538 wifi_setApEnable(Public2GApIndex, FALSE);
539 wifi_setApEnable(Public2GApIndex, TRUE);
540 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
541}
542
543void wifi_RestartHostapd_5G()
544{
545 int Public5GApIndex = 5;
546
547 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
548 wifi_setApEnable(Public5GApIndex, FALSE);
549 wifi_setApEnable(Public5GApIndex, TRUE);
550 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
551}
552
553void wifi_RestartPrivateWifi_2G()
554{
555 int PrivateApIndex = 0;
556
557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
558 wifi_setApEnable(PrivateApIndex, FALSE);
559 wifi_setApEnable(PrivateApIndex, TRUE);
560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
561}
562
563void wifi_RestartPrivateWifi_5G()
564{
565 int Private5GApIndex = 1;
566
567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
568 wifi_setApEnable(Private5GApIndex, FALSE);
569 wifi_setApEnable(Private5GApIndex, TRUE);
570 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
571}
572
573static int writeBandWidth(int radioIndex,char *bw_value)
574{
575 char buf[MAX_BUF_SIZE];
576 char cmd[MAX_CMD_SIZE];
577
578 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
579 if(_syscmd(cmd, buf, sizeof(buf)))
580 {
581 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
582 _syscmd(cmd, buf, sizeof(buf));
583 return RETURN_OK;
584 }
585
586 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
587 _syscmd(cmd,buf,sizeof(buf));
588 return RETURN_OK;
589}
590
591static int readBandWidth(int radioIndex,char *bw_value)
592{
593 char buf[MAX_BUF_SIZE];
594 char cmd[MAX_CMD_SIZE];
595 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
596 _syscmd(cmd,buf,sizeof(buf));
597 if(NULL!=strstr(buf,"20MHz"))
598 {
599 strcpy(bw_value,"20MHz");
600 }
601 else if(NULL!=strstr(buf,"40MHz"))
602 {
603 strcpy(bw_value,"40MHz");
604 }
605 else if(NULL!=strstr(buf,"80MHz"))
606 {
607 strcpy(bw_value,"80MHz");
608 }
609 else
610 {
611 return RETURN_ERR;
612 }
613 return RETURN_OK;
614}
615
616INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
617{
618 return 0;
619}
620
621INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
622{
623 return 0;
624}
625
626INT wifi_setLED(INT radioIndex, BOOL enable)
627{
628 return 0;
629}
630INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
631{
632 return RETURN_OK;
633}
634/**********************************************************************************
635 *
636 * Wifi Subsystem level function prototypes
637 *
638**********************************************************************************/
639//---------------------------------------------------------------------------------------------------
640//Wifi system api
641//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
642INT wifi_getHalVersion(CHAR *output_string) //RDKB
643{
644 if(!output_string)
645 return RETURN_ERR;
646 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
647
648 return RETURN_OK;
649}
650
651
652/* wifi_factoryReset() function */
653/**
654* @description Clears internal variables to implement a factory reset of the Wi-Fi
655* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
656*
657* @param None
658*
659* @return The status of the operation.
660* @retval RETURN_OK if successful.
661* @retval RETURN_ERR if any error is detected
662*
663* @execution Synchronous
664* @sideeffect None
665*
666* @note This function must not suspend and must not invoke any blocking system
667* calls. It should probably just send a message to a driver event handler task.
668*
669*/
670INT wifi_factoryReset()
671{
672 char cmd[128];
673
674 /*delete running hostapd conf files*/
675 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
676 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
677 system(cmd);
678 system("systemctl restart hostapd.service");
679
680 return RETURN_OK;
681}
682
683/* wifi_factoryResetRadios() function */
684/**
685* @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.
686*
687* @param None
688* @return The status of the operation
689* @retval RETURN_OK if successful
690* @retval RETURN_ERR if any error is detected
691*
692* @execution Synchronous
693*
694* @sideeffect None
695*
696* @note This function must not suspend and must not invoke any blocking system
697* calls. It should probably just send a message to a driver event handler task.
698*
699*/
700INT wifi_factoryResetRadios()
701{
702 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
703 return RETURN_OK;
704
705 return RETURN_ERR;
706}
707
708
709/* wifi_factoryResetRadio() function */
710/**
711* @description Restore selected radio parameters without touching access point parameters
712*
713* @param radioIndex - Index of Wi-Fi Radio channel
714*
715* @return The status of the operation.
716* @retval RETURN_OK if successful.
717* @retval RETURN_ERR if any error is detected
718*
719* @execution Synchronous.
720* @sideeffect None.
721*
722* @note This function must not suspend and must not invoke any blocking system
723* calls. It should probably just send a message to a driver event handler task.
724*
725*/
726INT wifi_factoryResetRadio(int radioIndex) //RDKB
727{
developer5ff7f5f2022-09-13 15:12:16 +0800728 system("systemctl stop hostapd.service");
729
developer06a01d92022-09-07 16:32:39 +0800730 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
731 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800732 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800733 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800734 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800735 else
736 return RETURN_ERR;
737
developer5ff7f5f2022-09-13 15:12:16 +0800738 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800739 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
740 return RETURN_OK;
741}
742
743/* wifi_initRadio() function */
744/**
745* Description: This function call initializes the specified radio.
746* Implementation specifics may dictate the functionality since
747* different hardware implementations may have different initilization requirements.
748* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
749*
750* @return The status of the operation.
751* @retval RETURN_OK if successful.
752* @retval RETURN_ERR if any error is detected
753*
754* @execution Synchronous.
755* @sideeffect None.
756*
757* @note This function must not suspend and must not invoke any blocking system
758* calls. It should probably just send a message to a driver event handler task.
759*
760*/
761INT wifi_initRadio(INT radioIndex)
762{
763 //TODO: Initializes the wifi subsystem (for specified radio)
764 return RETURN_OK;
765}
766void macfilter_init()
767{
768 char count[4]={'\0'};
769 char buf[253]={'\0'};
770 char tmp[19]={'\0'};
771 int dev_count,block,mac_entry=0;
772 char res[4]={'\0'};
773 char acl_file_path[64] = {'\0'};
774 FILE *fp = NULL;
775 int index=0;
776 char iface[10]={'\0'};
777 char config_file[MAX_BUF_SIZE] = {0};
778
779
780 sprintf(acl_file_path,"/tmp/mac_filter.sh");
781
782 fp=fopen(acl_file_path,"w+");
783 sprintf(buf,"#!/bin/sh \n");
784 fprintf(fp,"%s\n",buf);
785
786 system("chmod 0777 /tmp/mac_filter.sh");
787
788 for(index=0;index<=1;index++)
789 {
790 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
791 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
792 sprintf(buf,"syscfg get %dcountfilter",index);
793 _syscmd(buf,count,sizeof(count));
794 mac_entry=atoi(count);
795
796 sprintf(buf,"syscfg get %dblockall",index);
797 _syscmd(buf,res,sizeof(res));
798 block = atoi(res);
799
800 //Allow only those macs mentioned in ACL
801 if(block==1)
802 {
803 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
804 fprintf(fp,"%s\n",buf);
805 for(dev_count=1;dev_count<=mac_entry;dev_count++)
806 {
807 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
808 _syscmd(buf,tmp,sizeof(tmp));
809 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
810 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
811 fprintf(fp,"%s\n",buf);
812 }
813 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
814 fprintf(fp,"%s\n",buf);
815 }
816
817 //Block all the macs mentioned in ACL
818 else if(block==2)
819 {
820 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
821 fprintf(fp,"%s\n",buf);
822
823 for(dev_count=1;dev_count<=mac_entry;dev_count++)
824 {
825 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
826 _syscmd(buf,tmp,sizeof(tmp));
827 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
828 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
829 fprintf(fp,"%s\n",buf);
830 }
831 }
832 }
833 fclose(fp);
834}
835
836// Initializes the wifi subsystem (all radios)
837INT wifi_init() //RDKB
838{
839 char interface[MAX_BUF_SIZE]={'\0'};
840 char bridge_name[MAX_BUF_SIZE]={'\0'};
841 INT len=0;
842
843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
844 //Not intitializing macfilter for Turris-Omnia Platform for now
845 //macfilter_init();
846
847 system("/usr/sbin/iw reg set US");
848 system("systemctl start hostapd.service");
849 sleep(2);//sleep to wait for hostapd to start
850
851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
852
853 return RETURN_OK;
854}
855
856/* wifi_reset() function */
857/**
858* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
859* Implementation specifics may dictate what is actualy reset since
860* different hardware implementations may have different requirements.
861* Parameters : None
862*
863* @return The status of the operation.
864* @retval RETURN_OK if successful.
865* @retval RETURN_ERR if any error is detected
866*
867* @execution Synchronous.
868* @sideeffect None.
869*
870* @note This function must not suspend and must not invoke any blocking system
871* calls. It should probably just send a message to a driver event handler task.
872*
873*/
874INT wifi_reset()
875{
876 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800877 system("systemctl stop hostapd.service");
878 sleep(2);
879 system("systemctl start hostapd.service");
880 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800881 return RETURN_OK;
882}
883
884/* wifi_down() function */
885/**
886* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
887* Implementation specifics may dictate some functionality since
888* different hardware implementations may have different requirements.
889*
890* @param None
891*
892* @return The status of the operation
893* @retval RETURN_OK if successful
894* @retval RETURN_ERR if any error is detected
895*
896* @execution Synchronous
897* @sideeffect None
898*
899* @note This function must not suspend and must not invoke any blocking system
900* calls. It should probably just send a message to a driver event handler task.
901*
902*/
903INT wifi_down()
904{
905 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +0800906 system("systemctl stop hostapd.service");
907 sleep(2);
developer06a01d92022-09-07 16:32:39 +0800908 return RETURN_OK;
909}
910
911
912/* wifi_createInitialConfigFiles() function */
913/**
914* @description This function creates wifi configuration files. The format
915* and content of these files are implementation dependent. This function call is
916* used to trigger this task if necessary. Some implementations may not need this
917* function. If an implementation does not need to create config files the function call can
918* do nothing and return RETURN_OK.
919*
920* @param None
921*
922* @return The status of the operation
923* @retval RETURN_OK if successful
924* @retval RETURN_ERR if any error is detected
925*
926* @execution Synchronous
927* @sideeffect None
928*
929* @note This function must not suspend and must not invoke any blocking system
930* calls. It should probably just send a message to a driver event handler task.
931*
932*/
933INT wifi_createInitialConfigFiles()
934{
935 //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)
936 return RETURN_OK;
937}
938
939// outputs the country code to a max 64 character string
940INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
941{
developer7543b3b2022-09-13 13:47:17 +0800942 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
943 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +0800944 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +0800945
946 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
947 _syscmd(cmd, buf, sizeof(buf));
948 if(strlen(buf) > 0)
949 snprintf(output_string, 64, "%s", buf);
950 else
951 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800952
953 return RETURN_OK;
954}
955
956INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
957{
958 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +0800959 char str[MAX_BUF_SIZE]={'\0'};
960 char cmd[MAX_CMD_SIZE]={'\0'};
961 struct params params;
962 char config_file[MAX_BUF_SIZE] = {0};
963
964 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
965 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
966 return RETURN_ERR;
967
968 params.name = "country_code";
969 params.value = CountryCode;
970 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
971 int ret = wifi_hostapdWrite(config_file, &params, 1);
972 if (ret) {
973 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
974 ,__func__, ret);
975 }
976
977 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
978 if (ret) {
979 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
980 ,__func__, ret);
981 }
982 wifi_reloadAp(radioIndex);
983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
984
developer06a01d92022-09-07 16:32:39 +0800985 return RETURN_OK;
986}
987
988/**********************************************************************************
989 *
990 * Wifi radio level function prototypes
991 *
992**********************************************************************************/
993
994//Get the total number of radios in this wifi subsystem
995INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
996{
997 if (NULL == output)
998 return RETURN_ERR;
999 *output = 2;
1000
1001 return RETURN_OK;
1002}
1003
1004//Get the total number of SSID entries in this wifi subsystem
1005INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1006{
1007 if (NULL == output)
1008 return RETURN_ERR;
1009 *output = MAX_APS;
1010
1011 return RETURN_OK;
1012}
1013
1014//Get the Radio enable config parameter
1015INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1016{
1017 char interface_path[MAX_CMD_SIZE] = {0};
1018 FILE *fp = NULL;
1019
1020 if (NULL == output_bool)
1021 return RETURN_ERR;
1022
1023 *output_bool = FALSE;
1024 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1025 return RETURN_ERR;
1026
1027 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1028 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001029 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001030 {
developercf48e482022-09-13 14:49:50 +08001031 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001032 }
1033 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001034 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1035 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1036 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001037
developercf48e482022-09-13 14:49:50 +08001038 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1039 *output_bool = TRUE;
1040 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001041 return RETURN_OK;
1042}
1043
1044INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1045{
1046 char cmd[MAX_CMD_SIZE] = {0};
1047 char buf[MAX_CMD_SIZE] = {0};
1048 int apIndex, ret;
1049 FILE *fp = NULL;
1050
1051 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1052 if(enable==FALSE)
1053 {
1054 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1055 {
1056 //Detaching %s%d from hostapd daemon
1057 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1058 _syscmd(cmd, buf, sizeof(buf));
1059 if(strncmp(buf, "OK", 2))
1060 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1061 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1062 _syscmd(cmd, buf, sizeof(buf));
1063 }
developer456aa3e2022-09-13 14:27:36 +08001064 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001065 _syscmd(cmd, buf, sizeof(buf));
1066 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001067 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001068 }
1069 else
1070 {
developer456aa3e2022-09-13 14:27:36 +08001071 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001072 _syscmd(cmd, buf, sizeof(buf));
1073 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001074 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001075 sleep(1);
1076 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1077 {
1078 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1079 fp = fopen(cmd, "r");
1080 if(!fp)
1081 {
1082 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1083 _syscmd(cmd, buf, sizeof(buf));
1084 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1085 _syscmd(cmd, buf, sizeof(buf));
1086 }
1087 if(fp)
1088 fclose(fp);
1089 }
1090 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1091 {
1092 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1093 ret = _syscmd(cmd, buf, sizeof(buf));
1094 if ( ret == RETURN_ERR)
1095 {
1096 fprintf(stderr, "VAP interface creation failed\n");
1097 continue;
1098 }
1099 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1100 _syscmd(cmd, buf, sizeof(buf));
1101 if(*buf == '1')
1102 {
1103 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1104 radioIndex, apIndex);
1105 _syscmd(cmd, buf, sizeof(buf));
1106 if(strncmp(buf, "OK", 2))
1107 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1108 }
1109 }
1110 }
1111
1112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1113 return RETURN_OK;
1114}
1115
1116//Get the Radio enable status
1117INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1118{
1119 if (NULL == output_bool)
1120 return RETURN_ERR;
1121
1122 return wifi_getRadioEnable(radioIndex, output_bool);
1123}
1124
1125//Get the Radio Interface name from platform, eg "wlan0"
1126INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1127{
1128 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1129 return RETURN_ERR;
1130 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1131
1132 return RETURN_OK;
1133}
1134
1135//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1136//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.
1137INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1138{
1139 char cmd[1024] = {0};
1140 char buf[1024] = {0};
1141 char HConf_file[MAX_BUF_SIZE] = {'\0'};
1142 char interface_name[50] = {0};
1143
1144 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1145 if (NULL == output_string)
1146 return RETURN_ERR;
1147
1148 sprintf(HConf_file,"%s%d%s","/nvram/hostapd",radioIndex,".conf");
1149 GetInterfaceName(interface_name,HConf_file);
1150
1151 sprintf(cmd, "iwconfig %s | grep 'Bit Rate' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1,2", interface_name);
1152 _syscmd(cmd, buf, sizeof(buf));
1153
1154 if(strlen(buf) > 0)
1155 snprintf(output_string, 64, "%s", buf);
1156 else
1157 {
1158 wifi_getRadioOperatingChannelBandwidth(radioIndex,buf);
1159 if((strcmp(buf,"20MHz") == 0) && (radioIndex == 0))
1160 strcpy(output_string,"144 Mb/s");
1161 else if((strcmp(buf,"20MHz") == 0) && (radioIndex == 1))
1162 strcpy(output_string,"54 Mb/s");
1163 else if((strcmp(buf,"40MHz") == 0) && (radioIndex == 1))
1164 strcpy(output_string,"300 Mb/s");
1165 //TODO: CHECK VALID VALUE
1166 }
1167 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1168
1169 return RETURN_OK;
1170}
1171#if 0
1172INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1173{
1174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1175 char cmd[64];
1176 char buf[1024];
1177 int apIndex;
1178
1179 if (NULL == output_string)
1180 return RETURN_ERR;
1181
1182 apIndex=(radioIndex==0)?0:1;
1183
1184 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1185 _syscmd(cmd,buf, sizeof(buf));
1186
1187 snprintf(output_string, 64, "%s", buf);
1188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1189 return RETURN_OK;
1190}
1191#endif
1192
1193
1194//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1195//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.
1196INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1197{
1198 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1199 if (NULL == output_string)
1200 return RETURN_ERR;
1201 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1203
1204 return RETURN_OK;
1205#if 0
1206 char buf[MAX_BUF_SIZE]={'\0'};
1207 char str[MAX_BUF_SIZE]={'\0'};
1208 char cmd[MAX_CMD_SIZE]={'\0'};
1209 char *ch=NULL;
1210 char *ch2=NULL;
1211
1212 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1213 if (NULL == output_string)
1214 return RETURN_ERR;
1215
1216
1217 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1218
1219 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1220 {
1221 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1222 return RETURN_ERR;
1223 }
1224 ch=strchr(buf,'\n');
1225 *ch='\0';
1226 ch=strchr(buf,'=');
1227 if(ch==NULL)
1228 return RETURN_ERR;
1229
1230
1231 ch++;
1232
1233 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1234 strcpy(buf,"0");
1235 if(strlen(ch) == 1)
1236 ch=strcat(buf,ch);
1237
1238
1239 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1240
1241 if(_syscmd(cmd,str,64) == RETURN_ERR)
1242 {
1243 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1244 return RETURN_ERR;
1245 }
1246
1247
1248 ch2=strchr(str,'\n');
1249 //replace \n with \0
1250 *ch2='\0';
1251 ch2=strchr(str,'=');
1252 if(ch2==NULL)
1253 {
1254 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1255 return RETURN_ERR;
1256 }
1257 else
1258 wifi_dbg_printf("%s",ch2+1);
1259
1260
1261 ch2++;
1262
1263
1264 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1265
1266 memset(buf,'\0',sizeof(buf));
1267 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1268 {
1269 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1270 return RETURN_ERR;
1271 }
1272 if (strstr(buf,"2.4") != NULL )
1273 strcpy(output_string,"2.4GHz");
1274 else if(strstr(buf,"5.") != NULL )
1275 strcpy(output_string,"5GHz");
1276 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1277
1278 return RETURN_OK;
1279#endif
1280}
1281
1282//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1283//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.
1284INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1285{
1286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1287 if (NULL == output_string)
1288 return RETURN_ERR;
1289 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1291
1292 return RETURN_OK;
1293#if 0
1294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1295 char buf[MAX_BUF_SIZE]={'\0'};
1296 char str[MAX_BUF_SIZE]={'\0'};
1297 char cmd[MAX_CMD_SIZE]={'\0'};
1298 char *ch=NULL;
1299 char *ch2=NULL;
1300 char ch1[5]="0";
1301
1302 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1303
1304 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1305 {
1306 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1307 return RETURN_ERR;
1308 }
1309
1310 ch=strchr(buf,'\n');
1311 *ch='\0';
1312 ch=strchr(buf,'=');
1313 if(ch==NULL)
1314 return RETURN_ERR;
1315 ch++;
1316
1317 if(strlen(ch)==1)
1318 {
1319 strcat(ch1,ch);
1320
1321 }
1322 else
1323 {
1324 strcpy(ch1,ch);
1325 }
1326
1327
1328
1329 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1330 if(_syscmd(cmd,str,64) == RETURN_ERR)
1331 {
1332 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1333 return RETURN_ERR;
1334 }
1335
1336
1337 ch2=strchr(str,'\n');
1338 //replace \n with \0
1339 *ch2='\0';
1340 ch2=strchr(str,'=');
1341 if(ch2==NULL)
1342 {
1343 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1344 return RETURN_ERR;
1345 }
1346 else
1347 wifi_dbg_printf("%s",ch2+1);
1348 ch2++;
1349
1350
1351 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1352 memset(buf,'\0',sizeof(buf));
1353 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1354 {
1355 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1356 return RETURN_ERR;
1357 }
1358
1359
1360 if(strstr(buf,"2.4")!=NULL)
1361 {
1362 strcpy(output_string,"2.4GHz");
1363 }
1364 if(strstr(buf,"5.")!=NULL)
1365 {
1366 strcpy(output_string,"5GHz");
1367 }
1368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1369 return RETURN_OK;
1370#endif
1371}
1372
1373//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1374//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.
1375INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1376{
1377 if (NULL == output_string)
1378 return RETURN_ERR;
1379 snprintf(output_string, 64, (radioIndex==0)?"b,g,n":"a,n,ac");
1380
1381 return RETURN_OK;
1382}
1383
1384//Get the radio operating mode, and pure mode flag. eg: "ac"
1385//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.
1386INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1387{
1388 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1389 if (NULL == output_string)
1390 return RETURN_ERR;
1391
1392 if (radioIndex == 0) {
1393 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1394 *gOnly = FALSE;
1395 *nOnly = TRUE;
1396 *acOnly = FALSE;
1397 } else {
1398 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1399 *gOnly = FALSE;
1400 *nOnly = FALSE;
1401 *acOnly = FALSE;
1402 }
1403 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1404
1405 return RETURN_OK;
1406#if 0
1407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1408 char buf[64] = {0};
1409 char config_file[MAX_BUF_SIZE] = {0};
1410
1411 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1412 return RETURN_ERR;
1413
1414 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1415 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1416
1417 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1418 if (strlen(buf) == 0)
1419 {
1420 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1421 return RETURN_ERR;
1422 }
1423 if(strcmp(buf,"g")==0)
1424 {
1425 wifi_dbg_printf("\nG\n");
1426 *gOnly=TRUE;
1427 *nOnly=FALSE;
1428 *acOnly=FALSE;
1429 }
1430 else if(strcmp(buf,"n")==0)
1431 {
1432 wifi_dbg_printf("\nN\n");
1433 *gOnly=FALSE;
1434 *nOnly=TRUE;
1435 *acOnly=FALSE;
1436 }
1437 else if(strcmp(buf,"ac")==0)
1438 {
1439 wifi_dbg_printf("\nac\n");
1440 *gOnly=FALSE;
1441 *nOnly=FALSE;
1442 *acOnly=TRUE;
1443 }
1444 /* hostapd-5G.conf has "a" as hw_mode */
1445 else if(strcmp(buf,"a")==0)
1446 {
1447 wifi_dbg_printf("\na\n");
1448 *gOnly=FALSE;
1449 *nOnly=FALSE;
1450 *acOnly=FALSE;
1451 }
1452 else
1453 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1454
1455 //for a,n mode
1456 if(radioIndex == 1)
1457 {
1458 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1459 if(strcmp(buf,"1")==0)
1460 {
1461 strncpy(output_string, "n", 1);
1462 *nOnly=FALSE;
1463 }
1464 }
1465
1466 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1468 return RETURN_OK;
1469#endif
1470}
1471
1472//Set the radio operating mode, and pure mode flag.
1473INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1474{
1475 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1476 if (strcmp (channelMode,"11A") == 0)
1477 {
1478 writeBandWidth(radioIndex,"20MHz");
1479 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1480 printf("\nChannel Mode is 802.11a (5GHz)\n");
1481 }
1482 else if (strcmp (channelMode,"11NAHT20") == 0)
1483 {
1484 writeBandWidth(radioIndex,"20MHz");
1485 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1486 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1487 }
1488 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1489 {
1490 writeBandWidth(radioIndex,"40MHz");
1491 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1492 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1493 }
1494 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1495 {
1496 writeBandWidth(radioIndex,"40MHz");
1497 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1498 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1499 }
1500 else if (strcmp (channelMode,"11ACVHT20") == 0)
1501 {
1502 writeBandWidth(radioIndex,"20MHz");
1503 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1504 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1505 }
1506 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1507 {
1508 writeBandWidth(radioIndex,"40MHz");
1509 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1510 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1511 }
1512 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1513 {
1514 writeBandWidth(radioIndex,"40MHz");
1515 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1516 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1517 }
1518 else if (strcmp (channelMode,"11ACVHT80") == 0)
1519 {
1520 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1521 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1522 }
1523 else if (strcmp (channelMode,"11ACVHT160") == 0)
1524 {
1525 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1526 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1527 }
1528 else if (strcmp (channelMode,"11B") == 0)
1529 {
1530 writeBandWidth(radioIndex,"20MHz");
1531 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1532 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1533 }
1534 else if (strcmp (channelMode,"11G") == 0)
1535 {
1536 writeBandWidth(radioIndex,"20MHz");
1537 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1538 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1539 }
1540 else if (strcmp (channelMode,"11NGHT20") == 0)
1541 {
1542 writeBandWidth(radioIndex,"20MHz");
1543 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1544 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1545 }
1546 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1547 {
1548 writeBandWidth(radioIndex,"40MHz");
1549 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1550 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1551 }
1552 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1553 {
1554 writeBandWidth(radioIndex,"40MHz");
1555 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1556 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1557 }
1558 else
1559 {
1560 return RETURN_ERR;
1561 }
1562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1563
1564 return RETURN_OK;
1565}
1566
1567//Get the list of supported channel. eg: "1-11"
1568//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.
1569INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
1570{
developer6318ed52022-09-13 15:17:58 +08001571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001572 if (NULL == output_string)
1573 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08001574 char cmd[256] = {0};
1575 char buf[128] = {0};
1576 BOOL dfs_enable = false;
1577 // Parse possible channel number and separate them with commas.
1578 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
1579 if (dfs_enable)
1580 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
1581 else
1582 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);
1583
1584 _syscmd(cmd,buf,sizeof(buf));
1585 strncpy(output_string, buf, sizeof(buf));
1586
1587 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1588 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08001589#if 0
1590 char IFName[50] ={0};
1591 char buf[MAX_BUF_SIZE] = {0};
1592 char cmd[MAX_CMD_SIZE] = {0};
1593 int count = 0;
1594 if (NULL == output_string)
1595 return RETURN_ERR;
1596
1597 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
1598 if(radioIndex == 0)
1599 {
1600 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
1601 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'");
1602 }
1603 else if(radioIndex == 1)
1604 {
1605 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
1606 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'");
1607 }
1608 _syscmd(cmd, buf, sizeof(buf));
1609 if(strlen(buf) > 0)
1610 strcpy(output_string,buf);
1611 else
1612 strcpy(output_string,"0");
1613#endif
1614 return RETURN_OK;
1615}
1616
1617//Get the list for used channel. eg: "1,6,9,11"
1618//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.
1619INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
1620{
1621 if (NULL == output_string)
1622 return RETURN_ERR;
1623 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
1624#if 0
1625 char IFName[50] ={0};
1626 char buf[MAX_BUF_SIZE] = {0};
1627 char cmd[MAX_CMD_SIZE] = {0};
1628 if (NULL == output_string)
1629 return RETURN_ERR;
1630
1631 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
1632 if(radioIndex == 0)
1633 {
1634 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
1635 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'");
1636 }
1637 else if(radioIndex == 1)
1638 {
1639 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
1640 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'");
1641 }
1642 _syscmd(cmd,buf, sizeof(buf));
1643 if(strlen(buf) > 0)
1644 strcpy(output_string,buf);
1645 else
1646 strcpy(output_string,"0");
1647#endif
1648 return RETURN_OK;
1649}
1650
1651//Get the running channel number
1652INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
1653{
developerda1ed692022-09-13 13:59:20 +08001654#ifdef MTK_IMPL
1655 if(!wifi_getApChannel(radioIndex, output_ulong))
1656 return RETURN_OK;
1657 else
1658 return RETURN_ERR;
1659#else
developer06a01d92022-09-07 16:32:39 +08001660 char cmd[1024] = {0}, buf[5] = {0};
1661
1662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1663 if (NULL == output_ulong)
1664 return RETURN_ERR;
1665
1666 snprintf(cmd, sizeof(cmd),
1667 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
1668 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
1669 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
1670 _syscmd(cmd, buf, sizeof(buf));
1671
1672 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
1673 if (*output_ulong <= 0) {
1674 *output_ulong = 0;
1675 return RETURN_ERR;
1676 }
1677
1678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1679 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08001680#endif
developer06a01d92022-09-07 16:32:39 +08001681}
1682
1683
1684INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
1685{
1686 char cmd[1024] = {0}, buf[5] = {0};
1687 char interface_name[50] = {0};
1688
1689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1690 if (NULL == output_ulong)
1691 return RETURN_ERR;
1692
1693 wifi_getApName(apIndex,interface_name);
1694 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
1695 _syscmd(cmd,buf,sizeof(buf));
1696 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
1697 if (*output_ulong == 0) {
1698 return RETURN_ERR;
1699 }
1700
1701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1702 return RETURN_OK;
1703}
1704
1705//Storing the previous channel value
1706INT wifi_storeprevchanval(INT radioIndex)
1707{
1708 char buf[256] = {0};
1709 char output[4]={'\0'};
1710 char config_file[MAX_BUF_SIZE] = {0};
1711 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
1712 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
1713 if(radioIndex == 0)
1714 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
1715 else if(radioIndex == 1)
1716 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
1717 system(buf);
1718 Radio_flag = FALSE;
1719 return RETURN_OK;
1720}
1721
1722//Set the running channel number
1723INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
1724{
1725 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1726 struct params params={'\0'};
1727 char str_channel[4]={'\0'};
1728 struct params list;
1729 char config_file[MAX_BUF_SIZE] = {0};
1730
1731 list.name = "channel";
1732
1733 if(Radio_flag == TRUE)
1734 wifi_storeprevchanval(radioIndex); //for autochannel
1735
1736 if(radioIndex == 0)
1737 {
1738 switch(channel)
1739 {
1740 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
1741 sprintf(str_channel,"%ld", channel);
1742 list.value = str_channel;
1743 break;
1744 default:
1745 return RETURN_ERR;
1746 }
1747 }
1748 else if(radioIndex == 1)
1749 {
1750 switch(channel)
1751 {
1752 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:
1753 sprintf(str_channel,"%ld", channel);
1754 list.value = str_channel;
1755 break;
1756 default:
1757 return RETURN_ERR;
1758 }
1759 }
1760
1761 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
1762 {
1763 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
1764 wifi_hostapdWrite(config_file,&list,1);
1765 }
1766
1767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1768 return RETURN_OK;
1769 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
1770 }
1771
1772INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
1773{
1774 struct params list;
1775 char str_idx[16];
1776 char config_file[MAX_BUF_SIZE];
1777
1778 list.name = "vht_oper_centr_freq_seg0_idx";
1779 snprintf(str_idx, sizeof(str_idx), "%d", channel);
1780 list.value = str_idx;
1781
1782 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
1783 {
1784 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
1785 wifi_hostapdWrite(config_file, &list, 1);
1786 }
1787
1788 return RETURN_OK;
1789}
1790
1791//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
1792//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
1793INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
1794{
1795 //Set to wifi config only. Wait for wifi reset to apply.
1796 char buf[256] = {0};
1797 char str_channel[256] = {0};
1798 int count = 0;
1799 ULONG Value = 0;
1800 FILE *fp = NULL;
1801 if(enable == TRUE)
1802 {
1803 if(radioIndex == 0)
1804 {
1805 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
1806 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
1807 }
1808 else if(radioIndex == 1)
1809 {
1810 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
1811 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
1812 }
1813 if(fp == NULL) //first time boot-up
1814 {
1815 if(radioIndex == 0)
1816 Value = 6;
1817 else if(radioIndex == 1)
1818 Value = 36;
1819 }
1820 else
1821 {
1822 if(fgets(buf,sizeof(buf),fp) != NULL)
1823 {
1824 for(count = 0;buf[count]!='\n';count++)
1825 str_channel[count] = buf[count];
1826 str_channel[count] = '\0';
1827 Value = atol(str_channel);
1828 printf("%sValue is %ld \n",__FUNCTION__,Value);
1829 pclose(fp);
1830 }
1831 }
1832 Radio_flag = FALSE;//for storing previous channel value
1833 wifi_setRadioChannel(radioIndex,Value);
1834 return RETURN_OK;
1835 }
1836 return RETURN_ERR;
1837}
1838
1839INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
1840{
1841 if (NULL == output_bool)
1842 return RETURN_ERR;
1843 *output_bool=FALSE;
1844 return RETURN_OK;
1845}
1846
1847INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
1848{
1849 if (NULL == output_bool)
1850 return RETURN_ERR;
1851 *output_bool=FALSE;
1852 return RETURN_OK;
1853}
1854
1855INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
1856{
1857 //Set to wifi config only. Wait for wifi reset to apply.
1858 return RETURN_OK;
1859}
1860
1861INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
1862{
1863 return RETURN_OK;
1864}
1865
1866INT wifi_factoryResetAP(int apIndex)
1867{
1868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1869 //factory reset is not done for now on Turris
1870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1871 return RETURN_OK;
1872}
1873
1874//To set Band Steering AP group
1875//To-do
1876INT wifi_setBandSteeringApGroup(char *ApGroup)
1877{
1878 return RETURN_OK;
1879}
1880
1881INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
1882{
1883 return RETURN_OK;
1884}
1885
1886//Check if the driver support the Dfs
1887INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
1888{
1889 if (NULL == output_bool)
1890 return RETURN_ERR;
1891 *output_bool=FALSE;
1892 return RETURN_OK;
1893}
1894
1895//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.
1896//The value of this parameter is a comma seperated list of channel number
1897INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
1898{
1899 if (NULL == output_pool)
1900 return RETURN_ERR;
1901 if (radioIndex==1)
1902 return RETURN_OK;//TODO need to handle for 5GHz band, i think
1903 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
1904
1905 return RETURN_OK;
1906}
1907
1908INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
1909{
1910 //Set to wifi config. And apply instantly.
1911 return RETURN_OK;
1912}
1913
1914INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
1915{
1916 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
1917 return RETURN_ERR;
1918 *output_interval_seconds=1800;
1919 *output_dwell_milliseconds=40;
1920
1921 return RETURN_OK;
1922}
1923
1924INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
1925{
1926 //Set to wifi config. And apply instantly.
1927 return RETURN_OK;
1928}
1929
1930//Get the Dfs enable status
1931INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
1932{
1933 if (NULL == output_bool)
1934 return RETURN_ERR;
1935 *output_bool = FALSE;
1936
1937 return RETURN_OK;
1938}
1939
1940//Set the Dfs enable status
1941INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
1942{
1943 return RETURN_ERR;
1944}
1945
1946//Check if the driver support the AutoChannelRefreshPeriod
1947INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
1948{
1949 if (NULL == output_bool)
1950 return RETURN_ERR;
1951 *output_bool=FALSE; //not support
1952
1953 return RETURN_OK;
1954}
1955
1956//Get the ACS refresh period in seconds
1957INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
1958{
1959 if (NULL == output_ulong)
1960 return RETURN_ERR;
1961 *output_ulong=300;
1962
1963 return RETURN_OK;
1964}
1965
1966//Set the ACS refresh period in seconds
1967INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
1968{
1969 return RETURN_ERR;
1970}
1971
1972//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
1973//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.
1974INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
1975{
1976 if (NULL == output_string)
1977 return RETURN_ERR;
1978
1979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1980 char cmd[1024] = {0}, buf[64] = {0};
1981 int ret = 0, len=0;
1982
1983 snprintf(cmd, sizeof(cmd),
1984 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
1985 "xargs -I {} iw dev {} info | grep width | head -n1 | "
1986 "cut -d ' ' -f6", RADIO_PREFIX, radioIndex);
1987
1988 ret = _syscmd(cmd, buf, sizeof(buf));
1989 len = strlen(buf);
1990 if((ret != 0) || (len == 0))
1991 {
1992 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
1993 return RETURN_ERR;
1994 }
1995
1996 buf[len-1] = '\0';
1997 snprintf(output_string, 64, "%sMHz", buf);
1998 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1999
2000#if 0
2001 //TODO: revisit below implementation
2002 char output_buf[8]={0};
2003 char bw_value[10];
2004 char config_file[MAX_BUF_SIZE] = {0};
2005
2006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2007 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2008 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2009 readBandWidth(radioIndex,bw_value);
2010
2011 if(strstr (output_buf,"0") != NULL )
2012 {
2013 strcpy(output_string,bw_value);
2014 }
2015 else if (strstr (output_buf,"1") != NULL)
2016 {
2017 strcpy(output_string,"80MHz");
2018 }
2019 else if (strstr (output_buf,"2") != NULL)
2020 {
2021 strcpy(output_string,"160MHz");
2022 }
2023 else if (strstr (output_buf,"3") != NULL)
2024 {
2025 strcpy(output_string,"80+80");
2026 }
2027 else
2028 {
2029 strcpy(output_string,"Auto");
2030 }
2031 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2032#endif
2033
2034 return RETURN_OK;
2035}
2036
2037//Set the Operating Channel Bandwidth.
2038INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181 //AP only
2039{
2040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2041 char config_file[MAX_BUF_SIZE];
2042 struct params params[4];
2043 struct params *pptr = params;
2044
2045 if(NULL == output_string)
2046 return RETURN_ERR;
2047
2048 pptr->name = "vht_oper_chwidth";
2049 if(strcmp(output_string,"20MHz") == 0) // This piece of code only support for wifi hal api's validation
2050 pptr->value="0";
2051 else if(strcmp(output_string,"40MHz") == 0)
2052 pptr->value="0";
2053 else if(strcmp(output_string,"80MHz") == 0)
2054 pptr->value="1";
2055 else if(strcmp(output_string,"160MHz") == 0)
2056 pptr->value="2";
2057 else if(strcmp(output_string,"80+80") == 0)
2058 pptr->value="3";
2059 else
2060 {
2061 printf("Invalid Bandwidth \n");
2062 return RETURN_ERR;
2063 }
2064
2065 pptr++; // added vht_oper_chwidth
2066
2067 if(radioIndex == 1)
2068 {
2069 pptr->name= "ieee80211n";
2070 if(strcmp(output_string,"20MHz") == 0)
2071 pptr->value="0";
2072 else if(strcmp(output_string,"40MHz") == 0)
2073 pptr->value="1";
2074 else if(strcmp(output_string,"80MHz") == 0)
2075 pptr->value="1";
2076 else
2077 pptr->value="0";
2078
2079 pptr++; // added ieee80211n
2080
2081 pptr->name="ieee80211ac";
2082 if(strcmp(output_string,"80MHz") == 0)
2083 pptr->value="1";
2084 else
2085 pptr->value="0";
2086 pptr++;
2087 }
2088
2089 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2090 {
2091 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2092 wifi_hostapdWrite(config_file, params, (pptr - params));
2093 }
2094
2095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2096 return RETURN_OK;
2097}
2098
2099//Getting current radio extension channel
2100INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2101{
2102 CHAR buf[150] = {0};
2103 CHAR cmd[150] = {0};
2104 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2105 _syscmd(cmd, buf, sizeof(buf));
2106 if(NULL != strstr(buf,"HT40+"))
2107 strcpy(Value,"AboveControlChannel");
2108 else if(NULL != strstr(buf,"HT40-"))
2109 strcpy(Value,"BelowControlChannel");
2110 return RETURN_OK;
2111}
2112
2113//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2114//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.
2115INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2116{
2117 if (NULL == output_string)
2118 return RETURN_ERR;
2119
2120 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2121#if 0
2122 CHAR Value[100] = {0};
2123 if (NULL == output_string)
2124 return RETURN_ERR;
2125 if(radioIndex == 0)
2126 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2127 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2128 {
2129 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2130 if(strcmp(Value,"40MHz") == 0)
2131 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2132 else
2133 strcpy(Value,"Auto");
2134 }
2135 strcpy(output_string,Value);
2136#endif
2137
2138 return RETURN_OK;
2139}
2140
2141//Set the extension channel.
2142INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2143{
2144 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2145 struct params params={'\0'};
2146 char config_file[MAX_BUF_SIZE] = {0};
2147 char ext_channel[127]={'\0'};
2148
2149 params.name = "ht_capab";
2150
2151 if(radioIndex == 0)
2152 {
2153 if(NULL!= strstr(string,"Above"))
2154 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40+]");
2155 else if(NULL!= strstr(string,"Below"))
2156 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40-]");
2157 else
2158 strcpy(ext_channel, HOSTAPD_HT_CAPAB_20);
2159 }
2160 else if(radioIndex == 1)
2161 {
2162 if(NULL!= strstr(string,"Above"))
2163 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40+]");
2164 else if(NULL!= strstr(string,"Below"))
2165 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40-]");
2166 else
2167 strcpy(ext_channel, HOSTAPD_HT_CAPAB_20);
2168 }
2169
2170 params.value = ext_channel;
2171 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2172 {
2173 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2174 wifi_hostapdWrite(config_file, &params, 1);
2175 }
2176
2177 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2178 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2179 return RETURN_OK;
2180}
2181
2182//Get the guard interval value. eg "400nsec" or "800nsec"
2183//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.
2184INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2185{
2186 //save config and apply instantly
2187 if (NULL == output_string)
2188 return RETURN_ERR;
2189 snprintf(output_string, 64, (radioIndex == 0) ? "400nsec" : "400nsec");
2190
2191 return RETURN_OK;
2192}
2193
2194//Set the guard interval value.
2195INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2196{
2197 //Apply setting instantly
2198 return RETURN_ERR;
2199}
2200
2201//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2202INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2203{
2204 if (NULL == output_int)
2205 return RETURN_ERR;
2206 *output_int=(radioIndex==0)?1:3;
2207
2208 return RETURN_OK;
2209}
2210
2211//Set the Modulation Coding Scheme index
2212INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2213{
2214 return RETURN_ERR;
2215}
2216
2217//Get supported Transmit Power list, eg : "0,25,50,75,100"
2218//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.
2219INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2220{
2221 if (NULL == output_list)
2222 return RETURN_ERR;
2223 snprintf(output_list, 64,"0,25,50,75,100");
2224 return RETURN_OK;
2225}
2226
2227//Get current Transmit Power, eg "75", "100"
2228//The transmite power level is in units of full power for this radio.
2229INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2230{
2231 char cmd[128]={0};
2232 char buf[256]={0};
2233 INT apIndex;
2234 //save config and apply instantly
2235
2236 if (NULL == output_ulong)
2237 return RETURN_ERR;
2238
2239 //zqiu:TODO:save config
2240 apIndex = (radioIndex==0) ?0 :1;
2241
2242 snprintf(cmd, sizeof(cmd), "iwlist %s%d txpower | grep Tx-Power | cut -d'=' -f2", AP_PREFIX, apIndex);
2243 _syscmd(cmd, buf, sizeof(buf));
2244 *output_ulong = atol(buf);
2245
2246 return RETURN_OK;
2247}
2248
2249//Set Transmit Power
2250//The transmite power level is in units of full power for this radio.
2251INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2252{
2253 char cmd[128]={0};
2254 char buf[256]={0};
2255 INT apIndex;
2256
2257 snprintf(cmd, sizeof(cmd), "iwconfig %s%d txpower %lu", AP_PREFIX, radioIndex, TransmitPower);
2258 _syscmd(cmd, buf, sizeof(buf));
2259
2260 return RETURN_OK;
2261}
2262
2263//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2264INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2265{
2266 if (NULL == Supported)
2267 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002268 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002269
2270 return RETURN_OK;
2271}
2272
2273//Get 80211h feature enable
2274INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2275{
developer3885fec2022-09-13 15:13:47 +08002276 char buf[64]={'\0'};
2277 char config_file[64] = {'\0'};
2278
2279 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2280 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002281 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002282
2283 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2284 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002285
developer3885fec2022-09-13 15:13:47 +08002286 if (strncmp(buf, "1", 1) == 0)
2287 *enable = TRUE;
2288 else
2289 *enable = FALSE;
2290
2291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002292 return RETURN_OK;
2293}
2294
2295//Set 80211h feature enable
2296INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2297{
developer3885fec2022-09-13 15:13:47 +08002298 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2299 struct params params={'\0'};
2300 char config_file[MAX_BUF_SIZE] = {0};
2301
2302 params.name = "ieee80211h";
2303
2304 if (enable) {
2305 params.value = "1";
2306 } else {
2307 params.value = "0";
2308 }
2309
2310 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2311 wifi_hostapdWrite(config_file, &params, 1);
2312
2313 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2314 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2315 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002316}
2317
2318//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.
2319INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2320{
2321 if (NULL == output)
2322 return RETURN_ERR;
2323 *output=100;
2324
2325 return RETURN_OK;
2326}
2327
2328//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.
2329INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2330{
2331 if (NULL == output)
2332 return RETURN_ERR;
2333 *output = -99;
2334
2335 return RETURN_OK;
2336}
2337
2338INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2339{
2340 return RETURN_ERR;
2341}
2342
2343
2344//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2345INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2346{
2347 if (NULL == output)
2348 return RETURN_ERR;
2349 *output = 100;
2350
2351 return RETURN_OK;
2352}
2353
2354INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
2355{
2356 return RETURN_ERR;
2357}
2358
2359//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.
2360INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
2361{
2362 if (NULL == output)
2363 return RETURN_ERR;
2364 snprintf(output, 64, (radioIndex == 0) ? "1,2" : "1.5,150");
2365#if 0
2366 //TODO: need to revisit below implementation
2367 char *temp;
2368 char temp_output[128];
2369 char temp_TransmitRates[512];
2370 char config_file[MAX_BUF_SIZE] = {0};
2371
2372 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2373 if (NULL == output)
2374 return RETURN_ERR;
2375 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2376 wifi_hostapdRead(config_file,"basic_rates",output,64);
2377
2378 strcpy(temp_TransmitRates,output);
2379 strcpy(temp_output,"");
2380 temp = strtok(temp_TransmitRates," ");
2381 while(temp!=NULL)
2382 {
2383 temp[strlen(temp)-1]=0;
2384 if((temp[0]=='5') && (temp[1]=='\0'))
2385 {
2386 temp="5.5";
2387 }
2388 strcat(temp_output,temp);
2389 temp = strtok(NULL," ");
2390 if(temp!=NULL)
2391 {
2392 strcat(temp_output,",");
2393 }
2394 }
2395 strcpy(output,temp_output);
2396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2397#endif
2398 return RETURN_OK;
2399}
2400
2401INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
2402{
2403 char *temp;
2404 char temp1[128];
2405 char temp_output[128];
2406 char temp_TransmitRates[128];
2407 char set[128];
2408 char sub_set[128];
2409 int set_count=0,subset_count=0;
2410 int set_index=0,subset_index=0;
2411 char *token;
2412 int flag=0, i=0;
2413 struct params params={'\0'};
2414 char config_file[MAX_BUF_SIZE] = {0};
2415
2416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2417 if(NULL == TransmitRates)
2418 return RETURN_ERR;
2419 strcpy(sub_set,TransmitRates);
2420
2421 //Allow only supported Data transmit rate to be set
2422 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
2423 token = strtok(sub_set,",");
2424 while( token != NULL ) /* split the basic rate to be set, by comma */
2425 {
2426 sub_set[subset_count]=atoi(token);
2427 subset_count++;
2428 token=strtok(NULL,",");
2429 }
2430 token=strtok(set,",");
2431 while(token!=NULL) /* split the supported rate by comma */
2432 {
2433 set[set_count]=atoi(token);
2434 set_count++;
2435 token=strtok(NULL,",");
2436 }
2437 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
2438 {
2439 for(set_index=0;set_index < set_count;set_index++)
2440 {
2441 flag=0;
2442 if(sub_set[subset_index]==set[set_index])
2443 break;
2444 else
2445 flag=1; /* No match found */
2446 }
2447 if(flag==1)
2448 return RETURN_ERR; //If value not found return Error
2449 }
2450 strcpy(temp_TransmitRates,TransmitRates);
2451
2452 for(i=0;i<strlen(temp_TransmitRates);i++)
2453 {
2454 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
2455 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
2456 {
2457 continue;
2458 }
2459 else
2460 {
2461 return RETURN_ERR;
2462 }
2463 }
2464 strcpy(temp_output,"");
2465 temp = strtok(temp_TransmitRates,",");
2466 while(temp!=NULL)
2467 {
2468 strcpy(temp1,temp);
2469 if(radioIndex==1)
2470 {
2471 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
2472 {
2473 return RETURN_ERR;
2474 }
2475 }
2476
2477 if(strcmp(temp,"5.5")==0)
2478 {
2479 strcpy(temp1,"55");
2480 }
2481 else
2482 {
2483 strcat(temp1,"0");
2484 }
2485 strcat(temp_output,temp1);
2486 temp = strtok(NULL,",");
2487 if(temp!=NULL)
2488 {
2489 strcat(temp_output," ");
2490 }
2491 }
2492 strcpy(TransmitRates,temp_output);
2493
2494 params.name= "basic_rates";
2495 params.value =TransmitRates;
2496
2497 wifi_dbg_printf("\n%s:",__func__);
2498 wifi_dbg_printf("\nparams.value=%s\n",params.value);
2499 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
2500 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2501 wifi_hostapdWrite(config_file,&params,1);
2502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2503 return RETURN_OK;
2504}
2505
2506//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
2507INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
2508{
2509 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2510 FILE *fp = NULL;
2511 char path[256] = {0}, output_string[256] = {0};
2512 int count = 0;
2513 char *interface = NULL;
2514
2515 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
2516 if (fp == NULL)
2517 {
2518 printf("Failed to run command in Function %s\n", __FUNCTION__);
2519 return RETURN_ERR;
2520 }
2521 if (fgets(path, sizeof(path) - 1, fp) != NULL)
2522 {
2523 interface = strchr(path, '=');
2524
2525 if (interface != NULL)
2526 {
2527 strcpy(output_string, interface + 1);
2528 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
2529 interface_name[count] = output_string[count];
2530
2531 interface_name[count] = '\0';
2532 }
2533 }
2534 pclose(fp);
2535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2536 return RETURN_OK;
2537}
2538
2539INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
2540{
2541 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2542 output_struct->radio_BytesSent = 0;
2543 output_struct->radio_BytesReceived = 0;
2544 output_struct->radio_PacketsSent = 0;
2545 output_struct->radio_PacketsReceived = 0;
2546 output_struct->radio_ErrorsSent = 0;
2547 output_struct->radio_ErrorsReceived = 0;
2548 output_struct->radio_DiscardPacketsSent = 0;
2549 output_struct->radio_DiscardPacketsReceived = 0;
2550 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2551 return RETURN_OK;
2552}
2553
2554
2555INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
2556{
2557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2558 CHAR buf[MAX_CMD_SIZE] = {0};
2559 CHAR Value[MAX_BUF_SIZE] = {0};
2560 FILE *fp = NULL;
2561
2562 if (ifname == NULL || strlen(ifname) <= 1)
2563 return RETURN_OK;
2564
2565 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
2566 system(buf);
2567
2568 fp = fopen("/tmp/Radio_Stats.txt", "r");
2569 if(fp == NULL)
2570 {
2571 printf("/tmp/Radio_Stats.txt not exists \n");
2572 return RETURN_ERR;
2573 }
2574 fclose(fp);
2575
2576 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
2577 File_Reading(buf, Value);
2578 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
2579
2580 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
2581 File_Reading(buf, Value);
2582 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
2583
2584 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
2585 File_Reading(buf, Value);
2586 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
2587
2588 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
2589 File_Reading(buf, Value);
2590 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
2591
2592 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
2593 File_Reading(buf, Value);
2594 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
2595
2596 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
2597 File_Reading(buf, Value);
2598 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
2599
2600 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
2601 File_Reading(buf, Value);
2602 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
2603
2604 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
2605 File_Reading(buf, Value);
2606 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
2607
2608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2609 return RETURN_OK;
2610}
2611
2612INT GetIfacestatus(CHAR *interface_name, CHAR *status)
2613{
2614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2615 CHAR buf[MAX_CMD_SIZE] = {0};
2616 FILE *fp = NULL;
2617 INT count = 0;
2618
2619 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
2620 {
2621 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
2622 File_Reading(buf, status);
2623 }
2624 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2625 return RETURN_OK;
2626}
2627
2628//Get detail radio traffic static info
2629INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
2630{
2631
2632#if 0
2633 //ifconfig radio_x
2634 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
2635 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
2636 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
2637 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
2638
2639 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
2640 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
2641 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.
2642 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.
2643
2644 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
2645 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].
2646 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
2647 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.
2648 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
2649 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
2650 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
2651 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
2652 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
2653
2654 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
2655 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
2656 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
2657 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.
2658
2659 return RETURN_OK;
2660#endif
2661
2662 CHAR private_interface_name[MAX_BUF_SIZE] = {0}, public_interface_name[MAX_BUF_SIZE] = {0};
2663 CHAR private_interface_status[MAX_BUF_SIZE] = {0}, public_interface_status[MAX_BUF_SIZE] = {0};
2664 char buf[MAX_BUF_SIZE] = {0};
2665 char cmd[MAX_CMD_SIZE] = {0};
2666 wifi_radioTrafficStats2_t private_radioTrafficStats = {0}, public_radioTrafficStats = {0};
2667
2668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2669 if (NULL == output_struct)
2670 return RETURN_ERR;
2671
2672 if (radioIndex == 0) //2.4GHz ?
2673 {
2674
2675 GetInterfaceName(private_interface_name, "/nvram/hostapd0.conf");
2676
2677 GetIfacestatus(private_interface_name, private_interface_status);
2678
2679 sprintf(cmd, "%s", "cat /nvram/hostapd0.conf | grep bss=");
2680 File_Reading(cmd, buf);
2681
2682 if (buf[0] == '#')
2683 {
2684 GetInterfaceName(public_interface_name, "/nvram/hostapd4.conf");
2685 }
2686 else
2687 {
2688 GetInterfaceName_virtualInterfaceName_2G(public_interface_name);
2689 }
2690
2691 GetIfacestatus(public_interface_name, public_interface_status);
2692
2693 if (strcmp(private_interface_status, "1") == 0)
2694 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
2695 else
2696 wifi_halGetIfStatsNull(&private_radioTrafficStats);
2697
2698 if (strcmp(public_interface_status, "1") == 0)
2699 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
2700 else
2701 wifi_halGetIfStatsNull(&public_radioTrafficStats);
2702 }
2703 else if (radioIndex == 1) //5GHz ?
2704 {
2705 GetInterfaceName(private_interface_name, "/nvram/hostapd1.conf");
2706 GetIfacestatus(private_interface_name, private_interface_status);
2707
2708 GetInterfaceName(public_interface_name, "/nvram/hostapd5.conf");
2709 GetIfacestatus(public_interface_name, public_interface_status);
2710
2711 if (strcmp(private_interface_status, "1") == 0)
2712 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
2713 else
2714 wifi_halGetIfStatsNull(&private_radioTrafficStats);
2715
2716 if (strcmp(public_interface_status, "1") == 0)
2717 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
2718 else
2719 wifi_halGetIfStatsNull(&public_radioTrafficStats);
2720 }
2721
2722 output_struct->radio_BytesSent = private_radioTrafficStats.radio_BytesSent + public_radioTrafficStats.radio_BytesSent;
2723 output_struct->radio_BytesReceived = private_radioTrafficStats.radio_BytesReceived + public_radioTrafficStats.radio_BytesReceived;
2724 output_struct->radio_PacketsSent = private_radioTrafficStats.radio_PacketsSent + public_radioTrafficStats.radio_PacketsSent;
2725 output_struct->radio_PacketsReceived = private_radioTrafficStats.radio_PacketsReceived + public_radioTrafficStats.radio_PacketsReceived;
2726 output_struct->radio_ErrorsSent = private_radioTrafficStats.radio_ErrorsSent + public_radioTrafficStats.radio_ErrorsSent;
2727 output_struct->radio_ErrorsReceived = private_radioTrafficStats.radio_ErrorsReceived + public_radioTrafficStats.radio_ErrorsReceived;
2728 output_struct->radio_DiscardPacketsSent = private_radioTrafficStats.radio_DiscardPacketsSent + public_radioTrafficStats.radio_DiscardPacketsSent;
2729 output_struct->radio_DiscardPacketsReceived = private_radioTrafficStats.radio_DiscardPacketsReceived + public_radioTrafficStats.radio_DiscardPacketsReceived;
2730
2731 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
2732 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].
2733 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
2734 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.
2735 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
2736 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
2737 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
2738 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
2739 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
2740
2741 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
2742 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
2743 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
2744 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.
2745
2746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2747
2748 return RETURN_OK;
2749}
2750
2751//Set radio traffic static Measureing rules
2752INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
2753{
2754 //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
2755 // Else, save the MeasuringRate and MeasuringInterval for future usage
2756
2757 return RETURN_OK;
2758}
2759
2760//To start or stop RadioTrafficStats
2761INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
2762{
2763 //zqiu: If the RadioTrafficStats process running
2764 // if(enable)
2765 // return RETURN_OK.
2766 // else
2767 // Stop RadioTrafficStats process
2768 // Else
2769 // if(enable)
2770 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
2771 // else
2772 // return RETURN_OK.
2773
2774 return RETURN_OK;
2775}
2776
2777//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
2778INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
2779{
2780 //zqiu: Please ignor signalIndex.
2781 if (NULL == SignalLevel)
2782 return RETURN_ERR;
2783 *SignalLevel=(radioIndex==0)?-19:-19;
2784
2785 return RETURN_OK;
2786}
2787
2788//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
2789INT wifi_applyRadioSettings(INT radioIndex)
2790{
2791 return RETURN_OK;
2792}
2793
2794//Get the radio index assocated with this SSID entry
2795INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
2796{
2797 if (NULL == radioIndex)
2798 return RETURN_ERR;
2799 *radioIndex=ssidIndex%2;
2800
2801 return RETURN_OK;
2802}
2803
2804//Device.WiFi.SSID.{i}.Enable
2805//Get SSID enable configuration parameters (not the SSID enable status)
2806INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
2807{
2808 if (NULL == output_bool)
2809 return RETURN_ERR;
2810
2811 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
2812 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
2813 return wifi_getApEnable(ssidIndex, output_bool);
2814}
2815
2816//Device.WiFi.SSID.{i}.Enable
2817//Set SSID enable configuration parameters
2818INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
2819{
2820 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
2821 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
2822 return wifi_setApEnable(ssidIndex, enable);
2823}
2824
2825//Device.WiFi.SSID.{i}.Status
2826//Get the SSID enable status
2827INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
2828{
2829 char cmd[MAX_CMD_SIZE]={0};
2830 char buf[MAX_BUF_SIZE]={0};
2831 BOOL output_bool;
2832
2833 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2834 if (NULL == output_string)
2835 return RETURN_ERR;
2836 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
2837 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
2838
2839 wifi_getApEnable(ssidIndex,&output_bool);
2840 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
2841
2842 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2843 return RETURN_OK;
2844}
2845
2846// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
2847INT wifi_getSSIDName(INT apIndex, CHAR *output)
2848{
2849 char config_file[MAX_BUF_SIZE] = {0};
2850
2851 if (NULL == output)
2852 return RETURN_ERR;
2853
2854 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
2855 wifi_hostapdRead(config_file,"ssid",output,32);
2856
2857 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
2858 return RETURN_OK;
2859}
2860
2861// Set a max 32 byte string and sets an internal variable to the SSID name
2862INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
2863{
2864 char str[MAX_BUF_SIZE]={'\0'};
2865 char cmd[MAX_CMD_SIZE]={'\0'};
2866 struct params params;
2867 char config_file[MAX_BUF_SIZE] = {0};
2868
2869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2870 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
2871 return RETURN_ERR;
2872
2873 params.name = "ssid";
2874 params.value = ssid_string;
2875 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
2876 wifi_hostapdWrite(config_file, &params, 1);
2877 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2878 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2879
2880 return RETURN_OK;
2881}
2882
2883//Get the BSSID
2884INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
2885{
2886 char cmd[MAX_CMD_SIZE]="";
2887
2888 if (NULL == output_string)
2889 return RETURN_ERR;
2890
2891 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
2892 {
2893 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
2894 _syscmd(cmd, output_string, 64);
2895 return RETURN_OK;
2896 }
2897 strncpy(output_string, "\0", 1);
2898
2899 return RETURN_ERR;
2900}
2901
2902//Get the MAC address associated with this Wifi SSID
2903INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
2904{
2905 wifi_getBaseBSSID(ssidIndex,output_string);
2906 return RETURN_OK;
2907}
2908
2909//Get the basic SSID traffic static info
2910//Apply SSID and AP (in the case of Acess Point devices) to the hardware
2911//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
2912INT wifi_applySSIDSettings(INT ssidIndex)
2913{
2914 BOOL status = false;
2915 char cmd[MAX_CMD_SIZE] = {0};
2916 char buf[MAX_CMD_SIZE] = {0};
2917 int apIndex, ret;
2918 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
2919
2920 wifi_getApEnable(ssidIndex,&status);
2921 // Do not apply when ssid index is disabled
2922 if (status == false)
2923 return RETURN_OK;
2924
2925 /* Doing full remove and add for ssid Index
2926 * Not all hostapd options are supported with reload
2927 * for example macaddr_acl
2928 */
2929 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
2930 return RETURN_ERR;
2931
2932 ret = wifi_setApEnable(ssidIndex,true);
2933
2934 /* Workaround for hostapd issue with multiple bss definitions
2935 * when first created interface will be removed
2936 * then all vaps other vaps on same phy are removed
2937 * after calling setApEnable to false readd all enabled vaps */
2938 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
2939 apIndex = 2*i+radioIndex;
2940 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
2941 _syscmd(cmd, buf, sizeof(buf));
2942 if(*buf == '1')
2943 wifi_setApEnable(apIndex, true);
2944 }
2945
2946 return ret;
2947}
2948
2949//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
2950//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
2951INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
2952{
2953 INT status = RETURN_ERR;
2954 UINT index;
2955 wifi_neighbor_ap2_t *pt=NULL;
2956 char cmd[128]={0};
2957 char buf[8192]={0};
2958
2959 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2960 sprintf(cmd, "iwlist %s%d scan",AP_PREFIX,(radioIndex==0)?0:1); //suppose ap0 mapping to radio0
2961 _syscmd(cmd, buf, sizeof(buf));
2962
2963
2964 *output_array_size=2;
2965 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
2966 *neighbor_ap_array=(wifi_neighbor_ap2_t *)calloc(sizeof(wifi_neighbor_ap2_t), *output_array_size);
2967 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
2968 strcpy(pt->ap_SSID,"");
2969 strcpy(pt->ap_BSSID,"");
2970 strcpy(pt->ap_Mode,"");
2971 pt->ap_Channel=1;
2972 pt->ap_SignalStrength=0;
2973 strcpy(pt->ap_SecurityModeEnabled,"");
2974 strcpy(pt->ap_EncryptionMode,"");
2975 strcpy(pt->ap_OperatingFrequencyBand,"");
2976 strcpy(pt->ap_SupportedStandards,"");
2977 strcpy(pt->ap_OperatingStandards,"");
2978 strcpy(pt->ap_OperatingChannelBandwidth,"");
2979 pt->ap_BeaconPeriod=1;
2980 pt->ap_Noise=0;
2981 strcpy(pt->ap_BasicDataTransferRates,"");
2982 strcpy(pt->ap_SupportedDataTransferRates,"");
2983 pt->ap_DTIMPeriod=1;
2984 pt->ap_ChannelUtilization=0;
2985 }
2986
2987 status = RETURN_OK;
2988 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2989 return status;
2990}
2991
2992//>> Deprecated: used for old RDKB code.
2993INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
2994{
2995 INT status = RETURN_ERR;
2996
2997 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2998 output_struct->wifi_PLCPErrorCount = 0;
2999 output_struct->wifi_FCSErrorCount = 0;
3000 output_struct->wifi_InvalidMACCount = 0;
3001 output_struct->wifi_PacketsOtherReceived = 0;
3002 output_struct->wifi_Noise = 0;
3003 status = RETURN_OK;
3004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3005 return status;
3006}
3007
3008INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3009{
3010 char cmd[128];
3011 char buf[1280];
3012 char *pos = NULL;
3013
3014 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3015 if (NULL == output_struct)
3016 return RETURN_ERR;
3017
3018 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3019
3020 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3021 _syscmd(cmd, buf, sizeof(buf));
3022
3023 pos = buf;
3024 if ((pos = strstr(pos, "RX packets:")) == NULL)
3025 return RETURN_ERR;
3026 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3027
3028 if ((pos = strstr(pos, "TX packets:")) == NULL)
3029 return RETURN_ERR;
3030 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3031
3032 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3033 return RETURN_ERR;
3034 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3035
3036 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3037 return RETURN_ERR;
3038 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3039
3040 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3041 _syscmd(cmd, buf, sizeof(buf));
3042 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3043
3044#if 0
3045 //TODO: need to revisit below implementation
3046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3047 char interface_name[MAX_BUF_SIZE] = {0};
3048 char interface_status[MAX_BUF_SIZE] = {0};
3049 char Value[MAX_BUF_SIZE] = {0};
3050 char buf[MAX_CMD_SIZE] = {0};
3051 char cmd[MAX_CMD_SIZE] = {0};
3052 FILE *fp = NULL;
3053
3054 if (NULL == output_struct) {
3055 return RETURN_ERR;
3056 }
3057
3058 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3059
3060 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3061 {
3062 if(apIndex == 0) //private_wifi for 2.4G
3063 {
3064 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3065 }
3066 else if(apIndex == 1) //private_wifi for 5G
3067 {
3068 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3069 }
3070 else if(apIndex == 4) //public_wifi for 2.4G
3071 {
3072 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3073 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3074 {
3075 return RETURN_ERR;
3076 }
3077 if(buf[0] == '#')//tp-link
3078 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3079 else//tenda
3080 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3081 }
3082 else if(apIndex == 5) //public_wifi for 5G
3083 {
3084 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3085 }
3086
3087 GetIfacestatus(interface_name, interface_status);
3088
3089 if(0 != strcmp(interface_status, "1"))
3090 return RETURN_ERR;
3091
3092 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3093 system(cmd);
3094
3095 fp = fopen("/tmp/SSID_Stats.txt", "r");
3096 if(fp == NULL)
3097 {
3098 printf("/tmp/SSID_Stats.txt not exists \n");
3099 return RETURN_ERR;
3100 }
3101 fclose(fp);
3102
3103 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3104 File_Reading(buf, Value);
3105 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3106
3107 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3108 File_Reading(buf, Value);
3109 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3110
3111 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3112 File_Reading(buf, Value);
3113 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3114
3115 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3116 File_Reading(buf, Value);
3117 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3118
3119 /* There is no specific parameter from caller to associate the value wifi_Associations */
3120 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3121 //_syscmd(cmd, buf, sizeof(buf));
3122 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3123 }
3124#endif
3125 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3126 return RETURN_OK;
3127}
3128
3129INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3130{
3131 char interface_name[MAX_BUF_SIZE] = {0};
3132 char interface_status[MAX_BUF_SIZE] = {0};
3133 char Value[MAX_BUF_SIZE] = {0};
3134 char buf[MAX_CMD_SIZE] = {0};
3135 char cmd[MAX_CMD_SIZE] = {0};
3136 FILE *fp = NULL;
3137
3138 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3139 if (NULL == output_struct)
3140 return RETURN_ERR;
3141
3142 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3143
3144 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3145 {
3146 if(apIndex == 0) //private_wifi for 2.4G
3147 {
3148 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3149 }
3150 else if(apIndex == 1) //private_wifi for 5G
3151 {
3152 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3153 }
3154 else if(apIndex == 4) //public_wifi for 2.4G
3155 {
3156 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3157 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3158 {
3159 return RETURN_ERR;
3160 }
3161 if(buf[0] == '#')
3162 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3163 else
3164 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3165 }
3166 else if(apIndex == 5) //public_wifi for 5G
3167 {
3168 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3169 }
3170
3171 GetIfacestatus(interface_name, interface_status);
3172
3173 if(0 != strcmp(interface_status, "1"))
3174 return RETURN_ERR;
3175
3176 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3177 system(cmd);
3178
3179 fp = fopen("/tmp/SSID_Stats.txt", "r");
3180 if(fp == NULL)
3181 {
3182 printf("/tmp/SSID_Stats.txt not exists \n");
3183 return RETURN_ERR;
3184 }
3185 fclose(fp);
3186
3187 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3188 File_Reading(buf, Value);
3189 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
3190
3191 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3192 File_Reading(buf, Value);
3193 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
3194
3195 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3196 File_Reading(buf, Value);
3197 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
3198
3199 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3200 File_Reading(buf, Value);
3201 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
3202 }
3203
3204 output_struct->wifi_UnicastPacketsSent = 0;
3205 output_struct->wifi_UnicastPacketsReceived = 0;
3206 output_struct->wifi_MulticastPacketsSent = 0;
3207 output_struct->wifi_MulticastPacketsReceived = 0;
3208 output_struct->wifi_BroadcastPacketsSent = 0;
3209 output_struct->wifi_BroadcastPacketsRecevied = 0;
3210 output_struct->wifi_UnknownPacketsReceived = 0;
3211
3212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3213 return RETURN_OK;
3214}
3215
3216INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
3217{
3218 INT status = RETURN_ERR;
3219
3220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3221 //Below values should get updated from hal
3222 output_struct->wifi_RetransCount=0;
3223 output_struct->wifi_FailedRetransCount=0;
3224 output_struct->wifi_RetryCount=0;
3225 output_struct->wifi_MultipleRetryCount=0;
3226 output_struct->wifi_ACKFailureCount=0;
3227 output_struct->wifi_AggregatedPacketCount=0;
3228
3229 status = RETURN_OK;
3230 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3231
3232 return status;
3233}
3234
3235INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
3236{
3237 INT status = RETURN_ERR;
3238 UINT index;
3239 wifi_neighbor_ap_t *pt=NULL;
3240
3241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3242 *output_array_size=2;
3243 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
3244 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
3245 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
3246 strcpy(pt->ap_Radio,"");
3247 strcpy(pt->ap_SSID,"");
3248 strcpy(pt->ap_BSSID,"");
3249 strcpy(pt->ap_Mode,"");
3250 pt->ap_Channel=1;
3251 pt->ap_SignalStrength=0;
3252 strcpy(pt->ap_SecurityModeEnabled,"");
3253 strcpy(pt->ap_EncryptionMode,"");
3254 strcpy(pt->ap_OperatingFrequencyBand,"");
3255 strcpy(pt->ap_SupportedStandards,"");
3256 strcpy(pt->ap_OperatingStandards,"");
3257 strcpy(pt->ap_OperatingChannelBandwidth,"");
3258 pt->ap_BeaconPeriod=1;
3259 pt->ap_Noise=0;
3260 strcpy(pt->ap_BasicDataTransferRates,"");
3261 strcpy(pt->ap_SupportedDataTransferRates,"");
3262 pt->ap_DTIMPeriod=1;
3263 pt->ap_ChannelUtilization = 1;
3264 }
3265
3266 status = RETURN_OK;
3267 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3268
3269 return status;
3270}
3271
3272//----------------- AP HAL -------------------------------
3273
3274//>> Deprecated: used for old RDKB code.
3275INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
3276{
3277 if (NULL == output_ulong || NULL == output_struct)
3278 return RETURN_ERR;
3279 *output_ulong = 0;
3280 *output_struct = NULL;
3281 return RETURN_OK;
3282}
3283
3284#ifdef HAL_NETLINK_IMPL
3285static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
3286 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3287 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3288 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
3289 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
3290 char mac_addr[20];
3291 static int count=0;
3292 int rate=0;
3293
3294 wifi_device_info_t *out = (wifi_device_info_t*)arg;
3295
3296 nla_parse(tb,
3297 NL80211_ATTR_MAX,
3298 genlmsg_attrdata(gnlh, 0),
3299 genlmsg_attrlen(gnlh, 0),
3300 NULL);
3301
3302 if(!tb[NL80211_ATTR_STA_INFO]) {
3303 fprintf(stderr, "sta stats missing!\n");
3304 return NL_SKIP;
3305 }
3306
3307
3308 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
3309 fprintf(stderr, "failed to parse nested attributes!\n");
3310 return NL_SKIP;
3311 }
3312
3313 //devIndex starts from 1
3314 if( ++count == out->wifi_devIndex )
3315 {
3316 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
3317 //Getting the mac addrress
3318 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
3319
3320 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
3321 fprintf(stderr, "failed to parse nested rate attributes!");
3322 return NL_SKIP;
3323 }
3324
3325 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
3326 if(rinfo[NL80211_RATE_INFO_BITRATE])
3327 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
3328 out->wifi_devTxRate = rate/10;
3329 }
3330
3331 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
3332 fprintf(stderr, "failed to parse nested rate attributes!");
3333 return NL_SKIP;
3334 }
3335
3336 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
3337 if(rinfo[NL80211_RATE_INFO_BITRATE])
3338 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
3339 out->wifi_devRxRate = rate/10;
3340 }
3341 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
3342 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
3343
3344 out->wifi_devAssociatedDeviceAuthentiationState = 1;
3345 count = 0; //starts the count for next cycle
3346 return NL_STOP;
3347 }
3348
3349 return NL_SKIP;
3350
3351}
3352#endif
3353
3354INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
3355{
3356#ifdef HAL_NETLINK_IMPL
3357 Netlink nl;
3358 char if_name[10];
3359
3360 wifi_device_info_t info;
3361 info.wifi_devIndex = devIndex;
3362
3363 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
3364
3365 nl.id = initSock80211(&nl);
3366
3367 if (nl.id < 0) {
3368 fprintf(stderr, "Error initializing netlink \n");
3369 return -1;
3370 }
3371
3372 struct nl_msg* msg = nlmsg_alloc();
3373
3374 if (!msg) {
3375 fprintf(stderr, "Failed to allocate netlink message.\n");
3376 nlfree(&nl);
3377 return -2;
3378 }
3379
3380 genlmsg_put(msg,
3381 NL_AUTO_PORT,
3382 NL_AUTO_SEQ,
3383 nl.id,
3384 0,
3385 NLM_F_DUMP,
3386 NL80211_CMD_GET_STATION,
3387 0);
3388
3389 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
3390 nl_send_auto(nl.socket, msg);
3391 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
3392 nl_recvmsgs(nl.socket, nl.cb);
3393 nlmsg_free(msg);
3394 nlfree(&nl);
3395
3396 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
3397 output_struct->wifi_devRxRate = info.wifi_devRxRate;
3398 output_struct->wifi_devTxRate = info.wifi_devTxRate;
3399 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
3400 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
3401 return RETURN_OK;
3402#else
3403 //iw utility to retrieve station information
3404#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
3405#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
3406#define MACFILE "/tmp/wifi_AssoMac.txt"
3407#define TXRATEFILE "/tmp/wifi_txrate.txt"
3408#define RXRATEFILE "/tmp/wifi_rxrate.txt"
3409 FILE *file = NULL;
3410 char if_name[10] = {'\0'};
3411 char pipeCmd[256] = {'\0'};
3412 char line[256];
3413 int count,device = 0;
3414
3415 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
3416
3417 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
3418 file = popen(pipeCmd, "r");
3419
3420 if(file == NULL)
3421 return RETURN_ERR; //popen failed
3422
3423 fgets(line, sizeof line, file);
3424 device = atoi(line);
3425 pclose(file);
3426
3427 if(device == 0)
3428 return RETURN_ERR; //No devices are connected
3429
3430 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
3431 system(pipeCmd);
3432
3433 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
3434
3435 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
3436
3437 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
3438
3439 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
3440
3441 //devIndex starts from 1, ++count
3442 if((file = fopen(SIGNALFILE, "r")) != NULL )
3443 {
3444 for(count =0;fgets(line, sizeof line, file) != NULL;)
3445 {
3446 if (++count == devIndex)
3447 {
3448 output_struct->wifi_devSignalStrength = atoi(line);
3449 break;
3450 }
3451 }
3452 fclose(file);
3453 }
3454 else
3455 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
3456
3457 if((file = fopen(MACFILE, "r")) != NULL )
3458 {
3459 for(count =0;fgets(line, sizeof line, file) != NULL;)
3460 {
3461 if (++count == devIndex)
3462 {
3463 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]);
3464 break;
3465 }
3466 }
3467 fclose(file);
3468 }
3469 else
3470 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
3471
3472 if((file = fopen(TXRATEFILE, "r")) != NULL )
3473 {
3474 for(count =0;fgets(line, sizeof line, file) != NULL;)
3475 {
3476 if (++count == devIndex)
3477 {
3478 output_struct->wifi_devTxRate = atoi(line);
3479 break;
3480 }
3481 }
3482 fclose(file);
3483 }
3484 else
3485 fprintf(stderr,"fopen wifi_txrate.txt failed");
3486
3487 if((file = fopen(RXRATEFILE, "r")) != NULL)
3488 {
3489 for(count =0;fgets(line, sizeof line, file) != NULL;)
3490 {
3491 if (++count == devIndex)
3492 {
3493 output_struct->wifi_devRxRate = atoi(line);
3494 break;
3495 }
3496 }
3497 fclose(file);
3498 }
3499 else
3500 fprintf(stderr,"fopen wifi_rxrate.txt failed");
3501
3502 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
3503
3504 return RETURN_OK;
3505#endif
3506}
3507
3508INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
3509{
3510 if (NULL == device)
3511 return RETURN_ERR;
3512 return RETURN_OK;
3513}
3514//<<
3515
3516
3517//--------------wifi_ap_hal-----------------------------
3518//enables CTS protection for the radio used by this AP
3519INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
3520{
3521 //save config and Apply instantly
3522 return RETURN_ERR;
3523}
3524
3525// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
3526INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
3527{
3528 //save config and Apply instantly
3529 return RETURN_ERR;
3530}
3531
3532//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
3533INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
3534{
3535 char cmd[64];
3536 char buf[512];
3537 //save config and apply instantly
3538
3539 //zqiu:TODO: save config
3540 if (threshold > 0) {
3541 snprintf(cmd, sizeof(cmd), "iwconfig %s%d frag %d", AP_PREFIX, apIndex, threshold);
3542 } else {
3543 snprintf(cmd, sizeof(cmd), "iwconfig %s%d frag off", AP_PREFIX, apIndex );
3544 }
3545 _syscmd(cmd,buf, sizeof(buf));
3546
3547 return RETURN_OK;
3548}
3549
3550// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
3551INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
3552{
3553 //Save config and Apply instantly
3554 return RETURN_ERR;
3555}
3556
3557// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
3558INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
3559{
3560 return RETURN_ERR;
3561}
3562
3563// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
3564INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
3565{
3566 //Apply instantly
3567 return RETURN_ERR;
3568}
3569
3570//P2 // outputs the number of Tx streams
3571INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
3572{
3573 return RETURN_ERR;
3574}
3575
3576//P2 // sets the number of Tx streams to an enviornment variable
3577INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
3578{
3579 //save to wifi config, wait for wifi reset or wifi_pushTxChainMask to apply
3580 return RETURN_ERR;
3581}
3582
3583//P2 // outputs the number of Rx streams
3584INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
3585{
3586 if (NULL == output_int)
3587 return RETURN_ERR;
3588 *output_int = 1;
3589 return RETURN_OK;
3590}
3591
3592//P2 // sets the number of Rx streams to an enviornment variable
3593INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
3594{
3595 //save to wifi config, wait for wifi reset or wifi_pushRxChainMask to apply
3596 return RETURN_ERR;
3597}
3598
3599//Get radio RDG enable setting
3600INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
3601{
3602 if (NULL == output_bool)
3603 return RETURN_ERR;
3604 *output_bool = TRUE;
3605 return RETURN_OK;
3606}
3607
3608//Get radio RDG enable setting
3609INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
3610{
3611 if (NULL == output_bool)
3612 return RETURN_ERR;
3613 *output_bool = TRUE;
3614 return RETURN_OK;
3615}
3616
3617//Set radio RDG enable setting
3618INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
3619{
3620 return RETURN_ERR;
3621}
3622
3623//Get radio ADDBA enable setting
3624INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
3625{
3626 if (NULL == output_bool)
3627 return RETURN_ERR;
3628 *output_bool = TRUE;
3629 return RETURN_OK;
3630}
3631
3632//Set radio ADDBA enable setting
3633INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
3634{
3635 return RETURN_ERR;
3636}
3637
3638//Get radio auto block ack enable setting
3639INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
3640{
3641 if (NULL == output_bool)
3642 return RETURN_ERR;
3643 *output_bool = TRUE;
3644 return RETURN_OK;
3645}
3646
3647//Set radio auto block ack enable setting
3648INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
3649{
3650 return RETURN_ERR;
3651}
3652
3653//Get radio 11n pure mode enable support
3654INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
3655{
3656 if (NULL == output_bool)
3657 return RETURN_ERR;
3658 *output_bool = TRUE;
3659 return RETURN_OK;
3660}
3661
3662//Get radio 11n pure mode enable setting
3663INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
3664{
3665 if (NULL == output_bool)
3666 return RETURN_ERR;
3667 *output_bool = TRUE;
3668 return RETURN_OK;
3669}
3670
3671//Set radio 11n pure mode enable setting
3672INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
3673{
3674 return RETURN_ERR;
3675}
3676
3677//Get radio IGMP snooping enable setting
3678INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
3679{
3680 if (NULL == output_bool)
3681 return RETURN_ERR;
3682 *output_bool = TRUE;
3683 return RETURN_OK;
3684}
3685
3686//Set radio IGMP snooping enable setting
3687INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
3688{
3689 return RETURN_ERR;
3690}
3691
3692//Get the Reset count of radio
3693INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
3694{
3695 if (NULL == output_int)
3696 return RETURN_ERR;
3697 *output_int = (radioIndex==0)? 1: 3;
3698
3699 return RETURN_OK;
3700}
3701
3702
3703//---------------------------------------------------------------------------------------------------
3704//
3705// Additional Wifi AP level APIs used for Access Point devices
3706//
3707//---------------------------------------------------------------------------------------------------
3708
3709// creates a new ap and pushes these parameters to the hardware
3710INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
3711{
3712 char buf[1024];
3713 char cmd[128];
3714
3715 if (NULL == essid)
3716 return RETURN_ERR;
3717
3718 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
3719 _syscmd(cmd, buf, sizeof(buf));
3720
3721 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
3722 _syscmd(cmd, buf, sizeof(buf));
3723
3724 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
3725
3726 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
3727 _syscmd(cmd, buf, sizeof(buf));
3728
3729 return RETURN_OK;
3730}
3731
3732// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
3733INT wifi_deleteAp(INT apIndex)
3734{
3735 char buf[1024];
3736 char cmd[128];
3737
3738 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
3739 _syscmd(cmd, buf, sizeof(buf));
3740
3741 wifi_removeApSecVaribles(apIndex);
3742
3743 return RETURN_OK;
3744}
3745
3746// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
3747INT wifi_getApName(INT apIndex, CHAR *output_string)
3748{
3749 if(NULL == output_string)
3750 return RETURN_ERR;
3751
3752 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
3753 return RETURN_OK;
3754}
3755
3756// Outputs the index number in that corresponds to the SSID string
3757INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
3758{
3759 CHAR *pos = NULL;
3760
3761 *output_int = -1;
3762 pos = strstr(inputSsidString, AP_PREFIX);
3763 if(pos)
3764 {
3765 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
3766 return RETURN_OK;
3767 }
3768 return RETURN_ERR;
3769}
3770
3771INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
3772{
3773 return wifi_getIndexFromName(inputSsidString, output_int);
3774}
3775
3776// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
3777INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
3778{
3779 char buf[MAX_BUF_SIZE] = {0};
3780 char cmd[MAX_CMD_SIZE] = {0};
3781 char config_file[MAX_BUF_SIZE] = {0};
3782
3783 if(NULL == output_string)
3784 return RETURN_ERR;
3785
3786 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3787 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
3788 if((strcmp(buf,"3")==0))
3789 snprintf(output_string, 32, "WPAand11i");
3790 else if((strcmp(buf,"2")==0))
3791 snprintf(output_string, 32, "11i");
3792 else if((strcmp(buf,"1")==0))
3793 snprintf(output_string, 32, "WPA");
3794 else
3795 snprintf(output_string, 32, "None");
3796
3797 return RETURN_OK;
3798}
3799
3800// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
3801INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
3802{
3803 char config_file[MAX_BUF_SIZE] = {0};
3804 struct params list;
3805
3806 if (NULL == beaconTypeString)
3807 return RETURN_ERR;
3808 list.name = "wpa";
3809 list.value = "0";
3810
3811 if((strcmp(beaconTypeString,"WPAand11i")==0))
3812 list.value="3";
3813 else if((strcmp(beaconTypeString,"11i")==0))
3814 list.value="2";
3815 else if((strcmp(beaconTypeString,"WPA")==0))
3816 list.value="1";
3817
3818 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3819 wifi_hostapdWrite(config_file, &list, 1);
3820 wifi_hostapdProcessUpdate(apIndex, &list, 1);
3821 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
3822 return RETURN_OK;
3823}
3824
3825// sets the beacon interval on the hardware for this AP
3826INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
3827{
3828 //save config and apply instantly
3829 return RETURN_ERR;
3830}
3831
3832INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
3833{
3834 //save config and apply instantly
3835 return RETURN_ERR;
3836}
3837
3838// Get the packet size threshold supported.
3839INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
3840{
3841 //save config and apply instantly
3842 if (NULL == output_bool)
3843 return RETURN_ERR;
3844 *output_bool = FALSE;
3845 return RETURN_OK;
3846}
3847
3848// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
3849INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
3850{
3851 char cmd[128];
3852 char buf[512];
3853
3854 if (threshold > 0)
3855 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
3856 else
3857 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
3858 _syscmd(cmd, buf, sizeof(buf));
3859
3860 return RETURN_OK;
3861}
3862
3863// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
3864INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
3865{
3866 if (NULL == output_string)
3867 return RETURN_ERR;
3868 snprintf(output_string, 32, "TKIPandAESEncryption");
3869 return RETURN_OK;
3870
3871}
3872
3873// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
3874INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
3875{
3876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3877 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
3878
3879 if(NULL == output_string)
3880 return RETURN_ERR;
3881
3882 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3883 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
3884
3885 if(strcmp(buf,"0")==0)
3886 {
3887 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
3888 snprintf(output_string, 32, "None");
3889 return RETURN_OK;
3890 }
3891 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
3892 param_name = "rsn_pairwise";
3893 else if((strcmp(buf,"1")==0))
3894 param_name = "wpa_pairwise";
3895 else
3896 return RETURN_ERR;
3897 memset(output_string,'\0',32);
3898 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3899 wifi_hostapdRead(config_file,param_name,output_string,32);
3900 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
3901
3902 if(strcmp(output_string,"TKIP") == 0)
3903 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
3904 else if(strcmp(output_string,"CCMP") == 0)
3905 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
3906 else if(strcmp(output_string,"TKIP CCMP") == 0)
3907 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
3908
3909 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3910 return RETURN_OK;
3911}
3912
3913// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
3914INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
3915{
3916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3917 struct params params={'\0'};
3918 char output_string[32];
3919 char config_file[MAX_BUF_SIZE] = {0};
3920
3921 memset(output_string,'\0',32);
3922 wifi_getApWpaEncryptionMode(apIndex,output_string);
3923
3924 if(strcmp(encMode, "TKIPEncryption") == 0)
3925 params.value = "TKIP";
3926 else if(strcmp(encMode,"AESEncryption") == 0)
3927 params.value = "CCMP";
3928 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
3929 params.value = "TKIP CCMP";
3930
3931 if((strcmp(output_string,"WPAand11i")==0))
3932 {
3933 params.name = "wpa_pairwise";
3934 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3935 wifi_hostapdWrite(config_file, &params, 1);
3936 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3937
3938 params.name,"rsn_pairwise";
3939 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3940 wifi_hostapdWrite(config_file, &params, 1);
3941 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3942
3943 return RETURN_OK;
3944 }
3945 else if((strcmp(output_string,"11i")==0))
3946 {
3947 params.name = "rsn_pairwise";
3948 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3949 wifi_hostapdWrite(config_file, &params, 1);
3950 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3951 return RETURN_OK;
3952 }
3953 else if((strcmp(output_string,"WPA")==0))
3954 {
3955 params.name = "wpa_pairwise";
3956 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3957 wifi_hostapdWrite(config_file, &params, 1);
3958 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3959 return RETURN_OK;
3960 }
3961
3962 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3963 return RETURN_OK;
3964}
3965
3966// deletes internal security varable settings for this ap
3967INT wifi_removeApSecVaribles(INT apIndex)
3968{
3969 //TODO: remove the entry in hostapd config file
3970 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
3971 //_syscmd(cmd, buf, sizeof(buf));
3972
3973 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
3974 //_syscmd(cmd, buf, sizeof(buf));
3975 return RETURN_ERR;
3976}
3977
3978// changes the hardware settings to disable encryption on this ap
3979INT wifi_disableApEncryption(INT apIndex)
3980{
3981 //Apply instantly
3982 return RETURN_ERR;
3983}
3984
3985// set the authorization mode on this ap
3986// mode mapping as: 1: open, 2: shared, 4:auto
3987INT wifi_setApAuthMode(INT apIndex, INT mode)
3988{
3989 //Apply instantly
3990 return RETURN_ERR;
3991}
3992
3993// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
3994INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
3995{
3996 //save to wifi config, and wait for wifi restart to apply
3997 struct params params={'\0'};
3998 char config_file[MAX_BUF_SIZE] = {0};
3999 int ret;
4000
4001 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4002 if(authMode == NULL)
4003 return RETURN_ERR;
4004
4005 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
4006 params.name = "wpa_key_mgmt";
4007
4008 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
4009 params.value = "WPA-PSK";
4010 else if(strcmp(authMode,"EAPAuthentication") == 0)
4011 params.value = "WPA-EAP";
4012 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
4013 return RETURN_OK; //This is taken careof in beaconType
4014
4015 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4016 ret=wifi_hostapdWrite(config_file,&params,1);
4017 if(!ret)
4018 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
4019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4020
4021 return ret;
4022}
4023
4024// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4025INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4026{
4027 //save to wifi config, and wait for wifi restart to apply
4028 char BeaconType[50] = {0};
4029 char config_file[MAX_BUF_SIZE] = {0};
4030
4031 *authMode = 0;
4032 wifi_getApBeaconType(apIndex,BeaconType);
4033 printf("%s____%s \n",__FUNCTION__,BeaconType);
4034
4035 if(strcmp(BeaconType,"None") == 0)
4036 strcpy(authMode,"None");
4037 else
4038 {
4039 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4040 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
4041 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
4042 if(strcmp(authMode,"WPA-PSK") == 0)
4043 strcpy(authMode,"SharedAuthentication");
4044 else if(strcmp(authMode,"WPA-EAP") == 0)
4045 strcpy(authMode,"EAPAuthentication");
4046 }
4047
4048 return RETURN_OK;
4049}
4050
4051// Outputs the number of stations associated per AP
4052INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
4053{
4054 char cmd[128]={0};
4055 char buf[128]={0};
4056 BOOL status = false;
4057
4058 if(apIndex > MAX_APS)
4059 return RETURN_ERR;
4060
4061 wifi_getApEnable(apIndex,&status);
4062 if (!status)
4063 return RETURN_OK;
4064
4065 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
4066 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
4067 _syscmd(cmd, buf, sizeof(buf));
4068 sscanf(buf,"%lu", output_ulong);
4069
4070 return RETURN_OK;
4071}
4072
4073// manually removes any active wi-fi association with the device specified on this ap
4074INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
4075{
4076 char buf[126]={'\0'};
4077
4078 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
4079 system(buf);
4080
4081 return RETURN_OK;
4082}
4083
4084// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
4085INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
4086{
4087 if(NULL == output_int)
4088 return RETURN_ERR;
4089 *output_int = apIndex%2;
4090 return RETURN_OK;
4091}
4092
4093// sets the radio index for the specific ap
4094INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
4095{
4096 //set to config only and wait for wifi reset to apply settings
4097 return RETURN_ERR;
4098}
4099
4100// Get the ACL MAC list per AP
4101INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4102{
4103 char cmd[MAX_CMD_SIZE]={'\0'};
4104 int ret = 0;
4105
4106 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4107 ret = _syscmd(cmd,macArray,buf_size);
4108 if (ret != 0)
4109 return RETURN_ERR;
4110
4111 return RETURN_OK;
4112}
4113
developere6aafda2022-09-13 14:59:28 +08004114INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4115{
4116 char cmd[MAX_CMD_SIZE]={'\0'};
4117 int ret = 0;
4118
4119 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4120 ret = _syscmd(cmd,macArray,buf_size);
4121 if (ret != 0)
4122 return RETURN_ERR;
4123
4124 return RETURN_OK;
4125}
4126
4127
developer06a01d92022-09-07 16:32:39 +08004128// Get the list of stations associated per AP
4129INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
4130{
4131 char cmd[128];
4132
4133 if(apIndex > 3) //Currently supporting apIndex upto 3
4134 return RETURN_ERR;
4135 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
4136 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
4137 _syscmd(cmd, macArray, buf_size);
4138
4139 return RETURN_OK;
4140}
4141
4142// adds the mac address to the filter list
4143//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4144INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4145{
4146 char cmd[MAX_CMD_SIZE]={'\0'};
4147 char buf[MAX_BUF_SIZE]={'\0'};
4148
4149#if 0
4150 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
4151 if(_syscmd(cmd,buf,sizeof(buf)))
4152 return RETURN_ERR;
4153#endif
4154 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
4155 if(_syscmd(cmd,buf,sizeof(buf)))
4156 return RETURN_ERR;
4157
4158 return RETURN_OK;
4159}
4160
4161// deletes the mac address from the filter list
4162//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4163INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4164{
4165 char cmd[MAX_CMD_SIZE]={'\0'};
4166 char buf[MAX_BUF_SIZE]={'\0'};
4167
4168#if 0
4169 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
4170 if(_syscmd(cmd,buf,sizeof(buf)))
4171 return RETURN_ERR;
4172
4173#endif
4174 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
4175 if(_syscmd(cmd,buf,sizeof(buf)))
4176 return RETURN_ERR;
4177
4178 return RETURN_OK;
4179}
4180
4181// outputs the number of devices in the filter list
4182INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
4183{
developere6aafda2022-09-13 14:59:28 +08004184 char cmd[MAX_BUF_SIZE]={0};
4185 char buf[MAX_CMD_SIZE]={0};
4186
4187 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4188 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08004189 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08004190
4191 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
4192 _syscmd(cmd, buf, sizeof(buf));
4193
4194 *output_uint = atoi(buf);
4195
4196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4197 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004198}
4199
4200INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
4201{
4202 char cmd[128]={'\0'};
4203 char buf[128]={'\0'};
4204
4205 if(strcmp(action,"DENY")==0)
4206 {
4207 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
4208 system(buf);
4209 return RETURN_OK;
4210 }
4211
4212 if(strcmp(action,"ALLOW")==0)
4213 {
4214 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
4215 system(buf);
4216 return RETURN_OK;
4217 }
4218
4219 return RETURN_ERR;
4220
4221}
4222
4223// enable kick for devices on acl black list
4224INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
4225{
4226 char aclArray[512] = {0}, *acl = NULL;
4227 char assocArray[512] = {0}, *asso = NULL;
4228
developere6aafda2022-09-13 14:59:28 +08004229 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08004230 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
4231
4232 // if there are no devices connected there is nothing to do
4233 if (strlen(assocArray) < 17)
4234 return RETURN_OK;
4235
4236 if (enable == TRUE)
4237 {
4238 //kick off the MAC which is in ACL array (deny list)
4239 acl = strtok(aclArray, "\r\n");
4240 while (acl != NULL) {
4241 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
4242 wifi_kickApAssociatedDevice(apIndex, acl);
4243
4244 acl = strtok(NULL, "\r\n");
4245 }
developere6aafda2022-09-13 14:59:28 +08004246 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08004247 }
4248 else
4249 {
developere6aafda2022-09-13 14:59:28 +08004250 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08004251 }
4252
4253#if 0
4254 //TODO: need to revisit below implementation
4255 char aclArray[512]={0}, *acl=NULL;
4256 char assocArray[512]={0}, *asso=NULL;
4257 char buf[256]={'\0'};
4258 char action[10]={'\0'};
4259 FILE *fr=NULL;
4260 char interface[10]={'\0'};
4261 char config_file[MAX_BUF_SIZE] = {0};
4262
4263 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
4264 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
4265 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4266 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
4267
4268 sprintf(buf,"iptables -F WifiServices%d",apIndex);
4269 system(buf);
4270 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
4271 system(buf);
4272 sprintf(buf,"iptables -X WifiServices%d",apIndex);
4273 system(buf);
4274 sprintf(buf,"iptables -N WifiServices%d",apIndex);
4275 system(buf);
4276 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
4277 system(buf);
4278
4279 if ( enable == TRUE )
4280 {
4281 int device_count=0;
4282 strcpy(action,"DENY");
4283 //kick off the MAC which is in ACL array (deny list)
4284 acl = strtok (aclArray,",");
4285 while (acl != NULL) {
4286 if(strlen(acl)>=17)
4287 {
4288 apply_rules(apIndex, acl,action,interface);
4289 device_count++;
4290 //Register mac to be blocked ,in syscfg.db persistent storage
4291 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
4292 system(buf);
4293 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
4294 system(buf);
4295 system("syscfg commit");
4296
4297 wifi_kickApAssociatedDevice(apIndex, acl);
4298 }
4299 acl = strtok (NULL, ",");
4300 }
4301 }
4302 else
4303 {
4304 int device_count=0;
4305 char cmdmac[20]={'\0'};
4306 strcpy(action,"ALLOW");
4307 //kick off the MAC which is not in ACL array (allow list)
4308 acl = strtok (aclArray,",");
4309 while (acl != NULL) {
4310 if(strlen(acl)>=17)
4311 {
4312 apply_rules(apIndex, acl,action,interface);
4313 device_count++;
4314 //Register mac to be Allowed ,in syscfg.db persistent storage
4315 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
4316 system(buf);
4317 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
4318 system(buf);
4319 sprintf(cmdmac,"%s",acl);
4320 }
4321 acl = strtok (NULL, ",");
4322 }
4323 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
4324 system(buf);
4325
4326 //Disconnect the mac which is not in ACL
4327 asso = strtok (assocArray,",");
4328 while (asso != NULL) {
4329 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
4330 wifi_kickApAssociatedDevice(apIndex, asso);
4331 asso = strtok (NULL, ",");
4332 }
4333 }
4334#endif
4335 return RETURN_OK;
4336}
4337
4338INT wifi_setPreferPrivateConnection(BOOL enable)
4339{
4340 char interface_name[100] = {0},ssid_cur_value[50] = {0};
4341 char buf[1024] = {0};
4342
4343 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
4344 if(enable == TRUE)
4345 {
4346 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4347 sprintf(buf,"ifconfig %s down" ,interface_name);
4348 system(buf);
4349 memset(buf,0,sizeof(buf));
4350 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4351 sprintf(buf,"ifconfig %s down" ,interface_name);
4352 system(buf);
4353 }
4354 else
4355 {
4356 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
4357 if(strcmp(ssid_cur_value,"1") == 0)
4358 wifi_RestartPrivateWifi_5G();
4359 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
4360 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
4361 if(strcmp(ssid_cur_value,"1") == 0)
4362 wifi_RestartHostapd_2G();
4363 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
4364 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
4365 if(strcmp(ssid_cur_value,"1") == 0)
4366 wifi_RestartHostapd_5G();
4367 }
4368 return RETURN_OK;
4369}
4370
4371// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
4372INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
4373{
4374 int items = 1;
4375 struct params list[2];
4376 char buf[MAX_BUF_SIZE] = {0};
4377 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08004378 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08004379
4380 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08004381
developer10adcc12022-09-13 14:39:17 +08004382 if (filterMode == 0) {
4383 sprintf(buf, "%d", 0);
4384 list[0].value = buf;
4385
4386 char cmd[128], rtn[128];
4387 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
4388 _syscmd(cmd, rtn, sizeof(rtn));
4389 memset(cmd,0,sizeof(cmd));
4390 // Delete deny_mac_file in hostapd configuration
4391 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
4392 _syscmd(cmd, rtn, sizeof(rtn));
4393 }
4394 else if (filterMode == 1) {
4395 sprintf(buf, "%d", filterMode);
4396 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08004397 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
4398 list[1].name = "accept_mac_file";
4399 list[1].value = acl_file;
4400 items = 2;
developer10adcc12022-09-13 14:39:17 +08004401 } else if (filterMode == 2) {
4402 //TODO: deny_mac_file
4403 sprintf(buf, "%d", 0);
4404 list[0].value = buf;
4405 list[1].name = "deny_mac_file";
4406 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
4407 list[1].value = deny_file;
4408 items = 2;
4409 } else {
4410 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004411 }
developer10adcc12022-09-13 14:39:17 +08004412
developer06a01d92022-09-07 16:32:39 +08004413 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4414 wifi_hostapdWrite(config_file, list, items);
4415
4416 return RETURN_OK;
4417
4418#if 0
4419 if(apIndex==0 || apIndex==1)
4420 {
4421 //set the filtermode
4422 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
4423 system(buf);
4424 system("syscfg commit");
4425
4426 if(filterMode==0)
4427 {
4428 sprintf(buf,"iptables -F WifiServices%d",apIndex);
4429 system(buf);
4430 return RETURN_OK;
4431 }
4432 }
4433 return RETURN_OK;
4434#endif
4435}
4436
4437// 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.
4438INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
4439{
4440 return RETURN_ERR;
4441}
4442
4443// gets the vlan ID for this ap from an internal enviornment variable
4444INT wifi_getApVlanID(INT apIndex, INT *output_int)
4445{
4446 if(apIndex=0)
4447 {
4448 *output_int=100;
4449 return RETURN_OK;
4450 }
4451
4452 return RETURN_ERR;
4453}
4454
4455// sets the vlan ID for this ap to an internal enviornment variable
4456INT wifi_setApVlanID(INT apIndex, INT vlanId)
4457{
4458 //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)
4459 return RETURN_ERR;
4460}
4461
4462// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
4463INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
4464{
4465 snprintf(bridgeName, 32, "brlan0");
4466 snprintf(IP, 32, "10.0.0.1");
4467 snprintf(subnet, 32, "255.255.255.0");
4468
4469 return RETURN_OK;
4470}
4471
4472//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
4473INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
4474{
4475 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
4476 return RETURN_ERR;
4477}
4478
4479// reset the vlan configuration for this ap
4480INT wifi_resetApVlanCfg(INT apIndex)
4481{
4482 //TODO: remove existing vlan for this ap
4483
4484 //Reapply vlan settings
4485 wifi_pushBridgeInfo(apIndex);
4486
4487 return RETURN_ERR;
4488}
4489
4490// 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.
4491INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
4492{
4493 return RETURN_ERR;
4494}
4495
4496// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
4497INT wifi_startHostApd()
4498{
4499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4500 system("systemctl start hostapd.service");
4501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4502 return RETURN_OK;
4503 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
4504}
4505
4506// stops hostapd
4507INT wifi_stopHostApd()
4508{
4509 char cmd[128] = {0};
4510 char buf[128] = {0};
4511
4512 sprintf(cmd,"systemctl stop hostapd");
4513 _syscmd(cmd, buf, sizeof(buf));
4514
4515 return RETURN_OK;
4516}
4517
4518// restart hostapd dummy function
4519INT wifi_restartHostApd()
4520{
4521 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4522 system("systemctl restart hostapd-global");
4523 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4524
4525 return RETURN_OK;
4526}
4527
4528static int align_hostapd_config(int index)
4529{
4530 ULONG lval;
4531 wifi_getRadioChannel(index%2, &lval);
4532 wifi_setRadioChannel(index%2, lval);
4533}
4534
4535// sets the AP enable status variable for the specified ap.
4536INT wifi_setApEnable(INT apIndex, BOOL enable)
4537{
4538 char config_file[MAX_BUF_SIZE] = {0};
4539 char cmd[MAX_CMD_SIZE] = {0};
4540 char buf[MAX_BUF_SIZE] = {0};
4541 BOOL status;
4542
4543 wifi_getApEnable(apIndex,&status);
4544 if (enable == status)
4545 return RETURN_OK;
4546
4547 if (enable == TRUE) {
4548 int radioIndex = apIndex % NUMBER_OF_RADIOS;
4549 align_hostapd_config(apIndex);
4550 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4551 //Hostapd will bring up this interface
4552 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
4553 _syscmd(cmd, buf, sizeof(buf));
4554 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
4555 _syscmd(cmd, buf, sizeof(buf));
4556 }
4557 else {
4558 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
4559 _syscmd(cmd, buf, sizeof(buf));
4560 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
4561 _syscmd(cmd, buf, sizeof(buf));
4562 }
4563 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
4564 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
4565 _syscmd(cmd, buf, sizeof(buf));
4566 //Wait for wifi up/down to apply
4567 return RETURN_OK;
4568}
4569
4570// Outputs the setting of the internal variable that is set by wifi_setApEnable().
4571INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
4572{
4573 char cmd[MAX_CMD_SIZE] = {'\0'};
4574 char buf[MAX_BUF_SIZE] = {'\0'};
4575
4576 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
4577 return RETURN_ERR;
4578
4579 *output_bool = 0;
4580
4581 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
4582 {
4583 sprintf(cmd, "%s%s%d%s", "ifconfig ", AP_PREFIX, apIndex, " | grep UP");
4584 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
4585 }
4586
4587 return RETURN_OK;
4588}
4589
4590// Outputs the AP "Enabled" "Disabled" status from driver
4591INT wifi_getApStatus(INT apIndex, CHAR *output_string)
4592{
4593 char cmd[128] = {0};
4594 char buf[128] = {0};
4595 BOOL output_bool;
4596
4597 if ( NULL == output_string)
4598 return RETURN_ERR;
4599 wifi_getApEnable(apIndex,&output_bool);
4600
4601 if(output_bool == 1)
4602 snprintf(output_string, 32, "Up");
4603 else
4604 snprintf(output_string, 32, "Disable");
4605
4606 return RETURN_OK;
4607}
4608
4609//Indicates whether or not beacons include the SSID name.
4610// outputs a 1 if SSID on the AP is enabled, else outputs 0
4611INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
4612{
4613 //get the running status
4614 char config_file[MAX_BUF_SIZE] = {0};
4615 char buf[16] = {0};
4616
4617 if (!output)
4618 return RETURN_ERR;
4619
4620 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4621 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
4622 *output = (strncmp("0",buf,1) == 0);
4623
4624 return RETURN_OK;
4625}
4626
4627// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
4628INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
4629{
4630 //store the config, apply instantly
4631 char config_file[MAX_BUF_SIZE] = {0};
4632 struct params list;
4633
4634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4635 list.name = "ignore_broadcast_ssid";
4636 list.value = enable?"0":"1";
4637
4638 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4639 wifi_hostapdWrite(config_file, &list, 1);
4640 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4641 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08004642 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08004643 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4644
4645 return RETURN_OK;
4646}
4647
4648//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
4649INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
4650{
4651 //get the running status
4652 if(!output_uint)
4653 return RETURN_ERR;
4654 *output_uint=16;
4655 return RETURN_OK;
4656}
4657
4658INT wifi_setApRetryLimit(INT apIndex, UINT number)
4659{
4660 //apply instantly
4661 return RETURN_ERR;
4662}
4663
4664//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
4665INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
4666{
4667 if(!output)
4668 return RETURN_ERR;
4669 *output=TRUE;
4670 return RETURN_OK;
4671}
4672
4673//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
4674INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
4675{
4676 //get the running status from driver
4677 if(!output)
4678 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08004679
4680 char config_file[MAX_BUF_SIZE] = {0};
4681 char buf[16] = {0};
4682
4683 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4684 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
4685 if (strncmp("1",buf,1) == 0)
4686 *output = TRUE;
4687 else
4688 *output = FALSE;
4689
developer06a01d92022-09-07 16:32:39 +08004690 return RETURN_OK;
4691}
4692
4693//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
4694INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
4695{
4696 //get the running status from driver
4697 if(!output)
4698 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08004699
4700 char config_file[MAX_BUF_SIZE] = {0};
4701 char buf[16] = {0};
4702
4703 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4704 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
4705 if (strncmp("1",buf,1) == 0)
4706 *output = TRUE;
4707 else
4708 *output = FALSE;
4709
developer06a01d92022-09-07 16:32:39 +08004710 return RETURN_OK;
4711}
4712
4713// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
4714INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
4715{
4716 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08004717 char config_file[MAX_BUF_SIZE] = {0};
4718 struct params list;
4719
4720 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4721 list.name = "wmm_enabled";
4722 list.value = enable?"1":"0";
4723
4724 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4725 wifi_hostapdWrite(config_file, &list, 1);
4726 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4727 wifi_reloadAp(apIndex);
4728 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4729
4730 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004731}
4732
4733//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.
4734INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
4735{
4736 //get the running status from driver
4737 if(!output)
4738 return RETURN_ERR;
4739 *output=TRUE;
4740 return RETURN_OK;
4741}
4742
4743// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
4744INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
4745{
4746 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08004747 char config_file[MAX_BUF_SIZE] = {0};
4748 struct params list;
4749
4750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4751 list.name = "uapsd_advertisement_enabled";
4752 list.value = enable?"1":"0";
4753
4754 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4755 wifi_hostapdWrite(config_file, &list, 1);
4756 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4757 wifi_reloadAp(apIndex);
4758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4759
4760 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004761}
4762
4763// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
4764INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
4765{
4766 //save config and apply instantly.
4767 return RETURN_ERR;
4768}
4769
4770//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.
4771INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
4772{
4773 //get the running status from driver
4774 if(!output_uint)
4775 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08004776
4777 char output[16]={'\0'};
4778 char config_file[MAX_BUF_SIZE] = {0};
4779
4780 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4781 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
4782 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
4783 else {
4784 int device_num = atoi(output);
4785 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
4786 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
4787 return RETURN_ERR;
4788 }
4789 else {
4790 *output_uint = device_num;
4791 }
4792 }
4793
developer06a01d92022-09-07 16:32:39 +08004794 return RETURN_OK;
4795}
4796
4797INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
4798{
4799 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08004800 char str[MAX_BUF_SIZE]={'\0'};
4801 char cmd[MAX_CMD_SIZE]={'\0'};
4802 struct params params;
4803 char config_file[MAX_BUF_SIZE] = {0};
4804
4805 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4806 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
4807 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
4808 return RETURN_ERR;
4809 }
4810 sprintf(str, "%d", number);
4811 params.name = "max_num_sta";
4812 params.value = str;
4813
4814 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
4815 int ret = wifi_hostapdWrite(config_file, &params, 1);
4816 if (ret) {
4817 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
4818 ,__func__, ret);
4819 }
4820
4821 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
4822 if (ret) {
4823 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
4824 ,__func__, ret);
4825 }
4826 wifi_reloadAp(apIndex);
4827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4828
4829 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004830}
4831
4832//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.
4833INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
4834{
4835 //get the current threshold
4836 if(!output_uint)
4837 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08004838 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
4839 if (*output_uint == 0)
4840 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08004841 return RETURN_OK;
4842}
4843
4844INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
4845{
4846 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08004847 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
4848 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004849 return RETURN_ERR;
4850}
4851
4852//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.
4853INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
4854{
4855 if(!output_uint)
4856 return RETURN_ERR;
4857 *output_uint = 3;
4858 return RETURN_OK;
4859}
4860
4861//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
4862INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
4863{
4864 if(!output_uint)
4865 return RETURN_ERR;
4866 *output_uint = 3;
4867 return RETURN_OK;
4868}
4869
4870//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.
4871INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
4872{
4873 if(!output_in_seconds)
4874 return RETURN_ERR;
4875 *output_in_seconds = 0;
4876 return RETURN_OK;
4877}
4878
4879//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
4880INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
4881{
4882 if(!output || apIndex>=MAX_APS)
4883 return RETURN_ERR;
4884 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
4885 snprintf(output, 128, "None,WPA2-Personal");
4886 return RETURN_OK;
4887}
4888
4889//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
4890INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
4891{
4892 char config_file[MAX_BUF_SIZE] = {0};
4893 char buf[32] = {0};
4894 if (!output)
4895 return RETURN_ERR;
4896
4897 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4898 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4899
4900 strcpy(output,"None");//Copying "None" to output string for default case
4901 if((strcmp(buf, "3")==0))
4902 snprintf(output, 32, "WPA-WPA2-Personal");
4903 else if((strcmp(buf, "2")==0))
4904 snprintf(output, 32, "WPA2-Personal");
4905 else if((strcmp(buf, "1")==0))
4906 snprintf(output, 32, "WPA-Personal");
4907 //TODO: need to handle enterprise authmode
4908
4909 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4910 return RETURN_OK;
4911#if 0
4912 //TODO: need to revisit below implementation
4913 char securityType[32], authMode[32];
4914 int enterpriseMode=0;
4915
4916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4917 if(!output)
4918 return RETURN_ERR;
4919
4920 wifi_getApBeaconType(apIndex, securityType);
4921 strcpy(output,"None");//By default, copying "None" to output string
4922 if (strncmp(securityType,"None", strlen("None")) == 0)
4923 return RETURN_OK;
4924
4925 wifi_getApBasicAuthenticationMode(apIndex, authMode);
4926 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
4927
4928 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
4929 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
4930 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
4931 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
4932 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
4933 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
4934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4935
4936 return RETURN_OK;
4937#endif
4938}
4939
4940INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
4941{
4942 char securityType[32];
4943 char authMode[32];
4944
4945 //store settings and wait for wifi up to apply
4946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4947 if(!encMode)
4948 return RETURN_ERR;
4949
4950 printf("%s: apIndex %d, encMode %s\n",__func__, apIndex, encMode);
4951 if (strcmp(encMode, "None")==0)
4952 {
4953 strcpy(securityType,"None");
4954 strcpy(authMode,"None");
4955 }
4956 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
4957 {
4958 strcpy(securityType,"WPAand11i");
4959 strcpy(authMode,"PSKAuthentication");
4960 }
4961 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
4962 {
4963 strcpy(securityType,"WPAand11i");
4964 strcpy(authMode,"EAPAuthentication");
4965 }
4966 else if (strcmp(encMode, "WPA-Personal")==0)
4967 {
4968 strcpy(securityType,"WPA");
4969 strcpy(authMode,"PSKAuthentication");
4970 }
4971 else if (strcmp(encMode, "WPA-Enterprise")==0)
4972 {
4973 strcpy(securityType,"WPA");
4974 strcpy(authMode,"EAPAuthentication");
4975 }
4976 else if (strcmp(encMode, "WPA2-Personal")==0)
4977 {
4978 strcpy(securityType,"11i");
4979 strcpy(authMode,"PSKAuthentication");
4980 }
4981 else if (strcmp(encMode, "WPA2-Enterprise")==0)
4982 {
4983 strcpy(securityType,"11i");
4984 strcpy(authMode,"EAPAuthentication");
4985 }
4986 else
4987 {
4988 strcpy(securityType,"None");
4989 strcpy(authMode,"None");
4990 }
4991 wifi_setApBeaconType(apIndex, securityType);
4992 wifi_setApBasicAuthenticationMode(apIndex, authMode);
4993 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4994
4995 return RETURN_OK;
4996}
4997
4998
4999//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
5000// output_string must be pre-allocated as 64 character string by caller
5001// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5002INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
5003{
5004 char buf[16];
5005 char config_file[MAX_BUF_SIZE] = {0};
5006
5007 if(output_string==NULL)
5008 return RETURN_ERR;
5009
5010 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5011 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5012
5013 if(strcmp(buf,"0")==0)
5014 {
5015 printf("wpa_mode is %s ......... \n",buf);
5016 return RETURN_ERR;
5017 }
5018
5019 wifi_dbg_printf("\nFunc=%s\n",__func__);
5020 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5021 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5022 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5023
5024 return RETURN_OK;
5025}
5026
5027// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
5028// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5029INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
5030{
5031 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5032 struct params params={'\0'};
5033 int ret;
5034 char config_file[MAX_BUF_SIZE] = {0};
5035
5036 if(NULL == preSharedKey)
5037 return RETURN_ERR;
5038
5039 params.name = "wpa_passphrase";
5040
5041 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
5042 {
5043 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5044 return RETURN_ERR;
5045 }
5046 params.value = preSharedKey;
5047 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5048 ret = wifi_hostapdWrite(config_file, &params, 1);
5049 if(!ret)
5050 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5051 return ret;
5052 //TODO: call hostapd_cli for dynamic_config_control
5053}
5054
5055//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
5056// outputs the passphrase, maximum 63 characters
5057INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
5058{
5059 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
5060
5061 wifi_dbg_printf("\nFunc=%s\n",__func__);
5062 if (NULL == output_string)
5063 return RETURN_ERR;
5064
5065 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5066 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5067 if(strcmp(buf,"0")==0)
5068 {
5069 printf("wpa_mode is %s ......... \n",buf);
5070 return RETURN_ERR;
5071 }
5072
5073 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5074 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5075
5076 return RETURN_OK;
5077}
5078
5079// sets the passphrase enviornment variable, max 63 characters
5080INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
5081{
5082 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5083 struct params params={'\0'};
5084 char config_file[MAX_BUF_SIZE] = {0};
5085 int ret;
5086
5087 if(NULL == passPhrase)
5088 return RETURN_ERR;
5089
5090 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
5091 {
5092 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5093 return RETURN_ERR;
5094 }
5095 params.name = "wpa_passphrase";
5096 params.value = passPhrase;
5097 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5098 ret=wifi_hostapdWrite(config_file,&params,1);
5099 if(!ret)
5100 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5101
5102 return ret;
5103}
5104
5105//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.
5106INT wifi_setApSecurityReset(INT apIndex)
5107{
5108 //apply instantly
5109 return RETURN_ERR;
5110}
5111
5112//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).
5113INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
5114{
5115 if(!IP_output || !Port_output || !RadiusSecret_output)
5116 return RETURN_ERR;
5117 snprintf(IP_output, 64, "75.56.77.78");
5118 *Port_output = 123;
5119 snprintf(RadiusSecret_output, 64, "12345678");
5120
5121 return RETURN_OK;
5122}
5123
5124INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
5125{
5126 //store the paramters, and apply instantly
5127 return RETURN_ERR;
5128}
5129
5130INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
5131{
5132 if(!IP_output || !Port_output || !RadiusSecret_output)
5133 return RETURN_ERR;
5134 snprintf(IP_output, 64, "75.56.77.78");
5135 *Port_output = 123;
5136 snprintf(RadiusSecret_output, 64, "12345678");
5137 return RETURN_OK;
5138}
5139
5140INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
5141{
5142 //store the paramters, and apply instantly
5143 return RETURN_ERR;
5144}
5145
5146//RadiusSettings
5147INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
5148{
5149 if(!output)
5150 return RETURN_ERR;
5151
5152 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
5153 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
5154 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
5155 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
5156 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
5157 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.
5158 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
5159 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
5160 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
5161 //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.
5162
5163 return RETURN_OK;
5164}
5165
5166INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
5167{
5168 //store the paramters, and apply instantly
5169 return RETURN_ERR;
5170}
5171
5172//Device.WiFi.AccessPoint.{i}.WPS.Enable
5173//Enables or disables WPS functionality for this access point.
5174// outputs the WPS enable state of this ap in output_bool
5175INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
5176{
5177 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
5178 if(!output_bool || !(apIndex==0 || apIndex==1))
5179 return RETURN_ERR;
5180 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
5181 _syscmd(cmd, buf, sizeof(buf));
5182 if(strstr(buf, "configured"))
5183 *output_bool=TRUE;
5184 else
5185 *output_bool=FALSE;
5186
5187 return RETURN_OK;
5188}
5189
5190//Device.WiFi.AccessPoint.{i}.WPS.Enable
5191// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
5192INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
5193{
5194 char config_file[MAX_BUF_SIZE] = {0};
5195 struct params params;
5196
5197 if(!(apIndex==0 || apIndex==1))
5198 return RETURN_ERR;
5199 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5200 //store the paramters, and wait for wifi up to apply
5201 params.name = "wps_state";
5202 params.value = enable ? "2":"0";
5203
5204 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5205 wifi_hostapdWrite(config_file, &params, 1);
5206 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5207 wifi_reloadAp(apIndex);
5208
5209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5210 return RETURN_OK;
5211}
5212
5213//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
5214INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
5215{
5216 if(!output)
5217 return RETURN_ERR;
5218 snprintf(output, 128, "PushButton,PIN");
5219 return RETURN_OK;
5220}
5221
5222//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
5223//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.
5224// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
5225INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
5226{
5227 if(!output)
5228 return RETURN_ERR;
5229 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
5230
5231 return RETURN_OK;
5232}
5233
5234//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
5235// 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
5236INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
5237{
5238 //apply instantly. No setting need to be stored.
5239 char methods[MAX_BUF_SIZE], *token, *next_token;
5240 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
5241 struct params params;
5242
5243 if(!methodString || !(apIndex==0 || apIndex==1))
5244 return RETURN_ERR;
5245 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5246 //store the paramters, and wait for wifi up to apply
5247
5248 snprintf(methods, sizeof(methods), "%s", methodString);
5249 for(token=methods; *token; token=next_token)
5250 {
5251 strtok_r(token, ",", &next_token);
5252 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
5253 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
5254 else if(*token=='E')
5255 {
5256 if(!strcmp(methods, "Ethernet"))
5257 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
5258 else if(!strcmp(methods, "ExternalNFCToken"))
5259 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
5260 else
5261 printf("%s: Unknown WpsConfigMethod\n", __func__);
5262 }
5263 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
5264 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
5265 else if(*token=='N' && !strcmp(token, "NFCInterface"))
5266 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
5267 else if(*token=='P' )
5268 {
5269 if(!strcmp(token, "PushButton"))
5270 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
5271 else if(!strcmp(token, "PIN"))
5272 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
5273 else
5274 printf("%s: Unknown WpsConfigMethod\n", __func__);
5275 }
5276 else
5277 printf("%s: Unknown WpsConfigMethod\n", __func__);
5278 }
5279 params.name = "config_methods";
5280 params.value = config_methods;
5281 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5282 wifi_hostapdWrite(config_file, &params, 1);
5283 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5285
5286 return RETURN_OK;
5287}
5288
5289// outputs the pin value, ulong_pin must be allocated by the caller
5290INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
5291{
5292 char buf[MAX_BUF_SIZE] = {0};
5293 char cmd[MAX_CMD_SIZE] = {0};
5294
5295 if(!output_ulong || !(apIndex==0 || apIndex==1))
5296 return RETURN_ERR;
5297 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
5298 _syscmd(cmd, buf, sizeof(buf));
5299 if(strlen(buf) > 0)
5300 *output_ulong=strtoul(buf, NULL, 10);
5301
5302 return RETURN_OK;
5303}
5304
5305// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
5306INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
5307{
5308 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
5309 char ap_pin[16] = {0};
5310 char buf[MAX_BUF_SIZE] = {0};
5311 char config_file[MAX_BUF_SIZE] = {0};
5312 ULONG prev_pin = 0;
5313 struct params params;
5314
5315 if(!(apIndex==0 || apIndex==1))
5316 return RETURN_ERR;
5317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5318 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
5319 params.name = "ap_pin";
5320 params.value = ap_pin;
5321 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5322 wifi_hostapdWrite(config_file, &params, 1);
5323 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5325
5326 return RETURN_OK;
5327}
5328
5329// Output string is either Not configured or Configured, max 32 characters
5330INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
5331{
5332 char cmd[MAX_CMD_SIZE];
5333 char buf[MAX_BUF_SIZE]={0};
5334
5335 if(!output_string || !(apIndex==0 || apIndex==1))
5336 return RETURN_ERR;
5337 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5338 snprintf(output_string, 32, "Not configured");
5339 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
5340 _syscmd(cmd, buf, sizeof(buf));
5341
developer348e3d92022-09-13 14:48:41 +08005342 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08005343 snprintf(output_string, 32, "Configured");
5344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5345
5346 return RETURN_OK;
5347}
5348
5349// sets the WPS pin for this AP
5350INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
5351{
5352 char cmd[MAX_CMD_SIZE];
5353 char buf[MAX_BUF_SIZE]={0};
5354 BOOL enable;
5355
5356 if(!(apIndex==0 || apIndex==1))
5357 return RETURN_ERR;
5358 wifi_getApEnable(apIndex, &enable);
5359 if (!enable)
5360 return RETURN_ERR;
5361 wifi_getApWpsEnable(apIndex, &enable);
5362 if (!enable)
5363 return RETURN_ERR;
5364
5365 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
5366 _syscmd(cmd, buf, sizeof(buf));
5367 if((strstr(buf, "OK"))!=NULL)
5368 return RETURN_OK;
5369
5370 return RETURN_ERR;
5371}
5372
5373// This function is called when the WPS push button has been pressed for this AP
5374INT wifi_setApWpsButtonPush(INT apIndex)
5375{
5376 char cmd[MAX_CMD_SIZE];
5377 char buf[MAX_BUF_SIZE]={0};
5378 BOOL enable=FALSE;
5379
5380 if(!(apIndex==0 || apIndex==1))
5381 return RETURN_ERR;
5382 wifi_getApEnable(apIndex, &enable);
5383 if (!enable)
5384 return RETURN_ERR;
5385
5386 wifi_getApWpsEnable(apIndex, &enable);
5387 if (!enable)
5388 return RETURN_ERR;
5389
5390 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
5391 _syscmd(cmd, buf, sizeof(buf));
5392
5393 if((strstr(buf, "OK"))!=NULL)
5394 return RETURN_OK;
5395 return RETURN_ERR;
5396}
5397
5398// cancels WPS mode for this AP
5399INT wifi_cancelApWPS(INT apIndex)
5400{
5401 char cmd[MAX_CMD_SIZE];
5402 char buf[MAX_BUF_SIZE]={0};
5403
5404 if(!(apIndex==0 || apIndex==1))
5405 return RETURN_ERR;
5406 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
5407 _syscmd(cmd,buf, sizeof(buf));
5408
5409 if((strstr(buf, "OK"))!=NULL)
5410 return RETURN_OK;
5411 return RETURN_ERR;
5412}
5413
5414//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
5415//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
5416INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
5417{
5418 FILE *f;
5419 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
5420 char cmd[256], buf[2048];
5421 char *param , *value, *line=NULL;
5422 size_t len = 0;
5423 ssize_t nread;
5424 wifi_associated_dev_t *dev=NULL;
5425
5426 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5427 *associated_dev_array = NULL;
5428 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
5429 _syscmd(cmd,buf,sizeof(buf));
5430 *output_array_size = atoi(buf);
5431
5432 if (*output_array_size <= 0)
5433 return RETURN_OK;
5434
5435 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
5436 *associated_dev_array = dev;
5437 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
5438 _syscmd(cmd,buf,sizeof(buf));
5439 f = fopen("/tmp/connected_devices.txt", "r");
5440 if (f==NULL)
5441 {
5442 *output_array_size=0;
5443 return RETURN_ERR;
5444 }
5445 while ((nread = getline(&line, &len, f)) != -1)
5446 {
5447 param = strtok(line,"=");
5448 value = strtok(NULL,"=");
5449
5450 if( strcmp("flags",param) == 0 )
5451 {
5452 value[strlen(value)-1]='\0';
5453 if(strstr (value,"AUTHORIZED") != NULL )
5454 {
5455 dev[auth_temp].cli_AuthenticationState = 1;
5456 dev[auth_temp].cli_Active = 1;
5457 auth_temp++;
5458 read_flag=1;
5459 }
5460 }
5461 if(read_flag==1)
5462 {
5463 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
5464 {
5465 value[strlen(value)-1]='\0';
5466 sscanf(value, "%x:%x:%x:%x:%x:%x",
5467 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
5468 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
5469 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
5470 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
5471 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
5472 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
5473 mac_temp++;
5474 read_flag=0;
5475 }
5476 }
5477 }
5478 *output_array_size = auth_temp;
5479 auth_temp=0;
5480 mac_temp=0;
5481 free(line);
5482 fclose(f);
5483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5484 return RETURN_OK;
5485}
5486
5487#define MACADDRESS_SIZE 6
5488
5489INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
5490{
5491 FILE *fp = NULL;
5492 char str[MAX_BUF_SIZE] = {0};
5493 int wificlientindex = 0 ;
5494 int count = 0;
5495 int signalstrength = 0;
5496 int arr[MACADDRESS_SIZE] = {0};
5497 unsigned char mac[MACADDRESS_SIZE] = {0};
5498 UINT wifi_count = 0;
5499 char virtual_interface_name[MAX_BUF_SIZE] = {0};
5500 char pipeCmd[MAX_CMD_SIZE] = {0};
5501
5502 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5503 *output_array_size = 0;
5504 *associated_dev_array = NULL;
5505
5506 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
5507 fp = popen(pipeCmd, "r");
5508 if (fp == NULL)
5509 {
5510 printf("Failed to run command inside function %s\n",__FUNCTION__ );
5511 return RETURN_ERR;
5512 }
5513
5514 /* Read the output a line at a time - output it. */
5515 fgets(str, sizeof(str)-1, fp);
5516 wifi_count = (unsigned int) atoi ( str );
5517 *output_array_size = wifi_count;
5518 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
5519 pclose(fp);
5520
5521 if(wifi_count == 0)
5522 {
5523 return RETURN_OK;
5524 }
5525 else
5526 {
5527 wifi_associated_dev3_t* temp = NULL;
5528 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
5529 if(temp == NULL)
5530 {
5531 printf("Error Statement. Insufficient memory \n");
5532 return RETURN_ERR;
5533 }
5534
5535 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
5536 system(pipeCmd);
5537 memset(pipeCmd,0,sizeof(pipeCmd));
5538 if(apIndex == 0)
5539 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
5540 else if(apIndex == 1)
5541 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
5542 system(pipeCmd);
5543
5544 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
5545 if(fp == NULL)
5546 {
5547 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
5548 return RETURN_ERR;
5549 }
5550 fclose(fp);
5551
5552 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
5553 fp = popen(pipeCmd, "r");
5554 if(fp)
5555 {
5556 for(count =0 ; count < wifi_count; count++)
5557 {
5558 fgets(str, MAX_BUF_SIZE, fp);
5559 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
5560 {
5561 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
5562 {
5563 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
5564
5565 }
5566 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
5567 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]);
5568 }
5569 temp[count].cli_AuthenticationState = 1; //TODO
5570 temp[count].cli_Active = 1; //TODO
5571 }
5572 pclose(fp);
5573 }
5574
5575 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
5576 fp = popen(pipeCmd, "r");
5577 if(fp)
5578 {
5579 pclose(fp);
5580 }
5581 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
5582 if(fp)
5583 {
5584 for(count =0 ; count < wifi_count ;count++)
5585 {
5586 fgets(str, MAX_BUF_SIZE, fp);
5587 signalstrength = atoi(str);
5588 temp[count].cli_SignalStrength = signalstrength;
5589 temp[count].cli_RSSI = signalstrength;
5590 temp[count].cli_SNR = signalstrength + 95;
5591 }
5592 pclose(fp);
5593 }
5594
5595
5596 if((apIndex == 0) || (apIndex == 4))
5597 {
5598 for(count =0 ; count < wifi_count ;count++)
5599 {
5600 strcpy(temp[count].cli_OperatingStandard,"g");
5601 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
5602 }
5603
5604 //BytesSent
5605 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
5606 fp = popen(pipeCmd, "r");
5607 if(fp)
5608 {
5609 pclose(fp);
5610 }
5611 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
5612 if(fp)
5613 {
5614 for (count = 0; count < wifi_count; count++)
5615 {
5616 fgets(str, MAX_BUF_SIZE, fp);
5617 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
5618 }
5619 pclose(fp);
5620 }
5621
5622 //BytesReceived
5623 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
5624 fp = popen(pipeCmd, "r");
5625 if (fp)
5626 {
5627 pclose(fp);
5628 }
5629 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
5630 if (fp)
5631 {
5632 for (count = 0; count < wifi_count; count++)
5633 {
5634 fgets(str, MAX_BUF_SIZE, fp);
5635 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
5636 }
5637 pclose(fp);
5638 }
5639
5640 //PacketsSent
5641 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
5642 fp = popen(pipeCmd, "r");
5643 if (fp)
5644 {
5645 pclose(fp);
5646 }
5647
5648 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
5649 if (fp)
5650 {
5651 for (count = 0; count < wifi_count; count++)
5652 {
5653 fgets(str, MAX_BUF_SIZE, fp);
5654 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
5655 }
5656 pclose(fp);
5657 }
5658
5659 //PacketsReceived
5660 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
5661 fp = popen(pipeCmd, "r");
5662 if (fp)
5663 {
5664 pclose(fp);
5665 }
5666 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
5667 if (fp)
5668 {
5669 for (count = 0; count < wifi_count; count++)
5670 {
5671 fgets(str, MAX_BUF_SIZE, fp);
5672 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
5673 }
5674 pclose(fp);
5675 }
5676
5677 //ErrorsSent
5678 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
5679 fp = popen(pipeCmd, "r");
5680 if (fp)
5681 {
5682 pclose(fp);
5683 }
5684 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
5685 if (fp)
5686 {
5687 for (count = 0; count < wifi_count; count++)
5688 {
5689 fgets(str, MAX_BUF_SIZE, fp);
5690 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
5691 }
5692 pclose(fp);
5693 }
5694
5695 //ErrorsSent
5696 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
5697 fp = popen(pipeCmd, "r");
5698 if (fp)
5699 {
5700 pclose(fp);
5701 }
5702 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
5703 if (fp)
5704 {
5705 for (count = 0; count < wifi_count; count++)
5706 {
5707 fgets(str, MAX_BUF_SIZE, fp);
5708 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
5709 }
5710 pclose(fp);
5711 }
5712
5713 //LastDataDownlinkRate
5714 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
5715 fp = popen(pipeCmd, "r");
5716 if (fp)
5717 {
5718 pclose(fp);
5719 }
5720 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
5721 if (fp)
5722 {
5723 for (count = 0; count < wifi_count; count++)
5724 {
5725 fgets(str, MAX_BUF_SIZE, fp);
5726 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
5727 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
5728 }
5729 pclose(fp);
5730 }
5731
5732 //LastDataUplinkRate
5733 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
5734 fp = popen(pipeCmd, "r");
5735 if (fp)
5736 {
5737 pclose(fp);
5738 }
5739 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
5740 if (fp)
5741 {
5742 for (count = 0; count < wifi_count; count++)
5743 {
5744 fgets(str, MAX_BUF_SIZE, fp);
5745 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
5746 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
5747 }
5748 pclose(fp);
5749 }
5750
5751 }
5752 else if ((apIndex == 1) || (apIndex == 5))
5753 {
5754 for (count = 0; count < wifi_count; count++)
5755 {
5756 strcpy(temp[count].cli_OperatingStandard, "a");
5757 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
5758 temp[count].cli_BytesSent = 0;
5759 temp[count].cli_BytesReceived = 0;
5760 temp[count].cli_LastDataUplinkRate = 0;
5761 temp[count].cli_LastDataDownlinkRate = 0;
5762 temp[count].cli_PacketsSent = 0;
5763 temp[count].cli_PacketsReceived = 0;
5764 temp[count].cli_ErrorsSent = 0;
5765 }
5766 }
5767
5768 for (count = 0; count < wifi_count; count++)
5769 {
5770 temp[count].cli_Retransmissions = 0;
5771 temp[count].cli_DataFramesSentAck = 0;
5772 temp[count].cli_DataFramesSentNoAck = 0;
5773 temp[count].cli_MinRSSI = 0;
5774 temp[count].cli_MaxRSSI = 0;
5775 strncpy(temp[count].cli_InterferenceSources, "", 64);
5776 memset(temp[count].cli_IPAddress, 0, 64);
5777 temp[count].cli_RetransCount = 0;
5778 temp[count].cli_FailedRetransCount = 0;
5779 temp[count].cli_RetryCount = 0;
5780 temp[count].cli_MultipleRetryCount = 0;
5781 }
5782 *associated_dev_array = temp;
5783 }
5784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5785 return RETURN_OK;
5786}
5787
5788int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
5789{
5790 FILE *fp = NULL;
5791 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
5792 char cmd[MAX_CMD_SIZE];
5793 int count = 0;
5794
5795 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5796 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
5797 fp = popen(cmd,"r");
5798 if(fp == NULL)
5799 {
5800 printf("Failed to run command in Function %s\n",__FUNCTION__);
5801 return 0;
5802 }
5803 if(fgets(path, sizeof(path)-1, fp) != NULL)
5804 {
5805 for(count=0;path[count]!='\n';count++)
5806 status[count]=path[count];
5807 status[count]='\0';
5808 }
5809 strcpy(wifi_status,status);
5810 pclose(fp);
5811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5812 return RETURN_OK;
5813}
5814
5815/* #define HOSTAPD_STA_PARAM_ENTRIES 29
5816struct hostapd_sta_param {
5817 char key[50];
5818 char value[100];
5819}
5820
5821static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
5822 int i = 0;
5823
5824 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
5825 if (strncmp(params[i].key,key,50) == 0){
5826 return &params[i].value;
5827 }
5828 i++;
5829 }
5830 return NULL;
5831
5832} */
5833
5834static unsigned int count_occurences(const char *buf, const char *word)
5835{
5836 unsigned int n = 0;
5837 char *ptr = strstr(buf, word);
5838
5839 while (ptr++) {
5840 n++;
5841 ptr = strstr(ptr, word);
5842 }
5843
5844 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
5845 return n;
5846}
5847
5848static const char *get_line_from_str_buf(const char *buf, char *line)
5849{
5850 int i;
5851 int n = strlen(buf);
5852
5853 for (i = 0; i < n; i++) {
5854 line[i] = buf[i];
5855 if (buf[i] == '\n') {
5856 line[i] = '\0';
5857 return &buf[i + 1];
5858 }
5859 }
5860
5861 return NULL;
5862}
5863
5864INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
5865{
5866 unsigned int assoc_cnt = 0;
5867 char interface_name[50] = {0};
5868 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
5869 char cmd[MAX_CMD_SIZE] = {'\0'};
5870 char line[256] = {'\0'};
5871 int i = 0;
5872 int ret = 0;
5873 const char *ptr = NULL;
5874 char *key = NULL;
5875 char *val = NULL;
5876 wifi_associated_dev3_t *temp = NULL;
5877 int rssi;
5878
5879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5880
5881 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
5882 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
5883 return RETURN_ERR;
5884 }
5885
5886 // Example filtered output of 'iw dev' command:
5887 // Station 0a:69:72:10:d2:fa (on wifi0)
5888 // signal avg:-67 [-71, -71] dBm
5889 // Station 28:c2:1f:25:5f:99 (on wifi0)
5890 // signal avg:-67 [-71, -70] dBm
5891 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
5892 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
5893 return RETURN_ERR;
5894 }
5895
5896 ret = _syscmd(cmd, buf, sizeof(buf));
5897 if (ret == RETURN_ERR) {
5898 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
5899 return RETURN_ERR;
5900 }
5901
5902 *output_array_size = count_occurences(buf, "Station");
5903 if (*output_array_size == 0) return RETURN_OK;
5904
5905 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
5906 if (temp == NULL) {
5907 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
5908 return RETURN_ERR;
5909 }
5910 *associated_dev_array = temp;
5911
5912 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
5913 ptr = get_line_from_str_buf(buf, line);
5914 i = -1;
5915 while (ptr) {
5916 if (strstr(line, "Station")) {
5917 i++;
5918 key = strtok(line, " ");
5919 val = strtok(NULL, " ");
5920 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
5921 &temp[i].cli_MACAddress[0],
5922 &temp[i].cli_MACAddress[1],
5923 &temp[i].cli_MACAddress[2],
5924 &temp[i].cli_MACAddress[3],
5925 &temp[i].cli_MACAddress[4],
5926 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
5927 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
5928 free(*associated_dev_array);
5929 return RETURN_ERR;
5930 }
5931 }
5932 else if (i < 0) {
5933 ptr = get_line_from_str_buf(ptr, line);
5934 continue; // We didn't detect 'station' entry yet
5935 }
5936 else if (strstr(line, "signal avg")) {
5937 key = strtok(line, ":");
5938 val = strtok(NULL, " ");
5939 if (sscanf(val, "%d", &rssi) <= 0 ) {
5940 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
5941 free(*associated_dev_array);
5942 return RETURN_ERR;
5943 }
5944 temp[i].cli_RSSI = rssi;
5945 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
5946 }
5947 // Here other fields can be parsed if added to filter of 'iw dev' command
5948
5949 ptr = get_line_from_str_buf(ptr, line);
5950 };
5951
5952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5953
5954 return RETURN_OK;
5955}
5956
5957#if 0
5958//To-do
5959INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
5960{
5961 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5962
5963 //Using different approach to get required WiFi Parameters from system available commands
5964#if 0
5965 FILE *f;
5966 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
5967 char cmd[256], buf[2048];
5968 char *param , *value, *line=NULL;
5969 size_t len = 0;
5970 ssize_t nread;
5971 wifi_associated_dev3_t *dev=NULL;
5972 *associated_dev_array = NULL;
5973 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
5974 _syscmd(cmd,buf,sizeof(buf));
5975 *output_array_size = atoi(buf);
5976
5977 if (*output_array_size <= 0)
5978 return RETURN_OK;
5979
5980 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
5981 *associated_dev_array = dev;
5982 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
5983 _syscmd(cmd,buf,sizeof(buf));
5984 f = fopen("/tmp/connected_devices.txt", "r");
5985 if (f==NULL)
5986 {
5987 *output_array_size=0;
5988 return RETURN_ERR;
5989 }
5990 while ((nread = getline(&line, &len, f)) != -1)
5991 {
5992 param = strtok(line,"=");
5993 value = strtok(NULL,"=");
5994
5995 if( strcmp("flags",param) == 0 )
5996 {
5997 value[strlen(value)-1]='\0';
5998 if(strstr (value,"AUTHORIZED") != NULL )
5999 {
6000 dev[auth_temp].cli_AuthenticationState = 1;
6001 dev[auth_temp].cli_Active = 1;
6002 auth_temp++;
6003 read_flag=1;
6004 }
6005 }
6006 if(read_flag==1)
6007 {
6008 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6009 {
6010 value[strlen(value)-1]='\0';
6011 sscanf(value, "%x:%x:%x:%x:%x:%x",
6012 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6013 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6014 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6015 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6016 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6017 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6018
6019 }
6020 else if( strcmp("rx_packets",param) == 0 )
6021 {
6022 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
6023 }
6024
6025 else if( strcmp("tx_packets",param) == 0 )
6026 {
6027 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
6028 }
6029
6030 else if( strcmp("rx_bytes",param) == 0 )
6031 {
6032 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
6033 }
6034
6035 else if( strcmp("tx_bytes",param) == 0 )
6036 {
6037 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
6038 mac_temp++;
6039 read_flag=0;
6040 }
6041 }
6042 }
6043
6044 *output_array_size = auth_temp;
6045 auth_temp=0;
6046 mac_temp=0;
6047 free(line);
6048 fclose(f);
6049#endif
6050 char interface_name[MAX_BUF_SIZE] = {0};
6051 char wifi_status[MAX_BUF_SIZE] = {0};
6052 char hostapdconf[MAX_BUF_SIZE] = {0};
6053
6054 wifi_associated_dev3_t *dev_array = NULL;
6055 ULONG wifi_count = 0;
6056
6057 *associated_dev_array = NULL;
6058 *output_array_size = 0;
6059
6060 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
6061 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
6062 {
6063 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
6064
6065 GetInterfaceName(interface_name, hostapdconf);
6066
6067 if(strlen(interface_name) > 1)
6068 {
6069 wifihal_interfacestatus(wifi_status,interface_name);
6070 if(strcmp(wifi_status,"RUNNING") == 0)
6071 {
6072 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
6073
6074 *associated_dev_array = dev_array;
6075 *output_array_size = wifi_count;
6076 }
6077 else
6078 {
6079 *associated_dev_array = NULL;
6080 }
6081 }
6082 }
6083
6084 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6085 return RETURN_OK;
6086}
6087#endif
6088
6089/* getIPAddress function */
6090/**
6091* @description Returning IpAddress of the Matched String
6092*
6093* @param
6094* @str Having MacAddress
6095* @ipaddr Having ipaddr
6096* @return The status of the operation
6097* @retval RETURN_OK if successful
6098* @retval RETURN_ERR if any error is detected
6099*
6100*/
6101
6102INT getIPAddress(char *str,char *ipaddr)
6103{
6104 FILE *fp = NULL;
6105 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
6106 int LeaseTime = 0,ret = 0;
6107 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
6108 {
6109 return RETURN_ERR;
6110 }
6111
6112 while ( fgets(buf, sizeof(buf), fp)!= NULL )
6113 {
6114 /*
6115 Sample:sss
6116 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
6117 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
6118 */
6119 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
6120 &(LeaseTime),
6121 phyAddr,
6122 ipAddr,
6123 hostName
6124 );
6125 if(ret != 4)
6126 continue;
6127 if(strcmp(str,phyAddr) == 0)
6128 strcpy(ipaddr,ipAddr);
6129 }
6130 return RETURN_OK;
6131}
6132
6133/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
6134/**
6135* @description Returning Inactive wireless connected clients informations
6136*
6137* @param
6138* @filename Holding private_wifi 2g/5g content files
6139* @associated_dev_array Having inactiv wireless clients informations
6140* @output_array_size Returning Inactive wireless counts
6141* @return The status of the operation
6142* @retval RETURN_OK if successful
6143* @retval RETURN_ERR if any error is detected
6144*
6145*/
6146
6147INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6148{
6149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6150 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
6151 FILE *fp = NULL;
6152 int arr[MACADDRESS_SIZE] = {0};
6153 unsigned char mac[MACADDRESS_SIZE] = {0};
6154 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
6155 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
6156 fp = popen(buf,"r");
6157 if(fp == NULL)
6158 return RETURN_ERR;
6159 else
6160 {
6161 fgets(path,sizeof(path),fp);
6162 maccount = atoi(path);
6163 }
6164 pclose(fp);
6165 *output_array_size = maccount;
6166 wifi_associated_dev3_t* temp = NULL;
6167 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
6168 *associated_dev_array = temp;
6169 if(temp == NULL)
6170 {
6171 printf("Error Statement. Insufficient memory \n");
6172 return RETURN_ERR;
6173 }
6174 memset(buf,0,sizeof(buf));
6175 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
6176 fp = popen(buf,"r");
6177 for(count = 0; count < maccount ; count++)
6178 {
6179 fgets(path,sizeof(path),fp);
6180 for(i = 0; path[i]!='\n';i++)
6181 str[i]=path[i];
6182 str[i]='\0';
6183 getIPAddress(str,ipaddr);
6184 memset(buf,0,sizeof(buf));
6185 if(strlen(ipaddr) > 0)
6186 {
6187 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
6188 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
6189 {
6190 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6191 {
6192 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6193 {
6194 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6195
6196 }
6197 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6198 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]);
6199 }
6200 temp[count].cli_AuthenticationState = 0; //TODO
6201 temp[count].cli_Active = 0; //TODO
6202 temp[count].cli_SignalStrength = 0;
6203 }
6204 else //Active wireless clients info
6205 {
6206 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6207 {
6208 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6209 {
6210 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6211
6212 }
6213 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6214 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]);
6215 }
6216 temp[count].cli_Active = 1;
6217 }
6218 }
6219 memset(ipaddr,0,sizeof(ipaddr));
6220 }
6221 pclose(fp);
6222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6223 return RETURN_OK;
6224}
6225//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
6226//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
6227//To get Band Steering Capability
6228INT wifi_getBandSteeringCapability(BOOL *support)
6229{
6230 *support = FALSE;
6231 return RETURN_OK;
6232}
6233
6234
6235//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
6236//To get Band Steering enable status
6237INT wifi_getBandSteeringEnable(BOOL *enable)
6238{
6239 *enable = FALSE;
6240 return RETURN_OK;
6241}
6242
6243//To turn on/off Band steering
6244INT wifi_setBandSteeringEnable(BOOL enable)
6245{
6246 return RETURN_OK;
6247}
6248
6249//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
6250//To get Band Steering AP group
6251INT wifi_getBandSteeringApGroup(char *output_ApGroup)
6252{
6253 if (NULL == output_ApGroup)
6254 return RETURN_ERR;
6255
6256 strcpy(output_ApGroup, "1,2");
6257 return RETURN_OK;
6258}
6259
6260//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
6261//to set and read the band steering BandUtilizationThreshold parameters
6262INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
6263{
6264 return RETURN_ERR;
6265}
6266
6267INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
6268{
6269 return RETURN_ERR;
6270}
6271
6272//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
6273//to set and read the band steering RSSIThreshold parameters
6274INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
6275{
6276 return RETURN_ERR;
6277}
6278
6279INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
6280{
6281 return RETURN_ERR;
6282}
6283
6284
6285//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
6286//to set and read the band steering physical modulation rate threshold parameters
6287INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
6288{
6289 //If chip is not support, return -1
6290 return RETURN_ERR;
6291}
6292
6293INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
6294{
6295 //If chip is not support, return -1
6296 return RETURN_ERR;
6297}
6298
6299//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
6300//to set and read the inactivity time (in seconds) for steering under overload condition
6301INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
6302{
6303 return RETURN_ERR;
6304}
6305
6306INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
6307{
6308 return RETURN_ERR;
6309}
6310
6311//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
6312//to set and read the inactivity time (in seconds) for steering under Idle condition
6313INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
6314{
6315 return RETURN_ERR;
6316}
6317
6318INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
6319{
6320 return RETURN_ERR;
6321}
6322
6323//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
6324//pClientMAC[64]
6325//pSourceSSIDIndex[64]
6326//pDestSSIDIndex[64]
6327//pSteeringReason[256]
6328INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
6329{
6330 //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
6331 *pSteeringTime=time(NULL);
6332 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
6333 return RETURN_OK;
6334}
6335
6336INT wifi_ifConfigDown(INT apIndex)
6337{
6338 INT status = RETURN_OK;
6339 char cmd[64];
6340
6341 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
6342 printf("%s: %s\n", __func__, cmd);
6343 system(cmd);
6344
6345 return status;
6346}
6347
6348INT wifi_ifConfigUp(INT apIndex)
6349{
6350 char cmd[128];
6351 char buf[1024];
6352
6353 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
6354 _syscmd(cmd, buf, sizeof(buf));
6355 return 0;
6356}
6357
6358//>> Deprecated. Replace with wifi_applyRadioSettings
6359INT wifi_pushBridgeInfo(INT apIndex)
6360{
6361 char ip[32];
6362 char subnet[32];
6363 char bridge[32];
6364 int vlanId;
6365 char cmd[128];
6366 char buf[1024];
6367
6368 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
6369 wifi_getApVlanID(apIndex,&vlanId);
6370
6371 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
6372 _syscmd(cmd,buf, sizeof(buf));
6373
6374 return 0;
6375}
6376
6377INT wifi_pushChannel(INT radioIndex, UINT channel)
6378{
6379 char cmd[128];
6380 char buf[1024];
6381 int apIndex;
6382
6383 apIndex=(radioIndex==0)?0:1;
6384 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
6385 _syscmd(cmd,buf, sizeof(buf));
6386
6387 return 0;
6388}
6389
6390INT wifi_pushChannelMode(INT radioIndex)
6391{
6392 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
6393 return RETURN_ERR;
6394}
6395
6396INT wifi_pushDefaultValues(INT radioIndex)
6397{
6398 //Apply Comcast specified default radio settings instantly
6399 //AMPDU=1
6400 //AMPDUFrames=32
6401 //AMPDULim=50000
6402 //txqueuelen=1000
6403
6404 return RETURN_ERR;
6405}
6406
6407INT wifi_pushTxChainMask(INT radioIndex)
6408{
6409 //Apply default TxChainMask instantly
6410 return RETURN_ERR;
6411}
6412
6413INT wifi_pushRxChainMask(INT radioIndex)
6414{
6415 //Apply default RxChainMask instantly
6416 return RETURN_ERR;
6417}
6418
6419INT wifi_pushSSID(INT apIndex, CHAR *ssid)
6420{
6421 INT status;
6422
6423 status = wifi_setSSIDName(apIndex,ssid);
6424 wifi_setApEnable(apIndex,FALSE);
6425 wifi_setApEnable(apIndex,TRUE);
6426
6427 return status;
6428}
6429
6430INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
6431{
6432 //Apply default Ssid Advertisement instantly
6433 return RETURN_ERR;
6434}
6435
6436INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
6437{
6438 INT status = RETURN_ERR;
6439 *output = 0;
6440 return RETURN_ERR;
6441}
6442
6443INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
6444{
6445 return RETURN_OK;
6446}
6447
6448INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
6449{
6450 return RETURN_OK;
6451}
6452
6453//To-do
6454INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
6455{
developereb199ae2022-09-13 14:04:27 +08006456 char output[16]={'\0'};
6457 char config_file[MAX_BUF_SIZE] = {0};
6458
6459 if (!output_string)
6460 return RETURN_ERR;
6461
6462 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6463 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
6464
6465 if (strlen(output) == 0)
6466 snprintf(output_string, 64, "Disabled");
6467 else if (strncmp(output, "0", 1) == 0)
6468 snprintf(output_string, 64, "Disabled");
6469 else if (strncmp(output, "1", 1) == 0)
6470 snprintf(output_string, 64, "Optional");
6471 else if (strncmp(output, "2", 1) == 0)
6472 snprintf(output_string, 64, "Required");
6473 else {
6474 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
6475 return RETURN_ERR;
6476 }
6477
6478 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08006479 return RETURN_OK;
6480}
6481INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
6482{
developereb199ae2022-09-13 14:04:27 +08006483 char str[MAX_BUF_SIZE]={'\0'};
6484 char cmd[MAX_CMD_SIZE]={'\0'};
6485 struct params params;
6486 char config_file[MAX_BUF_SIZE] = {0};
6487
6488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6489 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
6490 return RETURN_ERR;
6491
6492 params.name = "ieee80211w";
6493 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
6494 params.value = "0";
6495 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
6496 params.value = "1";
6497 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
6498 params.value = "2";
6499 else{
6500 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
6501 return RETURN_ERR;
6502 }
6503 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6504 wifi_hostapdWrite(config_file, &params, 1);
6505 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006506 return RETURN_OK;
6507}
6508INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
6509{
6510 char output[16]={'\0'};
6511 char config_file[MAX_BUF_SIZE] = {0};
6512
6513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6514 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
6515 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
6516
6517 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
6518 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
6519
6520 return RETURN_OK;
6521}
6522
6523INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
6524{
6525 return RETURN_OK;
6526}
6527
6528INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
6529{
6530 return RETURN_OK;
6531}
6532
6533INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
6534{
6535 return RETURN_OK;
6536}
6537
6538INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
6539{
6540 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6541 char config_file[MAX_BUF_SIZE] = {0};
6542
6543 if (NULL == output)
6544 return RETURN_ERR;
6545 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
6546 wifi_hostapdRead(config_file,"hw_mode",output,64);
6547
6548 if(strcmp(output,"b")==0)
6549 sprintf(output, "%s", "1,2,5.5,11");
6550 else if (strcmp(output,"a")==0)
6551 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
6552 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
6553 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
6554
6555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6556 return RETURN_OK;
6557}
6558
6559INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
6560{
6561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6562 char *temp;
6563 char temp_output[128];
6564 char temp_TransmitRates[128];
6565 char config_file[MAX_BUF_SIZE] = {0};
6566
6567 if (NULL == output)
6568 return RETURN_ERR;
6569
6570 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
6571 wifi_hostapdRead(config_file,"supported_rates",output,64);
6572
6573 strcpy(temp_TransmitRates,output);
6574 strcpy(temp_output,"");
6575 temp = strtok(temp_TransmitRates," ");
6576 while(temp!=NULL)
6577 {
6578 temp[strlen(temp)-1]=0;
6579 if((temp[0]=='5') && (temp[1]=='\0'))
6580 {
6581 temp="5.5";
6582 }
6583 strcat(temp_output,temp);
6584 temp = strtok(NULL," ");
6585 if(temp!=NULL)
6586 {
6587 strcat(temp_output,",");
6588 }
6589 }
6590 strcpy(output,temp_output);
6591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6592
6593 return RETURN_OK;
6594}
6595
6596INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
6597{
6598 return RETURN_OK;
6599}
6600
6601
6602INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
6603{
6604 int i=0;
6605 char *temp;
6606 char temp1[128];
6607 char temp_output[128];
6608 char temp_TransmitRates[128];
6609 struct params params={'\0'};
6610 char config_file[MAX_BUF_SIZE] = {0};
6611
6612 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6613 if(NULL == output)
6614 return RETURN_ERR;
6615
6616 strcpy(temp_TransmitRates,output);
6617
6618 for(i=0;i<strlen(temp_TransmitRates);i++)
6619 {
6620 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
6621 {
6622 continue;
6623 }
6624 else
6625 {
6626 return RETURN_ERR;
6627 }
6628 }
6629 strcpy(temp_output,"");
6630 temp = strtok(temp_TransmitRates," ");
6631 while(temp!=NULL)
6632 {
6633 strcpy(temp1,temp);
6634 if(wlanIndex==1)
6635 {
6636 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
6637 {
6638 return RETURN_ERR;
6639 }
6640 }
6641
6642 if(strcmp(temp,"5.5")==0)
6643 {
6644 strcpy(temp1,"55");
6645 }
6646 else
6647 {
6648 strcat(temp1,"0");
6649 }
6650 strcat(temp_output,temp1);
6651 temp = strtok(NULL," ");
6652 if(temp!=NULL)
6653 {
6654 strcat(temp_output," ");
6655 }
6656 }
6657 strcpy(output,temp_output);
6658
6659
6660 params.name = "supported_rates";
6661 params.value = output;
6662
6663 wifi_dbg_printf("\n%s:",__func__);
6664 wifi_dbg_printf("params.value=%s\n",params.value);
6665 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
6666 wifi_hostapdWrite(config_file,&params,1);
6667 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6668
6669 return RETURN_OK;
6670}
6671
6672
6673static char *sncopy(char *dst, int dst_sz, const char *src)
6674{
6675 if (src && dst && dst_sz > 0) {
6676 strncpy(dst, src, dst_sz);
6677 dst[dst_sz - 1] = '\0';
6678 }
6679 return dst;
6680}
6681
6682static int util_get_sec_chan_offset(int channel, const char* ht_mode)
6683{
6684 if (0 == strcmp(ht_mode, "HT40") ||
6685 0 == strcmp(ht_mode, "HT80") ||
6686 0 == strcmp(ht_mode, "HT160")) {
6687 switch (channel) {
6688 case 1 ... 7:
6689 case 36:
6690 case 44:
6691 case 52:
6692 case 60:
6693 case 100:
6694 case 108:
6695 case 116:
6696 case 124:
6697 case 132:
6698 case 140:
6699 case 149:
6700 case 157:
6701 return 1;
6702 case 8 ... 13:
6703 case 40:
6704 case 48:
6705 case 56:
6706 case 64:
6707 case 104:
6708 case 112:
6709 case 120:
6710 case 128:
6711 case 136:
6712 case 144:
6713 case 153:
6714 case 161:
6715 return -1;
6716 default:
6717 return -EINVAL;
6718 }
6719 }
6720
6721 return -EINVAL;
6722}
6723
6724static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
6725{
6726 if (NULL == hw_mode) return;
6727
6728 if (0 == strcmp(hw_mode, "ac"))
6729 sncopy(bw_mode, bw_mode_len, "ht vht");
6730
6731 if (0 == strcmp(hw_mode, "n"))
6732 sncopy(bw_mode, bw_mode_len, "ht");
6733
6734 return;
6735}
6736
6737static int util_chan_to_freq(int chan)
6738{
6739 if (chan == 14)
6740 return 2484;
6741 else if (chan < 14)
6742 return 2407 + chan * 5;
6743 else if (chan >= 182 && chan <= 196)
6744 return 4000 + chan * 5;
6745 else
6746 return 5000 + chan * 5;
6747 return 0;
6748}
6749
6750const int *util_unii_5g_chan2list(int chan, int width)
6751{
6752 static const int lists[] = {
6753 // <width>, <chan1>, <chan2>..., 0,
6754 20, 36, 0,
6755 20, 40, 0,
6756 20, 44, 0,
6757 20, 48, 0,
6758 20, 52, 0,
6759 20, 56, 0,
6760 20, 60, 0,
6761 20, 64, 0,
6762 20, 100, 0,
6763 20, 104, 0,
6764 20, 108, 0,
6765 20, 112, 0,
6766 20, 116, 0,
6767 20, 120, 0,
6768 20, 124, 0,
6769 20, 128, 0,
6770 20, 132, 0,
6771 20, 136, 0,
6772 20, 140, 0,
6773 20, 144, 0,
6774 20, 149, 0,
6775 20, 153, 0,
6776 20, 157, 0,
6777 20, 161, 0,
6778 20, 165, 0,
6779 40, 36, 40, 0,
6780 40, 44, 48, 0,
6781 40, 52, 56, 0,
6782 40, 60, 64, 0,
6783 40, 100, 104, 0,
6784 40, 108, 112, 0,
6785 40, 116, 120, 0,
6786 40, 124, 128, 0,
6787 40, 132, 136, 0,
6788 40, 140, 144, 0,
6789 40, 149, 153, 0,
6790 40, 157, 161, 0,
6791 80, 36, 40, 44, 48, 0,
6792 80, 52, 56, 60, 64, 0,
6793 80, 100, 104, 108, 112, 0,
6794 80, 116, 120, 124, 128, 0,
6795 80, 132, 136, 140, 144, 0,
6796 80, 149, 153, 157, 161, 0,
6797 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
6798 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
6799 -1 // final delimiter
6800 };
6801 const int *start;
6802 const int *p;
6803
6804 for (p = lists; *p != -1; p++) {
6805 if (*p == width) {
6806 for (start = ++p; *p != 0; p++) {
6807 if (*p == chan)
6808 return start;
6809 }
6810 }
6811 // move to the end of channel list of given width
6812 while (*p != 0) {
6813 p++;
6814 }
6815 }
6816
6817 return NULL;
6818}
6819
6820static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
6821{
6822 if (NULL == ht_mode)
6823 return 0;
6824
6825 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
6826 const int *chans = util_unii_5g_chan2list(channel, width);
6827 int sum = 0;
6828 int cnt = 0;
6829
6830 if (NULL == chans)
6831 return 0;
6832
6833 while (*chans) {
6834 sum += *chans;
6835 cnt++;
6836 chans++;
6837 }
6838 return sum / cnt;
6839}
6840
6841static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
6842{
6843 BOOL onlyG, onlyN, onlyA;
6844 CHAR tmp[64];
6845 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
6846 if (ret == RETURN_OK) {
6847 sncopy(hw_mode, hw_mode_size, tmp);
6848 }
6849 return ret;
6850}
6851
6852INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
6853{
6854 // Sample commands:
6855 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
6856 // hostapd_cli -i wifi0 chan_switch 30 2437
6857 char cmd[MAX_CMD_SIZE] = {0};
6858 char buf[MAX_BUF_SIZE] = {0};
6859 int freq = 0, ret = 0;
6860 char center_freq1_str[32] = ""; // center_freq1=%d
6861 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
6862 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
6863 char hw_mode[16] = ""; // n|ac
6864 char bw_mode[16] = ""; // ht|ht vht
6865 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
6866 int sec_chan_offset;
6867 int width;
6868
6869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6870
6871 freq = util_chan_to_freq(channel);
6872
6873 // Get radio mode HT20|HT40|HT80 etc.
6874 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
6875 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
6876 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
6877 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
6878 if (sec_chan_offset != -EINVAL)
6879 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
6880
6881
6882 // Provide bandwith if specified
6883 if (channel_width_MHz > 20) {
6884 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
6885 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
6886 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
6887
6888 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
6889 }
6890
6891 int center_chan = 0;
6892 if (channel_width_MHz > 20) {
6893 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
6894 if (center_chan > 0) {
6895 int center_freq1 = util_chan_to_freq(center_chan);
6896 if (center_freq1)
6897 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
6898 }
6899 }
6900
6901 {
6902 // Only the first AP, other are hanging on the same radio
6903 int apIndex = radioIndex;
6904 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
6905 AP_PREFIX, apIndex, csa_beacon_count, freq,
6906 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
6907 wifi_dbg_printf("execute: '%s'\n", cmd);
6908 ret = _syscmd(cmd, buf, sizeof(buf));
6909 }
6910
6911 wifi_setRadioChannel(radioIndex, channel);
6912
6913 char *ext_str = "None";
6914 if (sec_chan_offset == 1) ext_str = "Above";
6915 else if (sec_chan_offset == -1) ext_str = "Below";
6916 wifi_setRadioExtChannel(radioIndex, ext_str);
6917
6918 wifi_setRadioCenterChannel(radioIndex, center_chan);
6919
6920 char mhz_str[16];
6921 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
6922 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
6923
6924 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6925
6926 return RETURN_OK;
6927}
6928
6929INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
6930{
6931 char cmd[1024] = {0};
6932 char buf[1024] = {0};
6933 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6934 wifi_neighbor_ap2_t *scan_array = NULL;
6935 int scan_count=0;
6936 int i =0;
6937 int freq=0;
6938 size_t len=0;
6939 FILE *f = NULL;
6940 ssize_t read = 0;
6941 char *line =NULL;
6942 char radio_ifname[64];
6943 char secondary_chan[64];
6944 int vht_channel_width = 0;
6945
6946 if(wifi_getRadioIfName(radio_index,radio_ifname)!=RETURN_OK)
6947 return RETURN_ERR;
6948
6949 /* sched_start is not supported on open source ath9k ath10k firmware
6950 * Using active scan as a workaround */
6951 sprintf(cmd,"iw dev %s scan |grep '^BSS\\|SSID:\\|freq:\\|signal:\\|HT operation:\\|secondary channel offset:\\|* channel width:'", radio_ifname);
6952 if((f = popen(cmd, "r")) == NULL) {
6953 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
6954 return RETURN_ERR;
6955 }
6956 read = getline(&line, &len, f);
6957 while (read != -1) {
6958 if(strncmp(line,"BSS",3) == 0) {
6959 i = scan_count;
6960 scan_count++;
6961 scan_array = realloc(scan_array,sizeof(wifi_neighbor_ap2_t)*scan_count);
6962 memset(&(scan_array[i]),0, sizeof(wifi_neighbor_ap2_t));
6963 sscanf(line,"BSS %17s", scan_array[i].ap_BSSID);
6964
6965 read = getline(&line, &len, f);
6966 sscanf(line," freq: %d", &freq);
6967 scan_array[i].ap_Channel = ieee80211_frequency_to_channel(freq);
6968
6969 read = getline(&line, &len, f);
6970 sscanf(line," signal: %d", &(scan_array[i].ap_SignalStrength));
6971
6972 read = getline(&line, &len, f);
6973 sscanf(line," SSID: %s", scan_array[i].ap_SSID);
6974 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);
6975 read = getline(&line, &len, f);
6976 if(strncmp(line,"BSS",3)==0) {
6977 // No HT and no VHT => 20Mhz
6978 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11%s", radio_index%1 ? "A": "G");
6979 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
6980 continue;
6981 }
6982 if(strncmp(line," HT operation:",14)!= 0) {
6983 wifi_dbg_printf("HT output parsing error (%s)\n", line);
6984 goto output_error;
6985 }
6986
6987 read = getline(&line, &len, f);
6988 sscanf(line," * secondary channel offset: %s", &secondary_chan);
6989
6990 if(!strcmp(secondary_chan, "no")) {
6991 //20Mhz
6992 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
6993 }
6994
6995 if(!strcmp(secondary_chan, "above")) {
6996 //40Mhz +
6997 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
6998 }
6999
7000 if(!strcmp(secondary_chan, "below")) {
7001 //40Mhz -
7002 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
7003 }
7004
7005
7006 read = getline(&line, &len, f);
7007 if(strncmp(line," VHT operation:",15) !=0) {
7008 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7009 // No VHT
7010 continue;
7011 }
7012 read = getline(&line, &len, f);
7013 sscanf(line," * channel width: %d", &vht_channel_width);
7014 if(vht_channel_width == 1) {
7015 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT80");
7016 } else {
7017 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT40");
7018 }
7019
7020 }
7021 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7022 read = getline(&line, &len, f);
7023 }
7024 wifi_dbg_printf("%s:Counted BSS: %d\n",__func__, scan_count);
7025 *output_array_size = scan_count;
7026 *neighbor_ap_array = scan_array;
7027 free(line);
7028 pclose(f);
7029 return RETURN_OK;
7030
7031output_error:
7032 pclose(f);
7033 free(line);
7034 free(scan_array);
7035 return RETURN_ERR;
7036}
7037INT wifi_getApAssociatedDeviceStats(
7038 INT apIndex,
7039 mac_address_t *clientMacAddress,
7040 wifi_associated_dev_stats_t *associated_dev_stats,
7041 u64 *handle)
7042{
7043 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
7044 char interface_name[50] = {0};
7045 char cmd[1024] = {0};
7046 char mac_str[18] = {0};
7047 char *key = NULL;
7048 char *val = NULL;
7049 FILE *f = NULL;
7050 char *line = NULL;
7051 size_t len = 0;
7052 ssize_t read = 0;
7053
7054 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7055 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7056 return RETURN_ERR;
7057 }
7058
7059 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
7060 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
7061 if((f = popen(cmd, "r")) == NULL) {
7062 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
7063 return RETURN_ERR;
7064 }
7065
7066 while ((read = getline(&line, &len, f)) != -1) {
7067 key = strtok(line,":");
7068 val = strtok(NULL,":");
7069
7070 if(!strncmp(key,"rx bytes",8))
7071 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
7072 if(!strncmp(key,"tx bytes",8))
7073 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
7074 if(!strncmp(key,"rx packets",10))
7075 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
7076 if(!strncmp(key,"tx packets",10))
7077 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
7078 if(!strncmp(key,"tx retries",10))
7079 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
7080 if(!strncmp(key,"tx failed",9))
7081 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
7082 if(!strncmp(key,"rx drop misc",13))
7083 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
7084 if(!strncmp(key,"rx bitrate",10)) {
7085 val = strtok(val, " ");
7086 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
7087 }
7088 if(!strncmp(key,"tx bitrate",10)) {
7089 val = strtok(val, " ");
7090 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
7091 }
7092 }
7093 free(line);
7094 pclose(f);
7095 return RETURN_OK;
7096}
7097
7098INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
7099{
7100 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
7101
7102 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7103 if (NULL == output_string)
7104 return RETURN_ERR;
7105
7106 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
7107 _syscmd(cmd, buf, sizeof(buf));
7108
7109 //size of SSID name restricted to value less than 32 bytes
7110 snprintf(output_string, 32, "%s", buf);
7111 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7112
7113 return RETURN_OK;
7114}
7115
7116INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
7117{
7118 //char cmd[MAX_CMD_SIZE] = {0};
7119 char config_file[MAX_BUF_SIZE] = {0};
7120 char buf[32] = {0};
7121
7122 if (!output_filterMode)
7123 return RETURN_ERR;
7124
7125 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
7126 //_syscmd(cmd, buf, sizeof(buf));
7127 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7128 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08007129 if(strlen(buf) == 0) {
7130 *output_filterMode = 0;
7131 }
7132 else {
7133 int macaddr_acl_mode = strtol(buf, NULL, 10);
7134 if (macaddr_acl_mode == 1) {
7135 *output_filterMode = 1;
7136 } else if (macaddr_acl_mode == 0) {
7137 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
7138 if (strlen(buf) == 0) {
7139 *output_filterMode = 0;
7140 } else {
7141 *output_filterMode = 2;
7142 }
7143 } else {
7144 return RETURN_ERR;
7145 }
7146 }
developer06a01d92022-09-07 16:32:39 +08007147
7148 return RETURN_OK;
7149}
7150
7151INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
7152{
7153 FILE *fp = NULL;
7154 char str[MAX_BUF_SIZE] = {0};
7155 int wificlientindex = 0 ;
7156 int count = 0;
7157 int signalstrength = 0;
7158 int arr[MACADDRESS_SIZE] = {0};
7159 unsigned char mac[MACADDRESS_SIZE] = {0};
7160 UINT wifi_count = 0;
7161 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7162 char pipeCmd[MAX_CMD_SIZE] = {0};
7163
7164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7165 *output_array_size = 0;
7166 *associated_dev_array = NULL;
7167 char interface_name[50] = {0};
7168
7169 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7170 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7171 return RETURN_ERR;
7172 }
7173
7174 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7175 fp = popen(pipeCmd, "r");
7176 if (fp == NULL)
7177 {
7178 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7179 return RETURN_ERR;
7180 }
7181
7182 /* Read the output a line at a time - output it. */
7183 fgets(str, sizeof(str)-1, fp);
7184 wifi_count = (unsigned int) atoi ( str );
7185 *output_array_size = wifi_count;
7186 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7187 pclose(fp);
7188
7189 if(wifi_count == 0)
7190 {
7191 return RETURN_OK;
7192 }
7193 else
7194 {
7195 wifi_associated_dev2_t* temp = NULL;
7196 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
7197 *associated_dev_array = temp;
7198 if(temp == NULL)
7199 {
7200 printf("Error Statement. Insufficient memory \n");
7201 return RETURN_ERR;
7202 }
7203
7204 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7205 system(pipeCmd);
7206
7207 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7208 if(fp == NULL)
7209 {
7210 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7211 return RETURN_ERR;
7212 }
7213 fclose(fp);
7214
7215 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7216 fp = popen(pipeCmd, "r");
7217 if(fp)
7218 {
7219 for(count =0 ; count < wifi_count; count++)
7220 {
7221 fgets(str, MAX_BUF_SIZE, fp);
7222 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7223 {
7224 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7225 {
7226 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7227
7228 }
7229 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7230 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]);
7231 }
7232 temp[count].cli_AuthenticationState = 1; //TODO
7233 temp[count].cli_Active = 1; //TODO
7234 }
7235 pclose(fp);
7236 }
7237
7238 //Updating RSSI per client
7239 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7240 fp = popen(pipeCmd, "r");
7241 if(fp)
7242 {
7243 pclose(fp);
7244 }
7245 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7246 if(fp)
7247 {
7248 for(count =0 ; count < wifi_count ;count++)
7249 {
7250 fgets(str, MAX_BUF_SIZE, fp);
7251 signalstrength = atoi(str);
7252 temp[count].cli_RSSI = signalstrength;
7253 }
7254 pclose(fp);
7255 }
7256
7257
7258 //LastDataDownlinkRate
7259 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7260 fp = popen(pipeCmd, "r");
7261 if (fp)
7262 {
7263 pclose(fp);
7264 }
7265 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7266 if (fp)
7267 {
7268 for (count = 0; count < wifi_count; count++)
7269 {
7270 fgets(str, MAX_BUF_SIZE, fp);
7271 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7272 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7273 }
7274 pclose(fp);
7275 }
7276
7277 //LastDataUplinkRate
7278 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7279 fp = popen(pipeCmd, "r");
7280 if (fp)
7281 {
7282 pclose(fp);
7283 }
7284 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7285 if (fp)
7286 {
7287 for (count = 0; count < wifi_count; count++)
7288 {
7289 fgets(str, MAX_BUF_SIZE, fp);
7290 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7291 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7292 }
7293 pclose(fp);
7294 }
7295 }
7296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7297 return RETURN_OK;
7298
7299}
7300
7301INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
7302{
7303#if 0
7304 /*char buf[1024] = {0};
7305 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
7306 _syscmd(cmd, buf, sizeof(buf));*/
7307
7308 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
7309 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
7310 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
7311 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
7312
7313 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.
7314 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].
7315 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].
7316 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].
7317 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
7318 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
7319
7320 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
7321 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
7322 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
7323 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.
7324 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.
7325 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.
7326 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.
7327 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.
7328 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.
7329 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.
7330 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
7331#endif
7332
7333 FILE *fp = NULL;
7334 char HConf_file[MAX_BUF_SIZE] = {'\0'};
7335 char interface_name[50] = {0};
7336 char pipeCmd[MAX_CMD_SIZE] = {0};
7337 char str[MAX_BUF_SIZE] = {0};
7338 wifi_ssidTrafficStats2_t *out = output_struct;
7339
7340 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7341 if (!output_struct)
7342 return RETURN_ERR;
7343
7344 if (ssidIndex >= 4)
7345 return RETURN_ERR;
7346
7347 sprintf(HConf_file,"%s%d%s","/nvram/hostapd",ssidIndex,".conf");
7348 GetInterfaceName(interface_name,HConf_file);
7349 sprintf(pipeCmd,"%s%s%s","cat /proc/net/dev | grep ",interface_name," | tr -s ' ' | cut -d ' ' -f11 | tr -d '\n'");
7350 fp = popen(pipeCmd, "r");
7351 fgets(str, MAX_BUF_SIZE,fp);
7352 out->ssid_BytesSent = atol(str);
7353 pclose(fp);
7354
7355 sprintf(pipeCmd,"%s%s%s","cat /proc/net/dev | grep ",interface_name," | tr -s ' ' | cut -d ' ' -f3 | tr -d '\n'");
7356 fp = popen(pipeCmd, "r");
7357 fgets(str, MAX_BUF_SIZE,fp);
7358 out->ssid_BytesReceived = atol(str);
7359 pclose(fp);
7360
7361 sprintf(pipeCmd,"%s%s%s","cat /proc/net/dev | grep ",interface_name," | tr -s ' ' | cut -d ' ' -f12 | tr -d '\n'");
7362 fp = popen(pipeCmd, "r");
7363 fgets(str, MAX_BUF_SIZE,fp);
7364 out->ssid_PacketsSent = atol(str);
7365 pclose(fp);
7366
7367 sprintf(pipeCmd,"%s%s%s","cat /proc/net/dev | grep ",interface_name," | tr -s ' ' | cut -d ' ' -f4 | tr -d '\n'");
7368 fp = popen(pipeCmd, "r");
7369 fgets(str, MAX_BUF_SIZE,fp);
7370 out->ssid_PacketsReceived = atol(str);
7371 pclose(fp);
7372 /*
7373 //TODO:
7374 out->ssid_UnicastPacketsSent = uni->ims_tx_data_packets;
7375 out->ssid_UnicastPacketsReceived = uni->ims_rx_data_packets;
7376 out->ssid_MulticastPacketsSent = multi->ims_tx_data_packets - multi->ims_tx_bcast_data_packets;
7377 out->ssid_MulticastPacketsReceived = multi->ims_rx_data_packets - multi->ims_rx_bcast_data_packets;
7378 out->ssid_BroadcastPacketsSent = multi->ims_tx_bcast_data_packets;
7379 out->ssid_BroadcastPacketsRecevied = multi->ims_rx_bcast_data_packets;
7380 */
7381 return RETURN_OK;
7382}
7383
7384//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).
7385INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
7386{
7387 char output_val[16]={'\0'};
7388 char config_file[MAX_BUF_SIZE] = {0};
7389
7390 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7391 if (!output)
7392 return RETURN_ERR;
7393 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7394 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
7395
7396 if( strcmp(output_val,"1") == 0 )
7397 *output = TRUE;
7398 else
7399 *output = FALSE;
7400 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7401
7402 return RETURN_OK;
7403}
7404
7405INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
7406{
7407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7408 char str[MAX_BUF_SIZE]={'\0'};
7409 char string[MAX_BUF_SIZE]={'\0'};
7410 char cmd[MAX_CMD_SIZE]={'\0'};
7411 char *ch;
7412 char config_file[MAX_BUF_SIZE] = {0};
7413 struct params params;
7414
7415 if(enable == TRUE)
7416 strcpy(string,"1");
7417 else
7418 strcpy(string,"0");
7419
7420 params.name = "ap_isolate";
7421 params.value = string;
7422
7423 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7424 wifi_hostapdWrite(config_file,&params,1);
7425 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7426
7427 return RETURN_OK;
7428}
7429
7430INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
7431{
7432 if (NULL == output_dBm)
7433 return RETURN_ERR;
7434
7435 *output_dBm = 0;
7436 return RETURN_OK;
7437}
7438
7439INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
7440{
7441 return RETURN_OK;
7442}
7443INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
7444{
7445 return RETURN_OK;
7446}
7447INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
7448{
7449 return RETURN_OK;
7450}
7451INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
7452{
7453 return RETURN_OK;
7454}
7455INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
7456{
7457 return RETURN_OK;
7458}
7459INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
7460{
7461 char config_file[MAX_BUF_SIZE] = {0};
7462 struct params list;
7463
7464 list.name = "bss_transition";
7465 list.value = activate?"1":"0";
7466 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
7467 wifi_hostapdWrite(config_file, &list, 1);
7468
7469 return RETURN_OK;
7470}
7471wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
7472
7473void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
7474{
7475 return;
7476}
7477
7478INT wifi_setApCsaDeauth(INT apIndex, INT mode)
7479{
7480 // TODO Implement me!
7481 return RETURN_OK;
7482}
7483
7484INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
7485{
7486 // TODO Implement me!
7487 return RETURN_OK;
7488}
7489
7490INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
7491{
7492 // TODO Implement me!
7493 //Apply wifi_pushRadioChannel() instantly
7494 return RETURN_ERR;
7495}
7496
7497INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
7498{
7499 // TODO Implement me!
7500 return RETURN_OK;
7501}
7502
7503#ifdef HAL_NETLINK_IMPL
7504static int tidStats_callback(struct nl_msg *msg, void *arg) {
7505 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7506 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7507 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
7508 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
7509 int rem , tid_index = 0;
7510
7511 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
7512 wifi_associated_dev_tid_entry_t *stats_entry;
7513
7514 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
7515 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
7516 };
7517 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
7518 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
7519 };
7520
7521 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7522 genlmsg_attrlen(gnlh, 0), NULL);
7523
7524
7525 if (!tb[NL80211_ATTR_STA_INFO]) {
7526 fprintf(stderr, "station stats missing!\n");
7527 return NL_SKIP;
7528 }
7529
7530 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
7531 tb[NL80211_ATTR_STA_INFO],
7532 stats_policy)) {
7533 fprintf(stderr, "failed to parse nested attributes!\n");
7534 return NL_SKIP;
7535 }
7536
7537 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
7538 {
7539 stats_entry = &out->tid_array[tid_index];
7540
7541 stats_entry->tid = tid_index;
7542 stats_entry->ac = _tid_ac_index_get[tid_index];
7543
7544 if(sinfo[NL80211_STA_INFO_TID_STATS])
7545 {
7546 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
7547 printf("failed to parse nested stats attributes!");
7548 return NL_SKIP;
7549 }
7550 }
7551 if(stats_info[NL80211_TID_STATS_TX_MSDU])
7552 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
7553
7554 if(tid_index < (PS_MAX_TID - 1))
7555 tid_index++;
7556 }
7557 //ToDo: sum_time_ms, ewma_time_ms
7558 return NL_SKIP;
7559}
7560#endif
7561
7562INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
7563{
7564#ifdef HAL_NETLINK_IMPL
7565 Netlink nl;
7566 char if_name[10];
7567
7568 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
7569
7570 nl.id = initSock80211(&nl);
7571
7572 if (nl.id < 0) {
7573 fprintf(stderr, "Error initializing netlink \n");
7574 return -1;
7575 }
7576
7577 struct nl_msg* msg = nlmsg_alloc();
7578
7579 if (!msg) {
7580 fprintf(stderr, "Failed to allocate netlink message.\n");
7581 nlfree(&nl);
7582 return -2;
7583 }
7584
7585 genlmsg_put(msg,
7586 NL_AUTO_PORT,
7587 NL_AUTO_SEQ,
7588 nl.id,
7589 0,
7590 0,
7591 NL80211_CMD_GET_STATION,
7592 0);
7593
7594 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
7595 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
7596 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
7597 nl_send_auto(nl.socket, msg);
7598 nl_recvmsgs(nl.socket, nl.cb);
7599 nlmsg_free(msg);
7600 nlfree(&nl);
7601 return RETURN_OK;
7602#else
7603//iw implementation
7604#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
7605#define TOTAL_MAX_LINES 50
7606
7607 char buf[256] = {'\0'}; /* or other suitable maximum line size */
7608 char if_name[10];
7609 FILE *fp=NULL;
7610 char pipeCmd[1024]= {'\0'};
7611 int lines,tid_index=0;
7612 char mac_addr[20] = {'\0'};
7613
7614 wifi_associated_dev_tid_entry_t *stats_entry;
7615
7616 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
7617 strcpy(mac_addr,clientMacAddress);
7618
7619 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
7620 fp= popen(pipeCmd,"r");
7621 if(fp == NULL)
7622 {
7623 perror("popen for station dump failed\n");
7624 return RETURN_ERR;
7625 }
7626 pclose(fp);
7627
7628 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
7629 fp=popen(pipeCmd,"r");
7630 if(fp == NULL)
7631 {
7632 perror("popen for grep station failed\n");
7633 return RETURN_ERR;
7634 }
7635 else if(fgets(buf,sizeof(buf),fp) != NULL)
7636 lines=atoi(buf);
7637 else
7638 {
7639 pclose(fp);
7640 fprintf(stderr,"No devices are connected \n");
7641 return RETURN_ERR;
7642 }
7643 pclose(fp);
7644
7645 if(lines == 1)
7646 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
7647
7648 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
7649 {
7650 stats_entry = &tid_stats->tid_array[tid_index];
7651 stats_entry->tid = tid_index;
7652
7653 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);
7654
7655 fp=popen(pipeCmd,"r");
7656 if(fp ==NULL)
7657 {
7658 perror("Failed to read from tid file \n");
7659 return RETURN_ERR;
7660 }
7661 else if(fgets(buf,sizeof(buf),fp) != NULL)
7662 stats_entry->num_msdus = atol(buf);
7663
7664 pclose(fp);
7665 stats_entry->ac = _tid_ac_index_get[tid_index];
7666// TODO:
7667// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
7668// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
7669 }
7670 return RETURN_OK;
7671#endif
7672}
7673
7674
7675INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
7676{
7677 // TODO Implement me!
7678 return RETURN_OK;
7679}
7680
7681
7682INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
7683{
7684 // TODO Implement me!
7685 return RETURN_ERR;
7686}
7687
7688INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
7689{
7690 // TODO Implement me!
7691 return RETURN_ERR;
7692}
7693
7694INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
7695{
7696 // TODO Implement me!
7697 return RETURN_ERR;
7698}
7699
7700INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
7701{
7702 // TODO Implement me!
7703 return RETURN_ERR;
7704}
7705
7706INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
7707{
7708 // TODO Implement me!
7709 return RETURN_ERR;
7710}
7711
7712INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
7713{
7714 // TODO Implement me!
7715 return RETURN_ERR;
7716}
7717
7718INT wifi_steering_eventUnregister(void)
7719{
7720 // TODO Implement me!
7721 return RETURN_ERR;
7722}
7723
7724INT wifi_delApAclDevices(INT apIndex)
7725{
7726#if 0
7727 char cmd[MAX_BUF_SIZE] = {0};
7728 char buf[MAX_BUF_SIZE] = {0};
7729
7730 /* Not reset proof solution */
7731 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
7732 if(_syscmd(cmd,buf,sizeof(buf)))
7733 return RETURN_ERR;
7734#endif
developere6aafda2022-09-13 14:59:28 +08007735 char cmd[MAX_CMD_SIZE]={0};
7736 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08007737
developere6aafda2022-09-13 14:59:28 +08007738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7739 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
7740 if(_syscmd(cmd, buf, sizeof(buf)))
7741 return RETURN_ERR;
7742 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007743
7744 return RETURN_OK;
7745}
7746
7747#ifdef HAL_NETLINK_IMPL
7748static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
7749 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7750 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7751 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
7752 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
7753 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
7754 char mac_addr[20],dev[20];
7755
7756 nla_parse(tb,
7757 NL80211_ATTR_MAX,
7758 genlmsg_attrdata(gnlh, 0),
7759 genlmsg_attrlen(gnlh, 0),
7760 NULL);
7761
7762 if(!tb[NL80211_ATTR_STA_INFO]) {
7763 fprintf(stderr, "sta stats missing!\n");
7764 return NL_SKIP;
7765 }
7766
7767 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
7768 fprintf(stderr, "failed to parse nested attributes!\n");
7769 return NL_SKIP;
7770 }
7771 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
7772
7773 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
7774
7775 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
7776 fprintf(stderr, "failed to parse nested rate attributes!");
7777 return NL_SKIP;
7778 }
7779
7780 if(sinfo[NL80211_STA_INFO_TID_STATS])
7781 {
7782 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
7783 printf("failed to parse nested stats attributes!");
7784 return NL_SKIP;
7785 }
7786 }
7787
7788 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
7789 {
7790 printf("Type is VHT\n");
7791 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
7792 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
7793
7794 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
7795 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
7796 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
7797 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
7798 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
7799 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
7800 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
7801 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
7802 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
7803 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
7804 }
7805 else
7806 {
7807 printf(" OFDM or CCK \n");
7808 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
7809 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
7810 }
7811
7812 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
7813 if(rinfo[NL80211_RATE_INFO_MCS])
7814 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
7815 }
7816 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
7817 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
7818 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
7819 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
7820
7821 if(stats_info[NL80211_TID_STATS_RX_MSDU])
7822 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
7823
7824 if (sinfo[NL80211_STA_INFO_SIGNAL])
7825 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
7826 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
7827 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
7828 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
7829 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
7830 //rssi_array need to be filled
7831 return NL_SKIP;
7832}
7833#endif
7834
7835INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
7836{
7837#ifdef HAL_NETLINK_IMPL
7838 Netlink nl;
7839 char if_name[10];
7840
7841 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
7842
7843 if (*output_array_size <= 0)
7844 return RETURN_OK;
7845
7846 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
7847 nl.id = initSock80211(&nl);
7848
7849 if (nl.id < 0) {
7850 fprintf(stderr, "Error initializing netlink \n");
7851 return 0;
7852 }
7853
7854 struct nl_msg* msg = nlmsg_alloc();
7855
7856 if (!msg) {
7857 fprintf(stderr, "Failed to allocate netlink message.\n");
7858 nlfree(&nl);
7859 return 0;
7860 }
7861
7862 genlmsg_put(msg,
7863 NL_AUTO_PORT,
7864 NL_AUTO_SEQ,
7865 nl.id,
7866 0,
7867 0,
7868 NL80211_CMD_GET_STATION,
7869 0);
7870
7871 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
7872 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
7873 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
7874 nl_send_auto(nl.socket, msg);
7875 nl_recvmsgs(nl.socket, nl.cb);
7876 nlmsg_free(msg);
7877 nlfree(&nl);
7878 return RETURN_OK;
7879#else
7880 //TODO Implement me
7881 return RETURN_OK;
7882#endif
7883}
7884
7885#ifdef HAL_NETLINK_IMPL
7886static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
7887 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7888 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7889 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
7890 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
7891 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
7892 char mac_addr[20],dev[20];
7893
7894 nla_parse(tb,
7895 NL80211_ATTR_MAX,
7896 genlmsg_attrdata(gnlh, 0),
7897 genlmsg_attrlen(gnlh, 0),
7898 NULL);
7899
7900 if(!tb[NL80211_ATTR_STA_INFO]) {
7901 fprintf(stderr, "sta stats missing!\n");
7902 return NL_SKIP;
7903 }
7904
7905 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
7906 fprintf(stderr, "failed to parse nested attributes!\n");
7907 return NL_SKIP;
7908 }
7909
7910 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
7911
7912 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
7913
7914 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
7915 fprintf(stderr, "failed to parse nested rate attributes!");
7916 return NL_SKIP;
7917 }
7918
7919 if(sinfo[NL80211_STA_INFO_TID_STATS])
7920 {
7921 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
7922 printf("failed to parse nested stats attributes!");
7923 return NL_SKIP;
7924 }
7925 }
7926 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
7927 {
7928 printf("Type is VHT\n");
7929 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
7930 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
7931
7932 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
7933 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
7934 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
7935 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
7936 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
7937 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
7938 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
7939 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
7940 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
7941 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
7942 }
7943 else
7944 {
7945 printf(" OFDM or CCK \n");
7946 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
7947 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
7948 }
7949
7950 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
7951 if(rinfo[NL80211_RATE_INFO_MCS])
7952 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
7953 }
7954
7955 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
7956 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
7957 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
7958 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
7959
7960 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
7961 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
7962 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
7963
7964 if(stats_info[NL80211_TID_STATS_TX_MSDU])
7965 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
7966
7967 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
7968 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
7969
7970 if(sinfo[NL80211_STA_INFO_TX_FAILED])
7971 ((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]);
7972
7973 return NL_SKIP;
7974}
7975#endif
7976
7977INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
7978{
7979#ifdef HAL_NETLINK_IMPL
7980 Netlink nl;
7981 char if_name[10];
7982
7983 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
7984
7985 if (*output_array_size <= 0)
7986 return RETURN_OK;
7987
7988 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
7989
7990 nl.id = initSock80211(&nl);
7991
7992 if(nl.id < 0) {
7993 fprintf(stderr, "Error initializing netlink \n");
7994 return 0;
7995 }
7996
7997 struct nl_msg* msg = nlmsg_alloc();
7998
7999 if(!msg) {
8000 fprintf(stderr, "Failed to allocate netlink message.\n");
8001 nlfree(&nl);
8002 return 0;
8003 }
8004
8005 genlmsg_put(msg,
8006 NL_AUTO_PORT,
8007 NL_AUTO_SEQ,
8008 nl.id,
8009 0,
8010 0,
8011 NL80211_CMD_GET_STATION,
8012 0);
8013
8014 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8015 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8016 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
8017 nl_send_auto(nl.socket, msg);
8018 nl_recvmsgs(nl.socket, nl.cb);
8019 nlmsg_free(msg);
8020 nlfree(&nl);
8021 return RETURN_OK;
8022#else
8023 //TODO Implement me
8024 return RETURN_OK;
8025#endif
8026}
8027
8028INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
8029{
8030 // TODO Implement me!
8031 char buf[MAX_BUF_SIZE] = {0};
8032 char config_file[MAX_BUF_SIZE] = {0};
8033
8034 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8035 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
8036 *activate = (strncmp("1",buf,1) == 0);
8037
8038 return RETURN_OK;
8039}
8040
8041INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
8042{
8043 char config_file[MAX_BUF_SIZE] = {0};
8044 struct params list;
8045
8046 list.name = "rrm_neighbor_report";
8047 list.value = activate?"1":"0";
8048 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8049 wifi_hostapdWrite(config_file, &list, 1);
8050
8051 return RETURN_OK;
8052}
8053
8054INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
8055{
8056 char buf[32] = {0};
8057 char config_file[MAX_BUF_SIZE] = {0};
8058
8059 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8060 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
8061 *activate = (strncmp("1",buf,1) == 0);
8062
8063 return RETURN_OK;
8064}
8065#undef HAL_NETLINK_IMPL
8066#ifdef HAL_NETLINK_IMPL
8067static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
8068 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8069 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8070 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
8071 char dev[20];
8072 int freq =0 ;
8073 static int i=0;
8074
8075 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
8076
8077 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
8078 };
8079
8080 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
8081
8082 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8083
8084 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
8085 fprintf(stderr, "survey data missing!\n");
8086 return NL_SKIP;
8087 }
8088
8089 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
8090 {
8091 fprintf(stderr, "failed to parse nested attributes!\n");
8092 return NL_SKIP;
8093 }
8094
8095
8096 if(out[0].array_size == 1 )
8097 {
8098 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
8099 {
8100 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
8101 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
8102 out[0].ch_number = ieee80211_frequency_to_channel(freq);
8103
8104 if (sinfo[NL80211_SURVEY_INFO_NOISE])
8105 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
8106 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
8107 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
8108 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
8109 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
8110 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
8111 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
8112 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
8113 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
8114 if (sinfo[NL80211_SURVEY_INFO_TIME])
8115 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
8116 return NL_STOP;
8117 }
8118 }
8119 else
8120 {
8121 if ( i <= out[0].array_size )
8122 {
8123 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
8124 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
8125 out[i].ch_number = ieee80211_frequency_to_channel(freq);
8126
8127 if (sinfo[NL80211_SURVEY_INFO_NOISE])
8128 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
8129 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
8130 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
8131 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
8132 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
8133 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
8134 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
8135 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
8136 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
8137 if (sinfo[NL80211_SURVEY_INFO_TIME])
8138 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
8139 }
8140 }
8141
8142 i++;
8143 return NL_SKIP;
8144}
8145#endif
8146
8147static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
8148{
8149 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
8150 FILE *fp;
8151
8152 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
8153 {
8154 printf("Creating Frequency-Channel Map\n");
8155 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
8156 }
8157 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
8158 if((fp = popen(command, "r")))
8159 {
8160 fgets(output, sizeof(output), fp);
8161 *freqMHz = atoi(output);
8162 fclose(fp);
8163 }
8164
8165 return 0;
8166}
8167
8168static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
8169{
8170 int freqMHz = -1;
8171 char cmd[MAX_CMD_SIZE] = {'\0'};
8172
8173 ieee80211_channel_to_frequency(channel, &freqMHz);
8174 if (freqMHz == -1) {
8175 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
8176 return -1;
8177 }
8178
8179 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
8180 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
8181 radioIndex, freqMHz);
8182 return -1;
8183 }
8184
8185 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
8186 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
8187 return -1;
8188 }
8189
8190 return 0;
8191}
8192
8193static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
8194{
8195 const char *ptr = buf;
8196 char *key = NULL;
8197 char *val = NULL;
8198 char line[256] = { '\0' };
8199
8200 while (ptr = get_line_from_str_buf(ptr, line)) {
8201 if (strstr(line, "Frequency")) continue;
8202
8203 key = strtok(line, ":");
8204 val = strtok(NULL, " ");
8205 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
8206
8207 if (!strcmp(key, "noise")) {
8208 sscanf(val, "%d", &stats->ch_noise);
8209 if (stats->ch_noise == 0) {
8210 // Workaround for missing noise information.
8211 // Assume -95 for 2.4G and -103 for 5G
8212 if (radioIndex == 0) stats->ch_noise = -95;
8213 if (radioIndex == 1) stats->ch_noise = -103;
8214 }
8215 }
8216 else if (!strcmp(key, "channel active time")) {
8217 sscanf(val, "%llu", &stats->ch_utilization_total);
8218 }
8219 else if (!strcmp(key, "channel busy time")) {
8220 sscanf(val, "%llu", &stats->ch_utilization_busy);
8221 }
8222 else if (!strcmp(key, "channel receive time")) {
8223 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
8224 }
8225 else if (!strcmp(key, "channel transmit time")) {
8226 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
8227 }
8228 };
8229
8230 return 0;
8231}
8232
8233INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
8234{
8235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8236#ifdef HAL_NETLINK_IMPL
8237 Netlink nl;
8238 wifi_channelStats_t_loc local[array_size];
8239 char if_name[10];
8240
8241 local[0].array_size = array_size;
8242
8243 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8244
8245 nl.id = initSock80211(&nl);
8246
8247 if (nl.id < 0) {
8248 fprintf(stderr, "Error initializing netlink \n");
8249 return -1;
8250 }
8251
8252 struct nl_msg* msg = nlmsg_alloc();
8253
8254 if (!msg) {
8255 fprintf(stderr, "Failed to allocate netlink message.\n");
8256 nlfree(&nl);
8257 return -2;
8258 }
8259
8260 genlmsg_put(msg,
8261 NL_AUTO_PORT,
8262 NL_AUTO_SEQ,
8263 nl.id,
8264 0,
8265 NLM_F_DUMP,
8266 NL80211_CMD_GET_SURVEY,
8267 0);
8268
8269 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8270 nl_send_auto(nl.socket, msg);
8271 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
8272 nl_recvmsgs(nl.socket, nl.cb);
8273 nlmsg_free(msg);
8274 nlfree(&nl);
8275 //Copying the Values
8276 for(int i=0;i<array_size;i++)
8277 {
8278 input_output_channelStats_array[i].ch_number = local[i].ch_number;
8279 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
8280 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
8281 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
8282 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
8283 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
8284 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
8285 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
8286 }
8287#else
8288 ULONG channel = 0;
8289 int i;
8290 int number_of_channels = array_size;
8291 char buf[512];
8292 INT ret;
8293 wifi_channelStats_t tmp_stats;
8294
8295 if (number_of_channels == 0) {
8296 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
8297 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
8298 return RETURN_ERR;
8299 }
8300 number_of_channels = 1;
8301 input_output_channelStats_array[0].ch_number = channel;
8302 }
8303
8304 for (i = 0; i < number_of_channels; i++) {
8305
8306 input_output_channelStats_array[i].ch_noise = 0;
8307 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
8308 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
8309 input_output_channelStats_array[i].ch_utilization_busy = 0;
8310 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
8311 input_output_channelStats_array[i].ch_utilization_total = 0;
8312
8313 memset(buf, 0, sizeof(buf));
8314 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
8315 return RETURN_ERR;
8316 }
8317 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
8318 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
8319 return RETURN_ERR;
8320 }
8321
8322 // XXX: fake missing 'self' counter which is not available in iw survey output
8323 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
8324 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
8325
8326 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
8327 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
8328 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
8329 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
8330 input_output_channelStats_array[i].ch_utilization_total *= 1000;
8331
8332 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",
8333 __func__,
8334 input_output_channelStats_array[i].ch_number,
8335 input_output_channelStats_array[i].ch_noise,
8336 input_output_channelStats_array[i].ch_utilization_total,
8337 input_output_channelStats_array[i].ch_utilization_busy,
8338 input_output_channelStats_array[i].ch_utilization_busy_rx,
8339 input_output_channelStats_array[i].ch_utilization_busy_tx,
8340 input_output_channelStats_array[i].ch_utilization_busy_self,
8341 input_output_channelStats_array[i].ch_utilization_busy_ext);
8342 }
8343#endif
8344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8345 return RETURN_OK;
8346}
8347#define HAL_NETLINK_IMPL
8348
8349/* Hostapd events */
8350
8351#ifndef container_of
8352#define offset_of(st, m) ((size_t)&(((st *)0)->m))
8353#define container_of(ptr, type, member) \
8354 ((type *)((char *)ptr - offset_of(type, member)))
8355#endif /* container_of */
8356
8357struct ctrl {
8358 char sockpath[128];
8359 char sockdir[128];
8360 char bss[IFNAMSIZ];
8361 char reply[4096];
8362 int ssid_index;
8363 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
8364 void (*overrun)(struct ctrl *ctrl);
8365 struct wpa_ctrl *wpa;
8366 unsigned int ovfl;
8367 size_t reply_len;
8368 int initialized;
8369 ev_timer retry;
8370 ev_timer watchdog;
8371 ev_stat stat;
8372 ev_io io;
8373};
8374static wifi_newApAssociatedDevice_callback clients_connect_cb;
8375static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
8376static struct ctrl wpa_ctrl[MAX_APS];
8377static int initialized;
8378
8379static unsigned int ctrl_get_drops(struct ctrl *ctrl)
8380{
8381 char cbuf[256] = {};
8382 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
8383 struct cmsghdr *cmsg;
8384 unsigned int ovfl = ctrl->ovfl;
8385 unsigned int drop;
8386
8387 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
8388 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
8389 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
8390 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
8391
8392 drop = ovfl - ctrl->ovfl;
8393 ctrl->ovfl = ovfl;
8394
8395 return drop;
8396}
8397
8398static void ctrl_close(struct ctrl *ctrl)
8399{
8400 if (ctrl->io.cb)
8401 ev_io_stop(EV_DEFAULT_ &ctrl->io);
8402 if (ctrl->retry.cb)
8403 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
8404 if (!ctrl->wpa)
8405 return;
8406
8407 wpa_ctrl_detach(ctrl->wpa);
8408 wpa_ctrl_close(ctrl->wpa);
8409 ctrl->wpa = NULL;
8410 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
8411}
8412
8413static void ctrl_process(struct ctrl *ctrl)
8414{
8415 const char *str;
8416 int drops;
8417 int level;
8418 int err;
8419
8420 /* Example events:
8421 *
8422 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
8423 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
8424 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
8425 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
8426 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
8427 */
8428 if (!(str = index(ctrl->reply, '>')))
8429 return;
8430 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
8431 return;
8432
8433 str++;
8434
8435 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
8436 if (!(str = index(ctrl->reply, ' ')))
8437 return;
8438 wifi_associated_dev_t sta;
8439 memset(&sta, 0, sizeof(sta));
8440
8441 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
8442 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
8443 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
8444
8445 sta.cli_Active=true;
8446
8447 (clients_connect_cb)(ctrl->ssid_index, &sta);
8448 goto handled;
8449 }
8450
8451 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
8452 if (!(str = index(ctrl->reply, ' ')))
8453 return;
8454
8455 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
8456 goto handled;
8457 }
8458
8459 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
8460 printf("CTRL_WPA: handle TERMINATING event\n");
8461 goto retry;
8462 }
8463
8464 if (strncmp("AP-DISABLED", str, 11) == 0) {
8465 printf("CTRL_WPA: handle AP-DISABLED\n");
8466 goto retry;
8467 }
8468
8469 printf("Event not supported!!\n");
8470
8471handled:
8472
8473 if ((drops = ctrl_get_drops(ctrl))) {
8474 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
8475 if (ctrl->overrun)
8476 ctrl->overrun(ctrl);
8477 }
8478
8479 return;
8480
8481retry:
8482 printf("WPA_CTRL: closing\n");
8483 ctrl_close(ctrl);
8484 printf("WPA_CTRL: retrying from ctrl prcoess\n");
8485 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
8486}
8487
8488static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
8489{
8490 struct ctrl *ctrl = container_of(io, struct ctrl, io);
8491 int err;
8492
8493 memset(ctrl->reply, 0, sizeof(ctrl->reply));
8494 ctrl->reply_len = sizeof(ctrl->reply) - 1;
8495 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
8496 ctrl->reply[ctrl->reply_len] = 0;
8497 if (err < 0) {
8498 if (errno == EAGAIN || errno == EWOULDBLOCK)
8499 return;
8500 ctrl_close(ctrl);
8501 ev_timer_again(EV_A_ &ctrl->retry);
8502 return;
8503 }
8504
8505 ctrl_process(ctrl);
8506}
8507
8508static int ctrl_open(struct ctrl *ctrl)
8509{
8510 int fd;
8511
8512 if (ctrl->wpa)
8513 return 0;
8514
8515 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
8516 if (!ctrl->wpa)
8517 goto err;
8518
8519 if (wpa_ctrl_attach(ctrl->wpa) < 0)
8520 goto err_close;
8521
8522 fd = wpa_ctrl_get_fd(ctrl->wpa);
8523 if (fd < 0)
8524 goto err_detach;
8525
8526 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
8527 goto err_detach;
8528
8529 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
8530 ev_io_start(EV_DEFAULT_ &ctrl->io);
8531
8532 return 0;
8533
8534err_detach:
8535 wpa_ctrl_detach(ctrl->wpa);
8536err_close:
8537 wpa_ctrl_close(ctrl->wpa);
8538err:
8539 ctrl->wpa = NULL;
8540 return -1;
8541}
8542
8543static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
8544{
8545 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
8546
8547 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
8548 ctrl_open(ctrl);
8549}
8550
8551static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
8552{
8553 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
8554
8555 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
8556 if (ctrl_open(ctrl) == 0) {
8557 printf("WPA_CTRL: retry successful\n");
8558 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
8559 }
8560}
8561
8562int ctrl_enable(struct ctrl *ctrl)
8563{
8564 if (ctrl->wpa)
8565 return 0;
8566
8567 if (!ctrl->stat.cb) {
8568 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
8569 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
8570 }
8571
8572 if (!ctrl->retry.cb) {
8573 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
8574 }
8575
8576 return ctrl_open(ctrl);
8577}
8578
8579static void
8580ctrl_msg_cb(char *buf, size_t len)
8581{
8582 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
8583
8584 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
8585 ctrl_process(ctrl);
8586}
8587
8588static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
8589{
8590 int err;
8591
8592 if (!ctrl->wpa)
8593 return -1;
8594 if (*reply_len < 2)
8595 return -1;
8596
8597 (*reply_len)--;
8598 ctrl->reply_len = sizeof(ctrl->reply);
8599 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
8600 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
8601 if (err < 0)
8602 return err;
8603
8604 if (ctrl->reply_len > *reply_len)
8605 ctrl->reply_len = *reply_len;
8606
8607 *reply_len = ctrl->reply_len;
8608 memcpy(reply, ctrl->reply, *reply_len);
8609 reply[*reply_len - 1] = 0;
8610 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
8611 return 0;
8612}
8613
8614static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
8615{
8616 const char *pong = "PONG";
8617 const char *ping = "PING";
8618 char reply[1024];
8619 size_t len = sizeof(reply);
8620 int err;
8621 ULONG s, snum;
8622 INT ret;
8623 BOOL status;
8624
8625 printf("WPA_CTRL: watchdog cb\n");
8626
8627 ret = wifi_getSSIDNumberOfEntries(&snum);
8628 if (ret != RETURN_OK) {
8629 printf("%s: failed to get SSID count", __func__);
8630 return;
8631 }
8632
8633 if (snum > MAX_APS) {
8634 printf("more ssid than supported! %lu\n", snum);
8635 return;
8636 }
8637
8638 for (s = 0; s < snum; s++) {
8639 if (wifi_getApEnable(s, &status) != RETURN_OK) {
8640 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
8641 continue;
8642 }
8643 if (status == false) continue;
8644
8645 memset(reply, 0, sizeof(reply));
8646 len = sizeof(reply);
8647 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
8648 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
8649 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
8650 continue;
8651
8652 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
8653 ctrl_close(&wpa_ctrl[s]);
8654 printf("WPA_CTRL: ev_timer_again %d\n", s);
8655 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
8656 }
8657}
8658
8659static int init_wpa()
8660{
8661 int ret = 0, i = 0;
8662 ULONG s, snum;
8663
8664 ret = wifi_getSSIDNumberOfEntries(&snum);
8665 if (ret != RETURN_OK) {
8666 printf("%s: failed to get SSID count", __func__);
8667 return RETURN_ERR;
8668 }
8669
8670 if (snum > MAX_APS) {
8671 printf("more ssid than supported! %lu\n", snum);
8672 return RETURN_ERR;
8673 }
8674
8675 for (s = 0; s < snum; s++) {
8676 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
8677 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
8678 wpa_ctrl[s].ssid_index = s;
8679 ctrl_enable(&wpa_ctrl[s]);
8680 }
8681
8682 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
8683 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
8684
8685 initialized = 1;
8686 printf("WPA_CTRL: initialized\n");
8687
8688 return RETURN_OK;
8689}
8690
8691void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
8692{
8693 clients_connect_cb = callback_proc;
8694 if (!initialized)
8695 init_wpa();
8696}
8697
8698void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
8699{
8700 clients_disconnect_cb = callback_proc;
8701 if (!initialized)
8702 init_wpa();
8703}
8704
8705INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
8706{
8707 // TODO Implement me!
8708 return RETURN_ERR;
8709}
8710
8711INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
8712{
8713 // TODO Implement me!
8714 return RETURN_ERR;
8715}
8716
8717INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
8718{
8719 int i;
8720 char cmd[256];
8721 char channel_numbers_buf[256];
8722 char dfs_state_buf[256];
8723 char line[256];
8724 const char *ptr;
8725
8726 memset(cmd, 0, sizeof(cmd));
8727 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
8728 memset(line, 0, sizeof(line));
8729 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
8730 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
8731
8732 if (radioIndex == 0) { // 2.4G - all allowed
8733 if (outputMapSize < 11) {
8734 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
8735 return RETURN_ERR;
8736 }
8737
8738 for (i = 0; i < 11; i++) {
8739 outputMap[i].ch_number = i + 1;
8740 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
8741 }
8742
8743 return RETURN_OK;
8744 }
8745
8746 if (radioIndex == 1) { // 5G
8747// Example output of iw list:
8748//
8749// Frequencies:
8750// * 5180 MHz [36] (17.0 dBm)
8751// * 5200 MHz [40] (17.0 dBm)
8752// * 5220 MHz [44] (17.0 dBm)
8753// * 5240 MHz [48] (17.0 dBm)
8754// * 5260 MHz [52] (23.0 dBm) (radar detection)
8755// DFS state: usable (for 78930 sec)
8756// DFS CAC time: 60000 ms
8757// * 5280 MHz [56] (23.0 dBm) (radar detection)
8758// DFS state: usable (for 78930 sec)
8759// DFS CAC time: 60000 ms
8760// * 5300 MHz [60] (23.0 dBm) (radar detection)
8761// DFS state: usable (for 78930 sec)
8762// DFS CAC time: 60000 ms
8763// * 5320 MHz [64] (23.0 dBm) (radar detection)
8764// DFS state: usable (for 78930 sec)
8765// DFS CAC time: 60000 ms
8766// * 5500 MHz [100] (disabled)
8767// * 5520 MHz [104] (disabled)
8768// * 5540 MHz [108] (disabled)
8769// * 5560 MHz [112] (disabled)
8770//
8771// Below command should fetch channel numbers of each enabled channel in 5GHz band:
8772 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
8773 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
8774 return RETURN_ERR;
8775 }
8776
8777 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
8778 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
8779 return RETURN_ERR;
8780 }
8781
8782 ptr = channel_numbers_buf;
8783 i = 0;
8784 while (ptr = get_line_from_str_buf(ptr, line)) {
8785 if (i >= outputMapSize) {
8786 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
8787 return RETURN_ERR;
8788 }
8789 sscanf(line, "%d", &outputMap[i].ch_number);
8790
8791 memset(cmd, 0, sizeof(cmd));
8792 // Below command should fetch string for DFS state (usable, available or unavailable)
8793 // Example line: "DFS state: usable (for 78930 sec)"
8794 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) {
8795 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
8796 return RETURN_ERR;
8797 }
8798
8799 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
8800 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
8801 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
8802 return RETURN_ERR;
8803 }
8804
8805 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
8806
8807 if (!strcmp(dfs_state_buf, "usable")) {
8808 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
8809 } else if (!strcmp(dfs_state_buf, "available")) {
8810 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
8811 } else if (!strcmp(dfs_state_buf, "unavailable")) {
8812 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
8813 } else {
8814 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
8815 }
8816 i++;
8817 }
8818
8819 return RETURN_OK;
8820 }
8821
8822 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
8823 return RETURN_ERR;
8824}
8825
8826INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
8827{
8828 // TODO Implement me!
8829 return RETURN_ERR;
8830}
8831
8832INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
8833{
8834 return RETURN_OK;
8835}
8836
8837INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
8838{
8839 // TODO Implement me!
8840 return RETURN_ERR;
8841}
8842
8843INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
8844{
8845 // TODO API refrence Implementaion is present on RPI hal
8846 return RETURN_ERR;
8847}
8848
8849INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
8850{
8851 //TO-Do Implement this
8852 txpwr_pcntg = 0;
8853 return RETURN_OK;
8854}
8855
8856INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
8857{
8858 //Zero-wait DFS not supported
8859 return RETURN_ERR;
8860}
8861
8862INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
8863{
8864 //Zero-wait DFS not supported
8865 return RETURN_ERR;
8866}
8867
8868INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
8869{
8870 *supported = false;
8871 return RETURN_OK;
8872}
8873
8874/* multi-psk support */
8875INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
8876{
8877 char cmd[256];
8878
8879 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
8880 AP_PREFIX,
8881 apIndex,
8882 mac[0],
8883 mac[1],
8884 mac[2],
8885 mac[3],
8886 mac[4],
8887 mac[5]
8888 );
8889 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
8890 _syscmd(cmd, key->wifi_keyId, 64);
8891
8892
8893 return RETURN_OK;
8894}
8895
8896INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
8897{
8898 FILE *fd = NULL;
8899 char fname[100];
8900 char cmd[128] = {0};
8901 char out[64] = {0};
8902 wifi_key_multi_psk_t * key = NULL;
8903 if(keysNumber < 0)
8904 return RETURN_ERR;
8905
8906 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
8907 fd = fopen(fname, "w");
8908 if (!fd) {
8909 return RETURN_ERR;
8910 }
8911 key= (wifi_key_multi_psk_t *) keys;
8912 for(int i=0; i<keysNumber; ++i, key++) {
8913 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
8914 }
8915 fclose(fd);
8916
8917 //reload file
8918 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
8919 _syscmd(cmd, out, 64);
8920 return RETURN_OK;
8921}
8922
8923INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
8924{
8925 FILE *fd = NULL;
8926 char fname[100];
8927 char * line = NULL;
8928 char * pos = NULL;
8929 size_t len = 0;
8930 ssize_t read = 0;
8931 INT ret = RETURN_OK;
8932 wifi_key_multi_psk_t *keys_it = NULL;
8933
8934 if (keysNumber < 1) {
8935 return RETURN_ERR;
8936 }
8937
8938 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
8939 fd = fopen(fname, "r");
8940 if (!fd) {
8941 return RETURN_ERR;
8942 }
8943
8944 if (keys == NULL) {
8945 ret = RETURN_ERR;
8946 goto close;
8947 }
8948
8949 keys_it = keys;
8950 while ((read = getline(&line, &len, fd)) != -1) {
8951 //Strip trailing new line if present
8952 if (read > 0 && line[read-1] == '\n') {
8953 line[read-1] = '\0';
8954 }
8955
8956 if(strcmp(line,"keyid=")) {
8957 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
8958 if (!(pos = index(line, ' '))) {
8959 ret = RETURN_ERR;
8960 goto close;
8961 }
8962 pos++;
8963 //Here should be 00:00:00:00:00:00
8964 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
8965 printf("Not supported MAC: %s\n", pos);
8966 }
8967 if (!(pos = index(pos, ' '))) {
8968 ret = RETURN_ERR;
8969 goto close;
8970 }
8971 pos++;
8972
8973 //The rest is PSK
8974 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
8975 keys_it++;
8976
8977 if(--keysNumber <= 0)
8978 break;
8979 }
8980 }
8981
8982close:
8983 free(line);
8984 fclose(fd);
8985 return ret;
8986}
8987/* end of multi-psk support */
8988
8989INT wifi_setNeighborReports(UINT apIndex,
8990 UINT numNeighborReports,
8991 wifi_NeighborReport_t *neighborReports)
8992{
8993 char cmd[256] = { 0 };
8994 char hex_bssid[13] = { 0 };
8995 char bssid[18] = { 0 };
8996 char nr[256] = { 0 };
8997 char ssid[256];
8998 char hex_ssid[256];
8999 INT ret;
9000
9001 /*rmeove all neighbors*/
9002 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
9003 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);
9004 system(cmd);
9005
9006 for(unsigned int i = 0; i < numNeighborReports; i++)
9007 {
9008 memset(ssid, 0, sizeof(ssid));
9009 ret = wifi_getSSIDName(apIndex, ssid);
9010 if (ret != RETURN_OK)
9011 return RETURN_ERR;
9012
9013 memset(hex_ssid, 0, sizeof(hex_ssid));
9014 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
9015 sprintf(hex_ssid + k,"%02x", ssid[j]);
9016
9017 snprintf(hex_bssid, sizeof(hex_bssid),
9018 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
9019 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
9020 snprintf(bssid, sizeof(bssid),
9021 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
9022 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
9023
9024 snprintf(nr, sizeof(nr),
9025 "%s" // bssid
9026 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
9027 "%02hhx" // operclass
9028 "%02hhx" // channel
9029 "%02hhx", // phy_mode
9030 hex_bssid,
9031 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
9032 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
9033 neighborReports[i].opClass,
9034 neighborReports[i].channel,
9035 neighborReports[i].phyTable);
9036
9037 snprintf(cmd, sizeof(cmd),
9038 "hostapd_cli set_neighbor "
9039 "%s " // bssid
9040 "ssid=%s " // ssid
9041 "nr=%s " // nr
9042 "-i %s%d",
9043 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
9044
9045 if (WEXITSTATUS(system(cmd)) != 0)
9046 {
9047 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
9048 }
9049 }
9050
9051 return RETURN_OK;
9052}
9053
9054INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
9055{
9056 return RETURN_OK;
9057}
9058
9059#ifdef _WIFI_HAL_TEST_
9060int main(int argc,char **argv)
9061{
9062 int index;
9063 INT ret=0;
9064 char buf[1024]="";
9065
9066 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9067 if(argc<3)
9068 {
9069 if(argc==2)
9070 {
9071 if(!strcmp(argv[1], "init"))
9072 return wifi_init();
9073 if(!strcmp(argv[1], "reset"))
9074 return wifi_reset();
9075 if(!strcmp(argv[1], "wifi_getHalVersion"))
9076 {
9077 char buffer[64];
9078 if(wifi_getHalVersion(buffer)==RETURN_OK)
9079 printf("Version: %s\n", buffer);
9080 else
9081 printf("Error in wifi_getHalVersion\n");
9082 return RETURN_OK;
9083 }
9084 }
9085 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
9086 exit(-1);
9087 }
9088
9089 index = atoi(argv[2]);
9090 if(strstr(argv[1], "wifi_getApName")!=NULL)
9091 {
9092 wifi_getApName(index,buf);
9093 printf("Ap name is %s \n",buf);
9094 return 0;
9095 }
9096 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
9097 {
9098 BOOL b = FALSE;
9099 BOOL *output_bool = &b;
9100 wifi_getRadioAutoChannelEnable(index,output_bool);
9101 printf("Channel enabled = %d \n",b);
9102 return 0;
9103 }
9104 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
9105 {
9106 wifi_getApWpaEncryptionMode(index,buf);
9107 printf("encryption enabled = %s\n",buf);
9108 return 0;
9109 }
9110 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
9111 {
9112 BOOL b = FALSE;
9113 BOOL *output_bool = &b;
9114 wifi_getApSsidAdvertisementEnable(index,output_bool);
9115 printf("advertisment enabled = %d\n",b);
9116 return 0;
9117 }
9118 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
9119 {
9120 if(argc <= 3 )
9121 {
9122 printf("Insufficient arguments \n");
9123 exit(-1);
9124 }
9125
9126 char sta[20] = {'\0'};
9127 ULLONG handle= 0;
9128 strcpy(sta,argv[3]);
9129 mac_address_t st;
9130 mac_addr_aton(st,sta);
9131
9132 wifi_associated_dev_tid_stats_t tid_stats;
9133 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
9134 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
9135 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);
9136 }
9137
9138 if(strstr(argv[1], "getApEnable")!=NULL) {
9139 BOOL enable;
9140 ret=wifi_getApEnable(index, &enable);
9141 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
9142 }
9143 else if(strstr(argv[1], "setApEnable")!=NULL) {
9144 BOOL enable = atoi(argv[3]);
9145 ret=wifi_setApEnable(index, enable);
9146 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
9147 }
9148 else if(strstr(argv[1], "getApStatus")!=NULL) {
9149 char status[64];
9150 ret=wifi_getApStatus(index, status);
9151 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
9152 }
9153 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
9154 {
9155 wifi_getSSIDNameStatus(index,buf);
9156 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
9157 return 0;
9158 }
9159 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
9160 wifi_ssidTrafficStats2_t stats={0};
9161 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
9162 printf("%s %d: returns %d\n", argv[1], index, ret);
9163 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
9164 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
9165 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
9166 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
9167 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
9168 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
9169 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
9170 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
9171 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
9172 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
9173 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
9174 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
9175 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
9176 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
9177 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
9178 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
9179 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
9180 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
9181 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
9182 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
9183 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
9184 }
9185 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
9186 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
9187 UINT array_size=0;
9188 UINT i=0;
9189 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
9190 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
9191 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
9192 printf(" neighbor %d:\n", i);
9193 printf(" ap_SSID =%s\n", pt->ap_SSID);
9194 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
9195 printf(" ap_Mode =%s\n", pt->ap_Mode);
9196 printf(" ap_Channel =%d\n", pt->ap_Channel);
9197 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
9198 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
9199 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
9200 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
9201 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
9202 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
9203 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
9204 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
9205 printf(" ap_Noise =%d\n", pt->ap_Noise);
9206 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
9207 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
9208 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
9209 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
9210 }
9211 if(neighbor_ap_array)
9212 free(neighbor_ap_array); //make sure to free the list
9213 }
9214 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
9215 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
9216 UINT array_size=0;
9217 UINT i=0;
9218 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
9219 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
9220 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
9221 printf(" associated_dev %d:\n", i);
9222 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
9223 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
9224 printf(" cli_SNR =%d\n", pt->cli_SNR);
9225 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
9226 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
9227 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
9228 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
9229 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
9230 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
9231 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
9232 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
9233 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
9234 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
9235 }
9236 if(associated_dev_array)
9237 free(associated_dev_array); //make sure to free the list
9238 }
9239
9240 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
9241 {
9242#define MAX_ARRAY_SIZE 64
9243 int i, array_size;
9244 char *p, *ch_str;
9245 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
9246
9247 if(argc != 5)
9248 {
9249 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
9250 exit(-1);
9251 }
9252 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
9253
9254 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
9255 {
9256 strtok_r(ch_str, ",", &p);
9257 input_output_channelStats_array[i].ch_number = atoi(ch_str);
9258 }
9259 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
9260 if(!array_size)
9261 array_size=1;//Need to print current channel statistics
9262 for(i=0; i<array_size; i++)
9263 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
9264 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
9265 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
9266 input_output_channelStats_array[i].ch_number,\
9267 input_output_channelStats_array[i].ch_noise,\
9268 input_output_channelStats_array[i].ch_utilization_busy_rx,\
9269 input_output_channelStats_array[i].ch_utilization_busy_tx,\
9270 input_output_channelStats_array[i].ch_utilization_busy,\
9271 input_output_channelStats_array[i].ch_utilization_busy_ext,\
9272 input_output_channelStats_array[i].ch_utilization_total);
9273 }
9274
9275 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
9276 {
9277 if(argc <= 3 )
9278 {
9279 printf("Insufficient arguments \n");
9280 exit(-1);
9281 }
9282 char mac_addr[20] = {'\0'};
9283 wifi_device_t output_struct;
9284 int dev_index = atoi(argv[3]);
9285
9286 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
9287 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
9288 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);
9289 }
9290
9291 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
9292 {
9293 if (argc <= 3)
9294 {
9295 printf("Insufficient arguments\n");
9296 exit(-1);
9297 }
9298 char args[256];
9299 wifi_NeighborReport_t *neighborReports;
9300
9301 neighborReports = calloc(argc - 2, sizeof(neighborReports));
9302 if (!neighborReports)
9303 {
9304 printf("Failed to allocate memory");
9305 exit(-1);
9306 }
9307
9308 for (int i = 3; i < argc; ++i)
9309 {
9310 char *val;
9311 int j = 0;
9312 memset(args, 0, sizeof(args));
9313 strncpy(args, argv[i], sizeof(args));
9314 val = strtok(args, ";");
9315 while (val != NULL)
9316 {
9317 if (j == 0)
9318 {
9319 mac_addr_aton(neighborReports[i - 3].bssid, val);
9320 } else if (j == 1)
9321 {
9322 neighborReports[i - 3].info = strtol(val, NULL, 16);
9323 } else if (j == 2)
9324 {
9325 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
9326 } else if (j == 3)
9327 {
9328 neighborReports[i - 3].channel = strtol(val, NULL, 16);
9329 } else if (j == 4)
9330 {
9331 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
9332 } else {
9333 printf("Insufficient arguments]n\n");
9334 exit(-1);
9335 }
9336 val = strtok(NULL, ";");
9337 j++;
9338 }
9339 }
9340
9341 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
9342 if (ret != RETURN_OK)
9343 {
9344 printf("wifi_setNeighborReports ret = %d", ret);
9345 exit(-1);
9346 }
9347 }
9348 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
9349 {
9350 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
9351 printf("%s.\n", buf);
9352 else
9353 printf("Error returned\n");
9354 }
9355 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
9356 {
9357 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
9358 printf("%s.\n", buf);
9359 else
9360 printf("Error returned\n");
9361 }
9362 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
9363 {
9364 if (argc <= 2)
9365 {
9366 printf("Insufficient arguments\n");
9367 exit(-1);
9368 }
9369 char buf[64]= {'\0'};
9370 wifi_getRadioOperatingChannelBandwidth(index,buf);
9371 printf("Current bandwidth is %s \n",buf);
9372 return 0;
9373 }
9374 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
9375 {
9376 if (argc <= 5)
9377 {
9378 printf("Insufficient arguments\n");
9379 exit(-1);
9380 }
9381 UINT channel = atoi(argv[3]);
9382 UINT width = atoi(argv[4]);
9383 UINT beacon = atoi(argv[5]);
9384 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
9385 printf("Result = %d", ret);
9386 }
9387
9388 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9389 return 0;
9390}
9391
9392#endif
9393
9394#ifdef WIFI_HAL_VERSION_3
9395
9396INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
9397{
9398 // The only par-radio parameter is a channel number, however there's a 'dynamic' API
9399 // to change it ("wifi_pushRadioChannel2()") that is used instead.
9400 return RETURN_OK;
9401}
9402
9403INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
9404{
9405 INT ret;
9406 char band[128];
9407 ULONG channel;
9408 BOOL enabled;
9409 char buf[256];
9410
9411 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9412 printf("Entering %s index = %d\n", __func__, (int)index);
9413
9414 ret = wifi_getRadioEnable(index, &enabled);
9415 if (ret != RETURN_OK)
9416 {
9417 printf("%s: cannot get enabled state for radio index %d\n", __func__,
9418 index);
9419 return RETURN_ERR;
9420 }
9421 operationParam->enable = enabled;
9422
9423 memset(band, 0, sizeof(band));
9424 ret = wifi_getRadioOperatingFrequencyBand(index, band);
9425 if (ret != RETURN_OK)
9426 {
9427 printf("%s: cannot get radio band for radio index %d\n", __func__, index);
9428 return RETURN_ERR;
9429 }
9430
9431 if (!strcmp(band, "2.4GHz"))
9432 {
9433 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
9434 operationParam->variant = WIFI_80211_VARIANT_N;
9435 }
9436 else if (!strcmp(band, "5GHz"))
9437 {
9438 operationParam->band = WIFI_FREQUENCY_5_BAND;
9439 operationParam->variant = WIFI_80211_VARIANT_AC;
9440 }
9441 else
9442 {
9443 printf("%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
9444 band);
9445 }
9446
9447 memset(buf, 0, sizeof(buf));
9448 ret = wifi_getRadioOperatingChannelBandwidth(index, buf); // XXX: handle errors
9449 // XXX: only handle 20/40/80 modes for now
9450 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
9451 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
9452 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
9453 else
9454 {
9455 printf("%s: Unknown HT mode: '%s'\n", __func__, buf);
9456 operationParam->channelWidth = 0;
9457 }
9458
9459 ret = wifi_getRadioChannel(index, &channel);
9460 if (ret != RETURN_OK)
9461 {
9462 printf("%s: Failed to get channel number for radio index %d\n", __func__, index);
9463 channel = 0;
9464 }
9465 operationParam->channel = channel;
9466 operationParam->csa_beacon_count = 15; // XXX: hardcoded for now
9467
9468 operationParam->countryCode = wifi_countrycode_US; // XXX: hardcoded for now
9469
9470 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9471 return RETURN_OK;
9472}
9473
9474static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
9475{
9476 if (radioIndex != 0 && radioIndex != 1)
9477 {
9478 printf("%s: Wrong radio index (%d)\n", __func__, index);
9479 return -1;
9480 }
9481
9482 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
9483 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
9484
9485 return (arrayIndex * 2) + radioIndex;
9486}
9487
9488INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
9489{
9490 INT ret;
9491 int i;
9492 BOOL enabled = false;
9493 char buf[256];
9494 wifi_secur_list *secur_item;
9495 int vap_index;
9496 INT mode;
9497 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
9498
9499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9500 printf("Entering %s index = %d\n", __func__, (int)index);
9501
9502 map->vap_array[index].radio_index = index;
9503 for (i = 0; i < 5; i++)
9504 {
9505 vap_index = array_index_to_vap_index(index, i);
9506 if (vap_index < 0)
9507 {
9508 return RETURN_ERR;
9509 }
9510
9511 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
9512
9513 map->vap_array[i].vap_index = vap_index;
9514
9515 memset(buf, 0, sizeof(buf));
9516 wifi_getApName(vap_index, buf); // XXX: error handling
9517 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
9518
9519 ret = wifi_getSSIDEnable(vap_index, &enabled);
9520 if (ret != RETURN_OK)
9521 {
9522 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
9523 return RETURN_ERR;
9524 }
9525 map->vap_array[i].u.bss_info.enabled = enabled;
9526
9527 memset(buf, 0, sizeof(buf));
9528 wifi_getBaseBSSID(vap_index, buf);
9529 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9530 &map->vap_array[i].u.bss_info.bssid[0],
9531 &map->vap_array[i].u.bss_info.bssid[1],
9532 &map->vap_array[i].u.bss_info.bssid[2],
9533 &map->vap_array[i].u.bss_info.bssid[3],
9534 &map->vap_array[i].u.bss_info.bssid[4],
9535 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
9536
9537 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
9538 map->vap_array[i].u.bss_info.showSsid = enabled;
9539
9540 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
9541 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
9542 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
9543
9544 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
9545 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
9546
9547 memset(buf, 0, sizeof(buf));
9548 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
9549 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
9550
9551 wifi_getApSecurityModeEnabled(vap_index, buf);
9552
9553 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
9554 {
9555 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
9556 return RETURN_ERR;
9557 }
9558 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
9559
9560 memset(buf, 0, sizeof(buf));
9561 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
9562 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);
9563
9564 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
9565 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
9566
9567 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
9568 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
9569
9570 wifi_getApIsolationEnable(vap_index, &enabled);
9571 map->vap_array[i].u.bss_info.isolation = enabled;
9572 }
9573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9574 return RETURN_OK;
9575}
9576
9577INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
9578{
9579 unsigned int i;
9580 wifi_vap_info_t *vap_info = NULL;
9581 int acl_mode;
9582 char *sec_str = NULL;
9583
9584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9585 printf("Entering %s index = %d\n", __func__, (int)index);
9586 for (i = 0; i < map->num_vaps; i++)
9587 {
9588 vap_info = &map->vap_array[i];
9589 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
9590
9591 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
9592 else
9593 {
9594 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
9595 else acl_mode = 1;
9596 }
9597 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
9598 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
9599 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
9600
9601 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
9602 if (sec_str)
9603 {
9604 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
9605 }
9606 else
9607 {
9608 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
9609 }
9610
9611 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
9612 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
9613
9614 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
9615 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
9616
9617 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
9618
9619 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
9620 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
9621 }
9622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9623 return RETURN_OK;
9624}
9625
9626int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
9627{
9628 char *token, *next;
9629 const char s[2] = ",";
9630 int count =0;
9631
9632 /* get the first token */
9633 token = strtok_r(pchannels, s, &next);
9634
9635 /* walk through other tokens */
9636 while( token != NULL && count < MAX_CHANNELS) {
9637 chlistptr->channels_list[count++] = atoi(token);
9638 token = strtok_r(NULL, s, &next);
9639 }
9640
9641 return count;
9642}
9643
9644static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
9645{
9646 INT status;
9647 wifi_channels_list_t *chlistp;
9648 CHAR output_string[64];
9649 CHAR pchannels[128];
9650
9651 if(rcap == NULL)
9652 {
9653 return RETURN_ERR;
9654 }
9655
9656 rcap->numSupportedFreqBand = 1;
9657 if (1 == radioIndex)
9658 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
9659 else
9660 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
9661
9662
9663 chlistp = &(rcap->channel_list[0]);
9664 memset(pchannels, 0, sizeof(pchannels));
9665
9666 /* possible number of radio channels */
9667 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
9668 {
9669 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
9670 }
9671 /* Number of channels and list*/
9672 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
9673
9674 /* autoChannelSupported */
9675 /* always ON with wifi_getRadioAutoChannelSupported */
9676 rcap->autoChannelSupported = TRUE;
9677
9678 /* DCSSupported */
9679 /* always ON with wifi_getRadioDCSSupported */
9680 rcap->DCSSupported = TRUE;
9681
9682 /* zeroDFSSupported - TBD */
9683 rcap->zeroDFSSupported = FALSE;
9684
9685 /* Supported Country List*/
9686 memset(output_string, 0, sizeof(output_string));
9687 status = wifi_getRadioCountryCode(radioIndex, output_string);
9688 if( status != 0 ) {
9689 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
9690 return RETURN_ERR;
9691 } else {
9692 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
9693 }
9694 if(!strcmp(output_string,"US")){
9695 rcap->countrySupported[0] = wifi_countrycode_US;
9696 rcap->countrySupported[1] = wifi_countrycode_CA;
9697 } else if (!strcmp(output_string,"CA")) {
9698 rcap->countrySupported[0] = wifi_countrycode_CA;
9699 rcap->countrySupported[1] = wifi_countrycode_US;
9700 } else {
9701 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
9702 }
9703
9704 rcap->numcountrySupported = 2;
9705
9706 /* csi */
9707 rcap->csi.maxDevices = 8;
9708 rcap->csi.soudingFrameSupported = TRUE;
9709
9710 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
9711
9712 /* channelWidth - all supported bandwidths */
9713 int i=0;
9714 rcap->channelWidth[i] = 0;
9715 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
9716 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
9717 WIFI_CHANNELBANDWIDTH_40MHZ);
9718
9719 }
9720 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
9721 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
9722 WIFI_CHANNELBANDWIDTH_40MHZ |
9723 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
9724 }
9725
9726
9727 /* mode - all supported variants */
9728 // rcap->mode[i] = WIFI_80211_VARIANT_H;
9729 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
9730 rcap->mode[i] = (WIFI_80211_VARIANT_N);
9731 }
9732 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
9733 rcap->mode[i] = ( WIFI_80211_VARIANT_AC );
9734 }
9735 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
9736 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
9737
9738 /* supportedBitRate - all supported bitrates */
9739 rcap->supportedBitRate[i] = 0;
9740 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
9741 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
9742 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
9743 }
9744 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
9745 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
9746 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
9747 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
9748 }
9749
9750
9751 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
9752 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
9753 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
9754 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
9755 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
9756 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
9757 rcap->cipherSupported = 0;
9758 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
9759 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
9760
9761 return RETURN_OK;
9762}
9763
9764INT wifi_getHalCapability(wifi_hal_capability_t *cap)
9765{
9766 INT status, radioIndex;
9767 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
9768 int iter = 0;
9769 unsigned int j;
9770 wifi_interface_name_idex_map_t *iface_info;
9771
9772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9773
9774 memset(cap, 0, sizeof(wifi_hal_capability_t));
9775
9776 /* version */
9777 cap->version.major = WIFI_HAL_MAJOR_VERSION;
9778 cap->version.minor = WIFI_HAL_MINOR_VERSION;
9779
9780 /* number of radios platform property */
9781 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
9782 _syscmd(cmd, output, sizeof(output));
9783 cap->wifi_prop.numRadios = atoi(output);
9784
9785 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
9786 {
9787 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
9788 if (status != 0) {
9789 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
9790 return RETURN_ERR;
9791 }
9792
9793 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
9794 {
9795 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
9796 {
9797 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
9798 return RETURN_ERR;
9799 }
9800 iface_info = &cap->wifi_prop.interface_map[iter];
9801 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
9802 iface_info->rdk_radio_index = radioIndex;
9803 memset(output, 0, sizeof(output));
9804 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
9805 {
9806 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
9807 }
9808 // TODO: bridge name
9809 // TODO: vlan id
9810 // TODO: primary
9811 iface_info->index = array_index_to_vap_index(radioIndex, j);
9812 memset(output, 0, sizeof(output));
9813 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
9814 {
9815 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
9816 }
9817 iter++;
9818 }
9819 }
9820
9821 cap->BandSteeringSupported = FALSE;
9822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9823 return RETURN_OK;
9824}
9825
9826INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
9827{
9828 //TODO
9829 return RETURN_OK;
9830}
9831
9832INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
9833{
9834 //TODO
9835 return RETURN_OK;
9836}
9837
9838#endif /* WIFI_HAL_VERSION_3 */
9839
9840#ifdef WIFI_HAL_VERSION_3_PHASE2
9841INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
9842{
9843 return RETURN_OK;
9844}
9845#else
9846INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
9847{
9848 char cmd[128];
9849 BOOL status = false;
9850
9851 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
9852 return RETURN_ERR;
9853
9854 output_buf[0] = '\0';
9855
9856 wifi_getApEnable(ap_index,&status);
9857 if (!status)
9858 return RETURN_OK;
9859
9860 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
9861 _syscmd(cmd, output_buf, output_buf_size);
9862
9863 return RETURN_OK;
9864}
9865#endif
developer2f513ab2022-09-13 14:26:06 +08009866
9867INT wifi_getProxyArp(INT apIndex, BOOL *enable)
9868{
9869 char output[16]={'\0'};
9870 char config_file[MAX_BUF_SIZE] = {0};
9871
9872 if (!enable)
9873 return RETURN_ERR;
9874
9875 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9876 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
9877
9878 if (strlen(output) == 0)
9879 *enable = FALSE;
9880 else if (strncmp(output, "1", 1) == 0)
9881 *enable = TRUE;
9882 else
9883 *enable = FALSE;
9884
9885 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
9886 return RETURN_OK;
9887}
developer2d9c30f2022-09-13 15:06:14 +08009888
9889INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
9890{
9891 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
9892 return RETURN_ERR;
9893 *output_enable=TRUE;
9894 return RETURN_OK;
9895}