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