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