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