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