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