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