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